]> git.saurik.com Git - apple/javascriptcore.git/commitdiff
JavaScriptCore-1097.3.tar.gz ios-60 v1097.3
authorApple <opensource@apple.com>
Mon, 17 Sep 2012 19:58:38 +0000 (19:58 +0000)
committerApple <opensource@apple.com>
Mon, 17 Sep 2012 19:58:38 +0000 (19:58 +0000)
898 files changed:
API/APICast.h
API/APIShims.h
API/JSBase.cpp
API/JSBasePrivate.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/JSObjectRef.cpp
API/JSObjectRef.h
API/JSRetainPtr.h
API/JSStringRef.h
API/JSValueRef.cpp
API/JSWeakObjectMapRefPrivate.cpp
API/OpaqueJSString.h
API/WebKitAvailability.h
API/tests/JSNode.c
API/tests/JSNodeList.c
API/tests/testapi.c
API/tests/testapi.js
CMakeLists.txt
CMakeListsEfl.txt [deleted file]
CMakeListsWinCE.txt [deleted file]
DerivedSources.make
DerivedSources.pri [new file with mode: 0644]
DerivedSources.pro [deleted file]
GNUmakefile.am
GNUmakefile.list.am
Info.plist
JSCTypedArrayStubs.h [new file with mode: 0644]
JavaScriptCore.JSVALUE32_64only.exp [deleted file]
JavaScriptCore.JSVALUE64only.exp [deleted file]
JavaScriptCore.exp [deleted file]
JavaScriptCore.gyp/.gitignore [new file with mode: 0644]
JavaScriptCore.gyp/JavaScriptCore.gyp
JavaScriptCore.gypi
JavaScriptCore.order
JavaScriptCore.pri
JavaScriptCore.pro
KeywordLookupGenerator.py
PlatformBlackBerry.cmake [new file with mode: 0644]
PlatformEfl.cmake [new file with mode: 0644]
PlatformWinCE.cmake [new file with mode: 0644]
Target.pri [new file with mode: 0644]
assembler/ARMAssembler.cpp
assembler/ARMAssembler.h
assembler/ARMv7Assembler.h
assembler/AbstractMacroAssembler.h
assembler/AssemblerBuffer.h
assembler/AssemblerBufferWithConstantPool.h
assembler/LinkBuffer.h
assembler/MIPSAssembler.h
assembler/MacroAssembler.h
assembler/MacroAssemblerARM.h
assembler/MacroAssemblerARMv7.h
assembler/MacroAssemblerCodeRef.h
assembler/MacroAssemblerMIPS.h
assembler/MacroAssemblerSH4.cpp
assembler/MacroAssemblerSH4.h
assembler/MacroAssemblerX86.h
assembler/MacroAssemblerX86Common.h
assembler/MacroAssemblerX86_64.h
assembler/RepatchBuffer.h
assembler/SH4Assembler.h
assembler/X86Assembler.h
bytecode/BytecodeConventions.h [new file with mode: 0644]
bytecode/CallLinkInfo.cpp [new file with mode: 0644]
bytecode/CallLinkInfo.h [new file with mode: 0644]
bytecode/CallLinkStatus.cpp [new file with mode: 0644]
bytecode/CallLinkStatus.h [new file with mode: 0644]
bytecode/CallReturnOffsetToBytecodeOffset.h [new file with mode: 0644]
bytecode/CodeBlock.cpp
bytecode/CodeBlock.h
bytecode/CodeOrigin.h [new file with mode: 0644]
bytecode/CodeType.h [new file with mode: 0644]
bytecode/DFGExitProfile.cpp [new file with mode: 0644]
bytecode/DFGExitProfile.h [new file with mode: 0644]
bytecode/DataFormat.h [new file with mode: 0644]
bytecode/EvalCodeCache.h
bytecode/ExecutionCounter.cpp [new file with mode: 0644]
bytecode/ExecutionCounter.h [new file with mode: 0644]
bytecode/ExpressionRangeInfo.h [new file with mode: 0644]
bytecode/GetByIdStatus.cpp [new file with mode: 0644]
bytecode/GetByIdStatus.h [new file with mode: 0644]
bytecode/GlobalResolveInfo.h [new file with mode: 0644]
bytecode/HandlerInfo.h [new file with mode: 0644]
bytecode/Instruction.h
bytecode/LLIntCallLinkInfo.h [new file with mode: 0644]
bytecode/LazyOperandValueProfile.cpp [new file with mode: 0644]
bytecode/LazyOperandValueProfile.h [new file with mode: 0644]
bytecode/LineInfo.h [new file with mode: 0644]
bytecode/MethodCallLinkInfo.cpp [new file with mode: 0644]
bytecode/MethodCallLinkInfo.h [new file with mode: 0644]
bytecode/MethodCallLinkStatus.cpp [new file with mode: 0644]
bytecode/MethodCallLinkStatus.h [new file with mode: 0644]
bytecode/MethodOfGettingAValueProfile.cpp [new file with mode: 0644]
bytecode/MethodOfGettingAValueProfile.h [new file with mode: 0644]
bytecode/Opcode.cpp
bytecode/Opcode.h
bytecode/Operands.h [new file with mode: 0644]
bytecode/PolymorphicPutByIdList.cpp [new file with mode: 0644]
bytecode/PolymorphicPutByIdList.h [new file with mode: 0644]
bytecode/PredictedType.cpp [new file with mode: 0644]
bytecode/PredictedType.h [new file with mode: 0644]
bytecode/PutByIdStatus.cpp [new file with mode: 0644]
bytecode/PutByIdStatus.h [new file with mode: 0644]
bytecode/PutKind.h [new file with mode: 0644]
bytecode/SamplingTool.cpp
bytecode/SamplingTool.h
bytecode/StructureSet.h [new file with mode: 0644]
bytecode/StructureStubInfo.cpp
bytecode/StructureStubInfo.h
bytecode/ValueProfile.h [new file with mode: 0644]
bytecode/ValueRecovery.h [new file with mode: 0644]
bytecode/VirtualRegister.h [new file with mode: 0644]
bytecompiler/BytecodeGenerator.cpp
bytecompiler/BytecodeGenerator.h
bytecompiler/Label.h
bytecompiler/NodesCodegen.cpp
config.h
create_hash_table
debugger/Debugger.cpp
debugger/Debugger.h
debugger/DebuggerActivation.cpp
debugger/DebuggerActivation.h
debugger/DebuggerCallFrame.cpp
debugger/DebuggerCallFrame.h
dfg/DFGAbstractState.cpp [new file with mode: 0644]
dfg/DFGAbstractState.h [new file with mode: 0644]
dfg/DFGAbstractValue.h [new file with mode: 0644]
dfg/DFGAdjacencyList.h [new file with mode: 0644]
dfg/DFGAliasTracker.h [deleted file]
dfg/DFGArgumentPosition.h [new file with mode: 0644]
dfg/DFGAssemblyHelpers.cpp [new file with mode: 0644]
dfg/DFGAssemblyHelpers.h [new file with mode: 0644]
dfg/DFGBasicBlock.h [new file with mode: 0644]
dfg/DFGByteCodeCache.h [new file with mode: 0644]
dfg/DFGByteCodeParser.cpp
dfg/DFGByteCodeParser.h
dfg/DFGCCallHelpers.h [new file with mode: 0644]
dfg/DFGCFAPhase.cpp [new file with mode: 0644]
dfg/DFGCFAPhase.h [new file with mode: 0644]
dfg/DFGCSEPhase.cpp [new file with mode: 0644]
dfg/DFGCSEPhase.h [new file with mode: 0644]
dfg/DFGCapabilities.cpp [new file with mode: 0644]
dfg/DFGCapabilities.h [new file with mode: 0644]
dfg/DFGCommon.h [new file with mode: 0644]
dfg/DFGCorrectableJumpPoint.cpp [new file with mode: 0644]
dfg/DFGCorrectableJumpPoint.h [new file with mode: 0644]
dfg/DFGDoubleFormatState.h [new file with mode: 0644]
dfg/DFGDriver.cpp [new file with mode: 0644]
dfg/DFGDriver.h [new file with mode: 0644]
dfg/DFGEdge.h [new file with mode: 0644]
dfg/DFGFPRInfo.h
dfg/DFGFixupPhase.cpp [new file with mode: 0644]
dfg/DFGFixupPhase.h [new file with mode: 0644]
dfg/DFGGPRInfo.h
dfg/DFGGenerationInfo.h
dfg/DFGGraph.cpp
dfg/DFGGraph.h
dfg/DFGInsertionSet.h [new file with mode: 0644]
dfg/DFGJITCodeGenerator.cpp [deleted file]
dfg/DFGJITCodeGenerator.h [deleted file]
dfg/DFGJITCompiler.cpp
dfg/DFGJITCompiler.h
dfg/DFGNode.h
dfg/DFGNodeFlags.cpp [new file with mode: 0644]
dfg/DFGNodeFlags.h [new file with mode: 0644]
dfg/DFGNodeType.h [new file with mode: 0644]
dfg/DFGNonSpeculativeJIT.cpp [deleted file]
dfg/DFGNonSpeculativeJIT.h [deleted file]
dfg/DFGOSREntry.cpp [new file with mode: 0644]
dfg/DFGOSREntry.h [new file with mode: 0644]
dfg/DFGOSRExit.cpp [new file with mode: 0644]
dfg/DFGOSRExit.h [new file with mode: 0644]
dfg/DFGOSRExitCompiler.cpp [new file with mode: 0644]
dfg/DFGOSRExitCompiler.h [new file with mode: 0644]
dfg/DFGOSRExitCompiler32_64.cpp [new file with mode: 0644]
dfg/DFGOSRExitCompiler64.cpp [new file with mode: 0644]
dfg/DFGOperations.cpp
dfg/DFGOperations.h
dfg/DFGPhase.cpp [new file with mode: 0644]
dfg/DFGPhase.h [new file with mode: 0644]
dfg/DFGPredictionPropagationPhase.cpp [new file with mode: 0644]
dfg/DFGPredictionPropagationPhase.h [new file with mode: 0644]
dfg/DFGRedundantPhiEliminationPhase.cpp [new file with mode: 0644]
dfg/DFGRedundantPhiEliminationPhase.h [new file with mode: 0644]
dfg/DFGRegisterBank.h
dfg/DFGRepatch.cpp [new file with mode: 0644]
dfg/DFGRepatch.h [new file with mode: 0644]
dfg/DFGScoreBoard.h
dfg/DFGSpeculativeJIT.cpp
dfg/DFGSpeculativeJIT.h
dfg/DFGSpeculativeJIT32_64.cpp [new file with mode: 0644]
dfg/DFGSpeculativeJIT64.cpp [new file with mode: 0644]
dfg/DFGThunks.cpp [new file with mode: 0644]
dfg/DFGThunks.h [new file with mode: 0644]
dfg/DFGVariableAccessData.h [new file with mode: 0644]
dfg/DFGVirtualRegisterAllocationPhase.cpp [new file with mode: 0644]
dfg/DFGVirtualRegisterAllocationPhase.h [new file with mode: 0644]
gyp/JavaScriptCore.gyp
headers.pri [deleted file]
heap/BlockAllocator.cpp [new file with mode: 0644]
heap/BlockAllocator.h [new file with mode: 0644]
heap/CardSet.h [new file with mode: 0644]
heap/ConservativeRoots.cpp
heap/ConservativeRoots.h
heap/CopiedAllocator.h [new file with mode: 0644]
heap/CopiedBlock.h [new file with mode: 0644]
heap/CopiedSpace.cpp [new file with mode: 0644]
heap/CopiedSpace.h [new file with mode: 0644]
heap/CopiedSpaceInlineMethods.h [new file with mode: 0644]
heap/DFGCodeBlocks.cpp [new file with mode: 0644]
heap/DFGCodeBlocks.h [new file with mode: 0644]
heap/GCAssertions.h [new file with mode: 0644]
heap/Handle.h
heap/HandleHeap.cpp [deleted file]
heap/HandleHeap.h [deleted file]
heap/HandleSet.cpp [new file with mode: 0644]
heap/HandleSet.h [new file with mode: 0644]
heap/HandleStack.cpp
heap/HandleStack.h
heap/HandleTypes.h
heap/Heap.cpp
heap/Heap.h
heap/HeapBlock.h [new file with mode: 0644]
heap/HeapRootVisitor.h [new file with mode: 0644]
heap/ListableHandler.h [new file with mode: 0644]
heap/Local.h
heap/MachineStackMarker.cpp
heap/MachineStackMarker.h
heap/MarkStack.cpp
heap/MarkStack.h
heap/MarkStackPosix.cpp [deleted file]
heap/MarkStackSymbian.cpp [deleted file]
heap/MarkStackWin.cpp [deleted file]
heap/MarkedAllocator.cpp [new file with mode: 0644]
heap/MarkedAllocator.h [new file with mode: 0644]
heap/MarkedBlock.cpp
heap/MarkedBlock.h
heap/MarkedBlockSet.h [new file with mode: 0644]
heap/MarkedSpace.cpp
heap/MarkedSpace.h
heap/PassWeak.h [new file with mode: 0644]
heap/SlotVisitor.h [new file with mode: 0644]
heap/Strong.h
heap/StrongInlines.h [new file with mode: 0644]
heap/TinyBloomFilter.h [new file with mode: 0644]
heap/UnconditionalFinalizer.h [new file with mode: 0644]
heap/VTableSpectrum.cpp [new file with mode: 0644]
heap/VTableSpectrum.h [new file with mode: 0644]
heap/Weak.h
heap/WeakBlock.cpp [new file with mode: 0644]
heap/WeakBlock.h [new file with mode: 0644]
heap/WeakHandleOwner.cpp [new file with mode: 0644]
heap/WeakHandleOwner.h [new file with mode: 0644]
heap/WeakImpl.h [new file with mode: 0644]
heap/WeakReferenceHarvester.h [new file with mode: 0644]
heap/WeakSet.cpp [new file with mode: 0644]
heap/WeakSet.h [new file with mode: 0644]
heap/WeakSetInlines.h [new file with mode: 0644]
heap/WriteBarrierSupport.cpp [new file with mode: 0644]
heap/WriteBarrierSupport.h [new file with mode: 0644]
icu/unicode/uscript.h [new file with mode: 0644]
interpreter/AbstractPC.cpp [new file with mode: 0644]
interpreter/AbstractPC.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
javascriptcoregtk.pc.in [new file with mode: 0644]
jit/CompactJITCodeMap.h [new file with mode: 0644]
jit/ExecutableAllocator.cpp
jit/ExecutableAllocator.h
jit/ExecutableAllocatorFixedVMPool.cpp
jit/HostCallReturnValue.cpp [new file with mode: 0644]
jit/HostCallReturnValue.h [new file with mode: 0644]
jit/JIT.cpp
jit/JIT.h
jit/JITArithmetic.cpp
jit/JITArithmetic32_64.cpp
jit/JITCall.cpp
jit/JITCall32_64.cpp
jit/JITCode.h
jit/JITCompilationEffort.h [new file with mode: 0644]
jit/JITDriver.h [new file with mode: 0644]
jit/JITExceptions.cpp [new file with mode: 0644]
jit/JITExceptions.h [new file with mode: 0644]
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
jit/JSInterfaceJIT.h
jit/SpecializedThunkJIT.h
jit/ThunkGenerators.cpp
jit/ThunkGenerators.h
jsc.cpp
jsc.pro
llint/LLIntCommon.h [new file with mode: 0644]
llint/LLIntData.cpp [new file with mode: 0644]
llint/LLIntData.h [new file with mode: 0644]
llint/LLIntEntrypoints.cpp [new file with mode: 0644]
llint/LLIntEntrypoints.h [new file with mode: 0644]
llint/LLIntExceptions.cpp [new file with mode: 0644]
llint/LLIntExceptions.h [new file with mode: 0644]
llint/LLIntOfflineAsmConfig.h [new file with mode: 0644]
llint/LLIntOffsetsExtractor.cpp [new file with mode: 0644]
llint/LLIntSlowPaths.cpp [new file with mode: 0644]
llint/LLIntSlowPaths.h [new file with mode: 0644]
llint/LLIntThunks.cpp [new file with mode: 0644]
llint/LLIntThunks.h [new file with mode: 0644]
llint/LowLevelInterpreter.asm [new file with mode: 0644]
llint/LowLevelInterpreter.cpp [new file with mode: 0644]
llint/LowLevelInterpreter.h [new file with mode: 0644]
llint/LowLevelInterpreter32_64.asm [new file with mode: 0644]
llint/LowLevelInterpreter64.asm [new file with mode: 0644]
offlineasm/armv7.rb [new file with mode: 0644]
offlineasm/asm.rb [new file with mode: 0644]
offlineasm/ast.rb [new file with mode: 0644]
offlineasm/backends.rb [new file with mode: 0644]
offlineasm/generate_offset_extractor.rb [new file with mode: 0644]
offlineasm/instructions.rb [new file with mode: 0644]
offlineasm/offsets.rb [new file with mode: 0644]
offlineasm/opt.rb [new file with mode: 0644]
offlineasm/parser.rb [new file with mode: 0644]
offlineasm/registers.rb [new file with mode: 0644]
offlineasm/self_hash.rb [new file with mode: 0644]
offlineasm/settings.rb [new file with mode: 0644]
offlineasm/transform.rb [new file with mode: 0644]
offlineasm/x86.rb [new file with mode: 0644]
os-win32/WinMain.cpp
os-win32/inttypes.h
parser/ASTBuilder.h
parser/JSParser.cpp [deleted file]
parser/JSParser.h [deleted file]
parser/Keywords.table
parser/Lexer.cpp
parser/Lexer.h
parser/NodeConstructors.h
parser/NodeInfo.h
parser/Nodes.cpp
parser/Nodes.h
parser/Parser.cpp
parser/Parser.h
parser/ParserArena.cpp
parser/ParserArena.h
parser/ParserTokens.h [new file with mode: 0644]
parser/ResultType.h
parser/SourceCode.h
parser/SourceProvider.h
parser/SourceProviderCache.cpp
parser/SourceProviderCache.h
parser/SourceProviderCacheItem.h
parser/SyntaxChecker.h
profiler/CallIdentifier.h
profiler/Profile.cpp
profiler/Profile.h
profiler/ProfileNode.cpp
profiler/Profiler.cpp
profiler/Profiler.h
profiler/ProfilerServer.h [deleted file]
profiler/ProfilerServer.mm [deleted file]
qt/ChangeLog [deleted file]
qt/api/QtScript.pro [deleted file]
qt/api/qscriptconverter_p.h [deleted file]
qt/api/qscriptengine.cpp [deleted file]
qt/api/qscriptengine.h [deleted file]
qt/api/qscriptengine_p.cpp [deleted file]
qt/api/qscriptengine_p.h [deleted file]
qt/api/qscriptfunction.cpp [deleted file]
qt/api/qscriptfunction_p.h [deleted file]
qt/api/qscriptoriginalglobalobject_p.h [deleted file]
qt/api/qscriptprogram.cpp [deleted file]
qt/api/qscriptprogram.h [deleted file]
qt/api/qscriptprogram_p.h [deleted file]
qt/api/qscriptstring.cpp [deleted file]
qt/api/qscriptstring.h [deleted file]
qt/api/qscriptstring_p.h [deleted file]
qt/api/qscriptsyntaxcheckresult.cpp [deleted file]
qt/api/qscriptsyntaxcheckresult.h [deleted file]
qt/api/qscriptsyntaxcheckresult_p.h [deleted file]
qt/api/qscriptvalue.cpp [deleted file]
qt/api/qscriptvalue.h [deleted file]
qt/api/qscriptvalue_p.h [deleted file]
qt/api/qscriptvalueiterator.cpp [deleted file]
qt/api/qscriptvalueiterator.h [deleted file]
qt/api/qscriptvalueiterator_p.h [deleted file]
qt/api/qtscriptglobal.h [deleted file]
qt/benchmarks/benchmarks.pri [deleted file]
qt/benchmarks/benchmarks.pro [deleted file]
qt/benchmarks/qscriptengine/qscriptengine.pro [deleted file]
qt/benchmarks/qscriptengine/tst_qscriptengine.cpp [deleted file]
qt/benchmarks/qscriptvalue/qscriptvalue.pro [deleted file]
qt/benchmarks/qscriptvalue/tst_qscriptvalue.cpp [deleted file]
qt/tests/qscriptengine/qscriptengine.pro [deleted file]
qt/tests/qscriptengine/tst_qscriptengine.cpp [deleted file]
qt/tests/qscriptstring/qscriptstring.pro [deleted file]
qt/tests/qscriptstring/tst_qscriptstring.cpp [deleted file]
qt/tests/qscriptvalue/qscriptvalue.pro [deleted file]
qt/tests/qscriptvalue/tst_qscriptvalue.cpp [deleted file]
qt/tests/qscriptvalue/tst_qscriptvalue.h [deleted file]
qt/tests/qscriptvalue/tst_qscriptvalue_generated_comparison.cpp [deleted file]
qt/tests/qscriptvalue/tst_qscriptvalue_generated_init.cpp [deleted file]
qt/tests/qscriptvalue/tst_qscriptvalue_generated_istype.cpp [deleted file]
qt/tests/qscriptvalue/tst_qscriptvalue_generated_totype.cpp [deleted file]
qt/tests/qscriptvalueiterator/qscriptvalueiterator.pro [deleted file]
qt/tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp [deleted file]
qt/tests/tests.pri [deleted file]
qt/tests/tests.pro [deleted file]
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/BigInteger.h [new file with mode: 0644]
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/ClassInfo.h
runtime/CodeSpecializationKind.h [new file with mode: 0644]
runtime/CommonIdentifiers.h
runtime/CommonSlowPaths.h [new file with mode: 0644]
runtime/Completion.cpp
runtime/Completion.h
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/ExecutionHarness.h [new file with mode: 0644]
runtime/FunctionConstructor.cpp
runtime/FunctionConstructor.h
runtime/FunctionPrototype.cpp
runtime/FunctionPrototype.h
runtime/GCActivityCallback.cpp
runtime/GCActivityCallback.h
runtime/GCActivityCallbackCF.cpp
runtime/GetterSetter.cpp
runtime/GetterSetter.h
runtime/Identifier.cpp
runtime/Identifier.h
runtime/InitializeThreading.cpp
runtime/InitializeThreading.h
runtime/InternalFunction.cpp
runtime/InternalFunction.h
runtime/Intrinsic.h [new file with mode: 0644]
runtime/JSAPIValueWrapper.cpp
runtime/JSAPIValueWrapper.h
runtime/JSActivation.cpp
runtime/JSActivation.h
runtime/JSArray.cpp
runtime/JSArray.h
runtime/JSBoundFunction.cpp [new file with mode: 0644]
runtime/JSBoundFunction.h [new file with mode: 0644]
runtime/JSByteArray.cpp [deleted file]
runtime/JSByteArray.h [deleted file]
runtime/JSCell.cpp
runtime/JSCell.h
runtime/JSDateMath.cpp [new file with mode: 0644]
runtime/JSDateMath.h [new file with mode: 0644]
runtime/JSExportMacros.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/JSGlobalThis.cpp [new file with mode: 0644]
runtime/JSGlobalThis.h [new file with mode: 0644]
runtime/JSLock.cpp
runtime/JSLock.h
runtime/JSNotAnObject.cpp
runtime/JSNotAnObject.h
runtime/JSONObject.cpp
runtime/JSONObject.h
runtime/JSObject.cpp
runtime/JSObject.h
runtime/JSObjectWithGlobalObject.cpp [deleted file]
runtime/JSObjectWithGlobalObject.h [deleted file]
runtime/JSPropertyNameIterator.cpp
runtime/JSPropertyNameIterator.h
runtime/JSStaticScopeObject.cpp
runtime/JSStaticScopeObject.h
runtime/JSString.cpp
runtime/JSString.h
runtime/JSStringBuilder.h
runtime/JSStringJoiner.cpp [new file with mode: 0644]
runtime/JSStringJoiner.h [new file with mode: 0644]
runtime/JSType.h
runtime/JSTypeInfo.h
runtime/JSValue.cpp
runtime/JSValue.h
runtime/JSValueInlineMethods.h
runtime/JSVariableObject.cpp
runtime/JSVariableObject.h
runtime/JSWrapperObject.cpp
runtime/JSWrapperObject.h
runtime/JSZombie.cpp [deleted file]
runtime/JSZombie.h [deleted file]
runtime/LiteralParser.cpp
runtime/LiteralParser.h
runtime/Lookup.cpp
runtime/Lookup.h
runtime/MatchResult.h [new file with mode: 0644]
runtime/MathObject.cpp
runtime/MathObject.h
runtime/MemoryStatistics.h
runtime/NativeErrorConstructor.cpp
runtime/NativeErrorConstructor.h
runtime/NativeErrorPrototype.cpp
runtime/NativeErrorPrototype.h
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/Options.cpp [new file with mode: 0644]
runtime/Options.h [new file with mode: 0644]
runtime/PropertyDescriptor.cpp
runtime/PropertyDescriptor.h
runtime/PropertyMapHashTable.h
runtime/PropertyNameArray.cpp
runtime/PropertyNameArray.h
runtime/PropertySlot.cpp
runtime/PropertySlot.h
runtime/RegExp.cpp
runtime/RegExp.h
runtime/RegExpCache.cpp
runtime/RegExpCachedResult.cpp [new file with mode: 0644]
runtime/RegExpCachedResult.h [new file with mode: 0644]
runtime/RegExpConstructor.cpp
runtime/RegExpConstructor.h
runtime/RegExpMatchesArray.cpp [new file with mode: 0644]
runtime/RegExpMatchesArray.h
runtime/RegExpObject.cpp
runtime/RegExpObject.h
runtime/RegExpPrototype.cpp
runtime/RegExpPrototype.h
runtime/RopeImpl.cpp [deleted file]
runtime/RopeImpl.h [deleted file]
runtime/SamplingCounter.cpp [new file with mode: 0644]
runtime/SamplingCounter.h [new file with mode: 0644]
runtime/ScopeChain.cpp
runtime/ScopeChain.h
runtime/SmallStrings.cpp
runtime/SmallStrings.h
runtime/StorageBarrier.h [new file with mode: 0644]
runtime/StrictEvalActivation.cpp
runtime/StrictEvalActivation.h
runtime/StringConstructor.cpp
runtime/StringConstructor.h
runtime/StringObject.cpp
runtime/StringObject.h
runtime/StringObjectThatMasqueradesAsUndefined.h [deleted file]
runtime/StringPrototype.cpp
runtime/StringPrototype.h
runtime/StringRecursionChecker.cpp
runtime/StringRecursionChecker.h
runtime/Structure.cpp
runtime/Structure.h
runtime/StructureChain.cpp
runtime/StructureChain.h
runtime/StructureTransitionTable.h
runtime/SymbolTable.h
runtime/TimeoutChecker.cpp
runtime/TimeoutChecker.h
runtime/UString.cpp
runtime/UString.h
runtime/UStringConcatenate.h
runtime/Uint16WithFraction.h [new file with mode: 0644]
runtime/WeakGCMap.h
runtime/WriteBarrier.h
shell/CMakeLists.txt
shell/CMakeListsEfl.txt [deleted file]
shell/CMakeListsWinCE.txt [deleted file]
shell/PlatformBlackBerry.cmake [new file with mode: 0644]
shell/PlatformEfl.cmake [new file with mode: 0644]
shell/PlatformWinCE.cmake [new file with mode: 0644]
testRegExp.cpp [new file with mode: 0644]
tests/mozilla/ecma/Array/15.4.5.1-1.js
tests/mozilla/ecma/Expressions/11.12-1.js
tests/mozilla/ecma/GlobalObject/15.1.2.2-1.js
tests/mozilla/ecma/GlobalObject/15.1.2.2-2.js
tests/mozilla/ecma/LexicalConventions/7.7.4.js
tests/mozilla/ecma/String/15.5.4.11-2.js
tests/mozilla/ecma/String/15.5.4.6-2.js
tests/mozilla/ecma/String/15.5.4.8-2.js
tests/mozilla/ecma/TypeConversion/9.3.1-3.js
tests/mozilla/ecma_2/RegExp/constructor-001.js
tests/mozilla/ecma_2/RegExp/function-001.js
tests/mozilla/ecma_2/RegExp/hex-001.js
tests/mozilla/ecma_2/RegExp/properties-001.js
tests/mozilla/expected.html
tests/mozilla/js1_2/regexp/RegExp_multiline.js
tests/mozilla/js1_2/regexp/RegExp_multiline_as_array.js
tests/mozilla/js1_2/regexp/beginLine.js
tests/mozilla/js1_2/regexp/endLine.js
tests/mozilla/js1_2/regexp/hexadecimal.js
tests/mozilla/js1_6/Array/regress-304828.js
tests/regexp/RegExpTest.data [new file with mode: 0644]
tools/CodeProfile.cpp [new file with mode: 0644]
tools/CodeProfile.h [new file with mode: 0644]
tools/CodeProfiling.cpp [new file with mode: 0644]
tools/CodeProfiling.h [new file with mode: 0644]
tools/ProfileTreeNode.h [new file with mode: 0644]
tools/TieredMMapArray.h [new file with mode: 0644]
wscript
wtf/ASCIICType.h [deleted file]
wtf/AVLTree.h [deleted file]
wtf/Alignment.h [deleted file]
wtf/AlwaysInline.h [deleted file]
wtf/Assertions.cpp [deleted file]
wtf/Assertions.h [deleted file]
wtf/Atomics.h [deleted file]
wtf/Bitmap.h [deleted file]
wtf/BlockStack.h [deleted file]
wtf/BloomFilter.h [deleted file]
wtf/BumpPointerAllocator.h [deleted file]
wtf/ByteArray.cpp [deleted file]
wtf/ByteArray.h [deleted file]
wtf/CMakeLists.txt [deleted file]
wtf/CMakeListsEfl.txt [deleted file]
wtf/CMakeListsWinCE.txt [deleted file]
wtf/CONTRIBUTORS.pthreads-win32 [deleted file]
wtf/CheckedArithmetic.h [deleted file]
wtf/Complex.h [deleted file]
wtf/CrossThreadRefCounted.h [deleted file]
wtf/CryptographicallyRandomNumber.cpp [deleted file]
wtf/CryptographicallyRandomNumber.h [deleted file]
wtf/CurrentTime.cpp [deleted file]
wtf/CurrentTime.h [deleted file]
wtf/DateMath.cpp [deleted file]
wtf/DateMath.h [deleted file]
wtf/DecimalNumber.cpp [deleted file]
wtf/DecimalNumber.h [deleted file]
wtf/Decoder.h [deleted file]
wtf/Deque.h [deleted file]
wtf/DisallowCType.h [deleted file]
wtf/DoublyLinkedList.h [deleted file]
wtf/DynamicAnnotations.cpp [deleted file]
wtf/DynamicAnnotations.h [deleted file]
wtf/Encoder.h [deleted file]
wtf/ExportMacros.h [deleted file]
wtf/FastAllocBase.h [deleted file]
wtf/FastMalloc.cpp [deleted file]
wtf/FastMalloc.h [deleted file]
wtf/FixedArray.h [deleted file]
wtf/Forward.h [deleted file]
wtf/GetPtr.h [deleted file]
wtf/HashCountedSet.h [deleted file]
wtf/HashFunctions.h [deleted file]
wtf/HashIterators.h [deleted file]
wtf/HashMap.h [deleted file]
wtf/HashSet.h [deleted file]
wtf/HashTable.cpp [deleted file]
wtf/HashTable.h [deleted file]
wtf/HashTraits.h [deleted file]
wtf/HexNumber.h [deleted file]
wtf/ListHashSet.h [deleted file]
wtf/ListRefPtr.h [deleted file]
wtf/Locker.h [deleted file]
wtf/MD5.cpp [deleted file]
wtf/MD5.h [deleted file]
wtf/MainThread.cpp [deleted file]
wtf/MainThread.h [deleted file]
wtf/MallocZoneSupport.h [deleted file]
wtf/MathExtras.h [deleted file]
wtf/MessageQueue.h [deleted file]
wtf/NonCopyingSort.h [deleted file]
wtf/Noncopyable.h [deleted file]
wtf/NotFound.h [deleted file]
wtf/NullPtr.cpp [deleted file]
wtf/NullPtr.h [deleted file]
wtf/OSAllocator.h [deleted file]
wtf/OSAllocatorPosix.cpp [deleted file]
wtf/OSAllocatorSymbian.cpp [deleted file]
wtf/OSAllocatorWin.cpp [deleted file]
wtf/OSRandomSource.cpp [deleted file]
wtf/OSRandomSource.h [deleted file]
wtf/OwnArrayPtr.h [deleted file]
wtf/OwnFastMallocPtr.h [deleted file]
wtf/OwnPtr.h [deleted file]
wtf/OwnPtrCommon.h [deleted file]
wtf/PageAllocation.h [deleted file]
wtf/PageAllocationAligned.cpp [deleted file]
wtf/PageAllocationAligned.h [deleted file]
wtf/PageAllocatorSymbian.h [deleted file]
wtf/PageBlock.cpp [deleted file]
wtf/PageBlock.h [deleted file]
wtf/PageReservation.h [deleted file]
wtf/ParallelJobs.h [deleted file]
wtf/ParallelJobsGeneric.cpp [deleted file]
wtf/ParallelJobsGeneric.h [deleted file]
wtf/ParallelJobsLibdispatch.h [deleted file]
wtf/ParallelJobsOpenMP.h [deleted file]
wtf/PassOwnArrayPtr.h [deleted file]
wtf/PassOwnPtr.h [deleted file]
wtf/PassRefPtr.h [deleted file]
wtf/PassTraits.h [deleted file]
wtf/Platform.h [deleted file]
wtf/PossiblyNull.h [deleted file]
wtf/RandomNumber.cpp [deleted file]
wtf/RandomNumber.h [deleted file]
wtf/RandomNumberSeed.h [deleted file]
wtf/RefCounted.h [deleted file]
wtf/RefCountedLeakCounter.cpp [deleted file]
wtf/RefCountedLeakCounter.h [deleted file]
wtf/RefPtr.h [deleted file]
wtf/RefPtrHashMap.h [deleted file]
wtf/RetainPtr.h [deleted file]
wtf/SHA1.cpp [deleted file]
wtf/SHA1.h [deleted file]
wtf/SegmentedVector.h [deleted file]
wtf/SentinelLinkedList.h [deleted file]
wtf/SinglyLinkedList.h [deleted file]
wtf/SizeLimits.cpp [deleted file]
wtf/StackBounds.cpp [deleted file]
wtf/StackBounds.h [deleted file]
wtf/StaticConstructors.h [deleted file]
wtf/StdLibExtras.h [deleted file]
wtf/StringExtras.cpp [deleted file]
wtf/StringExtras.h [deleted file]
wtf/StringHasher.h [deleted file]
wtf/TCPackedCache.h [deleted file]
wtf/TCPageMap.h [deleted file]
wtf/TCSpinLock.h [deleted file]
wtf/TCSystemAlloc.cpp [deleted file]
wtf/TCSystemAlloc.h [deleted file]
wtf/ThreadFunctionInvocation.h [deleted file]
wtf/ThreadIdentifierDataPthreads.cpp [deleted file]
wtf/ThreadIdentifierDataPthreads.h [deleted file]
wtf/ThreadSafeRefCounted.h [deleted file]
wtf/ThreadSpecific.h [deleted file]
wtf/ThreadSpecificWin.cpp [deleted file]
wtf/Threading.cpp [deleted file]
wtf/Threading.h [deleted file]
wtf/ThreadingNone.cpp [deleted file]
wtf/ThreadingPrimitives.h [deleted file]
wtf/ThreadingPthreads.cpp [deleted file]
wtf/ThreadingWin.cpp [deleted file]
wtf/TypeTraits.cpp [deleted file]
wtf/TypeTraits.h [deleted file]
wtf/UnusedParam.h [deleted file]
wtf/VMTags.h [deleted file]
wtf/ValueCheck.h [deleted file]
wtf/Vector.h [deleted file]
wtf/VectorTraits.h [deleted file]
wtf/WTFThreadData.cpp [deleted file]
wtf/WTFThreadData.h [deleted file]
wtf/android/AndroidThreading.h [deleted file]
wtf/android/MainThreadAndroid.cpp [deleted file]
wtf/brew/MainThreadBrew.cpp [deleted file]
wtf/brew/OwnPtrBrew.cpp [deleted file]
wtf/brew/RefPtrBrew.h [deleted file]
wtf/brew/ShellBrew.h [deleted file]
wtf/brew/StringBrew.cpp [deleted file]
wtf/brew/SystemMallocBrew.h [deleted file]
wtf/chromium/ChromiumThreading.h [deleted file]
wtf/chromium/MainThreadChromium.cpp [deleted file]
wtf/dtoa.cpp [deleted file]
wtf/dtoa.h [deleted file]
wtf/efl/MainThreadEfl.cpp [deleted file]
wtf/gobject/GOwnPtr.cpp [deleted file]
wtf/gobject/GOwnPtr.h [deleted file]
wtf/gobject/GRefPtr.cpp [deleted file]
wtf/gobject/GRefPtr.h [deleted file]
wtf/gobject/GTypedefs.h [deleted file]
wtf/gtk/MainThreadGtk.cpp [deleted file]
wtf/gtk/ThreadingGtk.cpp [deleted file]
wtf/haiku/MainThreadHaiku.cpp [deleted file]
wtf/haiku/StringHaiku.cpp [deleted file]
wtf/iphone/WebCoreThread.cpp [deleted file]
wtf/iphone/WebCoreThread.h [deleted file]
wtf/mac/MainThreadMac.mm [deleted file]
wtf/qt/MainThreadQt.cpp [deleted file]
wtf/qt/StringQt.cpp [deleted file]
wtf/qt/ThreadingQt.cpp [deleted file]
wtf/text/AtomicString.cpp [deleted file]
wtf/text/AtomicString.h [deleted file]
wtf/text/AtomicStringHash.h [deleted file]
wtf/text/AtomicStringImpl.h [deleted file]
wtf/text/CString.cpp [deleted file]
wtf/text/CString.h [deleted file]
wtf/text/StringBuffer.h [deleted file]
wtf/text/StringBuilder.cpp [deleted file]
wtf/text/StringBuilder.h [deleted file]
wtf/text/StringConcatenate.h [deleted file]
wtf/text/StringHash.h [deleted file]
wtf/text/StringImpl.cpp [deleted file]
wtf/text/StringImpl.h [deleted file]
wtf/text/StringImplBase.h [deleted file]
wtf/text/StringOperators.h [deleted file]
wtf/text/StringStatics.cpp [deleted file]
wtf/text/TextPosition.h [deleted file]
wtf/text/WTFString.cpp [deleted file]
wtf/text/WTFString.h [deleted file]
wtf/unicode/CharacterNames.h [deleted file]
wtf/unicode/Collator.h [deleted file]
wtf/unicode/CollatorDefault.cpp [deleted file]
wtf/unicode/UTF8.cpp [deleted file]
wtf/unicode/UTF8.h [deleted file]
wtf/unicode/Unicode.h [deleted file]
wtf/unicode/UnicodeMacrosFromICU.h [deleted file]
wtf/unicode/brew/UnicodeBrew.cpp [deleted file]
wtf/unicode/brew/UnicodeBrew.h [deleted file]
wtf/unicode/glib/UnicodeGLib.cpp [deleted file]
wtf/unicode/glib/UnicodeGLib.h [deleted file]
wtf/unicode/icu/CollatorICU.cpp [deleted file]
wtf/unicode/icu/UnicodeIcu.h [deleted file]
wtf/unicode/qt4/UnicodeQt4.h [deleted file]
wtf/unicode/wince/UnicodeWinCE.cpp [deleted file]
wtf/unicode/wince/UnicodeWinCE.h [deleted file]
wtf/url/api/ParsedURL.cpp [deleted file]
wtf/url/api/ParsedURL.h [deleted file]
wtf/url/api/URLString.h [deleted file]
wtf/url/src/RawURLBuffer.h [deleted file]
wtf/url/src/URLBuffer.h [deleted file]
wtf/url/src/URLCharacterTypes.cpp [deleted file]
wtf/url/src/URLCharacterTypes.h [deleted file]
wtf/url/src/URLComponent.h [deleted file]
wtf/url/src/URLEscape.cpp [deleted file]
wtf/url/src/URLEscape.h [deleted file]
wtf/url/src/URLParser.h [deleted file]
wtf/url/src/URLQueryCanonicalizer.h [deleted file]
wtf/url/src/URLSegments.cpp [deleted file]
wtf/url/src/URLSegments.h [deleted file]
wtf/url/wtfurl.gyp [deleted file]
wtf/win/MainThreadWin.cpp [deleted file]
wtf/win/OwnPtrWin.cpp [deleted file]
wtf/wince/FastMallocWinCE.h [deleted file]
wtf/wince/MemoryManager.cpp [deleted file]
wtf/wince/MemoryManager.h [deleted file]
wtf/wtf.pri [deleted file]
wtf/wx/MainThreadWx.cpp [deleted file]
wtf/wx/StringWx.cpp [deleted file]
yarr/Yarr.h
yarr/YarrCanonicalizeUCS2.cpp [new file with mode: 0644]
yarr/YarrCanonicalizeUCS2.h [new file with mode: 0644]
yarr/YarrCanonicalizeUCS2.js [new file with mode: 0644]
yarr/YarrInterpreter.cpp
yarr/YarrInterpreter.h
yarr/YarrJIT.cpp
yarr/YarrJIT.h
yarr/YarrParser.h
yarr/YarrPattern.cpp
yarr/YarrPattern.h
yarr/yarr.pri

index 4294d3d682a816bb0467d27de6599b0f78325026..f019a7a4b9695dff8bccd7d489e7653ec9501487 100644 (file)
@@ -69,7 +69,7 @@ inline JSC::JSValue toJS(JSC::ExecState* exec, JSValueRef v)
     if (!jsCell)
         return JSC::JSValue();
     if (jsCell->isAPIValueWrapper())
     if (!jsCell)
         return JSC::JSValue();
     if (jsCell->isAPIValueWrapper())
-        return static_cast<JSC::JSAPIValueWrapper*>(jsCell)->value();
+        return JSC::jsCast<JSC::JSAPIValueWrapper*>(jsCell)->value();
     return jsCell;
 #else
     return JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(const_cast<OpaqueJSValue*>(v)));
     return jsCell;
 #else
     return JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(const_cast<OpaqueJSValue*>(v)));
index 2e13851417044b463b9941a9a5ec87d19ce63b4b..ac540a2ff9e5dfe817fed3d30a81376a66cb47be 100644 (file)
 namespace JSC {
 
 class APIEntryShimWithoutLock {
 namespace JSC {
 
 class APIEntryShimWithoutLock {
+public:
+    enum RefGlobalDataTag { DontRefGlobalData = 0, RefGlobalData };
+
 protected:
 protected:
-    APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread)
-        : m_globalData(globalData)
+    APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread, RefGlobalDataTag shouldRefGlobalData)
+        : m_shouldRefGlobalData(shouldRefGlobalData)
+        , m_globalData(globalData)
         , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable))
     {
         , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable))
     {
+        if (shouldRefGlobalData)
+            m_globalData->ref();
         UNUSED_PARAM(registerThread);
         UNUSED_PARAM(registerThread);
-#if ENABLE(JSC_MULTIPLE_THREADS)
         if (registerThread)
             globalData->heap.machineThreads().addCurrentThread();
         if (registerThread)
             globalData->heap.machineThreads().addCurrentThread();
-#endif
-        m_globalData->heap.activityCallback()->synchronize();
-        m_globalData->timeoutChecker.start();
+        if (m_globalData->heap.activityCallback())
+            m_globalData->heap.activityCallback()->synchronize();
     }
 
     ~APIEntryShimWithoutLock()
     {
     }
 
     ~APIEntryShimWithoutLock()
     {
-        m_globalData->timeoutChecker.stop();
         wtfThreadData().setCurrentIdentifierTable(m_entryIdentifierTable);
         wtfThreadData().setCurrentIdentifierTable(m_entryIdentifierTable);
+        if (m_shouldRefGlobalData)
+            m_globalData->deref();
     }
 
     }
 
-private:
+protected:
+    RefGlobalDataTag m_shouldRefGlobalData;
     JSGlobalData* m_globalData;
     IdentifierTable* m_entryIdentifierTable;
 };
     JSGlobalData* m_globalData;
     IdentifierTable* m_entryIdentifierTable;
 };
@@ -63,20 +69,38 @@ class APIEntryShim : public APIEntryShimWithoutLock {
 public:
     // Normal API entry
     APIEntryShim(ExecState* exec, bool registerThread = true)
 public:
     // Normal API entry
     APIEntryShim(ExecState* exec, bool registerThread = true)
-        : APIEntryShimWithoutLock(&exec->globalData(), registerThread)
-        , m_lock(exec)
+        : APIEntryShimWithoutLock(&exec->globalData(), registerThread, RefGlobalData)
     {
     {
+        init();
+    }
+
+    // This constructor is necessary for HeapTimer to prevent it from accidentally resurrecting 
+    // the ref count of a "dead" JSGlobalData.
+    APIEntryShim(JSGlobalData* globalData, RefGlobalDataTag refGlobalData, bool registerThread = true)
+        : APIEntryShimWithoutLock(globalData, registerThread, refGlobalData)
+    {
+        init();
     }
 
     // JSPropertyNameAccumulator only has a globalData.
     APIEntryShim(JSGlobalData* globalData, bool registerThread = true)
     }
 
     // JSPropertyNameAccumulator only has a globalData.
     APIEntryShim(JSGlobalData* globalData, bool registerThread = true)
-        : APIEntryShimWithoutLock(globalData, registerThread)
-        , m_lock(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly)
+        : APIEntryShimWithoutLock(globalData, registerThread, RefGlobalData)
+    {
+        init();
+    }
+
+    ~APIEntryShim()
     {
     {
+        m_globalData->timeoutChecker.stop();
+        m_globalData->apiLock().unlock();
     }
 
 private:
     }
 
 private:
-    JSLock m_lock;
+    void init()
+    {
+        m_globalData->apiLock().lock();
+        m_globalData->timeoutChecker.start();
+    }
 };
 
 class APICallbackShim {
 };
 
 class APICallbackShim {
@@ -90,7 +114,6 @@ public:
 
     ~APICallbackShim()
     {
 
     ~APICallbackShim()
     {
-        m_globalData->heap.activityCallback()->synchronize();
         wtfThreadData().setCurrentIdentifierTable(m_globalData->identifierTable);
     }
 
         wtfThreadData().setCurrentIdentifierTable(m_globalData->identifierTable);
     }
 
index c5f1b15ea90c1088852425e65ca7b35c86da086a..c0fe6ccdef00b1cee8a9e7e5e0e5521beeb7c642 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "APICast.h"
 #include "APIShims.h"
 
 #include "APICast.h"
 #include "APIShims.h"
-#include "Completion.h"
 #include "OpaqueJSString.h"
 #include "SourceCode.h"
 #include <interpreter/CallFrame.h>
 #include "OpaqueJSString.h"
 #include "SourceCode.h"
 #include <interpreter/CallFrame.h>
@@ -51,18 +50,20 @@ JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef th
 
     // evaluate sets "this" to the global object if it is NULL
     JSGlobalObject* globalObject = exec->dynamicGlobalObject();
 
     // evaluate sets "this" to the global object if it is NULL
     JSGlobalObject* globalObject = exec->dynamicGlobalObject();
-    SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber);
-    Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), source, jsThisObject);
+    SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first()));
 
 
-    if (completion.complType() == Throw) {
+    JSValue evaluationException;
+    JSValue returnValue = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), source, jsThisObject, &evaluationException);
+
+    if (evaluationException) {
         if (exception)
         if (exception)
-            *exception = toRef(exec, completion.value());
+            *exception = toRef(exec, evaluationException);
         return 0;
     }
 
         return 0;
     }
 
-    if (completion.value())
-        return toRef(exec, completion.value());
-    
+    if (returnValue)
+        return toRef(exec, returnValue);
+
     // happens, for example, when the only statement is an empty (';') statement
     return toRef(exec, jsUndefined());
 }
     // happens, for example, when the only statement is an empty (';') statement
     return toRef(exec, jsUndefined());
 }
@@ -72,14 +73,17 @@ bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourc
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec);
 
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec);
 
-    SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber);
-    Completion completion = checkSyntax(exec->dynamicGlobalObject()->globalExec(), source);
-    if (completion.complType() == Throw) {
+    SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first()));
+    
+    JSValue syntaxException;
+    bool isValidSyntax = checkSyntax(exec->dynamicGlobalObject()->globalExec(), source, &syntaxException);
+
+    if (!isValidSyntax) {
         if (exception)
         if (exception)
-            *exception = toRef(exec, completion.value());
+            *exception = toRef(exec, syntaxException);
         return false;
     }
         return false;
     }
-    
+
     return true;
 }
 
     return true;
 }
 
@@ -96,13 +100,7 @@ void JSGarbageCollect(JSContextRef ctx)
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec, false);
 
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec, false);
 
-    JSGlobalData& globalData = exec->globalData();
-    if (!globalData.heap.isBusy())
-        globalData.heap.collectAllGarbage();
-
-    // FIXME: Perhaps we should trigger a second mark and sweep
-    // once the garbage collector is done if this is called when
-    // the collector is busy.
+    exec->globalData().heap.reportAbandonedObjectGraph();
 }
 
 void JSReportExtraMemoryCost(JSContextRef ctx, size_t size)
 }
 
 void JSReportExtraMemoryCost(JSContextRef ctx, size_t size)
@@ -111,3 +109,8 @@ void JSReportExtraMemoryCost(JSContextRef ctx, size_t size)
     APIEntryShim entryShim(exec);
     exec->globalData().heap.reportExtraMemoryCost(size);
 }
     APIEntryShim entryShim(exec);
     exec->globalData().heap.reportExtraMemoryCost(size);
 }
+
+void JSDisableGCTimer(void)
+{
+    GCActivityCallback::s_shouldCreateGCTimer = false;
+}
index befa31643eab931efe6720de8d81e2e2f318b26a..3d6be0c50014beb886dd575cb6a202ce92536655 100644 (file)
@@ -45,6 +45,9 @@ region.
 */
 JS_EXPORT void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) AVAILABLE_IN_WEBKIT_VERSION_4_0;
 
 */
 JS_EXPORT void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) AVAILABLE_IN_WEBKIT_VERSION_4_0;
 
+/* Please don't call this. Please. */
+JS_EXPORT void JSDisableGCTimer(void);
+
 #ifdef __cplusplus
 }
 #endif
 #ifdef __cplusplus
 }
 #endif
index fa9d216dd11250127ee685fe1ec8d59ff268c99e..c8b4c0659235b4ed6430f6f81108786484318192 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo JSCallbackConstructor::s_info = { "CallbackConstructor", &JSObjectWithGlobalObject::s_info, 0, 0 };
+const ClassInfo JSCallbackConstructor::s_info = { "CallbackConstructor", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSCallbackConstructor) };
 
 JSCallbackConstructor::JSCallbackConstructor(JSGlobalObject* globalObject, Structure* structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback)
 
 JSCallbackConstructor::JSCallbackConstructor(JSGlobalObject* globalObject, Structure* structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback)
-    : JSObjectWithGlobalObject(globalObject, structure)
+    : JSNonFinalObject(globalObject->globalData(), structure)
     , m_class(jsClass)
     , m_callback(callback)
 {
     , m_class(jsClass)
     , m_callback(callback)
 {
+}
+
+void JSCallbackConstructor::finishCreation(JSGlobalObject* globalObject, JSClassRef jsClass)
+{
+    Base::finishCreation(globalObject->globalData());
     ASSERT(inherits(&s_info));
     if (m_class)
         JSClassRetain(jsClass);
     ASSERT(inherits(&s_info));
     if (m_class)
         JSClassRetain(jsClass);
@@ -54,13 +59,18 @@ JSCallbackConstructor::~JSCallbackConstructor()
         JSClassRelease(m_class);
 }
 
         JSClassRelease(m_class);
 }
 
+void JSCallbackConstructor::destroy(JSCell* cell)
+{
+    jsCast<JSCallbackConstructor*>(cell)->JSCallbackConstructor::~JSCallbackConstructor();
+}
+
 static EncodedJSValue JSC_HOST_CALL constructJSCallback(ExecState* exec)
 {
     JSObject* constructor = exec->callee();
     JSContextRef ctx = toRef(exec);
     JSObjectRef constructorRef = toRef(constructor);
 
 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();
+    JSObjectCallAsConstructorCallback callback = jsCast<JSCallbackConstructor*>(constructor)->callback();
     if (callback) {
         int argumentCount = static_cast<int>(exec->argumentCount());
         Vector<JSValueRef, 16> arguments(argumentCount);
     if (callback) {
         int argumentCount = static_cast<int>(exec->argumentCount());
         Vector<JSValueRef, 16> arguments(argumentCount);
@@ -75,13 +85,16 @@ static EncodedJSValue JSC_HOST_CALL constructJSCallback(ExecState* exec)
         }
         if (exception)
             throwError(exec, toJS(exec, exception));
         }
         if (exception)
             throwError(exec, toJS(exec, exception));
+        // result must be a valid JSValue.
+        if (!result)
+            return throwVMTypeError(exec);
         return JSValue::encode(toJS(result));
     }
     
         return JSValue::encode(toJS(result));
     }
     
-    return JSValue::encode(toJS(JSObjectMake(ctx, static_cast<JSCallbackConstructor*>(constructor)->classRef(), 0)));
+    return JSValue::encode(toJS(JSObjectMake(ctx, jsCast<JSCallbackConstructor*>(constructor)->classRef(), 0)));
 }
 
 }
 
-ConstructType JSCallbackConstructor::getConstructData(ConstructData& constructData)
+ConstructType JSCallbackConstructor::getConstructData(JSCell*, ConstructData& constructData)
 {
     constructData.native.function = constructJSCallback;
     return ConstructTypeHost;
 {
     constructData.native.function = constructJSCallback;
     return ConstructTypeHost;
index 64b237dfd3d8baacc8a99389380f05edea69212d..25fde1324152853c90fd1c7e4f9dc35922bab0c2 100644 (file)
 #define JSCallbackConstructor_h
 
 #include "JSObjectRef.h"
 #define JSCallbackConstructor_h
 
 #include "JSObjectRef.h"
-#include <runtime/JSObjectWithGlobalObject.h>
+#include <runtime/JSObject.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
-class JSCallbackConstructor : public JSObjectWithGlobalObject {
+class JSCallbackConstructor : public JSNonFinalObject {
 public:
 public:
-    JSCallbackConstructor(JSGlobalObject*, Structure*, JSClassRef, JSObjectCallAsConstructorCallback);
-    virtual ~JSCallbackConstructor();
+    typedef JSNonFinalObject Base;
+
+    static JSCallbackConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSClassRef classRef, JSObjectCallAsConstructorCallback callback) 
+    {
+        JSCallbackConstructor* constructor = new (NotNull, allocateCell<JSCallbackConstructor>(*exec->heap())) JSCallbackConstructor(globalObject, structure, classRef, callback);
+        constructor->finishCreation(globalObject, classRef);
+        return constructor;
+    }
+    
+    ~JSCallbackConstructor();
+    static void destroy(JSCell*);
     JSClassRef classRef() const { return m_class; }
     JSObjectCallAsConstructorCallback callback() const { return m_callback; }
     static const ClassInfo s_info;
 
     JSClassRef classRef() const { return m_class; }
     JSObjectCallAsConstructorCallback callback() const { return m_callback; }
     static const ClassInfo s_info;
 
-    static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
+    static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) 
     {
     {
-        return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info);
     }
 
 protected:
     }
 
 protected:
+    JSCallbackConstructor(JSGlobalObject*, Structure*, JSClassRef, JSObjectCallAsConstructorCallback);
+    void finishCreation(JSGlobalObject*, JSClassRef);
     static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags;
 
 private:
     static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags;
 
 private:
-    virtual ConstructType getConstructData(ConstructData&);
+    static ConstructType getConstructData(JSCell*, ConstructData&);
 
     JSClassRef m_class;
     JSObjectCallAsConstructorCallback m_callback;
 
     JSClassRef m_class;
     JSObjectCallAsConstructorCallback m_callback;
index 28b341923dc350e43f88ec9720dce5b343dbc4a7..d287ab7784643487ab5f22a84efa6bbfd7ded560 100644 (file)
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSCallbackFunction);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSCallbackFunction);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSCallbackFunction);
 
 
-const ClassInfo JSCallbackFunction::s_info = { "CallbackFunction", &InternalFunction::s_info, 0, 0 };
+const ClassInfo JSCallbackFunction::s_info = { "CallbackFunction", &InternalFunction::s_info, 0, 0, CREATE_METHOD_TABLE(JSCallbackFunction) };
 
 
-JSCallbackFunction::JSCallbackFunction(ExecState* exec, JSGlobalObject* globalObject, JSObjectCallAsFunctionCallback callback, const Identifier& name)
-    : InternalFunction(&exec->globalData(), globalObject, globalObject->callbackFunctionStructure(), name)
+JSCallbackFunction::JSCallbackFunction(JSGlobalObject* globalObject, JSObjectCallAsFunctionCallback callback)
+    : InternalFunction(globalObject, globalObject->callbackFunctionStructure())
     , m_callback(callback)
 {
     , m_callback(callback)
 {
+}
+
+void JSCallbackFunction::finishCreation(JSGlobalData& globalData, const Identifier& name)
+{
+    Base::finishCreation(globalData, name);
     ASSERT(inherits(&s_info));
 }
 
     ASSERT(inherits(&s_info));
 }
 
@@ -64,15 +70,19 @@ EncodedJSValue JSCallbackFunction::call(ExecState* exec)
     JSValueRef result;
     {
         APICallbackShim callbackShim(exec);
     JSValueRef result;
     {
         APICallbackShim callbackShim(exec);
-        result = static_cast<JSCallbackFunction*>(toJS(functionRef))->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception);
+        result = jsCast<JSCallbackFunction*>(toJS(functionRef))->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception);
     }
     if (exception)
         throwError(exec, toJS(exec, exception));
 
     }
     if (exception)
         throwError(exec, toJS(exec, exception));
 
+    // result must be a valid JSValue.
+    if (!result)
+        return JSValue::encode(jsUndefined());
+
     return JSValue::encode(toJS(exec, result));
 }
 
     return JSValue::encode(toJS(exec, result));
 }
 
-CallType JSCallbackFunction::getCallData(CallData& callData)
+CallType JSCallbackFunction::getCallData(JSCell*, CallData& callData)
 {
     callData.native.function = call;
     return CallTypeHost;
 {
     callData.native.function = call;
     return CallTypeHost;
index 55c9ed4ae87c2290efb480446e98065d9c1849ef..fec4136f83c6d67a1444201b1ceb10a7304757b0 100644 (file)
 namespace JSC {
 
 class JSCallbackFunction : public InternalFunction {
 namespace JSC {
 
 class JSCallbackFunction : public InternalFunction {
+protected:
+    JSCallbackFunction(JSGlobalObject*, JSObjectCallAsFunctionCallback);
+    void finishCreation(JSGlobalData&, const Identifier& name);
+
 public:
 public:
-    JSCallbackFunction(ExecState*, JSGlobalObject*, JSObjectCallAsFunctionCallback, const Identifier& name);
+    typedef InternalFunction Base;
+
+    static JSCallbackFunction* create(ExecState* exec, JSGlobalObject* globalObject, JSObjectCallAsFunctionCallback callback, const Identifier& name)
+    {
+        JSCallbackFunction* function = new (NotNull, allocateCell<JSCallbackFunction>(*exec->heap())) JSCallbackFunction(globalObject, callback);
+        function->finishCreation(exec->globalData(), name);
+        return function;
+    }
 
     static const ClassInfo s_info;
     
     // InternalFunction mish-mashes constructor and function behavior -- we should 
     // refactor the code so this override isn't necessary
 
     static const ClassInfo s_info;
     
     // InternalFunction mish-mashes constructor and function behavior -- we should 
     // refactor the code so this override isn't necessary
-    static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
+    static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) 
     { 
     { 
-        return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
+        return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info); 
     }
 
 private:
     }
 
 private:
-    virtual CallType getCallData(CallData&);
+    static CallType getCallData(JSCell*, CallData&);
 
     static EncodedJSValue JSC_HOST_CALL call(ExecState*);
 
 
     static EncodedJSValue JSC_HOST_CALL call(ExecState*);
 
index 6a7462a9040f8ca1d7fb24ab959fd6003587cb64..68c26824da4e5f00df78ec27f7a5ac95102cddf6 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSObjectWithGlobalObject>);
+ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSNonFinalObject>);
 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<JSObjectWithGlobalObject>::s_info = { "CallbackObject", &JSObjectWithGlobalObject::s_info, 0, 0 };
-template <> const ClassInfo JSCallbackObject<JSGlobalObject>::s_info = { "CallbackGlobalObject", &JSGlobalObject::s_info, 0, 0 };
+template <> const ClassInfo JSCallbackObject<JSNonFinalObject>::s_info = { "CallbackObject", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSCallbackObject) };
+template <> const ClassInfo JSCallbackObject<JSGlobalObject>::s_info = { "CallbackGlobalObject", &JSGlobalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSCallbackObject) };
+
+template <>
+Structure* JSCallbackObject<JSNonFinalObject>::createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+{ 
+    return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info); 
+}
+    
+template <>
+Structure* JSCallbackObject<JSGlobalObject>::createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+{ 
+    return Structure::create(globalData, globalObject, proto, TypeInfo(GlobalObjectType, StructureFlags), &s_info); 
+}
+
+template <class Parent>
+void JSCallbackObject<Parent>::destroy(JSCell* cell)
+{
+    jsCast<JSCallbackObject*>(cell)->JSCallbackObject::~JSCallbackObject();
+}
 
 void JSCallbackObjectData::finalize(Handle<Unknown> handle, void* context)
 {
 
 void JSCallbackObjectData::finalize(Handle<Unknown> handle, void* context)
 {
@@ -47,8 +65,7 @@ void JSCallbackObjectData::finalize(Handle<Unknown> handle, void* context)
     for (; jsClass; jsClass = jsClass->parentClass)
         if (JSObjectFinalizeCallback finalize = jsClass->finalize)
             finalize(thisRef);
     for (; jsClass; jsClass = jsClass->parentClass)
         if (JSObjectFinalizeCallback finalize = jsClass->finalize)
             finalize(thisRef);
-    HandleSlot slot = handle.slot();
-    HandleHeap::heapFor(slot)->deallocate(slot);
+    WeakSet::deallocate(WeakImpl::asWeakImpl(handle.slot()));
 }
     
 } // namespace JSC
 }
     
 } // namespace JSC
index 2b322e7cf2c8386dc58c12d2fa7235496c5633bf..9aca0c7e18ca5ccccee7359ea391c2834b0a1ac8 100644 (file)
@@ -89,7 +89,7 @@ struct JSCallbackObjectData : WeakHandleOwner {
         void setPrivateProperty(JSGlobalData& globalData, JSCell* owner, const Identifier& propertyName, JSValue value)
         {
             WriteBarrier<Unknown> empty;
         void setPrivateProperty(JSGlobalData& globalData, JSCell* owner, const Identifier& propertyName, JSValue value)
         {
             WriteBarrier<Unknown> empty;
-            m_propertyMap.add(propertyName.impl(), empty).first->second.set(globalData, owner, value);
+            m_propertyMap.add(propertyName.impl(), empty).iterator->second.set(globalData, owner, value);
         }
         
         void deletePrivateProperty(const Identifier& propertyName)
         }
         
         void deletePrivateProperty(const Identifier& propertyName)
@@ -114,12 +114,32 @@ struct JSCallbackObjectData : WeakHandleOwner {
 };
 
     
 };
 
     
-template <class Base>
-class JSCallbackObject : public Base {
-public:
-    JSCallbackObject(ExecState*, JSGlobalObject*, Structure*, JSClassRef, void* data);
+template <class Parent>
+class JSCallbackObject : public Parent {
+protected:
+    JSCallbackObject(ExecState*, Structure*, JSClassRef, void* data);
     JSCallbackObject(JSGlobalData&, JSClassRef, Structure*);
 
     JSCallbackObject(JSGlobalData&, JSClassRef, Structure*);
 
+    void finishCreation(ExecState*);
+    void finishCreation(JSGlobalData&);
+
+public:
+    typedef Parent Base;
+
+    static JSCallbackObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSClassRef classRef, void* data)
+    {
+        ASSERT_UNUSED(globalObject, !structure->globalObject() || structure->globalObject() == globalObject);
+        JSCallbackObject* callbackObject = new (NotNull, allocateCell<JSCallbackObject>(*exec->heap())) JSCallbackObject(exec, structure, classRef, data);
+        callbackObject->finishCreation(exec);
+        return callbackObject;
+    }
+    static JSCallbackObject* create(JSGlobalData& globalData, JSClassRef classRef, Structure* structure)
+    {
+        JSCallbackObject* callbackObject = new (NotNull, allocateCell<JSCallbackObject>(globalData.heap)) JSCallbackObject(globalData, classRef, structure);
+        callbackObject->finishCreation(globalData);
+        return callbackObject;
+    }
+
     void setPrivate(void* data);
     void* getPrivate();
 
     void setPrivate(void* data);
     void* getPrivate();
 
@@ -128,10 +148,7 @@ public:
     JSClassRef classRef() const { return m_callbackObjectData->jsClass; }
     bool inherits(JSClassRef) const;
 
     JSClassRef classRef() const { return m_callbackObjectData->jsClass; }
     bool inherits(JSClassRef) const;
 
-    static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
-    { 
-        return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), Base::AnonymousSlotCount, &s_info); 
-    }
+    static Structure* createStructure(JSGlobalData&, JSGlobalObject*, JSValue);
     
     JSValue getPrivateProperty(const Identifier& propertyName) const
     {
     
     JSValue getPrivateProperty(const Identifier& propertyName) const
     {
@@ -148,34 +165,41 @@ public:
         m_callbackObjectData->deletePrivateProperty(propertyName);
     }
 
         m_callbackObjectData->deletePrivateProperty(propertyName);
     }
 
+    using Parent::methodTable;
+
 protected:
 protected:
-    static const unsigned StructureFlags = ProhibitsPropertyCaching | OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
+    static const unsigned StructureFlags = ProhibitsPropertyCaching | OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | Parent::StructureFlags;
 
 private:
 
 private:
-    virtual UString className() const;
+    static UString className(const JSObject*);
 
 
-    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-    virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
-    
-    virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+    static void destroy(JSCell*);
+
+    static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
 
 
-    virtual bool deleteProperty(ExecState*, const Identifier&);
-    virtual bool deleteProperty(ExecState*, unsigned);
+    static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+    static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+    
+    static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
 
 
-    virtual bool hasInstance(ExecState* exec, JSValue value, JSValue proto);
+    static bool deleteProperty(JSCell*, ExecState*, const Identifier&);
+    static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned);
 
 
-    virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+    static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue proto);
 
 
-    virtual double toNumber(ExecState*) const;
-    virtual UString toString(ExecState*) const;
+    static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
 
 
-    virtual ConstructType getConstructData(ConstructData&);
-    virtual CallType getCallData(CallData&);
+    static ConstructType getConstructData(JSCell*, ConstructData&);
+    static CallType getCallData(JSCell*, CallData&);
 
 
-    virtual void visitChildren(SlotVisitor& visitor)
+    static void visitChildren(JSCell* cell, SlotVisitor& visitor)
     {
     {
-        Base::visitChildren(visitor);
-        m_callbackObjectData->visitChildren(visitor);
+        JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(cell);
+        ASSERT_GC_OBJECT_INHERITS((static_cast<Parent*>(thisObject)), &JSCallbackObject<Parent>::s_info);
+        COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+        ASSERT(thisObject->Parent::structure()->typeInfo().overridesVisitChildren());
+        Parent::visitChildren(thisObject, visitor);
+        thisObject->m_callbackObjectData->visitChildren(visitor);
     }
 
     void init(ExecState*);
     }
 
     void init(ExecState*);
index cc8f3a870afc77c95d58a2e9e63d87ebd7d65317..b909dde7181b3cec0838e567efb15c33c66a2494 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-template <class Base>
-inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValue value)
+template <class Parent>
+inline JSCallbackObject<Parent>* JSCallbackObject<Parent>::asCallbackObject(JSValue value)
 {
     ASSERT(asObject(value)->inherits(&s_info));
 {
     ASSERT(asObject(value)->inherits(&s_info));
-    return static_cast<JSCallbackObject*>(asObject(value));
+    return jsCast<JSCallbackObject*>(asObject(value));
 }
 
 }
 
-template <class Base>
-JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSClassRef jsClass, void* data)
-    : Base(globalObject, structure)
+template <class Parent>
+JSCallbackObject<Parent>::JSCallbackObject(ExecState* exec, Structure* structure, JSClassRef jsClass, void* data)
+    : Parent(exec->globalData(), structure)
     , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(data, jsClass)))
 {
     , 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.
 }
 
 // Global object constructor.
 // FIXME: Move this into a separate JSGlobalCallbackObject class derived from this one.
-template <class Base>
-JSCallbackObject<Base>::JSCallbackObject(JSGlobalData& globalData, JSClassRef jsClass, Structure* structure)
-    : Base(globalData, structure)
+template <class Parent>
+JSCallbackObject<Parent>::JSCallbackObject(JSGlobalData& globalData, JSClassRef jsClass, Structure* structure)
+    : Parent(globalData, structure)
     , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(0, jsClass)))
 {
     , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(0, jsClass)))
 {
-    ASSERT(Base::inherits(&s_info));
-    ASSERT(Base::isGlobalObject());
-    init(static_cast<JSGlobalObject*>(this)->globalExec());
 }
 
 }
 
-template <class Base>
-void JSCallbackObject<Base>::init(ExecState* exec)
+template <class Parent>
+void JSCallbackObject<Parent>::finishCreation(ExecState* exec)
+{
+    Base::finishCreation(exec->globalData());
+    ASSERT(Parent::inherits(&s_info));
+    init(exec);
+}
+
+// This is just for Global object, so we can assume that Base::finishCreation is JSGlobalObject::finishCreation.
+template <class Parent>
+void JSCallbackObject<Parent>::finishCreation(JSGlobalData& globalData)
+{
+    ASSERT(Parent::inherits(&s_info));
+    ASSERT(Parent::isGlobalObject());
+    Base::finishCreation(globalData);
+    init(jsCast<JSGlobalObject*>(this)->globalExec());
+}
+
+template <class Parent>
+void JSCallbackObject<Parent>::init(ExecState* exec)
 {
     ASSERT(exec);
     
 {
     ASSERT(exec);
     
@@ -89,42 +102,41 @@ void JSCallbackObject<Base>::init(ExecState* exec)
         initialize(toRef(exec), toRef(this));
     }
 
         initialize(toRef(exec), toRef(this));
     }
 
-    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;
+    for (JSClassRef jsClassPtr = classRef(); jsClassPtr; jsClassPtr = jsClassPtr->parentClass) {
+        if (jsClassPtr->finalize) {
+            WeakSet::allocate(this, m_callbackObjectData.get(), classRef());
+            break;
+        }
     }
 }
 
     }
 }
 
-template <class Base>
-UString JSCallbackObject<Base>::className() const
+template <class Parent>
+UString JSCallbackObject<Parent>::className(const JSObject* object)
 {
 {
-    UString thisClassName = classRef()->className();
+    const JSCallbackObject* thisObject = jsCast<const JSCallbackObject*>(object);
+    UString thisClassName = thisObject->classRef()->className();
     if (!thisClassName.isEmpty())
         return thisClassName;
     
     if (!thisClassName.isEmpty())
         return thisClassName;
     
-    return Base::className();
+    return Parent::className(object);
 }
 
 }
 
-template <class Base>
-bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+template <class Parent>
+bool JSCallbackObject<Parent>::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
+    JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(cell);
     JSContextRef ctx = toRef(exec);
     JSContextRef ctx = toRef(exec);
-    JSObjectRef thisRef = toRef(this);
+    JSObjectRef thisRef = toRef(thisObject);
     RefPtr<OpaqueJSString> propertyNameRef;
     
     RefPtr<OpaqueJSString> propertyNameRef;
     
-    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
+    for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
         // optional optimization to bypass getProperty in cases when we only need to know if the property exists
         if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
             if (!propertyNameRef)
                 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
             APICallbackShim callbackShim(exec);
             if (hasProperty(ctx, thisRef, propertyNameRef.get())) {
         // optional optimization to bypass getProperty in cases when we only need to know if the property exists
         if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
             if (!propertyNameRef)
                 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
             APICallbackShim callbackShim(exec);
             if (hasProperty(ctx, thisRef, propertyNameRef.get())) {
-                slot.setCustom(this, callbackGetter);
+                slot.setCustom(thisObject, callbackGetter);
                 return true;
             }
         } else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
                 return true;
             }
         } else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
@@ -149,7 +161,7 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie
         
         if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
             if (staticValues->contains(propertyName.impl())) {
         
         if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
             if (staticValues->contains(propertyName.impl())) {
-                JSValue value = getStaticValue(exec, propertyName);
+                JSValue value = thisObject->getStaticValue(exec, propertyName);
                 if (value) {
                     slot.setValue(value);
                     return true;
                 if (value) {
                     slot.setValue(value);
                     return true;
@@ -159,20 +171,45 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie
         
         if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
             if (staticFunctions->contains(propertyName.impl())) {
         
         if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
             if (staticFunctions->contains(propertyName.impl())) {
-                slot.setCustom(this, staticFunctionGetter);
+                slot.setCustom(thisObject, staticFunctionGetter);
                 return true;
             }
         }
     }
     
                 return true;
             }
         }
     }
     
-    return Base::getOwnPropertySlot(exec, propertyName, slot);
+    return Parent::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+}
+
+template <class Parent>
+JSValue JSCallbackObject<Parent>::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint)
+{
+    const JSCallbackObject* thisObject = jsCast<const JSCallbackObject*>(object);
+    JSContextRef ctx = toRef(exec);
+    JSObjectRef thisRef = toRef(thisObject);
+    ::JSType jsHint = hint == PreferString ? kJSTypeString : kJSTypeNumber;
+
+    for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
+        if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
+            JSValueRef exception = 0;
+            JSValueRef result = convertToType(ctx, thisRef, jsHint, &exception);
+            if (exception) {
+                throwError(exec, toJS(exec, exception));
+                return jsUndefined();
+            }
+            if (result)
+                return toJS(exec, result);
+        }
+    }
+    
+    return Parent::defaultValue(object, exec, hint);
 }
 
 }
 
-template <class Base>
-bool JSCallbackObject<Base>::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+template <class Parent>
+bool JSCallbackObject<Parent>::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
+    JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(object);
     PropertySlot slot;
     PropertySlot slot;
-    if (getOwnPropertySlot(exec, propertyName, slot)) {
+    if (thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot)) {
         // Ideally we should return an access descriptor, but returning a value descriptor is better than nothing.
         JSValue value = slot.getValue(exec, propertyName);
         if (!exec->hadException())
         // Ideally we should return an access descriptor, but returning a value descriptor is better than nothing.
         JSValue value = slot.getValue(exec, propertyName);
         if (!exec->hadException())
@@ -184,18 +221,19 @@ bool JSCallbackObject<Base>::getOwnPropertyDescriptor(ExecState* exec, const Ide
         return true;
     }
 
         return true;
     }
 
-    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    return Parent::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
 }
 
 }
 
-template <class Base>
-void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+template <class Parent>
+void JSCallbackObject<Parent>::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
+    JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(cell);
     JSContextRef ctx = toRef(exec);
     JSContextRef ctx = toRef(exec);
-    JSObjectRef thisRef = toRef(this);
+    JSObjectRef thisRef = toRef(thisObject);
     RefPtr<OpaqueJSString> propertyNameRef;
     JSValueRef valueRef = toRef(exec, value);
     
     RefPtr<OpaqueJSString> propertyNameRef;
     JSValueRef valueRef = toRef(exec, value);
     
-    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
+    for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
             if (!propertyNameRef)
                 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
         if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
             if (!propertyNameRef)
                 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
@@ -236,23 +274,24 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName
             if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) {
                 if (entry->attributes & kJSPropertyAttributeReadOnly)
                     return;
             if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) {
                 if (entry->attributes & kJSPropertyAttributeReadOnly)
                     return;
-                JSCallbackObject<Base>::putDirect(exec->globalData(), propertyName, value); // put as override property
+                thisObject->JSCallbackObject<Parent>::putDirect(exec->globalData(), propertyName, value); // put as override property
                 return;
             }
         }
     }
     
                 return;
             }
         }
     }
     
-    return Base::put(exec, propertyName, value, slot);
+    return Parent::put(thisObject, exec, propertyName, value, slot);
 }
 
 }
 
-template <class Base>
-bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& propertyName)
+template <class Parent>
+bool JSCallbackObject<Parent>::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
 {
 {
+    JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(cell);
     JSContextRef ctx = toRef(exec);
     JSContextRef ctx = toRef(exec);
-    JSObjectRef thisRef = toRef(this);
+    JSObjectRef thisRef = toRef(thisObject);
     RefPtr<OpaqueJSString> propertyNameRef;
     
     RefPtr<OpaqueJSString> propertyNameRef;
     
-    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
+    for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
             if (!propertyNameRef)
                 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
         if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
             if (!propertyNameRef)
                 propertyNameRef = OpaqueJSString::create(propertyName.ustring());
@@ -285,19 +324,21 @@ bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& p
         }
     }
     
         }
     }
     
-    return Base::deleteProperty(exec, propertyName);
+    return Parent::deleteProperty(thisObject, exec, propertyName);
 }
 
 }
 
-template <class Base>
-bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, unsigned propertyName)
+template <class Parent>
+bool JSCallbackObject<Parent>::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName)
 {
 {
-    return deleteProperty(exec, Identifier::from(exec, propertyName));
+    JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(cell);
+    return thisObject->methodTable()->deleteProperty(thisObject, exec, Identifier::from(exec, propertyName));
 }
 
 }
 
-template <class Base>
-ConstructType JSCallbackObject<Base>::getConstructData(ConstructData& constructData)
+template <class Parent>
+ConstructType JSCallbackObject<Parent>::getConstructData(JSCell* cell, ConstructData& constructData)
 {
 {
-    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
+    JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(cell);
+    for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (jsClass->callAsConstructor) {
             constructData.native.function = construct;
             return ConstructTypeHost;
         if (jsClass->callAsConstructor) {
             constructData.native.function = construct;
             return ConstructTypeHost;
@@ -306,14 +347,14 @@ ConstructType JSCallbackObject<Base>::getConstructData(ConstructData& constructD
     return ConstructTypeNone;
 }
 
     return ConstructTypeNone;
 }
 
-template <class Base>
-EncodedJSValue JSCallbackObject<Base>::construct(ExecState* exec)
+template <class Parent>
+EncodedJSValue JSCallbackObject<Parent>::construct(ExecState* exec)
 {
     JSObject* constructor = exec->callee();
     JSContextRef execRef = toRef(exec);
     JSObjectRef constructorRef = toRef(constructor);
     
 {
     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) {
+    for (JSClassRef jsClass = jsCast<JSCallbackObject<Parent>*>(constructor)->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) {
             int argumentCount = static_cast<int>(exec->argumentCount());
             Vector<JSValueRef, 16> arguments(argumentCount);
         if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) {
             int argumentCount = static_cast<int>(exec->argumentCount());
             Vector<JSValueRef, 16> arguments(argumentCount);
@@ -335,13 +376,14 @@ EncodedJSValue JSCallbackObject<Base>::construct(ExecState* exec)
     return JSValue::encode(JSValue());
 }
 
     return JSValue::encode(JSValue());
 }
 
-template <class Base>
-bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue value, JSValue)
+template <class Parent>
+bool JSCallbackObject<Parent>::hasInstance(JSObject* object, ExecState* exec, JSValue value, JSValue)
 {
 {
+    JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(object);
     JSContextRef execRef = toRef(exec);
     JSContextRef execRef = toRef(exec);
-    JSObjectRef thisRef = toRef(this);
+    JSObjectRef thisRef = toRef(thisObject);
     
     
-    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
+    for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance) {
             JSValueRef valueRef = toRef(exec, value);
             JSValueRef exception = 0;
         if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance) {
             JSValueRef valueRef = toRef(exec, value);
             JSValueRef exception = 0;
@@ -358,10 +400,11 @@ bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue value, JSValue
     return false;
 }
 
     return false;
 }
 
-template <class Base>
-CallType JSCallbackObject<Base>::getCallData(CallData& callData)
+template <class Parent>
+CallType JSCallbackObject<Parent>::getCallData(JSCell* cell, CallData& callData)
 {
 {
-    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
+    JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(cell);
+    for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (jsClass->callAsFunction) {
             callData.native.function = call;
             return CallTypeHost;
         if (jsClass->callAsFunction) {
             callData.native.function = call;
             return CallTypeHost;
@@ -370,14 +413,14 @@ CallType JSCallbackObject<Base>::getCallData(CallData& callData)
     return CallTypeNone;
 }
 
     return CallTypeNone;
 }
 
-template <class Base>
-EncodedJSValue JSCallbackObject<Base>::call(ExecState* exec)
+template <class Parent>
+EncodedJSValue JSCallbackObject<Parent>::call(ExecState* exec)
 {
     JSContextRef execRef = toRef(exec);
     JSObjectRef functionRef = toRef(exec->callee());
     JSObjectRef thisObjRef = toRef(exec->hostThisValue().toThisObject(exec));
     
 {
     JSContextRef execRef = toRef(exec);
     JSObjectRef functionRef = toRef(exec->callee());
     JSObjectRef thisObjRef = toRef(exec->hostThisValue().toThisObject(exec));
     
-    for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(toJS(functionRef))->classRef(); jsClass; jsClass = jsClass->parentClass) {
+    for (JSClassRef jsClass = jsCast<JSCallbackObject<Parent>*>(toJS(functionRef))->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) {
             int argumentCount = static_cast<int>(exec->argumentCount());
             Vector<JSValueRef, 16> arguments(argumentCount);
         if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) {
             int argumentCount = static_cast<int>(exec->argumentCount());
             Vector<JSValueRef, 16> arguments(argumentCount);
@@ -399,13 +442,14 @@ EncodedJSValue JSCallbackObject<Base>::call(ExecState* exec)
     return JSValue::encode(JSValue());
 }
 
     return JSValue::encode(JSValue());
 }
 
-template <class Base>
-void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+template <class Parent>
+void JSCallbackObject<Parent>::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
+    JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(object);
     JSContextRef execRef = toRef(exec);
     JSContextRef execRef = toRef(exec);
-    JSObjectRef thisRef = toRef(this);
+    JSObjectRef thisRef = toRef(thisObject);
     
     
-    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
+    for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) {
             APICallbackShim callbackShim(exec);
             getPropertyNames(execRef, thisRef, toRef(&propertyNames));
         if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) {
             APICallbackShim callbackShim(exec);
             getPropertyNames(execRef, thisRef, toRef(&propertyNames));
@@ -416,7 +460,7 @@ void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameAr
             iterator end = staticValues->end();
             for (iterator it = staticValues->begin(); it != end; ++it) {
                 StringImpl* name = it->first.get();
             iterator end = staticValues->end();
             for (iterator it = staticValues->begin(); it != end; ++it) {
                 StringImpl* name = it->first.get();
-                StaticValueEntry* entry = it->second;
+                StaticValueEntry* entry = it->second.get();
                 if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties)))
                     propertyNames.add(Identifier(exec, name));
             }
                 if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties)))
                     propertyNames.add(Identifier(exec, name));
             }
@@ -427,87 +471,30 @@ void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameAr
             iterator end = staticFunctions->end();
             for (iterator it = staticFunctions->begin(); it != end; ++it) {
                 StringImpl* name = it->first.get();
             iterator end = staticFunctions->end();
             for (iterator it = staticFunctions->begin(); it != end; ++it) {
                 StringImpl* name = it->first.get();
-                StaticFunctionEntry* entry = it->second;
+                StaticFunctionEntry* entry = it->second.get();
                 if (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties))
                     propertyNames.add(Identifier(exec, name));
             }
         }
     }
     
                 if (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties))
                     propertyNames.add(Identifier(exec, name));
             }
         }
     }
     
-    Base::getOwnPropertyNames(exec, propertyNames, mode);
-}
-
-template <class Base>
-double JSCallbackObject<Base>::toNumber(ExecState* exec) const
-{
-    // We need this check to guard against the case where this object is rhs of
-    // a binary expression where lhs threw an exception in its conversion to
-    // primitive
-    if (exec->hadException())
-        return NaN;
-    JSContextRef ctx = toRef(exec);
-    JSObjectRef thisRef = toRef(this);
-    
-    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
-        if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
-            JSValueRef exception = 0;
-            JSValueRef value;
-            {
-                APICallbackShim callbackShim(exec);
-                value = convertToType(ctx, thisRef, kJSTypeNumber, &exception);
-            }
-            if (exception) {
-                throwError(exec, toJS(exec, exception));
-                return 0;
-            }
-
-            double dValue;
-            if (value)
-                return toJS(exec, value).getNumber(dValue) ? dValue : NaN;
-        }
-            
-    return Base::toNumber(exec);
-}
-
-template <class Base>
-UString JSCallbackObject<Base>::toString(ExecState* exec) const
-{
-    JSContextRef ctx = toRef(exec);
-    JSObjectRef thisRef = toRef(this);
-    
-    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
-        if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
-            JSValueRef exception = 0;
-            JSValueRef value;
-            {
-                APICallbackShim callbackShim(exec);
-                value = convertToType(ctx, thisRef, kJSTypeString, &exception);
-            }
-            if (exception) {
-                throwError(exec, toJS(exec, exception));
-                return "";
-            }
-            if (value)
-                return toJS(exec, value).getString(exec);
-        }
-            
-    return Base::toString(exec);
+    Parent::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
 }
 
 }
 
-template <class Base>
-void JSCallbackObject<Base>::setPrivate(void* data)
+template <class Parent>
+void JSCallbackObject<Parent>::setPrivate(void* data)
 {
     m_callbackObjectData->privateData = data;
 }
 
 {
     m_callbackObjectData->privateData = data;
 }
 
-template <class Base>
-void* JSCallbackObject<Base>::getPrivate()
+template <class Parent>
+void* JSCallbackObject<Parent>::getPrivate()
 {
     return m_callbackObjectData->privateData;
 }
 
 {
     return m_callbackObjectData->privateData;
 }
 
-template <class Base>
-bool JSCallbackObject<Base>::inherits(JSClassRef c) const
+template <class Parent>
+bool JSCallbackObject<Parent>::inherits(JSClassRef c) const
 {
     for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
         if (jsClass == c)
 {
     for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
         if (jsClass == c)
@@ -516,8 +503,8 @@ bool JSCallbackObject<Base>::inherits(JSClassRef c) const
     return false;
 }
 
     return false;
 }
 
-template <class Base>
-JSValue JSCallbackObject<Base>::getStaticValue(ExecState* exec, const Identifier& propertyName)
+template <class Parent>
+JSValue JSCallbackObject<Parent>::getStaticValue(ExecState* exec, const Identifier& propertyName)
 {
     JSObjectRef thisRef = toRef(this);
     RefPtr<OpaqueJSString> propertyNameRef;
 {
     JSObjectRef thisRef = toRef(this);
     RefPtr<OpaqueJSString> propertyNameRef;
@@ -545,14 +532,14 @@ JSValue JSCallbackObject<Base>::getStaticValue(ExecState* exec, const Identifier
     return JSValue();
 }
 
     return JSValue();
 }
 
-template <class Base>
-JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
+template <class Parent>
+JSValue JSCallbackObject<Parent>::staticFunctionGetter(ExecState* exec, JSValue slotParent, const Identifier& propertyName)
 {
 {
-    JSCallbackObject* thisObj = asCallbackObject(slotBase);
+    JSCallbackObject* thisObj = asCallbackObject(slotParent);
     
     // Check for cached or override property.
     PropertySlot slot2(thisObj);
     
     // Check for cached or override property.
     PropertySlot slot2(thisObj);
-    if (thisObj->Base::getOwnPropertySlot(exec, propertyName, slot2))
+    if (Parent::getOwnPropertySlot(thisObj, exec, propertyName, slot2))
         return slot2.getValue(exec, propertyName);
     
     for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) {
         return slot2.getValue(exec, propertyName);
     
     for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) {
@@ -560,7 +547,7 @@ JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, JSValue sl
             if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) {
                 if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) {
                     
             if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) {
                 if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) {
                     
-                    JSObject* o = new (exec) JSCallbackFunction(exec, asGlobalObject(thisObj->getAnonymousValue(0)), callAsFunction, propertyName);
+                    JSObject* o = JSCallbackFunction::create(exec, thisObj->globalObject(), callAsFunction, propertyName);
                     thisObj->putDirect(exec->globalData(), propertyName, o, entry->attributes);
                     return o;
                 }
                     thisObj->putDirect(exec->globalData(), propertyName, o, entry->attributes);
                     return o;
                 }
@@ -571,10 +558,10 @@ JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, JSValue sl
     return throwError(exec, createReferenceError(exec, "Static function property defined with NULL callAsFunction callback."));
 }
 
     return throwError(exec, createReferenceError(exec, "Static function property defined with NULL callAsFunction callback."));
 }
 
-template <class Base>
-JSValue JSCallbackObject<Base>::callbackGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
+template <class Parent>
+JSValue JSCallbackObject<Parent>::callbackGetter(ExecState* exec, JSValue slotParent, const Identifier& propertyName)
 {
 {
-    JSCallbackObject* thisObj = asCallbackObject(slotBase);
+    JSCallbackObject* thisObj = asCallbackObject(slotParent);
     
     JSObjectRef thisRef = toRef(thisObj);
     RefPtr<OpaqueJSString> propertyNameRef;
     
     JSObjectRef thisRef = toRef(thisObj);
     RefPtr<OpaqueJSString> propertyNameRef;
index 08dc7211b2f301536e71a36081e109bbc04d6c30..08fa5c5e0b0084173e0dcb2df8e49cb7076f6214 100644 (file)
@@ -71,39 +71,25 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass*
     , hasInstance(definition->hasInstance)
     , convertToType(definition->convertToType)
     , m_className(tryCreateStringFromUTF8(definition->className))
     , hasInstance(definition->hasInstance)
     , convertToType(definition->convertToType)
     , m_className(tryCreateStringFromUTF8(definition->className))
-    , m_staticValues(0)
-    , m_staticFunctions(0)
 {
     initializeThreading();
 
     if (const JSStaticValue* staticValue = definition->staticValues) {
 {
     initializeThreading();
 
     if (const JSStaticValue* staticValue = definition->staticValues) {
-        m_staticValues = new OpaqueJSClassStaticValuesTable();
+        m_staticValues = adoptPtr(new OpaqueJSClassStaticValuesTable);
         while (staticValue->name) {
             UString valueName = tryCreateStringFromUTF8(staticValue->name);
         while (staticValue->name) {
             UString valueName = tryCreateStringFromUTF8(staticValue->name);
-            if (!valueName.isNull()) {
-                // Use a local variable here to sidestep an RVCT compiler bug.
-                StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes);
-                StringImpl* impl = valueName.impl();
-                StaticValueEntry* existingEntry = m_staticValues->get(impl);
-                m_staticValues->set(impl, entry);
-                delete existingEntry;
-            }
+            if (!valueName.isNull())
+                m_staticValues->set(valueName.impl(), adoptPtr(new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes)));
             ++staticValue;
         }
     }
 
     if (const JSStaticFunction* staticFunction = definition->staticFunctions) {
             ++staticValue;
         }
     }
 
     if (const JSStaticFunction* staticFunction = definition->staticFunctions) {
-        m_staticFunctions = new OpaqueJSClassStaticFunctionsTable();
+        m_staticFunctions = adoptPtr(new OpaqueJSClassStaticFunctionsTable);
         while (staticFunction->name) {
             UString functionName = tryCreateStringFromUTF8(staticFunction->name);
         while (staticFunction->name) {
             UString functionName = tryCreateStringFromUTF8(staticFunction->name);
-            if (!functionName.isNull()) {
-                // Use a local variable here to sidestep an RVCT compiler bug.
-                StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes);
-                StringImpl* impl = functionName.impl();
-                StaticFunctionEntry* existingEntry = m_staticFunctions->get(impl);
-                m_staticFunctions->set(impl, entry);
-                delete existingEntry;
-            }
+            if (!functionName.isNull())
+                m_staticFunctions->set(functionName.impl(), adoptPtr(new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes)));
             ++staticFunction;
         }
     }
             ++staticFunction;
         }
     }
@@ -117,23 +103,19 @@ 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.length() || !m_className.impl()->isIdentifier());
 
     // 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.length() || !m_className.impl()->isIdentifier());
 
+#ifndef NDEBUG
     if (m_staticValues) {
         OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end();
     if (m_staticValues) {
         OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end();
-        for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) {
+        for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it)
             ASSERT(!it->first->isIdentifier());
             ASSERT(!it->first->isIdentifier());
-            delete it->second;
-        }
-        delete m_staticValues;
     }
 
     if (m_staticFunctions) {
         OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end();
     }
 
     if (m_staticFunctions) {
         OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end();
-        for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) {
+        for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it)
             ASSERT(!it->first->isIdentifier());
             ASSERT(!it->first->isIdentifier());
-            delete it->second;
-        }
-        delete m_staticFunctions;
     }
     }
+#endif
     
     if (prototypeClass)
         JSClassRelease(prototypeClass);
     
     if (prototypeClass)
         JSClassRelease(prototypeClass);
@@ -162,49 +144,29 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(JSC::JSGlobalData&, OpaqueJSC
     : m_class(jsClass)
 {
     if (jsClass->m_staticValues) {
     : m_class(jsClass)
 {
     if (jsClass->m_staticValues) {
-        staticValues = new OpaqueJSClassStaticValuesTable;
+        staticValues = adoptPtr(new OpaqueJSClassStaticValuesTable);
         OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end();
         for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) {
             ASSERT(!it->first->isIdentifier());
         OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end();
         for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) {
             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(StringImpl::create(it->first->characters(), it->first->length()), entry);
+            staticValues->add(StringImpl::create(it->first->characters(), it->first->length()), adoptPtr(new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes)));
         }
         }
-    } else
-        staticValues = 0;
+    }
 
     if (jsClass->m_staticFunctions) {
 
     if (jsClass->m_staticFunctions) {
-        staticFunctions = new OpaqueJSClassStaticFunctionsTable;
+        staticFunctions = adoptPtr(new OpaqueJSClassStaticFunctionsTable);
         OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end();
         for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) {
             ASSERT(!it->first->isIdentifier());
         OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end();
         for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) {
             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(StringImpl::create(it->first->characters(), it->first->length()), entry);
+            staticFunctions->add(StringImpl::create(it->first->characters(), it->first->length()), adoptPtr(new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes)));
         }
         }
-            
-    } else
-        staticFunctions = 0;
-}
-
-OpaqueJSClassContextData::~OpaqueJSClassContextData()
-{
-    if (staticValues) {
-        deleteAllValues(*staticValues);
-        delete staticValues;
-    }
-
-    if (staticFunctions) {
-        deleteAllValues(*staticFunctions);
-        delete staticFunctions;
     }
 }
 
 OpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec)
 {
     }
 }
 
 OpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec)
 {
-    OpaqueJSClassContextData*& contextData = exec->globalData().opaqueJSClassData.add(this, 0).first->second;
+    OwnPtr<OpaqueJSClassContextData>& contextData = exec->globalData().opaqueJSClassData.add(this, nullptr).iterator->second;
     if (!contextData)
     if (!contextData)
-        contextData = new OpaqueJSClassContextData(exec->globalData(), this);
+        contextData = adoptPtr(new OpaqueJSClassContextData(exec->globalData(), this));
     return *contextData;
 }
 
     return *contextData;
 }
 
@@ -216,14 +178,12 @@ UString OpaqueJSClass::className()
 
 OpaqueJSClassStaticValuesTable* OpaqueJSClass::staticValues(JSC::ExecState* exec)
 {
 
 OpaqueJSClassStaticValuesTable* OpaqueJSClass::staticValues(JSC::ExecState* exec)
 {
-    OpaqueJSClassContextData& jsClassData = contextData(exec);
-    return jsClassData.staticValues;
+    return contextData(exec).staticValues.get();
 }
 
 OpaqueJSClassStaticFunctionsTable* OpaqueJSClass::staticFunctions(JSC::ExecState* exec)
 {
 }
 
 OpaqueJSClassStaticFunctionsTable* OpaqueJSClass::staticFunctions(JSC::ExecState* exec)
 {
-    OpaqueJSClassContextData& jsClassData = contextData(exec);
-    return jsClassData.staticFunctions;
+    return contextData(exec).staticFunctions.get();
 }
 
 /*!
 }
 
 /*!
@@ -243,7 +203,7 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec)
      *       |        |          |
      *  DerivedClass  |  DerivedClassPrototype
      */
      *       |        |          |
      *  DerivedClass  |  DerivedClassPrototype
      */
-    
+
     if (!prototypeClass)
         return 0;
 
     if (!prototypeClass)
         return 0;
 
@@ -251,7 +211,7 @@ 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.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
+        jsClassData.cachedPrototype = PassWeak<JSObject>(JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData), 0); // set jsClassData as the object's private data, so it can clear our reference on destruction
         if (parentClass) {
             if (JSObject* prototype = parentClass->prototype(exec))
                 jsClassData.cachedPrototype->setPrototype(exec->globalData(), prototype);
         if (parentClass) {
             if (JSObject* prototype = parentClass->prototype(exec))
                 jsClassData.cachedPrototype->setPrototype(exec->globalData(), prototype);
index d346cc5dfcb036508e3915f790f11b71a1e378c8..82c7ab3f9729e3dfdcfa9db9dc7b1b8b808185ad 100644 (file)
@@ -59,8 +59,8 @@ public:
     JSPropertyAttributes attributes;
 };
 
     JSPropertyAttributes attributes;
 };
 
-typedef HashMap<RefPtr<StringImpl>, StaticValueEntry*> OpaqueJSClassStaticValuesTable;
-typedef HashMap<RefPtr<StringImpl>, StaticFunctionEntry*> OpaqueJSClassStaticFunctionsTable;
+typedef HashMap<RefPtr<StringImpl>, OwnPtr<StaticValueEntry> > OpaqueJSClassStaticValuesTable;
+typedef HashMap<RefPtr<StringImpl>, OwnPtr<StaticFunctionEntry> > OpaqueJSClassStaticFunctionsTable;
 
 struct OpaqueJSClass;
 
 
 struct OpaqueJSClass;
 
@@ -70,7 +70,6 @@ struct OpaqueJSClassContextData {
     WTF_MAKE_NONCOPYABLE(OpaqueJSClassContextData); WTF_MAKE_FAST_ALLOCATED;
 public:
     OpaqueJSClassContextData(JSC::JSGlobalData&, OpaqueJSClass*);
     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:
     // 1. A class is created and used, so its context data is stored in JSGlobalData hash map.
 
     // It is necessary to keep OpaqueJSClass alive because of the following rare scenario:
     // 1. A class is created and used, so its context data is stored in JSGlobalData hash map.
@@ -80,8 +79,8 @@ public:
     // 4. When it is used, the old context data is found in JSGlobalData and used.
     RefPtr<OpaqueJSClass> m_class;
 
     // 4. When it is used, the old context data is found in JSGlobalData and used.
     RefPtr<OpaqueJSClass> m_class;
 
-    OpaqueJSClassStaticValuesTable* staticValues;
-    OpaqueJSClassStaticFunctionsTable* staticFunctions;
+    OwnPtr<OpaqueJSClassStaticValuesTable> staticValues;
+    OwnPtr<OpaqueJSClassStaticFunctionsTable> staticFunctions;
     JSC::Weak<JSC::JSObject> cachedPrototype;
 };
 
     JSC::Weak<JSC::JSObject> cachedPrototype;
 };
 
@@ -121,8 +120,8 @@ private:
 
     // UStrings in these data members should not be put into any IdentifierTable.
     JSC::UString m_className;
 
     // UStrings in these data members should not be put into any IdentifierTable.
     JSC::UString m_className;
-    OpaqueJSClassStaticValuesTable* m_staticValues;
-    OpaqueJSClassStaticFunctionsTable* m_staticFunctions;
+    OwnPtr<OpaqueJSClassStaticValuesTable> m_staticValues;
+    OwnPtr<OpaqueJSClassStaticFunctionsTable> m_staticFunctions;
 };
 
 #endif // JSClassRef_h
 };
 
 #endif // JSClassRef_h
index 9c15b22f1deb481cca7f7ea83d1983599abb7cf1..7a57287ded4e02d4b0dcc4997dda90431b6da1ab 100644 (file)
@@ -38,7 +38,6 @@
 #include "UStringBuilder.h"
 #include <wtf/text/StringHash.h>
 
 #include "UStringBuilder.h"
 #include <wtf/text/StringHash.h>
 
-
 #if OS(DARWIN)
 #include <mach-o/dyld.h>
 
 #if OS(DARWIN)
 #include <mach-o/dyld.h>
 
@@ -47,6 +46,11 @@ static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500;
 
 using namespace JSC;
 
 
 using namespace JSC;
 
+// From the API's perspective, a context group remains alive iff
+//     (a) it has been JSContextGroupRetained
+//     OR
+//     (b) one of its contexts has been JSContextRetained
+
 JSContextGroupRef JSContextGroupCreate()
 {
     initializeThreading();
 JSContextGroupRef JSContextGroupCreate()
 {
     initializeThreading();
@@ -64,18 +68,16 @@ void JSContextGroupRelease(JSContextGroupRef group)
     toJS(group)->deref();
 }
 
     toJS(group)->deref();
 }
 
+// From the API's perspective, a global context remains alive iff it has been JSGlobalContextRetained.
+
 JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
 {
     initializeThreading();
 JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
 {
     initializeThreading();
+
 #if OS(DARWIN)
 #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.
-#ifndef BUILDING_ON_LEOPARD
+    // If the application was linked before JSGlobalContextCreate was changed to use a unique JSGlobalData,
+    // we use a shared one for backwards compatibility.
     if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) {
     if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) {
-#else
-    {
-#endif
-        JSLock lock(LockForReal);
         return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass);
     }
 #endif // OS(DARWIN)
         return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass);
     }
 #endif // OS(DARWIN)
@@ -87,21 +89,17 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass
 {
     initializeThreading();
 
 {
     initializeThreading();
 
-    JSLock lock(LockForReal);
     RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createContextGroup(ThreadStackTypeSmall);
 
     APIEntryShim entryShim(globalData.get(), false);
     RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createContextGroup(ThreadStackTypeSmall);
 
     APIEntryShim entryShim(globalData.get(), false);
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
     globalData->makeUsableFromMultipleThreads();
     globalData->makeUsableFromMultipleThreads();
-#endif
 
     if (!globalObjectClass) {
 
     if (!globalObjectClass) {
-        JSGlobalObject* globalObject = new (globalData.get()) JSGlobalObject(*globalData, JSGlobalObject::createStructure(*globalData, jsNull()));
+        JSGlobalObject* globalObject = JSGlobalObject::create(*globalData, JSGlobalObject::createStructure(*globalData, jsNull()));
         return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec()));
     }
 
         return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec()));
     }
 
-    JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(*globalData, globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(*globalData, jsNull()));
+    JSGlobalObject* globalObject = JSCallbackObject<JSGlobalObject>::create(*globalData, globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(*globalData, 0, jsNull()));
     ExecState* exec = globalObject->globalExec();
     JSValue prototype = globalObjectClass->prototype(exec);
     if (!prototype)
     ExecState* exec = globalObject->globalExec();
     JSValue prototype = globalObjectClass->prototype(exec);
     if (!prototype)
@@ -123,38 +121,19 @@ JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx)
 
 void JSGlobalContextRelease(JSGlobalContextRef ctx)
 {
 
 void JSGlobalContextRelease(JSGlobalContextRef ctx)
 {
+    IdentifierTable* savedIdentifierTable;
     ExecState* exec = toJS(ctx);
     ExecState* exec = toJS(ctx);
-    JSLock lock(exec);
+    {
+        JSLockHolder lock(exec);
 
 
-    JSGlobalData& globalData = exec->globalData();
-    JSGlobalObject* dgo = exec->dynamicGlobalObject();
-    IdentifierTable* savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable);
-
-    // One reference is held by JSGlobalObject, another added by JSGlobalContextRetain().
-    bool releasingContextGroup = globalData.refCount() == 2;
-    bool releasingGlobalObject = Heap::heap(dgo)->unprotect(dgo);
-    // If this is the last reference to a global data, it should also
-    // be the only remaining reference to the global object too!
-    ASSERT(!releasingContextGroup || releasingGlobalObject);
-
-    // An API 'JSGlobalContextRef' retains two things - a global object and a
-    // global data (or context group, in API terminology).
-    // * 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 - tickle the activity callback to
-    //   garbage collect soon.
-    // * If there are more references remaining the the global object, then do nothing
-    //   (specifically that is more protects, which we assume come from other JSGlobalContextRefs).
-    if (releasingContextGroup) {
-        globalData.clearBuiltinStructures();
-        globalData.heap.destroy();
-    } else if (releasingGlobalObject) {
-        globalData.heap.activityCallback()->synchronize();
-        (*globalData.heap.activityCallback())();
-    }
+        JSGlobalData& globalData = exec->globalData();
+        savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable);
 
 
-    globalData.deref();
+        bool protectCountIsZero = Heap::heap(exec->dynamicGlobalObject())->unprotect(exec->dynamicGlobalObject());
+        if (protectCountIsZero)
+            globalData.heap.reportAbandonedObjectGraph();
+        globalData.deref();
+    }
 
     wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable);
 }
 
     wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable);
 }
@@ -165,7 +144,7 @@ JSObjectRef JSContextGetGlobalObject(JSContextRef ctx)
     APIEntryShim entryShim(exec);
 
     // It is necessary to call toThisObject to get the wrapper object when used with WebCore.
     APIEntryShim entryShim(exec);
 
     // It is necessary to call toThisObject to get the wrapper object when used with WebCore.
-    return toRef(exec->lexicalGlobalObject()->toThisObject(exec));
+    return toRef(exec->lexicalGlobalObject()->methodTable()->toThisObject(exec->lexicalGlobalObject(), exec));
 }
 
 JSContextGroupRef JSContextGetGroup(JSContextRef ctx)
 }
 
 JSContextGroupRef JSContextGetGroup(JSContextRef ctx)
@@ -185,7 +164,7 @@ JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx)
 JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
 {
     ExecState* exec = toJS(ctx);
 JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
 {
     ExecState* exec = toJS(ctx);
-    JSLock lock(exec);
+    JSLockHolder lock(exec);
 
     unsigned count = 0;
     UStringBuilder builder;
 
     unsigned count = 0;
     UStringBuilder builder;
@@ -212,7 +191,7 @@ JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
         exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function);
 
         if (function)
         exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function);
 
         if (function)
-            functionName = asFunction(function)->name(exec);
+            functionName = jsCast<JSFunction*>(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.
         else {
             // Caller is unknown, but if frame is empty we should still add the frame, because
             // something called us, and gave us arguments.
index 2df010a5189f7c6ed2c9aef9c18e31f37089543b..e01214d5ebfa10ccf23b8779f062dd0f8febaa9c 100644 (file)
@@ -81,7 +81,7 @@ JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
     if (!jsClass)
         return toRef(constructEmptyObject(exec));
 
     if (!jsClass)
         return toRef(constructEmptyObject(exec));
 
-    JSCallbackObject<JSObjectWithGlobalObject>* object = new (exec) JSCallbackObject<JSObjectWithGlobalObject>(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
+    JSCallbackObject<JSNonFinalObject>* object = JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
     if (JSObject* prototype = jsClass->prototype(exec))
         object->setPrototype(exec->globalData(), prototype);
 
     if (JSObject* prototype = jsClass->prototype(exec))
         object->setPrototype(exec->globalData(), prototype);
 
@@ -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, exec->lexicalGlobalObject(), callAsFunction, nameID));
+    return toRef(JSCallbackFunction::create(exec, exec->lexicalGlobalObject(), callAsFunction, nameID));
 }
 
 JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
 }
 
 JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
@@ -107,7 +107,7 @@ 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(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
+    JSCallbackConstructor* constructor = JSCallbackConstructor::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
     constructor->putDirect(exec->globalData(), exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
     return toRef(constructor);
 }
     constructor->putDirect(exec->globalData(), exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
     return toRef(constructor);
 }
@@ -124,7 +124,7 @@ JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned pa
         args.append(jsString(exec, parameterNames[i]->ustring()));
     args.append(jsString(exec, body->ustring()));
 
         args.append(jsString(exec, parameterNames[i]->ustring()));
     args.append(jsString(exec, body->ustring()));
 
-    JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, sourceURL->ustring(), startingLineNumber);
+    JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, sourceURL->ustring(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first()));
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
@@ -274,10 +274,10 @@ void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef prope
     JSValue jsValue = toJS(exec, value);
 
     if (attributes && !jsObject->hasProperty(exec, name))
     JSValue jsValue = toJS(exec, value);
 
     if (attributes && !jsObject->hasProperty(exec, name))
-        jsObject->putWithAttributes(exec, name, jsValue, attributes);
+        jsObject->methodTable()->putDirectVirtual(jsObject, exec, name, jsValue, attributes);
     else {
         PutPropertySlot slot;
     else {
         PutPropertySlot slot;
-        jsObject->put(exec, name, jsValue, slot);
+        jsObject->methodTable()->put(jsObject, exec, name, jsValue, slot);
     }
 
     if (exec->hadException()) {
     }
 
     if (exec->hadException()) {
@@ -312,7 +312,7 @@ void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned p
     JSObject* jsObject = toJS(object);
     JSValue jsValue = toJS(exec, value);
     
     JSObject* jsObject = toJS(object);
     JSValue jsValue = toJS(exec, value);
     
-    jsObject->put(exec, propertyIndex, jsValue);
+    jsObject->methodTable()->putByIndex(jsObject, exec, propertyIndex, jsValue, false);
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
@@ -327,7 +327,7 @@ bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr
 
     JSObject* jsObject = toJS(object);
 
 
     JSObject* jsObject = toJS(object);
 
-    bool result = jsObject->deleteProperty(exec, propertyName->identifier(&exec->globalData()));
+    bool result = jsObject->methodTable()->deleteProperty(jsObject, exec, propertyName->identifier(&exec->globalData()));
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
@@ -341,9 +341,9 @@ void* JSObjectGetPrivate(JSObjectRef object)
     JSObject* jsObject = toJS(object);
     
     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
     JSObject* jsObject = toJS(object);
     
     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
-        return static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
-    if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info))
-        return static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->getPrivate();
+        return jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
+    if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info))
+        return jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivate();
     
     return 0;
 }
     
     return 0;
 }
@@ -353,11 +353,11 @@ bool JSObjectSetPrivate(JSObjectRef object, void* data)
     JSObject* jsObject = toJS(object);
     
     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
     JSObject* jsObject = toJS(object);
     
     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
-        static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
+        jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
         return true;
     }
         return true;
     }
-    if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info)) {
-        static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->setPrivate(data);
+    if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
+        jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivate(data);
         return true;
     }
         
         return true;
     }
         
@@ -372,9 +372,9 @@ JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSSt
     JSValue result;
     Identifier name(propertyName->identifier(&exec->globalData()));
     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
     JSValue result;
     Identifier name(propertyName->identifier(&exec->globalData()));
     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
-        result = static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
-    else if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info))
-        result = static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->getPrivateProperty(name);
+        result = jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
+    else if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info))
+        result = jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivateProperty(name);
     return toRef(exec, result);
 }
 
     return toRef(exec, result);
 }
 
@@ -386,11 +386,11 @@ bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRe
     JSValue jsValue = value ? toJS(exec, value) : JSValue();
     Identifier name(propertyName->identifier(&exec->globalData()));
     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
     JSValue jsValue = value ? toJS(exec, value) : JSValue();
     Identifier name(propertyName->identifier(&exec->globalData()));
     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
-        static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
+        jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
         return true;
     }
         return true;
     }
-    if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info)) {
-        static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
+    if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
+        jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
         return true;
     }
     return false;
         return true;
     }
     return false;
@@ -403,11 +403,11 @@ bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStrin
     JSObject* jsObject = toJS(object);
     Identifier name(propertyName->identifier(&exec->globalData()));
     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
     JSObject* jsObject = toJS(object);
     Identifier name(propertyName->identifier(&exec->globalData()));
     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
-        static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name);
+        jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name);
         return true;
     }
         return true;
     }
-    if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info)) {
-        static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->deletePrivateProperty(name);
+    if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
+        jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->deletePrivateProperty(name);
         return true;
     }
     return false;
         return true;
     }
     return false;
@@ -416,7 +416,8 @@ bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStrin
 bool JSObjectIsFunction(JSContextRef, JSObjectRef object)
 {
     CallData callData;
 bool JSObjectIsFunction(JSContextRef, JSObjectRef object)
 {
     CallData callData;
-    return toJS(object)->getCallData(callData) != CallTypeNone;
+    JSCell* cell = toJS(object);
+    return cell->methodTable()->getCallData(cell, callData) != CallTypeNone;
 }
 
 JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 }
 
 JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
@@ -435,7 +436,7 @@ JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObject
         argList.append(toJS(exec, arguments[i]));
 
     CallData callData;
         argList.append(toJS(exec, arguments[i]));
 
     CallData callData;
-    CallType callType = jsObject->getCallData(callData);
+    CallType callType = jsObject->methodTable()->getCallData(jsObject, callData);
     if (callType == CallTypeNone)
         return 0;
 
     if (callType == CallTypeNone)
         return 0;
 
@@ -453,7 +454,7 @@ bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
 {
     JSObject* jsObject = toJS(object);
     ConstructData constructData;
 {
     JSObject* jsObject = toJS(object);
     ConstructData constructData;
-    return jsObject->getConstructData(constructData) != ConstructTypeNone;
+    return jsObject->methodTable()->getConstructData(jsObject, constructData) != ConstructTypeNone;
 }
 
 JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 }
 
 JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
@@ -464,7 +465,7 @@ JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size
     JSObject* jsObject = toJS(object);
 
     ConstructData constructData;
     JSObject* jsObject = toJS(object);
 
     ConstructData constructData;
-    ConstructType constructType = jsObject->getConstructData(constructData);
+    ConstructType constructType = jsObject->methodTable()->getConstructData(jsObject, constructData);
     if (constructType == ConstructTypeNone)
         return 0;
 
     if (constructType == ConstructTypeNone)
         return 0;
 
@@ -505,7 +506,7 @@ JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef o
 
     JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(globalData);
     PropertyNameArray array(globalData);
 
     JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(globalData);
     PropertyNameArray array(globalData);
-    jsObject->getPropertyNames(exec, array);
+    jsObject->methodTable()->getPropertyNames(jsObject, exec, array, ExcludeDontEnumProperties);
 
     size_t size = array.size();
     propertyNames->array.reserveInitialCapacity(size);
 
     size_t size = array.size();
     propertyNames->array.reserveInitialCapacity(size);
index 3e8b0eb62e3107ffae1bb5a1c960475e70c4b7b6..5014726bc18332ddc93c713dc0e3a353000e6945 100644 (file)
@@ -288,7 +288,7 @@ typedef JSValueRef
 @field attributes A logically ORed set of JSPropertyAttributes to give to the property.
 */
 typedef struct {
 @field attributes A logically ORed set of JSPropertyAttributes to give to the property.
 */
 typedef struct {
-    const char* const name;
+    const char* name;
     JSObjectGetPropertyCallback getProperty;
     JSObjectSetPropertyCallback setProperty;
     JSPropertyAttributes attributes;
     JSObjectGetPropertyCallback getProperty;
     JSObjectSetPropertyCallback setProperty;
     JSPropertyAttributes attributes;
@@ -302,7 +302,7 @@ typedef struct {
 @field attributes A logically ORed set of JSPropertyAttributes to give to the property.
 */
 typedef struct {
 @field attributes A logically ORed set of JSPropertyAttributes to give to the property.
 */
 typedef struct {
-    const char* const name;
+    const char* name;
     JSObjectCallAsFunctionCallback callAsFunction;
     JSPropertyAttributes attributes;
 } JSStaticFunction;
     JSObjectCallAsFunctionCallback callAsFunction;
     JSPropertyAttributes attributes;
 } JSStaticFunction;
index 08ef57c31f7f61c4f023ab64f7321555609ab744..574f7aaf1eb6ca96aa68bc43045de76a1dde93a8 100644 (file)
@@ -71,9 +71,6 @@ public:
     
     void swap(JSRetainPtr&);
 
     
     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;
 };
index c5c154402cb558154d5b2a82289405a428d94a3b..75d73c919094855cba65163c522002213e1dc4a0 100644 (file)
@@ -37,7 +37,7 @@
 extern "C" {
 #endif
 
 extern "C" {
 #endif
 
-#if !defined(WIN32) && !defined(_WIN32) && !defined(__WINSCW__) \
+#if !defined(WIN32) && !defined(_WIN32) \
     && !((defined(__CC_ARM) || defined(__ARMCC__)) && !defined(__linux__)) /* RVCT */
 /*!
 @typedef JSChar
     && !((defined(__CC_ARM) || defined(__ARMCC__)) && !defined(__linux__)) /* RVCT */
 /*!
 @typedef JSChar
index d1603e2210404cf3f6e0050d99c4510e9ecad2d4..9b7268a2da63009ef255d00b30cb17be98ceddb6 100644 (file)
@@ -130,9 +130,9 @@ bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsCla
     
     if (JSObject* o = jsValue.getObject()) {
         if (o->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
     
     if (JSObject* o = jsValue.getObject()) {
         if (o->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
-            return static_cast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
-        if (o->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info))
-            return static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(o)->inherits(jsClass);
+            return jsCast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
+        if (o->inherits(&JSCallbackObject<JSNonFinalObject>::s_info))
+            return jsCast<JSCallbackObject<JSNonFinalObject>*>(o)->inherits(jsClass);
     }
     return false;
 }
     }
     return false;
 }
@@ -175,7 +175,7 @@ bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObject
     JSObject* jsConstructor = toJS(constructor);
     if (!jsConstructor->structure()->typeInfo().implementsHasInstance())
         return false;
     JSObject* jsConstructor = toJS(constructor);
     if (!jsConstructor->structure()->typeInfo().implementsHasInstance())
         return false;
-    bool result = jsConstructor->hasInstance(exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown
+    bool result = jsConstructor->methodTable()->hasInstance(jsConstructor, exec, jsValue, jsConstructor->get(exec, exec->propertyNames().prototype)); // false if an exception is thrown
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
@@ -217,7 +217,7 @@ JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
     // generated internally to JavaScriptCore naturally have that representation,
     // but an external NaN might not.
     if (isnan(value))
     // generated internally to JavaScriptCore naturally have that representation,
     // but an external NaN might not.
     if (isnan(value))
-        value = NaN;
+        value = std::numeric_limits<double>::quiet_NaN();
 
     return toRef(exec, jsNumber(value));
 }
 
     return toRef(exec, jsNumber(value));
 }
@@ -235,7 +235,11 @@ JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string)
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec);
     UString str = string->ustring();
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec);
     UString str = string->ustring();
-    LiteralParser parser(exec, str.characters(), str.length(), LiteralParser::StrictJSON);
+    if (str.is8Bit()) {
+        LiteralParser<LChar> parser(exec, str.characters8(), str.length(), StrictJSON);
+        return toRef(exec, parser.tryLiteralParse());
+    }
+    LiteralParser<UChar> parser(exec, str.characters16(), str.length(), StrictJSON);
     return toRef(exec, parser.tryLiteralParse());
 }
 
     return toRef(exec, parser.tryLiteralParse());
 }
 
@@ -277,7 +281,7 @@ double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception
         if (exception)
             *exception = toRef(exec, exec->exception());
         exec->clearException();
         if (exception)
             *exception = toRef(exec, exec->exception());
         exec->clearException();
-        number = NaN;
+        number = std::numeric_limits<double>::quiet_NaN();
     }
     return number;
 }
     }
     return number;
 }
@@ -289,7 +293,7 @@ JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef*
 
     JSValue jsValue = toJS(exec, value);
     
 
     JSValue jsValue = toJS(exec, value);
     
-    RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec)));
+    RefPtr<OpaqueJSString> stringRef(OpaqueJSString::create(jsValue.toString(exec)->value(exec)));
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
index 13900cf8327b4f026e203f4a12cb58464c203a14..bdd56f60269b05d808f297f1b54c1d782885b1f7 100644 (file)
@@ -57,7 +57,7 @@ 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>::s_info) || obj->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info));
+    ASSERT(obj->inherits(&JSCallbackObject<JSGlobalObject>::s_info) || obj->inherits(&JSCallbackObject<JSNonFinalObject>::s_info));
     map->map().set(exec->globalData(), key, obj);
 }
 
     map->map().set(exec->globalData(), key, obj);
 }
 
@@ -65,7 +65,7 @@ JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* k
 {
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec);
 {
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec);
-    return toRef(static_cast<JSObject*>(map->map().get(key)));
+    return toRef(jsCast<JSObject*>(map->map().get(key)));
 }
 
 void JSWeakObjectMapRemove(JSContextRef ctx, JSWeakObjectMapRef map, void* key)
 }
 
 void JSWeakObjectMapRemove(JSContextRef ctx, JSWeakObjectMapRef map, void* key)
index 69c0962a66703b57b3384e5b1ead7bc467364caf..1c63150cf154e71c8e3a96f47ebebd86f8827977 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef OpaqueJSString_h
 #define OpaqueJSString_h
 
 #ifndef OpaqueJSString_h
 #define OpaqueJSString_h
 
+#include <wtf/ThreadSafeRefCounted.h>
 #include <runtime/UString.h>
 
 namespace JSC {
 #include <runtime/UString.h>
 
 namespace JSC {
@@ -45,7 +46,7 @@ struct OpaqueJSString : public ThreadSafeRefCounted<OpaqueJSString> {
         return adoptRef(new OpaqueJSString(characters, length));
     }
 
         return adoptRef(new OpaqueJSString(characters, length));
     }
 
-    static PassRefPtr<OpaqueJSString> create(const JSC::UString&);
+    JS_EXPORT_PRIVATE static PassRefPtr<OpaqueJSString> create(const JSC::UString&);
 
     UChar* characters() { return this ? m_characters : 0; }
     unsigned length() { return this ? m_length : 0; }
 
     UChar* characters() { return this ? m_characters : 0; }
     unsigned length() { return this ? m_length : 0; }
index 0e4f091cc79991c0959ca6c7e080b40eeb79ab0e..7846058fa42b0e335f2762a765c47796740a92ee 100644 (file)
 #endif
 
 
 #endif
 
 
+
+
+
+
+/*
+ * AVAILABLE_AFTER_WEBKIT_VERSION_5_1
+ * 
+ * Used on functions introduced after WebKit 5.1
+ */
+#define AVAILABLE_AFTER_WEBKIT_VERSION_5_1
+
+/* AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_5_1
+ *
+ * Used on declarations introduced in WebKit 1.3,
+ * but later deprecated after WebKit 5.1
+ */
+#define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_5_1
+
+
 #endif /* __WebKitAvailability__ */
 #endif /* __WebKitAvailability__ */
index d9ac0a91303264ce9dedece744a5b9c119e595aa..052c88a0216e469ad9e89128a5e1e85d339c14d2 100644 (file)
@@ -30,7 +30,7 @@
 #include "JSValueRef.h"
 #include "Node.h"
 #include "NodeList.h"
 #include "JSValueRef.h"
 #include "Node.h"
 #include "NodeList.h"
-#include "UnusedParam.h"
+#include <wtf/UnusedParam.h>
 #include <wtf/Assertions.h>
 
 static JSValueRef JSNode_appendChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 #include <wtf/Assertions.h>
 
 static JSValueRef JSNode_appendChild(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
index bc4a8ad996d491323f5573533604d5d21f505feb..0d194845e02de03ce5cbfb5639308bdee75e5d1d 100644 (file)
@@ -27,7 +27,7 @@
 #include "JSNodeList.h"
 #include "JSObjectRef.h"
 #include "JSValueRef.h"
 #include "JSNodeList.h"
 #include "JSObjectRef.h"
 #include "JSValueRef.h"
-#include "UnusedParam.h"
+#include <wtf/UnusedParam.h>
 #include <wtf/Assertions.h>
 
 static JSValueRef JSNodeList_item(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 #include <wtf/Assertions.h>
 
 static JSValueRef JSNodeList_item(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
index e82d41d77b9b62a36049a499910f7c380a75f3c4..91978bbfd50f32aa635e34ebf1fe947a8c263de8 100644 (file)
@@ -311,6 +311,16 @@ static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef objec
     return JSValueMakeNull(context);
 }
 
     return JSValueMakeNull(context);
 }
 
+static JSValueRef MyObject_convertToTypeWrapper(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception)
+{
+    UNUSED_PARAM(context);
+    UNUSED_PARAM(object);
+    UNUSED_PARAM(type);
+    UNUSED_PARAM(exception);
+    // Forward to default object class
+    return 0;
+}
+
 static bool MyObject_set_nullGetForwardSet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
 {
     UNUSED_PARAM(ctx);
 static bool MyObject_set_nullGetForwardSet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
 {
     UNUSED_PARAM(ctx);
@@ -355,14 +365,65 @@ JSClassDefinition MyObject_definition = {
     MyObject_convertToType,
 };
 
     MyObject_convertToType,
 };
 
+JSClassDefinition MyObject_convertToTypeWrapperDefinition = {
+    0,
+    kJSClassAttributeNone,
+    
+    "MyObject",
+    NULL,
+    
+    NULL,
+    NULL,
+    
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    MyObject_convertToTypeWrapper,
+};
+
+JSClassDefinition MyObject_nullWrapperDefinition = {
+    0,
+    kJSClassAttributeNone,
+    
+    "MyObject",
+    NULL,
+    
+    NULL,
+    NULL,
+    
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+};
+
 static JSClassRef MyObject_class(JSContextRef context)
 {
     UNUSED_PARAM(context);
 
     static JSClassRef jsClass;
 static JSClassRef MyObject_class(JSContextRef context)
 {
     UNUSED_PARAM(context);
 
     static JSClassRef jsClass;
-    if (!jsClass)
-        jsClass = JSClassCreate(&MyObject_definition);
-    
+    if (!jsClass) {
+        JSClassRef baseClass = JSClassCreate(&MyObject_definition);
+        MyObject_convertToTypeWrapperDefinition.parentClass = baseClass;
+        JSClassRef wrapperClass = JSClassCreate(&MyObject_convertToTypeWrapperDefinition);
+        MyObject_nullWrapperDefinition.parentClass = wrapperClass;
+        jsClass = JSClassCreate(&MyObject_nullWrapperDefinition);
+    }
+
     return jsClass;
 }
 
     return jsClass;
 }
 
@@ -617,9 +678,22 @@ static JSValueRef Base_callAsFunction(JSContextRef ctx, JSObjectRef function, JS
     return JSValueMakeNumber(ctx, 1); // distinguish base call from derived call
 }
 
     return JSValueMakeNumber(ctx, 1); // distinguish base call from derived call
 }
 
+static JSValueRef Base_returnHardNull(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    UNUSED_PARAM(ctx);
+    UNUSED_PARAM(function);
+    UNUSED_PARAM(thisObject);
+    UNUSED_PARAM(argumentCount);
+    UNUSED_PARAM(arguments);
+    UNUSED_PARAM(exception);
+    
+    return 0; // should convert to undefined!
+}
+
 static JSStaticFunction Base_staticFunctions[] = {
     { "baseProtoDup", NULL, kJSPropertyAttributeNone },
     { "baseProto", Base_callAsFunction, kJSPropertyAttributeNone },
 static JSStaticFunction Base_staticFunctions[] = {
     { "baseProtoDup", NULL, kJSPropertyAttributeNone },
     { "baseProto", Base_callAsFunction, kJSPropertyAttributeNone },
+    { "baseHardNull", Base_returnHardNull, kJSPropertyAttributeNone },
     { 0, 0, 0 }
 };
 
     { 0, 0, 0 }
 };
 
@@ -791,6 +865,17 @@ static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjec
     return result;
 }
 
     return result;
 }
 
+static JSObjectRef myBadConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    UNUSED_PARAM(context);
+    UNUSED_PARAM(constructorObject);
+    UNUSED_PARAM(argumentCount);
+    UNUSED_PARAM(arguments);
+    UNUSED_PARAM(exception);
+    
+    return 0;
+}
+
 
 static void globalObject_initialize(JSContextRef context, JSObjectRef object)
 {
 
 static void globalObject_initialize(JSContextRef context, JSObjectRef object)
 {
@@ -937,6 +1022,14 @@ static bool checkForCycleInPrototypeChain()
     return result;
 }
 
     return result;
 }
 
+static void checkConstnessInJSObjectNames()
+{
+    JSStaticFunction fun;
+    fun.name = "something";
+    JSStaticValue val;
+    val.name = "something";
+}
+
 int main(int argc, char* argv[])
 {
 #if OS(WINDOWS)
 int main(int argc, char* argv[])
 {
 #if OS(WINDOWS)
@@ -1254,6 +1347,8 @@ int main(int argc, char* argv[])
     assertEqualsAsUTF8String(jsCFEmptyString, "");
     assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters, "");
     
     assertEqualsAsUTF8String(jsCFEmptyString, "");
     assertEqualsAsUTF8String(jsCFEmptyStringWithCharacters, "");
     
+    checkConstnessInJSObjectNames();
+    
     ASSERT(JSValueIsStrictEqual(context, jsTrue, jsTrue));
     ASSERT(!JSValueIsStrictEqual(context, jsOne, jsOneString));
 
     ASSERT(JSValueIsStrictEqual(context, jsTrue, jsTrue));
     ASSERT(!JSValueIsStrictEqual(context, jsOne, jsOneString));
 
@@ -1356,7 +1451,7 @@ int main(int argc, char* argv[])
     function = JSObjectMakeFunction(context, foo, 1, argumentNames, functionBody, NULL, 1, &exception);
     ASSERT(function && !exception);
     JSValueRef arguments[] = { JSValueMakeNumber(context, 2) };
     function = JSObjectMakeFunction(context, foo, 1, argumentNames, functionBody, NULL, 1, &exception);
     ASSERT(function && !exception);
     JSValueRef arguments[] = { JSValueMakeNumber(context, 2) };
-    v = JSObjectCallAsFunction(context, function, NULL, 1, arguments, &exception);
+    JSObjectCallAsFunction(context, function, NULL, 1, arguments, &exception);
     JSStringRelease(foo);
     JSStringRelease(functionBody);
     
     JSStringRelease(foo);
     JSStringRelease(functionBody);
     
@@ -1377,6 +1472,11 @@ int main(int argc, char* argv[])
     JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL);
     JSStringRelease(myConstructorIString);
     
     JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL);
     JSStringRelease(myConstructorIString);
     
+    JSStringRef myBadConstructorIString = JSStringCreateWithUTF8CString("MyBadConstructor");
+    JSObjectRef myBadConstructor = JSObjectMakeConstructor(context, NULL, myBadConstructor_callAsConstructor);
+    JSObjectSetProperty(context, globalObject, myBadConstructorIString, myBadConstructor, kJSPropertyAttributeNone, NULL);
+    JSStringRelease(myBadConstructorIString);
+    
     ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1));
     ASSERT(!JSObjectGetPrivate(myConstructor));
     
     ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1));
     ASSERT(!JSObjectGetPrivate(myConstructor));
     
@@ -1483,7 +1583,7 @@ int main(int argc, char* argv[])
     // an assert inside putDirect or lead to a crash during GC. <https://bugs.webkit.org/show_bug.cgi?id=25785>
     nullDefinition = kJSClassDefinitionEmpty;
     nullClass = JSClassCreate(&nullDefinition);
     // an assert inside putDirect or lead to a crash during GC. <https://bugs.webkit.org/show_bug.cgi?id=25785>
     nullDefinition = kJSClassDefinitionEmpty;
     nullClass = JSClassCreate(&nullDefinition);
-    myConstructor = JSObjectMakeConstructor(context, nullClass, 0);
+    JSObjectMakeConstructor(context, nullClass, 0);
     JSClassRelease(nullClass);
 
     char* scriptUTF8 = createStringWithContentsOfFile(scriptPath);
     JSClassRelease(nullClass);
 
     char* scriptUTF8 = createStringWithContentsOfFile(scriptPath);
index 61d4533e84f4bde092983e5429cfd924aeb1764e..28fa5443393558043cc2166f6e2cd6efb34615c5 100644 (file)
@@ -154,9 +154,11 @@ shouldBe("MyObject()", undefined);
 shouldBe("typeof myObject", "object");
 shouldBe("MyObject ? 1 : 0", true); // toBoolean
 shouldBe("+MyObject", 1); // toNumber
 shouldBe("typeof myObject", "object");
 shouldBe("MyObject ? 1 : 0", true); // toBoolean
 shouldBe("+MyObject", 1); // toNumber
+shouldBe("(Object.prototype.toString.call(MyObject))", "[object MyObject]"); // Object.prototype.toString
 shouldBe("(MyObject.toString())", "[object MyObject]"); // toString
 shouldBe("(MyObject.toString())", "[object MyObject]"); // toString
-shouldBe("String(MyObject)", "MyObjectAsString"); // type conversion to string
+shouldBe("String(MyObject)", "MyObjectAsString"); // toString
 shouldBe("MyObject - 0", 1); // toNumber
 shouldBe("MyObject - 0", 1); // toNumber
+shouldBe("MyObject.valueOf()", 1); // valueOf
 
 shouldBe("typeof MyConstructor", "object");
 constructedObject = new MyConstructor(1);
 
 shouldBe("typeof MyConstructor", "object");
 constructedObject = new MyConstructor(1);
@@ -165,6 +167,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("new MyBadConstructor()");
+
 MyObject.nullGetSet = 1;
 shouldBe("MyObject.nullGetSet", 1);
 shouldThrow("MyObject.nullCall()");
 MyObject.nullGetSet = 1;
 shouldBe("MyObject.nullGetSet", 1);
 shouldThrow("MyObject.nullCall()");
@@ -184,6 +188,8 @@ shouldBe("derived.protoOnly()", 2);
 shouldBe("derived.protoDup", 2);
 shouldBe("derived.derivedOnly", 2)
 
 shouldBe("derived.protoDup", 2);
 shouldBe("derived.derivedOnly", 2)
 
+shouldBe("derived.baseHardNull()", undefined)
+
 // base properties throw 1 when set; derived, 2
 shouldBe("derived.baseDup = 0", 2);
 shouldBe("derived.baseOnly = 0", 1);
 // base properties throw 1 when set; derived, 2
 shouldBe("derived.baseDup = 0", 2);
 shouldBe("derived.baseOnly = 0", 1);
index 870b15e347ce0230c24efc0b5c57115e3a179f2f..bf48f970d5a315556db1dd11dca5c8145c7d0ac2 100644 (file)
@@ -6,16 +6,20 @@ SET(JavaScriptCore_INCLUDE_DIRECTORIES
     "${JAVASCRIPTCORE_DIR}/assembler"
     "${JAVASCRIPTCORE_DIR}/bytecode"
     "${JAVASCRIPTCORE_DIR}/bytecompiler"
     "${JAVASCRIPTCORE_DIR}/assembler"
     "${JAVASCRIPTCORE_DIR}/bytecode"
     "${JAVASCRIPTCORE_DIR}/bytecompiler"
+    "${JAVASCRIPTCORE_DIR}/dfg"
     "${JAVASCRIPTCORE_DIR}/heap"
     "${JAVASCRIPTCORE_DIR}/debugger"
     "${JAVASCRIPTCORE_DIR}/interpreter"
     "${JAVASCRIPTCORE_DIR}/jit"
     "${JAVASCRIPTCORE_DIR}/heap"
     "${JAVASCRIPTCORE_DIR}/debugger"
     "${JAVASCRIPTCORE_DIR}/interpreter"
     "${JAVASCRIPTCORE_DIR}/jit"
+    "${JAVASCRIPTCORE_DIR}/llint"
     "${JAVASCRIPTCORE_DIR}/parser"
     "${JAVASCRIPTCORE_DIR}/profiler"
     "${JAVASCRIPTCORE_DIR}/runtime"
     "${JAVASCRIPTCORE_DIR}/parser"
     "${JAVASCRIPTCORE_DIR}/profiler"
     "${JAVASCRIPTCORE_DIR}/runtime"
+    "${JAVASCRIPTCORE_DIR}/tools"
     "${JAVASCRIPTCORE_DIR}/yarr"
     "${JAVASCRIPTCORE_DIR}/yarr"
-    "${WTF_INCLUDE_DIRECTORIES}"
-    "${CMAKE_SOURCE_DIR}"
+    "${WTF_DIR}"
+    "${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}"
+    "${CMAKE_SOURCE_DIR}/Source"
 )
 
 SET(JavaScriptCore_SOURCES
 )
 
 SET(JavaScriptCore_SOURCES
@@ -32,38 +36,88 @@ SET(JavaScriptCore_SOURCES
     API/JSWeakObjectMapRefPrivate.cpp
     API/OpaqueJSString.cpp
 
     API/JSWeakObjectMapRefPrivate.cpp
     API/OpaqueJSString.cpp
 
+    bytecode/CallLinkInfo.cpp
+    bytecode/CallLinkStatus.cpp
     bytecode/CodeBlock.cpp
     bytecode/CodeBlock.cpp
+    bytecode/DFGExitProfile.cpp
+    bytecode/ExecutionCounter.cpp
+    bytecode/GetByIdStatus.cpp
     bytecode/JumpTable.cpp
     bytecode/JumpTable.cpp
+    bytecode/LazyOperandValueProfile.cpp
+    bytecode/MethodCallLinkInfo.cpp
+    bytecode/MethodCallLinkStatus.cpp
+    bytecode/MethodOfGettingAValueProfile.cpp
     bytecode/Opcode.cpp
     bytecode/Opcode.cpp
+    bytecode/PolymorphicPutByIdList.cpp
+    bytecode/PredictedType.cpp
+    bytecode/PutByIdStatus.cpp
     bytecode/SamplingTool.cpp
     bytecode/StructureStubInfo.cpp
 
     bytecompiler/BytecodeGenerator.cpp
     bytecompiler/NodesCodegen.cpp
 
     bytecode/SamplingTool.cpp
     bytecode/StructureStubInfo.cpp
 
     bytecompiler/BytecodeGenerator.cpp
     bytecompiler/NodesCodegen.cpp
 
-    heap/Heap.cpp
-    heap/HandleHeap.cpp
+    dfg/DFGAbstractState.cpp
+    dfg/DFGAssemblyHelpers.cpp
+    dfg/DFGByteCodeParser.cpp
+    dfg/DFGCapabilities.cpp
+    dfg/DFGCFAPhase.cpp
+    dfg/DFGCorrectableJumpPoint.cpp
+    dfg/DFGCSEPhase.cpp
+    dfg/DFGDriver.cpp
+    dfg/DFGFixupPhase.cpp
+    dfg/DFGGraph.cpp
+    dfg/DFGJITCompiler.cpp
+    dfg/DFGNodeFlags.cpp
+    dfg/DFGOSREntry.cpp
+    dfg/DFGOSRExit.cpp
+    dfg/DFGOSRExitCompiler.cpp
+    dfg/DFGOSRExitCompiler32_64.cpp
+    dfg/DFGOSRExitCompiler64.cpp
+    dfg/DFGOperations.cpp
+    dfg/DFGPhase.cpp
+    dfg/DFGPredictionPropagationPhase.cpp
+    dfg/DFGRedundantPhiEliminationPhase.cpp
+    dfg/DFGRepatch.cpp
+    dfg/DFGSpeculativeJIT.cpp
+    dfg/DFGSpeculativeJIT32_64.cpp
+    dfg/DFGSpeculativeJIT64.cpp
+    dfg/DFGThunks.cpp
+    dfg/DFGVirtualRegisterAllocationPhase.cpp
+
+    heap/BlockAllocator.cpp
+    heap/CopiedSpace.cpp
+    heap/ConservativeRoots.cpp
+    heap/DFGCodeBlocks.cpp
+    heap/HandleSet.cpp
     heap/HandleStack.cpp
     heap/HandleStack.cpp
+    heap/Heap.cpp
     heap/MachineStackMarker.cpp
     heap/MachineStackMarker.cpp
+    heap/MarkedAllocator.cpp
     heap/MarkedBlock.cpp
     heap/MarkedSpace.cpp
     heap/MarkedBlock.cpp
     heap/MarkedSpace.cpp
-    heap/ConservativeRoots.cpp
     heap/MarkStack.cpp
     heap/MarkStack.cpp
+    heap/WeakSet.cpp
+    heap/WeakHandleOwner.cpp
+    heap/WeakBlock.cpp
 
     debugger/Debugger.cpp
     debugger/DebuggerActivation.cpp
     debugger/DebuggerCallFrame.cpp
 
     debugger/Debugger.cpp
     debugger/DebuggerActivation.cpp
     debugger/DebuggerCallFrame.cpp
-
+    
+    interpreter/AbstractPC.cpp
     interpreter/CallFrame.cpp
     interpreter/Interpreter.cpp
     interpreter/RegisterFile.cpp
 
     jit/ExecutableAllocator.cpp
     interpreter/CallFrame.cpp
     interpreter/Interpreter.cpp
     interpreter/RegisterFile.cpp
 
     jit/ExecutableAllocator.cpp
+    jit/HostCallReturnValue.cpp
     jit/JITArithmetic32_64.cpp
     jit/JITArithmetic.cpp
     jit/JITCall32_64.cpp
     jit/JITCall.cpp
     jit/JIT.cpp
     jit/JITArithmetic32_64.cpp
     jit/JITArithmetic.cpp
     jit/JITCall32_64.cpp
     jit/JITCall.cpp
     jit/JIT.cpp
+    jit/JITExceptions.cpp
     jit/JITOpcodes32_64.cpp
     jit/JITOpcodes.cpp
     jit/JITPropertyAccess32_64.cpp
     jit/JITOpcodes32_64.cpp
     jit/JITOpcodes.cpp
     jit/JITPropertyAccess32_64.cpp
@@ -71,7 +125,6 @@ SET(JavaScriptCore_SOURCES
     jit/JITStubs.cpp
     jit/ThunkGenerators.cpp
 
     jit/JITStubs.cpp
     jit/ThunkGenerators.cpp
 
-    parser/JSParser.cpp
     parser/Lexer.cpp
     parser/Nodes.cpp
     parser/Parser.cpp
     parser/Lexer.cpp
     parser/Nodes.cpp
     parser/Parser.cpp
@@ -114,24 +167,25 @@ SET(JavaScriptCore_SOURCES
     runtime/JSActivation.cpp
     runtime/JSAPIValueWrapper.cpp
     runtime/JSArray.cpp
     runtime/JSActivation.cpp
     runtime/JSAPIValueWrapper.cpp
     runtime/JSArray.cpp
-    runtime/JSByteArray.cpp
     runtime/JSCell.cpp
     runtime/JSCell.cpp
+    runtime/JSDateMath.cpp
     runtime/JSFunction.cpp
     runtime/JSFunction.cpp
+    runtime/JSBoundFunction.cpp
     runtime/JSGlobalData.cpp
     runtime/JSGlobalObject.cpp
     runtime/JSGlobalObjectFunctions.cpp
     runtime/JSGlobalData.cpp
     runtime/JSGlobalObject.cpp
     runtime/JSGlobalObjectFunctions.cpp
+    runtime/JSGlobalThis.cpp
     runtime/JSLock.cpp
     runtime/JSNotAnObject.cpp
     runtime/JSObject.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/JSONObject.cpp
     runtime/JSPropertyNameIterator.cpp
     runtime/JSStaticScopeObject.cpp
     runtime/JSString.cpp
+    runtime/JSStringJoiner.cpp
     runtime/JSValue.cpp
     runtime/JSVariableObject.cpp
     runtime/JSWrapperObject.cpp
     runtime/JSValue.cpp
     runtime/JSVariableObject.cpp
     runtime/JSWrapperObject.cpp
-    runtime/JSZombie.cpp
     runtime/LiteralParser.cpp
     runtime/Lookup.cpp
     runtime/MathObject.cpp
     runtime/LiteralParser.cpp
     runtime/Lookup.cpp
     runtime/MathObject.cpp
@@ -143,15 +197,17 @@ SET(JavaScriptCore_SOURCES
     runtime/ObjectConstructor.cpp
     runtime/ObjectPrototype.cpp
     runtime/Operations.cpp
     runtime/ObjectConstructor.cpp
     runtime/ObjectPrototype.cpp
     runtime/Operations.cpp
+    runtime/Options.cpp
     runtime/PropertyDescriptor.cpp
     runtime/PropertyNameArray.cpp
     runtime/PropertySlot.cpp
     runtime/RegExp.cpp
     runtime/RegExpCache.cpp
     runtime/RegExpConstructor.cpp
     runtime/PropertyDescriptor.cpp
     runtime/PropertyNameArray.cpp
     runtime/PropertySlot.cpp
     runtime/RegExp.cpp
     runtime/RegExpCache.cpp
     runtime/RegExpConstructor.cpp
+    runtime/RegExpCachedResult.cpp
+    runtime/RegExpMatchesArray.cpp
     runtime/RegExpObject.cpp
     runtime/RegExpPrototype.cpp
     runtime/RegExpObject.cpp
     runtime/RegExpPrototype.cpp
-    runtime/RopeImpl.cpp
     runtime/ScopeChain.cpp
     runtime/SmallStrings.cpp
     runtime/StrictEvalActivation.cpp
     runtime/ScopeChain.cpp
     runtime/SmallStrings.cpp
     runtime/StrictEvalActivation.cpp
@@ -164,16 +220,15 @@ SET(JavaScriptCore_SOURCES
     runtime/TimeoutChecker.cpp
     runtime/UString.cpp
 
     runtime/TimeoutChecker.cpp
     runtime/UString.cpp
 
+    tools/CodeProfile.cpp
+    tools/CodeProfiling.cpp
+
+    yarr/YarrCanonicalizeUCS2.cpp
     yarr/YarrPattern.cpp
     yarr/YarrInterpreter.cpp
     yarr/YarrJIT.cpp
     yarr/YarrSyntaxChecker.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
 
 SET(JavaScriptCore_LUT_FILES
     runtime/ArrayConstructor.cpp
@@ -244,10 +299,9 @@ ELSE ()
 ENDIF ()
 
 
 ENDIF ()
 
 
-INCLUDE_IF_EXISTS(${JAVASCRIPTCORE_DIR}/CMakeLists${PORT}.txt)
+WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS()
 
 
 
 
-ADD_SUBDIRECTORY(wtf)
 ADD_SUBDIRECTORY(shell)
 
 WEBKIT_WRAP_SOURCELIST(${JavaScriptCore_SOURCES})
 ADD_SUBDIRECTORY(shell)
 
 WEBKIT_WRAP_SOURCELIST(${JavaScriptCore_SOURCES})
@@ -255,6 +309,8 @@ 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})
 ADD_DEFINITIONS(-DBUILDING_JavaScriptCore)
 ADD_LIBRARY(${JavaScriptCore_LIBRARY_NAME} ${JavaScriptCore_LIBRARY_TYPE} ${JavaScriptCore_HEADERS} ${JavaScriptCore_SOURCES})
 TARGET_LINK_LIBRARIES(${JavaScriptCore_LIBRARY_NAME} ${JavaScriptCore_LIBRARIES})
+SET_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} PROPERTIES FOLDER "JavaScriptCore")
+SET_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "")
 
 IF (JavaScriptCore_LINK_FLAGS)
     ADD_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} LINK_FLAGS "${JavaScriptCore_LINK_FLAGS}")
 
 IF (JavaScriptCore_LINK_FLAGS)
     ADD_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} LINK_FLAGS "${JavaScriptCore_LINK_FLAGS}")
@@ -262,5 +318,5 @@ ENDIF ()
 
 IF (SHARED_CORE)
     SET_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
 
 IF (SHARED_CORE)
     SET_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
-    INSTALL(TARGETS ${JavaScriptCore_LIBRARY_NAME} DESTINATION lib)
+    INSTALL(TARGETS ${JavaScriptCore_LIBRARY_NAME} DESTINATION "${LIB_INSTALL_DIR}")
 ENDIF ()
 ENDIF ()
diff --git a/CMakeListsEfl.txt b/CMakeListsEfl.txt
deleted file mode 100644 (file)
index cdc3fe2..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-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
deleted file mode 100644 (file)
index d878863..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-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 80af4b6d506d551a096bc272b2ea3ece4716fae6..90e099d18d5920a1024d74d0e7c629e5f8dd393c 100644 (file)
@@ -43,8 +43,6 @@ all : \
     ErrorPrototype.lut.h \
     HeaderDetection.h \
     JSONObject.lut.h \
     ErrorPrototype.lut.h \
     HeaderDetection.h \
     JSONObject.lut.h \
-    JavaScriptCore.JSVALUE32_64.exp \
-    JavaScriptCore.JSVALUE64.exp \
     JSGlobalObject.lut.h \
     KeywordLookup.h \
     Lexer.lut.h \
     JSGlobalObject.lut.h \
     KeywordLookup.h \
     Lexer.lut.h \
@@ -80,15 +78,6 @@ RegExpJitTables.h: create_regex_tables
 KeywordLookup.h: KeywordLookupGenerator.py Keywords.table
        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)
 # header detection
 
 ifeq ($(OS),MACOS)
diff --git a/DerivedSources.pri b/DerivedSources.pri
new file mode 100644 (file)
index 0000000..755a5b0
--- /dev/null
@@ -0,0 +1,81 @@
+# -------------------------------------------------------------------
+# Derived sources for JavaScriptSource
+#
+# See 'Tools/qmake/README' for an overview of the build system
+# -------------------------------------------------------------------
+
+TEMPLATE = derived
+
+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 \
+
+KEYWORDLUT_FILES += \
+    parser/Keywords.table
+
+JIT_STUB_FILES += \
+    jit/JITStubs.cpp
+
+# GENERATOR 1-A: LUT creator
+lut.output = ${QMAKE_FILE_BASE}.lut.h
+lut.input = LUT_FILES
+lut.script = $$PWD/create_hash_table
+lut.commands = perl $$lut.script ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
+lut.depends = ${QMAKE_FILE_NAME}
+GENERATORS += lut
+
+# GENERATOR 1-B: particular LUT creator (for 1 file only)
+keywordlut.output = Lexer.lut.h
+keywordlut.input = KEYWORDLUT_FILES
+keywordlut.script = $$PWD/create_hash_table
+keywordlut.commands = perl $$keywordlut.script ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
+keywordlut.depends = ${QMAKE_FILE_NAME}
+GENERATORS += keywordlut
+
+# GENERATOR 2-A: JIT Stub functions for RVCT
+rvctstubs.output = Generated${QMAKE_FILE_BASE}_RVCT.h
+rvctstubs.script = $$PWD/create_jit_stubs
+rvctstubs.commands = perl -i $$rvctstubs.script --prefix RVCT ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT}
+rvctstubs.depends = ${QMAKE_FILE_NAME}
+rvctstubs.input = JIT_STUB_FILES
+rvctstubs.CONFIG += no_link
+GENERATORS += rvctstubs
+
+# GENERATOR 2-B: JIT Stub functions for MSVC
+msvcstubs.output = Generated${QMAKE_FILE_BASE}_MSVC.asm
+msvcstubs.script = $$PWD/create_jit_stubs
+msvcstubs.commands = perl -i $$msvcstubs.script --prefix MSVC ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT}
+msvcstubs.depends = ${QMAKE_FILE_NAME}
+msvcstubs.input = JIT_STUB_FILES
+msvcstubs.CONFIG += no_link
+GENERATORS += msvcstubs
+
+#GENERATOR: "RegExpJitTables.h": tables used by Yarr
+retgen.output = RegExpJitTables.h
+retgen.script = $$PWD/create_regex_tables
+retgen.input = retgen.script
+retgen.commands = python $$retgen.script > ${QMAKE_FILE_OUT}
+GENERATORS += retgen
+
+#GENERATOR: "KeywordLookup.h": decision tree used by the lexer
+klgen.output = KeywordLookup.h
+klgen.script = $$PWD/KeywordLookupGenerator.py
+klgen.input = KEYWORDLUT_FILES
+klgen.commands = python $$klgen.script ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT}
+GENERATORS += klgen
diff --git a/DerivedSources.pro b/DerivedSources.pro
deleted file mode 100644 (file)
index 0989605..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-# DerivedSources - qmake build info
-
-CONFIG -= debug_and_release
-
-TEMPLATE = lib
-TARGET = dummy
-
-QMAKE_EXTRA_TARGETS += generated_files
-
-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
-}
-
-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 \
-
-KEYWORDLUT_FILES += \
-    parser/Keywords.table
-
-JIT_STUB_FILES += \
-    jit/JITStubs.cpp
-
-defineTest(addExtraCompiler) {
-    eval($${1}.CONFIG = target_predeps no_link)
-    eval($${1}.variable_out =)
-    eval($${1}.dependency_type = TYPE_C)
-
-    wkScript = $$eval($${1}.wkScript)
-    eval($${1}.depends += $$wkScript)
-
-    export($${1}.CONFIG)
-    export($${1}.variable_out)
-    export($${1}.dependency_type)
-    export($${1}.depends)
-
-    QMAKE_EXTRA_COMPILERS += $$1
-    generated_files.depends += compiler_$${1}_make_all
-    export(QMAKE_EXTRA_COMPILERS)
-    export(generated_files.depends)
-    return(true)
-}
-
-# GENERATOR 1-A: LUT creator
-lut.output = $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.lut.h
-lut.input = LUT_FILES
-lut.wkScript = $$PWD/create_hash_table
-lut.commands = perl $$lut.wkScript ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
-lut.depends = ${QMAKE_FILE_NAME}
-addExtraCompiler(lut)
-
-# GENERATOR 1-B: particular LUT creator (for 1 file only)
-keywordlut.output = $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}Lexer.lut.h
-keywordlut.input = KEYWORDLUT_FILES
-keywordlut.wkScript = $$PWD/create_hash_table
-keywordlut.commands = perl $$keywordlut.wkScript ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT}
-keywordlut.depends = ${QMAKE_FILE_NAME}
-addExtraCompiler(keywordlut)
-
-# GENERATOR 2-A: JIT Stub functions for RVCT
-rvctstubs.output = $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}Generated${QMAKE_FILE_BASE}_RVCT.h
-rvctstubs.wkScript = $$PWD/create_jit_stubs
-rvctstubs.commands = perl -i $$rvctstubs.wkScript --prefix RVCT ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT}
-rvctstubs.depends = ${QMAKE_FILE_NAME}
-rvctstubs.input = JIT_STUB_FILES
-rvctstubs.CONFIG += no_link
-addExtraCompiler(rvctstubs)
-
-# 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
-retgen.wkScript = $$PWD/create_regex_tables 
-retgen.input = retgen.wkScript
-retgen.commands = python $$retgen.wkScript > ${QMAKE_FILE_OUT}
-addExtraCompiler(retgen)
-
-#GENERATOR: "KeywordLookup.h": decision tree used by the lexer
-klgen.output = $$JSC_GENERATED_SOURCES_DIR/KeywordLookup.h
-klgen.wkScript = $$PWD/KeywordLookupGenerator.py 
-klgen.input = KEYWORDLUT_FILES
-klgen.commands = python $$klgen.wkScript ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT}
-addExtraCompiler(klgen)
index c710d2aba427dee3ca4c429c426e3d89095f706f..e84528763ee365a0afcdfb93cd56db181a65ea62 100644 (file)
@@ -16,17 +16,18 @@ nodist_EXTRA_libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_M
 nodist_libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOURCES = \
        $(javascriptcore_built_sources)
 
 nodist_libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOURCES = \
        $(javascriptcore_built_sources)
 
-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@_ladir = $(libwebkitgtkincludedir)/JavaScriptCore
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_HEADERS = $(javascriptcore_h_api)
 
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOURCES = \
        $(javascriptcore_sources)
 
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_LIBADD = \
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_HEADERS = $(javascriptcore_h_api)
 
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOURCES = \
        $(javascriptcore_sources)
 
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_LIBADD = \
+       -lpthread \
+       libWTF.la \
        $(UNICODE_LIBS) \
        $(GLIB_LIBS) \
        $(UNICODE_LIBS) \
        $(GLIB_LIBS) \
-       $(WINMM_LIBS) \
-       -lpthread
+       $(WINMM_LIBS)
 
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CXXFLAGS = \
        $(global_cxxflags) \
 
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CXXFLAGS = \
        $(global_cxxflags) \
@@ -35,51 +36,57 @@ libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CFLAGS = \
        -fstrict-aliasing \
        -O3 \
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CFLAGS = \
        -fstrict-aliasing \
        -O3 \
-       $(global_cflags) \
-       $(GLIB_CFLAGS) \
-       $(UNICODE_CFLAGS)
+       $(javascriptcore_cflags)
 
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CPPFLAGS = \
        $(global_cppflags) \
        $(javascriptcore_cppflags)
 
 javascriptcore_cppflags += \
 
 libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CPPFLAGS = \
        $(global_cppflags) \
        $(javascriptcore_cppflags)
 
 javascriptcore_cppflags += \
+       $(JSC_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 \
        -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/dfg \
        -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/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/llint \
        -I$(srcdir)/Source/JavaScriptCore/parser \
        -I$(srcdir)/Source/JavaScriptCore/profiler \
        -I$(srcdir)/Source/JavaScriptCore/runtime \
        -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/tools \
        -I$(srcdir)/Source/JavaScriptCore/yarr \
        -I$(srcdir)/Source/JavaScriptCore/yarr \
-       -I$(top_builddir)/Source/JavaScriptCore \
-       -I$(top_builddir)/Source/JavaScriptCore/parser \
-       -I$(top_builddir)/Source/JavaScriptCore/runtime
+       -I$(top_builddir)/DerivedSources/JavaScriptCore
+
+javascriptcore_cppflags += \
+       -I$(srcdir)/Source/WTF
 
 
-Source/JavaScriptCore/Lexer.lut.h: $(srcdir)/Source/JavaScriptCore/create_hash_table $(srcdir)/Source/JavaScriptCore/parser/Keywords.table
+javascriptcore_cflags += \
+       $(global_cflags) \
+       $(GLIB_CFLAGS) \
+       $(UNICODE_CFLAGS)
+
+pkgconfig_DATA += Source/JavaScriptCore/javascriptcoregtk-@WEBKITGTK_API_VERSION@.pc
+
+$(shell mkdir -p DerivedSources/JavaScriptCore)
+
+DerivedSources/JavaScriptCore/Lexer.lut.h: $(srcdir)/Source/JavaScriptCore/create_hash_table $(srcdir)/Source/JavaScriptCore/parser/Keywords.table
        $(AM_V_GEN)$(PERL) $^ > $@
 
        $(AM_V_GEN)$(PERL) $^ > $@
 
-Source/JavaScriptCore/%.lut.h: $(srcdir)/Source/JavaScriptCore/create_hash_table $(srcdir)/Source/JavaScriptCore/%.cpp
+DerivedSources/JavaScriptCore/%.lut.h: $(srcdir)/Source/JavaScriptCore/create_hash_table $(srcdir)/Source/JavaScriptCore/runtime/%.cpp
        $(AM_V_GEN)$(PERL) $^ -i > $@
 
        $(AM_V_GEN)$(PERL) $^ -i > $@
 
-Source/JavaScriptCore/RegExpJitTables.h: $(srcdir)/Source/JavaScriptCore/create_regex_tables
+DerivedSources/JavaScriptCore/RegExpJitTables.h: $(srcdir)/Source/JavaScriptCore/create_regex_tables
        $(AM_V_GEN)$(PYTHON) $^ > $@
 
        $(AM_V_GEN)$(PYTHON) $^ > $@
 
-Source/JavaScriptCore/KeywordLookup.h: $(srcdir)/Source/JavaScriptCore/KeywordLookupGenerator.py $(srcdir)/Source/JavaScriptCore/parser/Keywords.table
+DerivedSources/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)
        $(AM_V_GEN)$(PYTHON) $^ > $@
 
 jsc: $(javascriptcore_built_nosources) Programs/jsc$(EXEEXT)
@@ -142,32 +149,15 @@ EXTRA_DIST += \
        Source/JavaScriptCore/create_regex_tables \
        Source/JavaScriptCore/icu/LICENSE \
        Source/JavaScriptCore/icu/README \
        Source/JavaScriptCore/create_regex_tables \
        Source/JavaScriptCore/icu/LICENSE \
        Source/JavaScriptCore/icu/README \
+       Source/JavaScriptCore/KeywordLookupGenerator.py \
        Source/JavaScriptCore/parser/Keywords.table \
        Source/JavaScriptCore/THANKS
 
        Source/JavaScriptCore/parser/Keywords.table \
        Source/JavaScriptCore/THANKS
 
-# Clean rules for JavaScriptCore
-# FIXME: Should this list be generated from javascriptcore_built_nosources?
 CLEANFILES += \
 CLEANFILES += \
-       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_built_nosources) \
        Programs/jsc \
        Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@ \
        Programs/minidom
        Programs/jsc \
        Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@ \
        Programs/minidom
+
+DISTCLEANFILES += \
+       $(top_builddir)/Source/JavaScriptCore/javascriptcoregtk-@WEBKITGTK_API_VERSION@.pc
index e33c2a46ebb045de383efa1761e001cc25e16d2e..b79bc53c4645e0d887d57b3a60221c8b102b4021 100644 (file)
@@ -11,26 +11,27 @@ javascriptcore_h_api += \
        Source/JavaScriptCore/API/WebKitAvailability.h
 
 javascriptcore_built_nosources += \
        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
+       DerivedSources/JavaScriptCore/KeywordLookup.h \
+       DerivedSources/JavaScriptCore/Lexer.lut.h \
+       DerivedSources/JavaScriptCore/RegExpJitTables.h \
+       DerivedSources/JavaScriptCore/ArrayConstructor.lut.h \
+       DerivedSources/JavaScriptCore/ArrayPrototype.lut.h \
+       DerivedSources/JavaScriptCore/BooleanPrototype.lut.h \
+       DerivedSources/JavaScriptCore/DateConstructor.lut.h \
+       DerivedSources/JavaScriptCore/DatePrototype.lut.h \
+       DerivedSources/JavaScriptCore/ErrorPrototype.lut.h \
+       DerivedSources/JavaScriptCore/JSGlobalObject.lut.h \
+       DerivedSources/JavaScriptCore/JSONObject.lut.h \
+       DerivedSources/JavaScriptCore/MathObject.lut.h \
+       DerivedSources/JavaScriptCore/NumberConstructor.lut.h \
+       DerivedSources/JavaScriptCore/NumberPrototype.lut.h \
+       DerivedSources/JavaScriptCore/ObjectConstructor.lut.h \
+       DerivedSources/JavaScriptCore/ObjectPrototype.lut.h \
+       DerivedSources/JavaScriptCore/RegExpConstructor.lut.h \
+       DerivedSources/JavaScriptCore/RegExpObject.lut.h \
+       DerivedSources/JavaScriptCore/RegExpPrototype.lut.h \
+       DerivedSources/JavaScriptCore/StringConstructor.lut.h \
+       DerivedSources/JavaScriptCore/StringPrototype.lut.h
 
 javascriptcore_sources += \
        Source/JavaScriptCore/API/APICast.h \
 
 javascriptcore_sources += \
        Source/JavaScriptCore/API/APICast.h \
@@ -65,65 +66,212 @@ javascriptcore_sources += \
        Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h \
        Source/JavaScriptCore/assembler/CodeLocation.h \
        Source/JavaScriptCore/assembler/LinkBuffer.h \
        Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h \
        Source/JavaScriptCore/assembler/CodeLocation.h \
        Source/JavaScriptCore/assembler/LinkBuffer.h \
+       Source/JavaScriptCore/assembler/MacroAssembler.h \
        Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp \
        Source/JavaScriptCore/assembler/MacroAssemblerARM.h \
        Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h \
        Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.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/MacroAssemblerMIPS.h \
        Source/JavaScriptCore/assembler/MacroAssemblerSH4.cpp \
        Source/JavaScriptCore/assembler/MacroAssemblerSH4.cpp \
-       Source/JavaScriptCore/assembler/SH4Assembler.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerSH4.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerX86.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h \
+       Source/JavaScriptCore/assembler/MIPSAssembler.h \
        Source/JavaScriptCore/assembler/RepatchBuffer.h \
        Source/JavaScriptCore/assembler/RepatchBuffer.h \
+       Source/JavaScriptCore/assembler/SH4Assembler.h \
        Source/JavaScriptCore/assembler/X86Assembler.h \
        Source/JavaScriptCore/assembler/X86Assembler.h \
+       Source/JavaScriptCore/bytecode/BytecodeConventions.h \
+       Source/JavaScriptCore/bytecode/CallLinkInfo.cpp \
+       Source/JavaScriptCore/bytecode/CallLinkInfo.h \
+       Source/JavaScriptCore/bytecode/CallLinkStatus.cpp \
+       Source/JavaScriptCore/bytecode/CallLinkStatus.h \
+       Source/JavaScriptCore/bytecode/CallReturnOffsetToBytecodeOffset.h \
+       Source/JavaScriptCore/bytecode/CodeType.h \
        Source/JavaScriptCore/bytecode/CodeBlock.cpp \
        Source/JavaScriptCore/bytecode/CodeBlock.h \
        Source/JavaScriptCore/bytecode/CodeBlock.cpp \
        Source/JavaScriptCore/bytecode/CodeBlock.h \
+       Source/JavaScriptCore/bytecode/CodeOrigin.h \
+       Source/JavaScriptCore/bytecode/DataFormat.h \
+       Source/JavaScriptCore/bytecode/DFGExitProfile.cpp \
+       Source/JavaScriptCore/bytecode/DFGExitProfile.h \
        Source/JavaScriptCore/bytecode/EvalCodeCache.h \
        Source/JavaScriptCore/bytecode/EvalCodeCache.h \
+       Source/JavaScriptCore/bytecode/ExecutionCounter.cpp \
+       Source/JavaScriptCore/bytecode/ExecutionCounter.h \
+       Source/JavaScriptCore/bytecode/ExpressionRangeInfo.h \
+       Source/JavaScriptCore/bytecode/GetByIdStatus.cpp \
+       Source/JavaScriptCore/bytecode/GetByIdStatus.h \
+       Source/JavaScriptCore/bytecode/GlobalResolveInfo.h \
+       Source/JavaScriptCore/bytecode/HandlerInfo.h \
        Source/JavaScriptCore/bytecode/Instruction.h \
        Source/JavaScriptCore/bytecode/JumpTable.cpp \
        Source/JavaScriptCore/bytecode/JumpTable.h \
        Source/JavaScriptCore/bytecode/Instruction.h \
        Source/JavaScriptCore/bytecode/JumpTable.cpp \
        Source/JavaScriptCore/bytecode/JumpTable.h \
+       Source/JavaScriptCore/bytecode/LLIntCallLinkInfo.h \
+       Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp \
+       Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h \
+       Source/JavaScriptCore/bytecode/LineInfo.h \
+       Source/JavaScriptCore/bytecode/MethodCallLinkInfo.cpp \
+       Source/JavaScriptCore/bytecode/MethodCallLinkInfo.h \
+       Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp \
+       Source/JavaScriptCore/bytecode/MethodCallLinkStatus.h \
+       Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp \
+       Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h \
        Source/JavaScriptCore/bytecode/Opcode.cpp \
        Source/JavaScriptCore/bytecode/Opcode.h \
        Source/JavaScriptCore/bytecode/Opcode.cpp \
        Source/JavaScriptCore/bytecode/Opcode.h \
+       Source/JavaScriptCore/bytecode/Operands.h \
+       Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.cpp \
+       Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h \
+       Source/JavaScriptCore/bytecode/PredictedType.cpp \
+       Source/JavaScriptCore/bytecode/PredictedType.h \
+       Source/JavaScriptCore/bytecode/PutByIdStatus.cpp \
+       Source/JavaScriptCore/bytecode/PutByIdStatus.h \
+       Source/JavaScriptCore/bytecode/PutKind.h \
        Source/JavaScriptCore/bytecode/SamplingTool.cpp \
        Source/JavaScriptCore/bytecode/SamplingTool.h \
        Source/JavaScriptCore/bytecode/SamplingTool.cpp \
        Source/JavaScriptCore/bytecode/SamplingTool.h \
+       Source/JavaScriptCore/bytecode/StructureSet.h \
        Source/JavaScriptCore/bytecode/StructureStubInfo.cpp \
        Source/JavaScriptCore/bytecode/StructureStubInfo.h \
        Source/JavaScriptCore/bytecode/StructureStubInfo.cpp \
        Source/JavaScriptCore/bytecode/StructureStubInfo.h \
+       Source/JavaScriptCore/bytecode/ValueProfile.h \
+       Source/JavaScriptCore/bytecode/ValueRecovery.h \
+       Source/JavaScriptCore/bytecode/VirtualRegister.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/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/dfg/DFGAbstractState.cpp \
+       Source/JavaScriptCore/dfg/DFGAbstractState.h \
+       Source/JavaScriptCore/dfg/DFGAbstractValue.h \
+       Source/JavaScriptCore/dfg/DFGArgumentPosition.h \
+       Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp \
+       Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h \
+       Source/JavaScriptCore/dfg/DFGBasicBlock.h \
+       Source/JavaScriptCore/dfg/DFGByteCodeCache.h \
+       Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp \
+       Source/JavaScriptCore/dfg/DFGByteCodeParser.h \
+       Source/JavaScriptCore/dfg/DFGCCallHelpers.h \
+       Source/JavaScriptCore/dfg/DFGCapabilities.cpp \
+       Source/JavaScriptCore/dfg/DFGCapabilities.h \
+       Source/JavaScriptCore/dfg/DFGCFAPhase.cpp \
+       Source/JavaScriptCore/dfg/DFGCFAPhase.h \
+       Source/JavaScriptCore/dfg/DFGCommon.h \
+       Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.cpp \
+       Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h \
+       Source/JavaScriptCore/dfg/DFGCSEPhase.cpp \
+       Source/JavaScriptCore/dfg/DFGCSEPhase.h \
+       Source/JavaScriptCore/dfg/DFGDoubleFormatState.h \
+       Source/JavaScriptCore/dfg/DFGDriver.cpp \
+       Source/JavaScriptCore/dfg/DFGDriver.h \
+       Source/JavaScriptCore/dfg/DFGFPRInfo.h \
+       Source/JavaScriptCore/dfg/DFGFixupPhase.cpp \
+       Source/JavaScriptCore/dfg/DFGFixupPhase.h \
+       Source/JavaScriptCore/dfg/DFGGenerationInfo.h \
+       Source/JavaScriptCore/dfg/DFGGPRInfo.h \
+       Source/JavaScriptCore/dfg/DFGGraph.cpp \
+       Source/JavaScriptCore/dfg/DFGGraph.h \
+       Source/JavaScriptCore/dfg/DFGInsertionSet.h \
+       Source/JavaScriptCore/dfg/DFGJITCompiler.cpp \
+       Source/JavaScriptCore/dfg/DFGJITCompiler.h \
+       Source/JavaScriptCore/dfg/DFGNode.h \
+       Source/JavaScriptCore/dfg/DFGNodeFlags.cpp \
+       Source/JavaScriptCore/dfg/DFGNodeFlags.h \
+       Source/JavaScriptCore/dfg/DFGAdjacencyList.h \
+       Source/JavaScriptCore/dfg/DFGNodeType.h \
+       Source/JavaScriptCore/dfg/DFGEdge.h \
+       Source/JavaScriptCore/dfg/DFGOperations.cpp \
+       Source/JavaScriptCore/dfg/DFGOperations.h \
+       Source/JavaScriptCore/dfg/DFGOSREntry.cpp \
+       Source/JavaScriptCore/dfg/DFGOSREntry.h \
+       Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp \
+       Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp \
+       Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp \
+       Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h \
+       Source/JavaScriptCore/dfg/DFGOSRExit.h \
+       Source/JavaScriptCore/dfg/DFGOSRExit.cpp \
+       Source/JavaScriptCore/dfg/DFGPhase.cpp \
+       Source/JavaScriptCore/dfg/DFGPhase.h \
+       Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp \
+       Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.h \
+       Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.cpp \
+       Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.h \
+       Source/JavaScriptCore/dfg/DFGRegisterBank.h \
+       Source/JavaScriptCore/dfg/DFGRepatch.cpp \
+       Source/JavaScriptCore/dfg/DFGRepatch.h \
+       Source/JavaScriptCore/dfg/DFGScoreBoard.h \
+       Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp \
+       Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp \
+       Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp \
+       Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h \
+       Source/JavaScriptCore/dfg/DFGThunks.cpp \
+       Source/JavaScriptCore/dfg/DFGThunks.h \
+       Source/JavaScriptCore/dfg/DFGVariableAccessData.h \
+       Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp \
+       Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.h \
+       Source/JavaScriptCore/heap/CopiedAllocator.h \
+       Source/JavaScriptCore/heap/CopiedBlock.h \
+       Source/JavaScriptCore/heap/CopiedSpace.cpp \
+       Source/JavaScriptCore/heap/CopiedSpace.h \
+       Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h \
+       Source/JavaScriptCore/heap/CardSet.h \
        Source/JavaScriptCore/heap/ConservativeRoots.cpp \
        Source/JavaScriptCore/heap/ConservativeRoots.h \
        Source/JavaScriptCore/heap/ConservativeRoots.cpp \
        Source/JavaScriptCore/heap/ConservativeRoots.h \
+       Source/JavaScriptCore/heap/DFGCodeBlocks.cpp \
+       Source/JavaScriptCore/heap/DFGCodeBlocks.h \
+       Source/JavaScriptCore/heap/GCAssertions.h \
        Source/JavaScriptCore/heap/Handle.h \
        Source/JavaScriptCore/heap/Handle.h \
-       Source/JavaScriptCore/heap/HandleHeap.cpp \
-       Source/JavaScriptCore/heap/HandleHeap.h \
+       Source/JavaScriptCore/heap/HandleSet.cpp \
+       Source/JavaScriptCore/heap/HandleSet.h \
+       Source/JavaScriptCore/heap/HeapBlock.h \
+       Source/JavaScriptCore/heap/SlotVisitor.h \
        Source/JavaScriptCore/heap/HandleStack.cpp \
        Source/JavaScriptCore/heap/HandleStack.h \
        Source/JavaScriptCore/heap/HandleTypes.h \
        Source/JavaScriptCore/heap/HandleStack.cpp \
        Source/JavaScriptCore/heap/HandleStack.h \
        Source/JavaScriptCore/heap/HandleTypes.h \
+       Source/JavaScriptCore/heap/BlockAllocator.cpp \
+       Source/JavaScriptCore/heap/BlockAllocator.h \
        Source/JavaScriptCore/heap/Heap.cpp \
        Source/JavaScriptCore/heap/Heap.h \
        Source/JavaScriptCore/heap/Heap.cpp \
        Source/JavaScriptCore/heap/Heap.h \
+       Source/JavaScriptCore/heap/ListableHandler.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/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/HeapRootVisitor.h \
+       Source/JavaScriptCore/heap/MarkedAllocator.cpp \
+       Source/JavaScriptCore/heap/MarkedAllocator.h \
        Source/JavaScriptCore/heap/MarkedBlock.cpp \
        Source/JavaScriptCore/heap/MarkedBlock.h \
        Source/JavaScriptCore/heap/MarkedBlock.cpp \
        Source/JavaScriptCore/heap/MarkedBlock.h \
+       Source/JavaScriptCore/heap/MarkedBlockSet.h \
+       Source/JavaScriptCore/heap/TinyBloomFilter.h \
        Source/JavaScriptCore/heap/MarkedSpace.cpp \
        Source/JavaScriptCore/heap/MarkedSpace.h \
        Source/JavaScriptCore/heap/MarkedSpace.cpp \
        Source/JavaScriptCore/heap/MarkedSpace.h \
+       Source/JavaScriptCore/heap/PassWeak.h \
        Source/JavaScriptCore/heap/Strong.h \
        Source/JavaScriptCore/heap/Strong.h \
+       Source/JavaScriptCore/heap/StrongInlines.h \
+       Source/JavaScriptCore/heap/UnconditionalFinalizer.h \
+       Source/JavaScriptCore/heap/VTableSpectrum.cpp \
+       Source/JavaScriptCore/heap/VTableSpectrum.h \
        Source/JavaScriptCore/heap/Weak.h \
        Source/JavaScriptCore/heap/Weak.h \
+       Source/JavaScriptCore/heap/WeakBlock.cpp \
+       Source/JavaScriptCore/heap/WeakBlock.h \
+       Source/JavaScriptCore/heap/WeakHandleOwner.cpp \
+       Source/JavaScriptCore/heap/WeakHandleOwner.h \
+       Source/JavaScriptCore/heap/WeakImpl.h \
+       Source/JavaScriptCore/heap/WeakSet.cpp \
+       Source/JavaScriptCore/heap/WeakSet.h \
+       Source/JavaScriptCore/heap/WeakSetInlines.h \
+       Source/JavaScriptCore/heap/WeakReferenceHarvester.h \
+       Source/JavaScriptCore/heap/WriteBarrierSupport.cpp \
+       Source/JavaScriptCore/heap/WriteBarrierSupport.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/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/heap/MarkedAllocator.cpp \
+    Source/JavaScriptCore/heap/MarkedAllocator.h \
        Source/JavaScriptCore/debugger/Debugger.h \
        Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/APICast.h \
        Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/APIShims.h \
        Source/JavaScriptCore/debugger/Debugger.h \
        Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/APICast.h \
        Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/APIShims.h \
@@ -160,6 +308,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/icu/unicode/utf_old.h \
        Source/JavaScriptCore/icu/unicode/utypes.h \
        Source/JavaScriptCore/icu/unicode/uversion.h \
        Source/JavaScriptCore/icu/unicode/utf_old.h \
        Source/JavaScriptCore/icu/unicode/utypes.h \
        Source/JavaScriptCore/icu/unicode/uversion.h \
+       Source/JavaScriptCore/interpreter/AbstractPC.cpp \
+       Source/JavaScriptCore/interpreter/AbstractPC.h \
        Source/JavaScriptCore/interpreter/CachedCall.h \
        Source/JavaScriptCore/interpreter/CallFrameClosure.h \
        Source/JavaScriptCore/interpreter/CallFrame.cpp \
        Source/JavaScriptCore/interpreter/CachedCall.h \
        Source/JavaScriptCore/interpreter/CallFrameClosure.h \
        Source/JavaScriptCore/interpreter/CallFrame.cpp \
@@ -170,15 +320,22 @@ javascriptcore_sources += \
        Source/JavaScriptCore/interpreter/RegisterFile.h \
        Source/JavaScriptCore/interpreter/Register.h \
        Source/JavaScriptCore/JavaScriptCorePrefix.h \
        Source/JavaScriptCore/interpreter/RegisterFile.h \
        Source/JavaScriptCore/interpreter/Register.h \
        Source/JavaScriptCore/JavaScriptCorePrefix.h \
+       Source/JavaScriptCore/jit/CompactJITCodeMap.h \
        Source/JavaScriptCore/jit/ExecutableAllocator.cpp \
        Source/JavaScriptCore/jit/ExecutableAllocator.h \
        Source/JavaScriptCore/jit/ExecutableAllocator.cpp \
        Source/JavaScriptCore/jit/ExecutableAllocator.h \
+       Source/JavaScriptCore/jit/HostCallReturnValue.cpp \
+       Source/JavaScriptCore/jit/HostCallReturnValue.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/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/JITCompilationEffort.h \
+       Source/JavaScriptCore/jit/JITDriver.h \
        Source/JavaScriptCore/jit/JIT.cpp \
        Source/JavaScriptCore/jit/JIT.h \
        Source/JavaScriptCore/jit/JIT.cpp \
        Source/JavaScriptCore/jit/JIT.h \
+       Source/JavaScriptCore/jit/JITExceptions.cpp \
+       Source/JavaScriptCore/jit/JITExceptions.h \
        Source/JavaScriptCore/jit/JITInlineMethods.h \
        Source/JavaScriptCore/jit/JITOpcodes32_64.cpp \
        Source/JavaScriptCore/jit/JITOpcodes.cpp \
        Source/JavaScriptCore/jit/JITInlineMethods.h \
        Source/JavaScriptCore/jit/JITOpcodes32_64.cpp \
        Source/JavaScriptCore/jit/JITOpcodes.cpp \
@@ -187,15 +344,19 @@ javascriptcore_sources += \
        Source/JavaScriptCore/jit/JITStubCall.h \
        Source/JavaScriptCore/jit/JITStubs.cpp \
        Source/JavaScriptCore/jit/JITStubs.h \
        Source/JavaScriptCore/jit/JITStubCall.h \
        Source/JavaScriptCore/jit/JITStubs.cpp \
        Source/JavaScriptCore/jit/JITStubs.h \
+       Source/JavaScriptCore/jit/JITWriteBarrier.h \
        Source/JavaScriptCore/jit/JSInterfaceJIT.h \
        Source/JavaScriptCore/jit/SpecializedThunkJIT.h \
        Source/JavaScriptCore/jit/ThunkGenerators.cpp \
        Source/JavaScriptCore/jit/ThunkGenerators.h \
        Source/JavaScriptCore/jit/JSInterfaceJIT.h \
        Source/JavaScriptCore/jit/SpecializedThunkJIT.h \
        Source/JavaScriptCore/jit/ThunkGenerators.cpp \
        Source/JavaScriptCore/jit/ThunkGenerators.h \
+       Source/JavaScriptCore/llint/LLIntData.h \
+       Source/JavaScriptCore/llint/LLIntEntrypoints.cpp \
+       Source/JavaScriptCore/llint/LLIntEntrypoints.h \
+       Source/JavaScriptCore/llint/LowLevelInterpreter.cpp \
+       Source/JavaScriptCore/llint/LowLevelInterpreter.h \
        Source/JavaScriptCore/os-win32/stdbool.h \
        Source/JavaScriptCore/os-win32/stdint.h \
        Source/JavaScriptCore/parser/ASTBuilder.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/Lexer.cpp \
        Source/JavaScriptCore/parser/Lexer.h \
        Source/JavaScriptCore/parser/NodeConstructors.h \
@@ -204,6 +365,7 @@ javascriptcore_sources += \
        Source/JavaScriptCore/parser/Nodes.h \
        Source/JavaScriptCore/parser/ParserArena.cpp \
        Source/JavaScriptCore/parser/ParserArena.h \
        Source/JavaScriptCore/parser/Nodes.h \
        Source/JavaScriptCore/parser/ParserArena.cpp \
        Source/JavaScriptCore/parser/ParserArena.h \
+       Source/JavaScriptCore/parser/ParserTokens.h \
        Source/JavaScriptCore/parser/Parser.cpp \
        Source/JavaScriptCore/parser/Parser.h \
        Source/JavaScriptCore/parser/ResultType.h \
        Source/JavaScriptCore/parser/Parser.cpp \
        Source/JavaScriptCore/parser/Parser.h \
        Source/JavaScriptCore/parser/ResultType.h \
@@ -231,6 +393,7 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/ArrayPrototype.cpp \
        Source/JavaScriptCore/runtime/ArrayPrototype.h \
        Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h \
        Source/JavaScriptCore/runtime/ArrayPrototype.cpp \
        Source/JavaScriptCore/runtime/ArrayPrototype.h \
        Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h \
+       Source/JavaScriptCore/runtime/BigInteger.h \
        Source/JavaScriptCore/runtime/BooleanConstructor.cpp \
        Source/JavaScriptCore/runtime/BooleanConstructor.h \
        Source/JavaScriptCore/runtime/BooleanObject.cpp \
        Source/JavaScriptCore/runtime/BooleanConstructor.cpp \
        Source/JavaScriptCore/runtime/BooleanConstructor.h \
        Source/JavaScriptCore/runtime/BooleanObject.cpp \
@@ -241,8 +404,10 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/CallData.cpp \
        Source/JavaScriptCore/runtime/CallData.h \
        Source/JavaScriptCore/runtime/ClassInfo.h \
        Source/JavaScriptCore/runtime/CallData.cpp \
        Source/JavaScriptCore/runtime/CallData.h \
        Source/JavaScriptCore/runtime/ClassInfo.h \
+       Source/JavaScriptCore/runtime/CodeSpecializationKind.h \
        Source/JavaScriptCore/runtime/CommonIdentifiers.cpp \
        Source/JavaScriptCore/runtime/CommonIdentifiers.h \
        Source/JavaScriptCore/runtime/CommonIdentifiers.cpp \
        Source/JavaScriptCore/runtime/CommonIdentifiers.h \
+       Source/JavaScriptCore/runtime/CommonSlowPaths.h \
        Source/JavaScriptCore/runtime/Completion.cpp \
        Source/JavaScriptCore/runtime/Completion.h \
        Source/JavaScriptCore/runtime/ConstructData.cpp \
        Source/JavaScriptCore/runtime/Completion.cpp \
        Source/JavaScriptCore/runtime/Completion.h \
        Source/JavaScriptCore/runtime/ConstructData.cpp \
@@ -268,6 +433,7 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/ExceptionHelpers.h \
        Source/JavaScriptCore/runtime/Executable.cpp \
        Source/JavaScriptCore/runtime/Executable.h \
        Source/JavaScriptCore/runtime/ExceptionHelpers.h \
        Source/JavaScriptCore/runtime/Executable.cpp \
        Source/JavaScriptCore/runtime/Executable.h \
+       Source/JavaScriptCore/runtime/ExecutionHarness.h \
        Source/JavaScriptCore/runtime/FunctionConstructor.cpp \
        Source/JavaScriptCore/runtime/FunctionConstructor.h \
        Source/JavaScriptCore/runtime/FunctionPrototype.cpp \
        Source/JavaScriptCore/runtime/FunctionConstructor.cpp \
        Source/JavaScriptCore/runtime/FunctionConstructor.h \
        Source/JavaScriptCore/runtime/FunctionPrototype.cpp \
@@ -282,32 +448,36 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/InitializeThreading.h \
        Source/JavaScriptCore/runtime/InternalFunction.cpp \
        Source/JavaScriptCore/runtime/InternalFunction.h \
        Source/JavaScriptCore/runtime/InitializeThreading.h \
        Source/JavaScriptCore/runtime/InternalFunction.cpp \
        Source/JavaScriptCore/runtime/InternalFunction.h \
+       Source/JavaScriptCore/runtime/Intrinsic.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/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/JSCell.cpp \
        Source/JavaScriptCore/runtime/JSCell.h \
+       Source/JavaScriptCore/runtime/JSDateMath.cpp \
+       Source/JavaScriptCore/runtime/JSDateMath.h \
        Source/JavaScriptCore/runtime/JSFunction.cpp \
        Source/JavaScriptCore/runtime/JSFunction.h \
        Source/JavaScriptCore/runtime/JSFunction.cpp \
        Source/JavaScriptCore/runtime/JSFunction.h \
+       Source/JavaScriptCore/runtime/JSBoundFunction.cpp \
+       Source/JavaScriptCore/runtime/JSBoundFunction.h \
+       Source/JavaScriptCore/runtime/JSExportMacros.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/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/JSGlobalThis.cpp \
+       Source/JavaScriptCore/runtime/JSGlobalThis.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/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/JSONObject.cpp \
        Source/JavaScriptCore/runtime/JSONObject.h \
        Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp \
@@ -315,6 +485,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp \
        Source/JavaScriptCore/runtime/JSStaticScopeObject.h \
        Source/JavaScriptCore/runtime/JSStringBuilder.h \
        Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp \
        Source/JavaScriptCore/runtime/JSStaticScopeObject.h \
        Source/JavaScriptCore/runtime/JSStringBuilder.h \
+       Source/JavaScriptCore/runtime/JSStringJoiner.cpp \
+       Source/JavaScriptCore/runtime/JSStringJoiner.h \
        Source/JavaScriptCore/runtime/JSString.cpp \
        Source/JavaScriptCore/runtime/JSString.h \
        Source/JavaScriptCore/runtime/JSType.h \
        Source/JavaScriptCore/runtime/JSString.cpp \
        Source/JavaScriptCore/runtime/JSString.h \
        Source/JavaScriptCore/runtime/JSType.h \
@@ -326,13 +498,14 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/JSVariableObject.h \
        Source/JavaScriptCore/runtime/JSWrapperObject.cpp \
        Source/JavaScriptCore/runtime/JSWrapperObject.h \
        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/LiteralParser.cpp \
        Source/JavaScriptCore/runtime/LiteralParser.h \
        Source/JavaScriptCore/runtime/Lookup.cpp \
        Source/JavaScriptCore/runtime/Lookup.h \
+       Source/JavaScriptCore/runtime/MatchResult.h \
        Source/JavaScriptCore/runtime/MathObject.cpp \
        Source/JavaScriptCore/runtime/MathObject.h \
        Source/JavaScriptCore/runtime/MathObject.cpp \
        Source/JavaScriptCore/runtime/MathObject.h \
+       Source/JavaScriptCore/runtime/MemoryStatistics.h \
        Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp \
        Source/JavaScriptCore/runtime/NativeErrorConstructor.h \
        Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp \
        Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp \
        Source/JavaScriptCore/runtime/NativeErrorConstructor.h \
        Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp \
@@ -350,6 +523,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/ObjectPrototype.h \
        Source/JavaScriptCore/runtime/Operations.cpp \
        Source/JavaScriptCore/runtime/Operations.h \
        Source/JavaScriptCore/runtime/ObjectPrototype.h \
        Source/JavaScriptCore/runtime/Operations.cpp \
        Source/JavaScriptCore/runtime/Operations.h \
+       Source/JavaScriptCore/runtime/Options.cpp \
+       Source/JavaScriptCore/runtime/Options.h \
        Source/JavaScriptCore/runtime/PropertyDescriptor.cpp \
        Source/JavaScriptCore/runtime/PropertyDescriptor.h \
        Source/JavaScriptCore/runtime/PropertyMapHashTable.h \
        Source/JavaScriptCore/runtime/PropertyDescriptor.cpp \
        Source/JavaScriptCore/runtime/PropertyDescriptor.h \
        Source/JavaScriptCore/runtime/PropertyMapHashTable.h \
@@ -366,25 +541,28 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/RegExp.cpp \
        Source/JavaScriptCore/runtime/RegExp.h \
        Source/JavaScriptCore/runtime/RegExpKey.h \
        Source/JavaScriptCore/runtime/RegExp.cpp \
        Source/JavaScriptCore/runtime/RegExp.h \
        Source/JavaScriptCore/runtime/RegExpKey.h \
+       Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp \
        Source/JavaScriptCore/runtime/RegExpMatchesArray.h \
        Source/JavaScriptCore/runtime/RegExpMatchesArray.h \
+       Source/JavaScriptCore/runtime/RegExpCachedResult.cpp \
+       Source/JavaScriptCore/runtime/RegExpCachedResult.h \
        Source/JavaScriptCore/runtime/RegExpObject.cpp \
        Source/JavaScriptCore/runtime/RegExpObject.h \
        Source/JavaScriptCore/runtime/RegExpPrototype.cpp \
        Source/JavaScriptCore/runtime/RegExpPrototype.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/SamplingCounter.cpp \
+       Source/JavaScriptCore/runtime/SamplingCounter.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/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/StorageBarrier.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/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/StringPrototype.cpp \
        Source/JavaScriptCore/runtime/StringPrototype.h \
        Source/JavaScriptCore/runtime/StringRecursionChecker.cpp \
@@ -399,6 +577,7 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/TimeoutChecker.cpp \
        Source/JavaScriptCore/runtime/TimeoutChecker.h \
        Source/JavaScriptCore/runtime/Tracing.h \
        Source/JavaScriptCore/runtime/TimeoutChecker.cpp \
        Source/JavaScriptCore/runtime/TimeoutChecker.h \
        Source/JavaScriptCore/runtime/Tracing.h \
+       Source/JavaScriptCore/runtime/Uint16WithFraction.h \
        Source/JavaScriptCore/runtime/UString.cpp \
        Source/JavaScriptCore/runtime/UString.h \
        Source/JavaScriptCore/runtime/UStringBuilder.h \
        Source/JavaScriptCore/runtime/UString.cpp \
        Source/JavaScriptCore/runtime/UString.h \
        Source/JavaScriptCore/runtime/UStringBuilder.h \
@@ -406,164 +585,15 @@ javascriptcore_sources += \
        Source/JavaScriptCore/runtime/WeakGCMap.h \
        Source/JavaScriptCore/runtime/WeakRandom.h \
        Source/JavaScriptCore/runtime/WriteBarrier.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/tools/CodeProfile.cpp \
+       Source/JavaScriptCore/tools/CodeProfile.h \
+       Source/JavaScriptCore/tools/CodeProfiling.cpp \
+       Source/JavaScriptCore/tools/CodeProfiling.h \
+       Source/JavaScriptCore/tools/ProfileTreeNode.h \
+       Source/JavaScriptCore/tools/TieredMMapArray.h \
        Source/JavaScriptCore/yarr/Yarr.h \
        Source/JavaScriptCore/yarr/Yarr.h \
+       Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.cpp \
+       Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.h \
        Source/JavaScriptCore/yarr/YarrInterpreter.cpp \
        Source/JavaScriptCore/yarr/YarrInterpreter.h \
        Source/JavaScriptCore/yarr/YarrJIT.cpp \
        Source/JavaScriptCore/yarr/YarrInterpreter.cpp \
        Source/JavaScriptCore/yarr/YarrInterpreter.h \
        Source/JavaScriptCore/yarr/YarrJIT.cpp \
@@ -575,35 +605,11 @@ javascriptcore_sources += \
        Source/JavaScriptCore/yarr/YarrSyntaxChecker.h
 
 if TARGET_WIN32
        Source/JavaScriptCore/yarr/YarrSyntaxChecker.h
 
 if TARGET_WIN32
-javascriptcore_sources += \
-       Source/JavaScriptCore/heap/MarkStackWin.cpp \
-       Source/JavaScriptCore/wtf/OSAllocatorWin.cpp
 else
 javascriptcore_sources += \
 else
 javascriptcore_sources += \
-       Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp \
-       Source/JavaScriptCore/heap/MarkStackPosix.cpp \
-       Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp
+       Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
 endif
 
 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 \
 # minidom
 Programs_minidom_SOURCES = \
        Source/JavaScriptCore/API/tests/JSNode.c \
@@ -617,4 +623,5 @@ Programs_minidom_SOURCES = \
        Source/JavaScriptCore/API/tests/minidom.c
 
 Programs_jsc_@WEBKITGTK_API_MAJOR_VERSION@_SOURCES = \
        Source/JavaScriptCore/API/tests/minidom.c
 
 Programs_jsc_@WEBKITGTK_API_MAJOR_VERSION@_SOURCES = \
+       Source/JavaScriptCore/JSCTypedArrayStubs.h \
        Source/JavaScriptCore/jsc.cpp
        Source/JavaScriptCore/jsc.cpp
index a8ae5cca56c2596f032e2d2515805e3d46e2b9db..3c0bf46cff050325c070f4d76ef7f0afd318dd2e 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-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>
+       <string>${BUNDLE_VERSION}, Copyright 2003-2012 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/JSCTypedArrayStubs.h b/JSCTypedArrayStubs.h
new file mode 100644 (file)
index 0000000..ca40301
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef JSCTypedArrayStubs_h
+#define JSCTypedArrayStubs_h
+
+#include "JSObject.h"
+#include "ObjectPrototype.h"
+#include <wtf/Float32Array.h>
+#include <wtf/Float64Array.h>
+#include <wtf/Forward.h>
+#include <wtf/Int16Array.h>
+#include <wtf/Int32Array.h>
+#include <wtf/Int8Array.h>
+#include <wtf/Uint16Array.h>
+#include <wtf/Uint32Array.h>
+#include <wtf/Uint8Array.h>
+#include <wtf/Uint8ClampedArray.h>
+
+namespace JSC {
+    
+#define TYPED_ARRAY(name, type) \
+class JS##name##Array : public JSNonFinalObject { \
+public: \
+    typedef JSNonFinalObject Base; \
+    static JS##name##Array* create(JSC::Structure* structure, JSGlobalObject* globalObject, PassRefPtr<name##Array> impl) \
+    { \
+        JS##name##Array* ptr = new (NotNull, JSC::allocateCell<JS##name##Array>(globalObject->globalData().heap)) JS##name##Array(structure, globalObject, impl); \
+        ptr->finishCreation(globalObject->globalData()); \
+        return ptr; \
+    }\
+\
+    static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\
+    static bool getOwnPropertyDescriptor(JSC::JSObject*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);\
+    static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\
+    static void put(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\
+    static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue, bool);\
+    static const JSC::ClassInfo s_info;\
+\
+    static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\
+    {\
+        return JSC::Structure::create(globalData, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), &s_info);\
+    }\
+\
+    static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\
+    static JSC::JSValue getConstructor(JSC::ExecState*, JSC::JSGlobalObject*);\
+\
+    static const JSC::TypedArrayType TypedArrayStorageType = JSC::TypedArray##name;\
+    uint32_t m_storageLength;\
+    type* m_storage;\
+    RefPtr<name##Array> m_impl;\
+protected:\
+    JS##name##Array(JSC::Structure*, JSGlobalObject*, PassRefPtr<name##Array>);\
+    void finishCreation(JSC::JSGlobalData&);\
+    static const unsigned StructureFlags = JSC::OverridesGetPropertyNames | JSC::OverridesGetOwnPropertySlot | Base::StructureFlags;\
+    JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\
+    void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue);\
+};\
+\
+const ClassInfo JS##name##Array::s_info = { #name "Array" , &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JS##name##Array) };\
+\
+JS##name##Array::JS##name##Array(Structure* structure, JSGlobalObject* globalObject, PassRefPtr<name##Array> impl)\
+    : Base(globalObject->globalData(), structure)\
+    , m_impl(impl)\
+{\
+}\
+\
+void JS##name##Array::finishCreation(JSGlobalData& globalData)\
+{\
+    Base::finishCreation(globalData);\
+    TypedArrayDescriptor descriptor(&JS##name##Array::s_info, OBJECT_OFFSETOF(JS##name##Array, m_storage), OBJECT_OFFSETOF(JS##name##Array, m_storageLength));\
+    globalData.registerTypedArrayDescriptor(m_impl.get(), descriptor);\
+    m_storage = m_impl->data();\
+    m_storageLength = m_impl->length();\
+    putDirect(globalData, globalData.propertyNames->length, jsNumber(m_storageLength), DontDelete | ReadOnly | DontEnum); \
+    ASSERT(inherits(&s_info));\
+}\
+\
+bool JS##name##Array::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\
+{\
+    JS##name##Array* thisObject = jsCast<JS##name##Array*>(cell);\
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\
+    bool ok;\
+    unsigned index = propertyName.toUInt32(ok);\
+    if (ok && index < thisObject->m_storageLength) {\
+        slot.setValue(thisObject->getByIndex(exec, index));\
+        return true;\
+    }\
+    return Base::getOwnPropertySlot(cell, exec, propertyName, slot);\
+}\
+\
+bool JS##name##Array::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\
+{\
+    JS##name##Array* thisObject = jsCast<JS##name##Array*>(object);\
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\
+    bool ok;\
+    unsigned index = propertyName.toUInt32(ok);\
+    if (ok && index < thisObject->m_storageLength) {\
+        descriptor.setDescriptor(thisObject->getByIndex(exec, index), DontDelete);\
+        return true;\
+    }\
+    return Base::getOwnPropertyDescriptor(object, exec, propertyName, descriptor);\
+}\
+\
+bool JS##name##Array::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)\
+{\
+    JS##name##Array* thisObject = jsCast<JS##name##Array*>(cell);\
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\
+    if (propertyName < thisObject->m_storageLength) {\
+        slot.setValue(thisObject->getByIndex(exec, propertyName));\
+        return true;\
+    }\
+    return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot);\
+}\
+\
+void JS##name##Array::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)\
+{\
+    JS##name##Array* thisObject = jsCast<JS##name##Array*>(cell);\
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\
+    bool ok;\
+    unsigned index = propertyName.toUInt32(ok);\
+    if (ok) {\
+        thisObject->indexSetter(exec, index, value);\
+        return;\
+    }\
+    Base::put(thisObject, exec, propertyName, value, slot);\
+}\
+\
+void JS##name##Array::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value) \
+{\
+    m_impl->set(index, value.toNumber(exec));\
+}\
+\
+void JS##name##Array::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool)\
+{\
+    JS##name##Array* thisObject = jsCast<JS##name##Array*>(cell);\
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\
+    thisObject->indexSetter(exec, propertyName, value);\
+    return;\
+}\
+\
+void JS##name##Array::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)\
+{\
+    JS##name##Array* thisObject = jsCast<JS##name##Array*>(object);\
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);\
+    for (unsigned i = 0; i < thisObject->m_storageLength; ++i)\
+        propertyNames.add(Identifier::from(exec, i));\
+    Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);\
+}\
+\
+JSValue JS##name##Array::getByIndex(ExecState*, unsigned index)\
+{\
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);\
+    type result = m_impl->item(index);\
+    if (isnan((double)result))\
+        return jsNaN();\
+    return JSValue(result);\
+}\
+static EncodedJSValue JSC_HOST_CALL constructJS##name##Array(ExecState* callFrame) { \
+    if (callFrame->argumentCount() < 1) \
+        return JSValue::encode(jsUndefined()); \
+    int32_t length = callFrame->argument(0).toInt32(callFrame); \
+    if (length < 0) \
+        return JSValue::encode(jsUndefined()); \
+    Structure* structure = JS##name##Array::createStructure(callFrame->globalData(), callFrame->lexicalGlobalObject(), callFrame->lexicalGlobalObject()->objectPrototype()); \
+    return JSValue::encode(JS##name##Array::create(structure, callFrame->lexicalGlobalObject(), name##Array::create(length)));\
+}
+
+TYPED_ARRAY(Uint8, uint8_t);
+TYPED_ARRAY(Uint8Clamped, uint8_t);
+TYPED_ARRAY(Uint16, uint16_t);
+TYPED_ARRAY(Uint32, uint32_t);
+TYPED_ARRAY(Int8, int8_t);
+TYPED_ARRAY(Int16, int16_t);
+TYPED_ARRAY(Int32, int32_t);
+TYPED_ARRAY(Float32, float);
+TYPED_ARRAY(Float64, double);
+
+}
+
+#endif
diff --git a/JavaScriptCore.JSVALUE32_64only.exp b/JavaScriptCore.JSVALUE32_64only.exp
deleted file mode 100644 (file)
index f9eee85..0000000
+++ /dev/null
@@ -1 +0,0 @@
-__ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEiRKNS_10IdentifierEPFxS2_E
diff --git a/JavaScriptCore.JSVALUE64only.exp b/JavaScriptCore.JSVALUE64only.exp
deleted file mode 100644 (file)
index eaa9f51..0000000
+++ /dev/null
@@ -1 +0,0 @@
-__ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEiRKNS_10IdentifierEPFPvS2_E
diff --git a/JavaScriptCore.exp b/JavaScriptCore.exp
deleted file mode 100644 (file)
index 9c88059..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-_JSCheckScriptSyntax
-_JSClassCreate
-_JSClassRelease
-_JSClassRetain
-_JSContextGetGlobalContext
-_JSContextGetGlobalObject
-_JSContextGetGroup
-_JSContextGroupCreate
-_JSContextGroupRelease
-_JSContextGroupRetain
-_JSContextCreateBacktrace
-_JSEndProfiling
-_JSEvaluateScript
-_JSGarbageCollect
-_JSGlobalContextCreate
-_JSGlobalContextCreateInGroup
-_JSGlobalContextRelease
-_JSGlobalContextRetain
-_JSObjectCallAsConstructor
-_JSObjectCallAsFunction
-_JSObjectCopyPropertyNames
-_JSObjectDeletePrivateProperty
-_JSObjectDeleteProperty
-_JSObjectGetPrivate
-_JSObjectGetPrivateProperty
-_JSObjectGetProperty
-_JSObjectGetPropertyAtIndex
-_JSObjectGetPrototype
-_JSObjectHasProperty
-_JSObjectIsConstructor
-_JSObjectIsFunction
-_JSObjectMake
-_JSObjectMakeArray
-_JSObjectMakeConstructor
-_JSObjectMakeDate
-_JSObjectMakeError
-_JSObjectMakeFunction
-_JSObjectMakeFunctionWithCallback
-_JSObjectMakeRegExp
-_JSObjectSetPrivate
-_JSObjectSetPrivateProperty
-_JSObjectSetProperty
-_JSObjectSetPropertyAtIndex
-_JSObjectSetPrototype
-_JSPropertyNameAccumulatorAddName
-_JSPropertyNameArrayGetCount
-_JSPropertyNameArrayGetNameAtIndex
-_JSPropertyNameArrayRelease
-_JSPropertyNameArrayRetain
-_JSReportExtraMemoryCost
-_JSStartProfiling
-_JSStringCopyCFString
-_JSStringCreateWithCFString
-_JSStringCreateWithCharacters
-_JSStringCreateWithUTF8CString
-_JSStringGetCharactersPtr
-_JSStringGetLength
-_JSStringGetMaximumUTF8CStringSize
-_JSStringGetUTF8CString
-_JSStringIsEqual
-_JSStringIsEqualToUTF8CString
-_JSStringRelease
-_JSStringRetain
-_JSValueCreateJSONString
-_JSValueGetType
-_JSValueIsBoolean
-_JSValueIsEqual
-_JSValueIsInstanceOfConstructor
-_JSValueIsNull
-_JSValueIsNumber
-_JSValueIsObject
-_JSValueIsObjectOfClass
-_JSValueIsStrictEqual
-_JSValueIsString
-_JSValueIsUndefined
-_JSValueMakeBoolean
-_JSValueMakeFromJSONString
-_JSValueMakeNull
-_JSValueMakeNumber
-_JSValueMakeString
-_JSValueMakeUndefined
-_JSValueProtect
-_JSValueToBoolean
-_JSValueToNumber
-_JSValueToObject
-_JSValueToStringCopy
-_JSValueUnprotect
-_JSWeakObjectMapClear
-_JSWeakObjectMapCreate
-_JSWeakObjectMapGet
-_JSWeakObjectMapRemove
-_JSWeakObjectMapSet
-_WTFLog
-_WTFLogVerbose
-_WTFReportArgumentAssertionFailure
-_WTFReportAssertionFailure
-_WTFReportAssertionFailureWithMessage
-_WTFReportBacktrace
-_WTFReportError
-_WTFReportFatalError
-_WebCoreWebThreadIsLockedOrDisabled
-__ZN14OpaqueJSString6createERKN3JSC7UStringE
-__ZN3JSC10HandleHeap12writeBarrierEPNS_7JSValueERKS1_
-__ZN3JSC10HandleHeap4growEv
-__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPN3WTF10StringImplE
-__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPN3WTF10StringImplE
-__ZN3JSC10Identifier27checkCurrentIdentifierTableEPNS_12JSGlobalDataE
-__ZN3JSC10Identifier27checkCurrentIdentifierTableEPNS_9ExecStateE
-__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
-__ZN3JSC10Identifier4fromEPNS_9ExecStateEi
-__ZN3JSC10Identifier4fromEPNS_9ExecStateEj
-__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
-__ZN3JSC11createErrorEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC11regExpFlagsERKNS_7UStringE
-__ZN3JSC12DateInstance6s_infoE
-__ZN3JSC12DateInstanceC1EPNS_9ExecStateEPNS_9StructureEd
-__ZN3JSC12JSGlobalData10ClientDataD2Ev
-__ZN3JSC12JSGlobalData11jsArrayVPtrE
-__ZN3JSC12JSGlobalData12createLeakedENS_15ThreadStackTypeE
-__ZN3JSC12JSGlobalData12jsStringVPtrE
-__ZN3JSC12JSGlobalData12stopSamplingEv
-__ZN3JSC12JSGlobalData13startSamplingEv
-__ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE
-__ZN3JSC12JSGlobalData14resetDateCacheEv
-__ZN3JSC12JSGlobalData14sharedInstanceEv
-__ZN3JSC12JSGlobalData15dumpRegExpTraceEv
-__ZN3JSC12JSGlobalData22clearBuiltinStructuresEv
-#ifndef NDEBUG
-__ZN3JSC12JSGlobalData23releaseExecutableMemoryEv
-#endif
-__ZN3JSC12JSGlobalData6createENS_15ThreadStackTypeE
-__ZN3JSC12JSGlobalDataD1Ev
-__ZN3JSC12RegExpObject6s_infoE
-__ZN3JSC12RegExpObjectC1EPNS_14JSGlobalObjectEPNS_9StructureEPNS_6RegExpE
-__ZN3JSC12SamplingTool5setupEv
-__ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
-__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
-__ZN3JSC12StringObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC12StringObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC12StringObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC12StringObject6s_infoE
-__ZN3JSC12StringObjectC2EPNS_9ExecStateEPNS_9StructureERKNS_7UStringE
-__ZN3JSC12nonInlineNaNEv
-__ZN3JSC13SamplingFlags4stopEv
-__ZN3JSC13SamplingFlags5startEv
-__ZN3JSC13SamplingFlags7s_flagsE
-__ZN3JSC13StatementNode6setLocEii
-__ZN3JSC14JSGlobalObject10globalExecEv
-__ZN3JSC14JSGlobalObject11disableEvalEv
-__ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
-__ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
-__ZN3JSC14JSGlobalObject13visitChildrenERNS_9MarkStackE
-__ZN3JSC14JSGlobalObject16addStaticGlobalsEPNS0_18GlobalPropertyInfoEi
-__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
-__ZN3JSC14JSGlobalObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC14JSGlobalObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE  
-__ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
-__ZN3JSC14JSGlobalObject6s_infoE
-__ZN3JSC14JSGlobalObjectD2Ev
-__ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
-__ZN3JSC14MachineThreads16addCurrentThreadEv
-__ZN3JSC14MachineThreads29makeUsableFromMultipleThreadsEv
-__ZN3JSC14SamplingThread4stopEv
-__ZN3JSC14SamplingThread5startEj
-__ZN3JSC14ScopeChainNode6s_infoE
-__ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
-__ZN3JSC14TimeoutChecker5resetEv
-__ZN3JSC14throwTypeErrorEPNS_9ExecStateE
-__ZN3JSC15JSWrapperObject13visitChildrenERNS_9MarkStackE
-__ZN3JSC15WeakHandleOwner26isReachableFromOpaqueRootsENS_6HandleINS_7UnknownEEEPvRNS_9MarkStackE
-__ZN3JSC15WeakHandleOwner8finalizeENS_6HandleINS_7UnknownEEEPv
-__ZN3JSC15WeakHandleOwnerD2Ev
-__ZN3JSC15createTypeErrorEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC16InternalFunction12vtableAnchorEv
-__ZN3JSC16InternalFunction4nameEPNS_9ExecStateE
-__ZN3JSC16InternalFunction6s_infoE
-__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEPNS_14JSGlobalObjectEPNS_9StructureERKNS_10IdentifierE
-__ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC16createRangeErrorEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC16slowValidateCellEPNS_14JSGlobalObjectE
-__ZN3JSC16slowValidateCellEPNS_6JSCellE
-__ZN3JSC16throwSyntaxErrorEPNS_9ExecStateE
-__ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb
-__ZN3JSC17PropertyNameArray3addEPN3WTF10StringImplE
-__ZN3JSC17constructFunctionEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
-__ZN3JSC17createSyntaxErrorEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC18DebuggerActivationC1ERNS_12JSGlobalDataEPNS_8JSObjectE
-__ZN3JSC18PropertyDescriptor11setWritableEb
-__ZN3JSC18PropertyDescriptor12setUndefinedEv
-__ZN3JSC18PropertyDescriptor13setDescriptorENS_7JSValueEj
-__ZN3JSC18PropertyDescriptor13setEnumerableEb
-__ZN3JSC18PropertyDescriptor15setConfigurableEb
-__ZN3JSC18PropertyDescriptor17defaultAttributesE
-__ZN3JSC18PropertyDescriptor21setAccessorDescriptorENS_7JSValueES1_j
-__ZN3JSC18PropertyDescriptor9setGetterENS_7JSValueE
-__ZN3JSC18PropertyDescriptor9setSetterENS_7JSValueE
-__ZN3JSC19SourceProviderCache5clearEv
-__ZN3JSC19SourceProviderCacheD1Ev
-__ZN3JSC19initializeThreadingEv
-__ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
-__ZN3JSC20createReferenceErrorEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC22globalMemoryStatisticsEv
-__ZN3JSC22objectConstructorTableE
-__ZN3JSC23AbstractSamplingCounter4dumpEv
-__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE
-__ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC24DynamicGlobalObjectScopeC1ERNS_12JSGlobalDataEPNS_14JSGlobalObjectE
-__ZN3JSC24JSObjectWithGlobalObjectC2EPNS_14JSGlobalObjectEPNS_9StructureE
-__ZN3JSC24JSObjectWithGlobalObjectC2ERNS_12JSGlobalDataEPNS_14JSGlobalObjectEPNS_9StructureE
-__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
-__ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
-__ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
-__ZN3JSC3NaNE
-__ZN3JSC41constructFunctionSkippingEvalEnabledCheckEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
-__ZN3JSC4Heap16activityCallbackEv
-__ZN3JSC4Heap16allocateSlowCaseEm
-__ZN3JSC4Heap16objectTypeCountsEv
-__ZN3JSC4Heap17collectAllGarbageEv
-__ZN3JSC4Heap17globalObjectCountEv
-__ZN3JSC4Heap19setActivityCallbackEN3WTF10PassOwnPtrINS_18GCActivityCallbackEEE
-__ZN3JSC4Heap20protectedObjectCountEv
-__ZN3JSC4Heap25protectedObjectTypeCountsEv
-__ZN3JSC4Heap26protectedGlobalObjectCountEv
-__ZN3JSC4Heap29reportExtraMemoryCostSlowCaseEm
-__ZN3JSC4Heap7destroyEv
-__ZN3JSC4Heap7protectENS_7JSValueE
-__ZN3JSC4Heap9unprotectENS_7JSValueE
-__ZN3JSC4Yarr11YarrPatternC1ERKNS_7UStringEbbPPKc
-__ZN3JSC4Yarr11byteCompileERNS0_11YarrPatternEPN3WTF20BumpPointerAllocatorE
-__ZN3JSC4Yarr9interpretEPNS0_15BytecodePatternEPKtjjPi
-__ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
-__ZN3JSC6JSCell11getCallDataERNS_8CallDataE
-__ZN3JSC6JSCell11getJSNumberEv
-__ZN3JSC6JSCell14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC6JSCell14deletePropertyEPNS_9ExecStateEj
-__ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE
-__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC6JSCell18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
-__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC6JSCell3putEPNS_9ExecStateEjNS_7JSValueE  
-__ZN3JSC6JSCell9getObjectEv
-__ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
-__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
-__ZN3JSC6JSLock12DropAllLocksD1Ev
-__ZN3JSC6JSLock26currentThreadIsHoldingLockEv
-__ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
-__ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE
-__ZN3JSC6JSLock9lockCountEv
-__ZN3JSC6JSLockC1EPNS_9ExecStateE
-__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringENS_11RegExpFlagsE
-__ZN3JSC6RegExpD1Ev
-__ZN3JSC7JSArray13visitChildrenERNS_9MarkStackE
-__ZN3JSC7JSArray15setSubclassDataEPv
-__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC7JSArray6s_infoE
-__ZN3JSC7JSArray9setLengthEj
-__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureE
-__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureERKNS_7ArgListE
-__ZN3JSC7JSArrayC2ERNS_12JSGlobalDataEPNS_9StructureE
-__ZN3JSC7JSArrayD2Ev
-__ZN3JSC7JSValue13isValidCalleeEv
-__ZN3JSC7Profile10restoreAllEv
-__ZN3JSC7Profile5focusEPKNS_11ProfileNodeE
-__ZN3JSC7Profile7excludeEPKNS_11ProfileNodeE
-__ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
-__ZN3JSC7UString6numberEd
-__ZN3JSC7UString6numberEi
-__ZN3JSC7UString6numberEj
-__ZN3JSC7UString6numberEl
-__ZN3JSC7UStringC1EPKc
-__ZN3JSC7UStringC1EPKcj
-__ZN3JSC7UStringC1EPKt
-__ZN3JSC7UStringC1EPKtj
-__ZN3JSC7toInt32Ed
-__ZN3JSC8Debugger23recompileAllJSFunctionsEPNS_12JSGlobalDataE
-__ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
-__ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
-__ZN3JSC8DebuggerD2Ev
-__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
-__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
-__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
-__ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC8JSObject13visitChildrenERNS_9MarkStackE
-__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
-__ZN3JSC8JSObject15unwrappedObjectEv
-__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC8JSObject17defineOwnPropertyEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorEb
-__ZN3JSC8JSObject17preventExtensionsERNS_12JSGlobalDataE
-__ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_10JSFunctionEj
-__ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
-__ZN3JSC8JSObject17putWithAttributesEPNS_12JSGlobalDataERKNS_10IdentifierENS_7JSValueEj
-__ZN3JSC8JSObject17putWithAttributesEPNS_12JSGlobalDataERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotE
-__ZN3JSC8JSObject17putWithAttributesEPNS_12JSGlobalDataEjNS_7JSValueEj
-__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
-__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotE
-__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateEjNS_7JSValueEj
-__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
-__ZN3JSC8JSObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC8JSObject21getPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_16WriteBarrierBaseINS_7UnknownEEE
-__ZN3JSC8JSObject23allocatePropertyStorageEmm
-__ZN3JSC8JSObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
-__ZN3JSC8JSObject6s_infoE
-__ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC8Profiler8profilerEv
-__ZN3JSC8evaluateEPNS_9ExecStateEPNS_14ScopeChainNodeERKNS_10SourceCodeENS_7JSValueE
-__ZN3JSC8isZombieEPKNS_6JSCellE
-__ZN3JSC9CodeBlockD1Ev
-__ZN3JSC9CodeBlockD2Ev
-__ZN3JSC9MarkStack10s_pageSizeE
-__ZN3JSC9MarkStack18initializePagesizeEv
-__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
-__ZN3JSC9Structure6s_infoE
-__ZN3JSC9StructureC1ERNS_12JSGlobalDataENS_7JSValueERKNS_8TypeInfoEjPKNS_9ClassInfoE
-__ZN3JSC9StructureD1Ev
-__ZN3JSC9constructEPNS_9ExecStateENS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
-__ZN3JSCeqERKNS_7UStringEPKc
-__ZN3JSCgtERKNS_7UStringES2_
-__ZN3JSCltERKNS_7UStringES2_
-__ZN3WTF10StringImpl11reverseFindEPS0_j
-__ZN3WTF10StringImpl11reverseFindEtj
-__ZN3WTF10StringImpl12sharedBufferEv
-__ZN3WTF10StringImpl16findIgnoringCaseEPKcj
-__ZN3WTF10StringImpl16findIgnoringCaseEPS0_j
-__ZN3WTF10StringImpl18simplifyWhiteSpaceEv
-__ZN3WTF10StringImpl19characterStartingAtEj
-__ZN3WTF10StringImpl19createUninitializedEjRPt
-__ZN3WTF10StringImpl22containsOnlyWhitespaceEv
-__ZN3WTF10StringImpl23defaultWritingDirectionEPb
-__ZN3WTF10StringImpl23reverseFindIgnoringCaseEPS0_j
-__ZN3WTF10StringImpl37createStrippingNullCharactersSlowCaseEPKtj
-__ZN3WTF10StringImpl4findEPFbtEj
-__ZN3WTF10StringImpl4findEPKcj
-__ZN3WTF10StringImpl4findEPS0_j
-__ZN3WTF10StringImpl4findEtj
-__ZN3WTF10StringImpl5adoptERNS_12StringBufferE
-__ZN3WTF10StringImpl5emptyEv
-__ZN3WTF10StringImpl5lowerEv
-__ZN3WTF10StringImpl5toIntEPb
-__ZN3WTF10StringImpl5upperEv
-__ZN3WTF10StringImpl6createEPKc
-__ZN3WTF10StringImpl6createEPKcj
-__ZN3WTF10StringImpl6createEPKtj
-__ZN3WTF10StringImpl6secureEtNS0_21LastCharacterBehaviorE
-__ZN3WTF10StringImpl7replaceEPS0_S1_
-__ZN3WTF10StringImpl7replaceEjjPS0_
-__ZN3WTF10StringImpl7replaceEtPS0_
-__ZN3WTF10StringImpl7replaceEtt
-__ZN3WTF10StringImpl8endsWithEPS0_b
-__ZN3WTF10StringImpl9substringEjj
-__ZN3WTF10StringImplD1Ev
-__ZN3WTF10fastCallocEmm
-__ZN3WTF10fastMallocEm
-__ZN3WTF10fastStrDupEPKc
-__ZN3WTF11OSAllocator16reserveAndCommitEmNS0_5UsageEbbb
-__ZN3WTF11OSAllocator18releaseDecommittedEPvm
-__ZN3WTF11commentAtomE
-__ZN3WTF11currentTimeEv
-__ZN3WTF11dtoaRoundDPEPcdiRbRiRj
-__ZN3WTF11dtoaRoundSFEPcdiRbRiRj
-__ZN3WTF11emptyStringEv
-__ZN3WTF11fastReallocEPvm
-__ZN3WTF12AtomicString11addSlowCaseEPNS_10StringImplE
-__ZN3WTF12AtomicString16fromUTF8InternalEPKcS2_
-__ZN3WTF12AtomicString3addEPKc
-__ZN3WTF12AtomicString3addEPKt
-__ZN3WTF12AtomicString3addEPKtj
-__ZN3WTF12AtomicString3addEPKtjj
-__ZN3WTF12AtomicString4findEPKtjj
-__ZN3WTF12AtomicString4initEv
-__ZN3WTF12createThreadEPFPvS0_ES0_
-__ZN3WTF12createThreadEPFPvS0_ES0_PKc
-__ZN3WTF12detachThreadEj
-__ZN3WTF12isMainThreadEv
-__ZN3WTF12randomNumberEv
-__ZN3WTF13StringBuilder11reifyStringEv
-__ZN3WTF13StringBuilder11shrinkToFitEv
-__ZN3WTF13StringBuilder15reserveCapacityEj
-__ZN3WTF13StringBuilder6appendEPKcj
-__ZN3WTF13StringBuilder6appendEPKtj
-__ZN3WTF13StringBuilder6resizeEj
-__ZN3WTF13WTFThreadData10staticDataE
-__ZN3WTF13WTFThreadDataC1Ev
-__ZN3WTF13WTFThreadDataD1Ev
-__ZN3WTF13currentThreadEv
-__ZN3WTF13tryFastCallocEmm
-__ZN3WTF13tryFastMallocEm
-__ZN3WTF14fastMallocSizeEPKv
-__ZN3WTF14numberToStringEdPt
-__ZN3WTF14tryFastReallocEPvm
-__ZN3WTF15ThreadCondition4waitERNS_5MutexE
-__ZN3WTF15ThreadCondition6signalEv
-__ZN3WTF15ThreadCondition9broadcastEv
-__ZN3WTF15ThreadCondition9timedWaitERNS_5MutexEd
-__ZN3WTF15ThreadConditionC1Ev
-__ZN3WTF15ThreadConditionD1Ev
-__ZN3WTF15charactersToIntEPKtmPb
-__ZN3WTF16callOnMainThreadEPFvPvES0_
-__ZN3WTF16codePointCompareERKNS_6StringES2_
-__ZN3WTF16fastZeroedMallocEm
-__ZN3WTF17charactersToFloatEPKtmPbS2_
-__ZN3WTF17equalIgnoringCaseEPKtPKcj
-__ZN3WTF17equalIgnoringCaseEPNS_10StringImplEPKc
-__ZN3WTF17equalIgnoringCaseEPNS_10StringImplES1_
-__ZN3WTF18calculateDSTOffsetEdd
-__ZN3WTF18calculateUTCOffsetEv
-__ZN3WTF18charactersToDoubleEPKtmPbS2_
-__ZN3WTF18dateToDaysFrom1970Eiii
-__ZN3WTF18monthFromDayInYearEib
-__ZN3WTF19initializeThreadingEv
-__ZN3WTF20equalIgnoringNullityEPNS_10StringImplES1_
-__ZN3WTF20fastMallocStatisticsEv
-__ZN3WTF20initializeMainThreadEv
-__ZN3WTF21RefCountedLeakCounter16suppressMessagesEPKc
-__ZN3WTF21RefCountedLeakCounter24cancelMessageSuppressionEPKc
-__ZN3WTF21RefCountedLeakCounter9decrementEv
-__ZN3WTF21RefCountedLeakCounter9incrementEv
-__ZN3WTF21RefCountedLeakCounterC1EPKc
-__ZN3WTF21RefCountedLeakCounterD1Ev
-__ZN3WTF21charactersToIntStrictEPKtmPbi
-__ZN3WTF22cancelCallOnMainThreadEPFvPvES0_
-__ZN3WTF22charactersToUIntStrictEPKtmPbi
-__ZN3WTF23callOnMainThreadAndWaitEPFvPvES0_
-__ZN3WTF23dayInMonthFromDayInYearEib
-__ZN3WTF23waitForThreadCompletionEjPPv
-__ZN3WTF27releaseFastMallocFreeMemoryEv
-__ZN3WTF28setMainThreadCallbacksPausedEb
-__ZN3WTF29cryptographicallyRandomNumberEv
-__ZN3WTF29cryptographicallyRandomValuesEPvm
-__ZN3WTF36lockAtomicallyInitializedStaticMutexEv
-__ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
-__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
-__ZN3WTF39initializeMainThreadToProcessMainThreadEv
-__ZN3WTF3MD58addBytesEPKhm
-__ZN3WTF3MD58checksumERNS_6VectorIhLm16EEE
-__ZN3WTF3MD5C1Ev
-__ZN3WTF4SHA111computeHashERNS_6VectorIhLm20EEE
-__ZN3WTF4SHA18addBytesEPKhm
-__ZN3WTF4SHA1C1Ev
-__ZN3WTF4dtoaEPcdRbRiRj
-__ZN3WTF5Mutex4lockEv
-__ZN3WTF5Mutex6unlockEv
-__ZN3WTF5Mutex7tryLockEv
-__ZN3WTF5MutexC1Ev
-__ZN3WTF5MutexD1Ev
-__ZN3WTF5equalEPKNS_10StringImplEPKc
-__ZN3WTF5equalEPKNS_10StringImplES2_
-__ZN3WTF5yieldEv
-__ZN3WTF6String26fromUTF8WithLatin1FallbackEPKcm
-__ZN3WTF6String29charactersWithNullTerminationEv
-__ZN3WTF6String6appendEPKtj
-__ZN3WTF6String6appendERKS0_
-__ZN3WTF6String6appendEc
-__ZN3WTF6String6appendEt
-__ZN3WTF6String6formatEPKcz
-__ZN3WTF6String6insertERKS0_j
-__ZN3WTF6String6numberEd
-__ZN3WTF6String6numberEi
-__ZN3WTF6String6numberEj
-__ZN3WTF6String6numberEl
-__ZN3WTF6String6numberEm
-__ZN3WTF6String6numberEt
-__ZN3WTF6String6numberEx
-__ZN3WTF6String6numberEy
-__ZN3WTF6String6removeEji
-__ZN3WTF6String8fromUTF8EPKc
-__ZN3WTF6String8fromUTF8EPKcm
-__ZN3WTF6String8truncateEj
-__ZN3WTF6StringC1EPKc
-__ZN3WTF6StringC1EPKcj
-__ZN3WTF6StringC1EPKt
-__ZN3WTF6StringC1EPKtj
-__ZN3WTF6strtodEPKcPPc
-__ZN3WTF7CString11mutableDataEv
-__ZN3WTF7CString16newUninitializedEmRPc
-__ZN3WTF7CStringC1EPKc
-__ZN3WTF7CStringC1EPKcm
-__ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
-__ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b
-__ZN3WTF7xmlAtomE
-__ZN3WTF8Collator18setOrderLowerFirstEb
-__ZN3WTF8CollatorC1EPKc
-__ZN3WTF8CollatorD1Ev
-__ZN3WTF8Internal21fastMallocMatchFailedEPv
-__ZN3WTF8fastFreeEPv
-__ZN3WTF8msToYearEd
-__ZN3WTF8nullAtomE
-__ZN3WTF8starAtomE
-__ZN3WTF8textAtomE
-__ZN3WTF9ByteArray6createEm
-__ZN3WTF9dayInYearEdi
-__ZN3WTF9emptyAtomE
-__ZN3WTF9xmlnsAtomE
-__ZN3WTFeqERKNS_12AtomicStringEPKc
-__ZN3WTFeqERKNS_12AtomicStringERKNS_6VectorItLm0EEE
-__ZN3WTFeqERKNS_7CStringES2_
-__ZNK3JSC10JSFunction23isHostFunctionNonInlineEv
-__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_10JSFunctionE
-__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
-__ZNK3JSC12PropertySlot14functionGetterEPNS_9ExecStateE
-__ZNK3JSC14JSGlobalObject14isDynamicScopeERb
-__ZNK3JSC16JSVariableObject16isVariableObjectEv
-__ZNK3JSC17DebuggerCallFrame10thisObjectEv
-__ZNK3JSC17DebuggerCallFrame12functionNameEv
-__ZNK3JSC17DebuggerCallFrame22calculatedFunctionNameEv
-__ZNK3JSC17DebuggerCallFrame4typeEv
-__ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_7JSValueE
-__ZNK3JSC18PropertyDescriptor10enumerableEv
-__ZNK3JSC18PropertyDescriptor12configurableEv
-__ZNK3JSC18PropertyDescriptor16isDataDescriptorEv
-__ZNK3JSC18PropertyDescriptor20isAccessorDescriptorEv
-__ZNK3JSC18PropertyDescriptor6getterEv
-__ZNK3JSC18PropertyDescriptor6setterEv
-__ZNK3JSC18PropertyDescriptor8writableEv
-__ZNK3JSC19SourceProviderCache8byteSizeEv
-__ZNK3JSC4Heap11objectCountEv
-__ZNK3JSC4Heap4sizeEv
-__ZNK3JSC4Heap8capacityEv
-__ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
-__ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
-__ZNK3JSC6JSCell14isGetterSetterEv
-__ZNK3JSC6JSCell8toNumberEPNS_9ExecStateE
-__ZNK3JSC6JSCell8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE
-__ZNK3JSC6JSCell8toStringEPNS_9ExecStateE
-__ZNK3JSC6JSCell9getStringEPNS_9ExecStateE
-__ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE
-__ZNK3JSC6JSCell9getUInt32ERj
-__ZNK3JSC6JSCell9toBooleanEPNS_9ExecStateE
-__ZNK3JSC7ArgList8getSliceEiRS0_
-__ZNK3JSC7JSArray12subclassDataEv
-__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateEPNS_14JSGlobalObjectE
-__ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
-__ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
-__ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
-__ZNK3JSC7UString20substringSharingImplEjj
-__ZNK3JSC7UString4utf8Eb
-__ZNK3JSC7UString5asciiEv
-__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
-__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
-__ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
-__ZNK3JSC8JSObject18toStrictThisObjectEPNS_9ExecStateE
-__ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
-__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE
-__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
-__ZNK3JSC8JSObject9classNameEv
-__ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
-__ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE
-__ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
-__ZNK3JSC9HashTable11deleteTableEv
-__ZNK3WTF12AtomicString5lowerEv
-__ZNK3WTF13DecimalNumber15toStringDecimalEPtj
-__ZNK3WTF13DecimalNumber19toStringExponentialEPtj
-__ZNK3WTF13DecimalNumber28bufferLengthForStringDecimalEv
-__ZNK3WTF13DecimalNumber32bufferLengthForStringExponentialEv
-__ZNK3WTF6String11toIntStrictEPbi
-__ZNK3WTF6String12toUIntStrictEPbi
-__ZNK3WTF6String13toInt64StrictEPbi
-__ZNK3WTF6String14threadsafeCopyEv
-__ZNK3WTF6String15stripWhiteSpaceEv
-__ZNK3WTF6String16removeCharactersEPFbtE
-__ZNK3WTF6String17crossThreadStringEv
-__ZNK3WTF6String18simplifyWhiteSpaceEv
-__ZNK3WTF6String19characterStartingAtEj
-__ZNK3WTF6String4utf8Eb
-__ZNK3WTF6String5asciiEv
-__ZNK3WTF6String5lowerEv
-__ZNK3WTF6String5splitERKS0_RNS_6VectorIS0_Lm0EEE
-__ZNK3WTF6String5splitERKS0_bRNS_6VectorIS0_Lm0EEE
-__ZNK3WTF6String5splitEtRNS_6VectorIS0_Lm0EEE
-__ZNK3WTF6String5splitEtbRNS_6VectorIS0_Lm0EEE
-__ZNK3WTF6String5toIntEPb
-__ZNK3WTF6String5upperEv
-__ZNK3WTF6String6latin1Ev
-__ZNK3WTF6String6toUIntEPb
-__ZNK3WTF6String7toFloatEPbS1_
-__ZNK3WTF6String8foldCaseEv
-__ZNK3WTF6String8toDoubleEPbS1_
-__ZNK3WTF6String8toIntPtrEPb
-__ZNK3WTF6String8toUInt64EPb
-__ZNK3WTF6String9substringEjj
-__ZNK3WTF8Collator7collateEPKtmS2_m
-__ZTVN3JSC12StringObjectE
-__ZTVN3JSC14JSGlobalObjectE
-__ZTVN3JSC14ScopeChainNodeE
-__ZTVN3JSC15JSWrapperObjectE
-__ZTVN3JSC15WeakHandleOwnerE
-__ZTVN3JSC16InternalFunctionE
-__ZTVN3JSC16JSVariableObjectE
-__ZTVN3JSC8DebuggerE
-__ZTVN3JSC8JSObjectE
-__ZTVN3JSC8JSStringE
-_jscore_fastmalloc_introspection
-_kJSClassDefinitionEmpty
-
-# iOS methods
-__ZN3WTF11isWebThreadEv
-__ZN3JSC12JSGlobalData23recompileAllJSFunctionsEv
-__ZN3JSC12JSGlobalData20sharedInstanceExistsEv
-__ZN3JSC25DefaultGCActivityCallbackC2EPNS_4HeapEP11__CFRunLoop
-__ZN3JSC25DefaultGCActivityCallbackD2Ev
-__ZN3JSC25DefaultGCActivityCallbackclEv
-__ZN3JSC25DefaultGCActivityCallback11synchronizeEv
-__ZTVN3JSC25DefaultGCActivityCallbackE
diff --git a/JavaScriptCore.gyp/.gitignore b/JavaScriptCore.gyp/.gitignore
new file mode 100644 (file)
index 0000000..9b06f58
--- /dev/null
@@ -0,0 +1,5 @@
+*.Makefile
+*.mk
+*.sln
+*.vcproj*
+JavaScriptCore.xcodeproj
index eff360736e209d0ca07c99e34a3ee416916e3fa2..a89ac51203cf246f0caf4181f753cced04f18a1a 100644 (file)
@@ -1,10 +1,10 @@
 #
 #
-# Copyright (C) 2009 Google Inc. All rights reserved.
-# 
+# Copyright (C) 2009, 2012 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:
 # 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
 #     * 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
@@ -14,7 +14,7 @@
 #     * 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.
 #     * 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
 # 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
@@ -30,8 +30,7 @@
 
 {
   'includes': [
 
 {
   'includes': [
-    # FIXME: Sense whether upstream or downstream build, and
-    # include the right features.gypi
+    '../../WebKit/chromium/WinPrecompile.gypi',
     '../../WebKit/chromium/features.gypi',
     '../JavaScriptCore.gypi',
   ],
     '../../WebKit/chromium/features.gypi',
     '../JavaScriptCore.gypi',
   ],
       }],
     ],
   },
       }],
     ],
   },
-  'targets': [
-    {
-      # This target sets up defines and includes that are required by WTF and
-      # its dependents.
-      'target_name': 'wtf_config',
-      'type': 'none',
-      'msvs_guid': '2E2D3301-2EC4-4C0F-B889-87073B30F673',
-      'direct_dependent_settings': {
-        'defines': [
-          # Import features_defines from features.gypi
-          '<@(feature_defines)',
-          
-          # Turns on #if PLATFORM(CHROMIUM)
-          'BUILDING_CHROMIUM__=1',
-          # Controls wtf/FastMalloc
-          # FIXME: consider moving into config.h
-          'USE_SYSTEM_MALLOC=1',
-        ],
-        'conditions': [
-          ['OS=="win"', {
-            'defines': [
-              '__STD_C',
-              '_CRT_SECURE_NO_DEPRECATE',
-              '_SCL_SECURE_NO_DEPRECATE',
-              'CRASH=__debugbreak',
-            ],
-            'include_dirs': [
-              '../os-win32',
-            ],
-          }],
-          ['OS=="mac"', {
-            'defines': [
-              # Use USE_NEW_THEME on Mac.
-              'WTF_USE_NEW_THEME=1',
-            ],
-          }],
-          ['OS=="linux" or OS=="freebsd"', {
-            'defines': [
-              'WTF_USE_PTHREADS=1',
-            ],
-          }],
-        ],
-      }
-    },
-    {
-      'target_name': 'wtf',
-      'type': '<(library)',
-      'msvs_guid': 'AA8A5A85-592B-4357-BC60-E0E91E026AF6',
-      'dependencies': [
-        'wtf_config',
-        '<(chromium_src_dir)/third_party/icu/icu.gyp:icui18n',
-        '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc',
-      ],
-      'include_dirs': [
-        '../',
-        '../wtf',
-        '../wtf/unicode',
-      ],
-      'sources': [
-        '<@(javascriptcore_publicheader_files)',
-        '<@(javascriptcore_privateheader_files)',
-        '<@(javascriptcore_files)',
-      ],
-      'sources/': [
-        # First exclude everything ...
-        ['exclude', '../'],
-        # ... Then include what we want.
-        ['include', '../wtf/'],
-        # FIXME: This is clearly not sustainable. 
-        ['exclude', '../wtf/android'], 
-        ['exclude', '../wtf/brew'], 
-        ['exclude', '../wtf/efl'], 
-        ['exclude', '../wtf/gobject'], 
-        ['exclude', '../wtf/gtk'], 
-        ['exclude', '../wtf/haiku'], 
-        ['exclude', '../wtf/mac'], 
-        ['exclude', '../wtf/qt'], 
-        ['exclude', '../wtf/url'], 
-        ['exclude', '../wtf/wince'], 
-        ['exclude', '../wtf/wx'], 
-        ['exclude', '../wtf/unicode/brew'], 
-        ['exclude', '../wtf/unicode/wince'], 
-        ['exclude', '../wtf/unicode/glib'], 
-        ['exclude', '../wtf/unicode/qt4'], 
-        # GLib/GTK, even though its name doesn't really indicate.
-        ['exclude', '/(gtk|glib|gobject)/.*\\.(cpp|h)$'],
-        ['exclude', '(Default|Gtk|Mac|None|Qt|Win|Wx|Efl|Symbian)\\.(cpp|mm)$'],
-        ['exclude', 'wtf/CurrentTime\\.cpp$'],
-        ['exclude', 'wtf/OSRandomSource\\.cpp$'],
-        ['exclude', 'wtf/MainThread.cpp$'],
-        ['exclude', 'wtf/TC.*\\.(cpp|h)$'],
-      ],
-      'direct_dependent_settings': {
-        'include_dirs': [
-          '../',
-          '../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,
-        ],
+  'conditions': [
+    ['os_posix == 1 and OS != "mac" and OS != "android" and gcc_version==46', {
+      'target_defaults': {
+        # Disable warnings about c++0x compatibility, as some names (such as nullptr) conflict
+        # with upcoming c++0x types.
+        'cflags_cc': ['-Wno-c++0x-compat'],
       },
       },
-      'export_dependent_settings': [
-        'wtf_config',
-        '<(chromium_src_dir)/third_party/icu/icu.gyp:icui18n',
-        '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc',
-      ],
-      'msvs_disabled_warnings': [4127, 4355, 4510, 4512, 4610, 4706],
-      'conditions': [
-        ['OS=="win"', {
-          'sources/': [
-            ['exclude', 'ThreadIdentifierDataPthreads\\.(h|cpp)$'],
-            ['exclude', 'ThreadingPthreads\\.cpp$'],
-            ['include', 'Thread(ing|Specific)Win\\.cpp$'],
-            ['exclude', 'OSAllocatorPosix\\.cpp$'],
-            ['include', 'OSAllocatorWin\\.cpp$']
-          ],
-          'include_dirs!': [
-            '<(SHARED_INTERMEDIATE_DIR)/webkit',
-          ],
-          'conditions': [
-            ['inside_chromium_build==1 and component=="shared_library"', {
-              # Chromium windows multi-dll build enables c++ exception and this
-              # causes wtf generates 4291 warning due to operator new/delete
-              # implementations. Disable the warning for chromium windows
-              # multi-dll build.
-              'msvs_disabled_warnings': [4291],
-              'direct_dependent_settings': {
-                'msvs_disabled_warnings': [4291],
-              },
-            }],
-          ],
-        }],
-      ],
-    },
+    }],
+  ],
+  'targets': [
     {
       'target_name': 'yarr',
     {
       'target_name': 'yarr',
-      'type': '<(library)',
+      'type': 'static_library',
       'dependencies': [
       'dependencies': [
-        'wtf',
-      ],
-      'conditions': [
-        ['OS=="win"', {
-          'dependencies': ['<(chromium_src_dir)/build/win/system.gyp:cygwin'],
-        }],
+        '../../WTF/WTF.gyp/WTF.gyp:wtf',
       ],
       ],
-      'msvs_guid': '49909552-0B0C-4C14-8CF6-DB8A2ADE0934',
+      'variables': { 'optimize': 'max' },
       'actions': [
         {
           'action_name': 'retgen',
       'actions': [
         {
           'action_name': 'retgen',
       ],
       'include_dirs': [
         '<(INTERMEDIATE_DIR)',
       ],
       'include_dirs': [
         '<(INTERMEDIATE_DIR)',
+        '..',
         '../runtime',
       ],
       'sources': [
         '../runtime',
       ],
       'sources': [
         ['exclude', '../yarr/YarrJIT\\.(h|cpp)$'],
       ],
       'export_dependent_settings': [
         ['exclude', '../yarr/YarrJIT\\.(h|cpp)$'],
       ],
       'export_dependent_settings': [
-        'wtf',
+        '../../WTF/WTF.gyp/WTF.gyp:wtf',
       ],
     },
   ], # targets
       ],
     },
   ], # targets
index c101031bdda2ac707c2874123b24fc8e2b1c032c..4a03be89345afb6938d7e6da341bba0a95247e55 100644 (file)
         'project_dir': ['.'],
         # These headers are part of JavaScriptCore's public API in the Apple Mac build.
         'javascriptcore_publicheader_files': [
         'project_dir': ['.'],
         # These headers are part of JavaScriptCore's public API in the Apple Mac build.
         'javascriptcore_publicheader_files': [
+            'API/APICast.h',
+            'API/APIShims.h',
             'API/JSBase.h',
             'API/JSContextRef.h',
             'API/JSBase.h',
             'API/JSContextRef.h',
+            'API/JSContextRefPrivate.h',
             'API/JSObjectRef.h',
             'API/JSObjectRef.h',
+            'API/JSObjectRefPrivate.h',
+            'API/JSRetainPtr.h',
             'API/JSStringRef.h',
             'API/JSStringRef.h',
+            'API/JSStringRefBSTR.h',
             'API/JSStringRefCF.h',
             'API/JSValueRef.h',
             'API/JSStringRefCF.h',
             'API/JSValueRef.h',
+            'API/JSWeakObjectMapRefInternal.h',
+            'API/JSWeakObjectMapRefPrivate.h',
             'API/JavaScript.h',
             'API/JavaScriptCore.h',
             'API/JavaScript.h',
             'API/JavaScriptCore.h',
+            'API/OpaqueJSString.h',
             'API/WebKitAvailability.h',
         ],
         # These headers are part of JavaScriptCore's private API in the Apple Mac build.
         'javascriptcore_privateheader_files': [
             'API/WebKitAvailability.h',
         ],
         # These headers are part of JavaScriptCore's private API in the Apple Mac build.
         'javascriptcore_privateheader_files': [
-            'API/APICast.h',
-            'API/APIShims.h',
-            'API/JSBasePrivate.h',
-            'API/JSContextRefPrivate.h',
-            'API/JSObjectRefPrivate.h',
-            'API/JSProfilerPrivate.h',
-            'API/JSRetainPtr.h',
-            'API/JSWeakObjectMapRefInternal.h',
-            'API/JSWeakObjectMapRefPrivate.h',
-            'API/OpaqueJSString.h',
+            'assembler/AbstractMacroAssembler.h',
+            'assembler/ARMAssembler.h',
+            'assembler/ARMv7Assembler.h',
+            'assembler/AssemblerBuffer.h',
+            'assembler/AssemblerBufferWithConstantPool.h',
+            'assembler/CodeLocation.h',
+            'assembler/LinkBuffer.h',
+            'assembler/MacroAssembler.h',
+            'assembler/MacroAssemblerARM.h',
+            'assembler/MacroAssemblerARMv7.h',
             'assembler/MacroAssemblerCodeRef.h',
             'assembler/MacroAssemblerCodeRef.h',
+            'assembler/MacroAssemblerMIPS.h',
+            'assembler/MacroAssemblerSH4.h',
+            'assembler/MacroAssemblerX86.h',
+            'assembler/MacroAssemblerX86Common.h',
+            'assembler/MacroAssemblerX86_64.h',
+            'assembler/MIPSAssembler.h',
+            'assembler/RepatchBuffer.h',
+            'assembler/SH4Assembler.h',
+            'assembler/X86Assembler.h',
+            'bytecode/BytecodeConventions.h',
+            'bytecode/CallLinkInfo.h',
+            'bytecode/CallLinkStatus.h',
+            'bytecode/CallReturnOffsetToBytecodeOffset.h',
+            'bytecode/CodeBlock.h',
+            'bytecode/CodeOrigin.h',
+            'bytecode/CodeType.h',
+            'bytecode/DataFormat.h',
+            'bytecode/DFGExitProfile.h',
+            'bytecode/EvalCodeCache.h',
+            'bytecode/ExecutionCounter.h',
+            'bytecode/ExpressionRangeInfo.h',
+            'bytecode/GetByIdStatus.h',
+            'bytecode/GlobalResolveInfo.h',
+            'bytecode/HandlerInfo.h',
+            'bytecode/Instruction.h',
+            'bytecode/JumpTable.h',
+            'bytecode/LazyOperandValueProfile.h',
+            'bytecode/LineInfo.h',
+            'bytecode/LLIntCallLinkInfo.h',
+            'bytecode/MethodCallLinkInfo.h',
+            'bytecode/MethodCallLinkStatus.h',
+            'bytecode/MethodOfGettingAValueProfile.h',
             'bytecode/Opcode.h',
             'bytecode/Opcode.h',
+            'bytecode/Operands.h',
+            'bytecode/PolymorphicPutByIdList.h',
+            'bytecode/PredictedType.h',
+            'bytecode/PredictionTracker.h',
+            'bytecode/PutByIdStatus.h',
+            'bytecode/PutKind.h',
+            'bytecode/SamplingTool.h',
+            'bytecode/StructureSet.h',
+            'bytecode/StructureStubInfo.h',
+            'bytecode/ValueProfile.h',
+            'bytecode/ValueRecovery.h',
+            'bytecode/VirtualRegister.h',
+            'dfg/DFGAbstractState.h',
+            'dfg/DFGAbstractValue.h',
+            'dfg/DFGAdjacencyList.h',
+            'dfg/DFGAssemblyHelpers.h',
+            'dfg/DFGBasicBlock.h',
+            'dfg/DFGByteCodeCache.h',
+            'dfg/DFGByteCodeParser.h',
+            'dfg/DFGCapabilities.h',
+            'dfg/DFGCCallHelpers.h',
+            'dfg/DFGCFAPhase.h',
+            'dfg/DFGCommon.h',
+            'dfg/DFGCorrectableJumpPoint.h',
+            'dfg/DFGCSEPhase.h',
+            'dfg/DFGDriver.h',
+            'dfg/DFGEdge.h',
+            'dfg/DFGFixupPhase.h',
+            'dfg/DFGFPRInfo.h',
+            'dfg/DFGGenerationInfo.h',
+            'dfg/DFGGPRInfo.h',
+            'dfg/DFGGraph.h',
+            'dfg/DFGInsertionSet.h',
+            'dfg/DFGJITCompiler.h',
+            'dfg/DFGNode.h',
+            'dfg/DFGNodeFlags.h',
+            'dfg/DFGNodeType.h',
+            'dfg/DFGOperations.h',
+            'dfg/DFGOSREntry.h',
+            'dfg/DFGOSRExit.h',
+            'dfg/DFGOSRExitCompiler.h',
+            'dfg/DFGPhase.h',
+            'dfg/DFGPredictionPropagationPhase.h',
+            'dfg/DFGRedundantPhiEliminationPhase.h',
+            'dfg/DFGRegisterBank.h',
+            'dfg/DFGRepatch.h',
+            'dfg/DFGScoreBoard.h',
+            'dfg/DFGSpeculativeJIT.h',
+            'dfg/DFGThunks.h',
+            'dfg/DFGVariableAccessData.h',
+            'dfg/DFGVirtualRegisterAllocationPhase.h',
+            'heap/CardSet.h',
             'heap/ConservativeRoots.h',
             'heap/ConservativeRoots.h',
+            'heap/CopiedAllocator.h',
+            'heap/CopiedBlock.h',
+            'heap/CopiedSpace.h',
+            'heap/CopiedSpaceInlineMethods.h',
+            'heap/DFGCodeBlocks.h',
+            'heap/GCAssertions.h',
             'heap/Handle.h',
             'heap/Handle.h',
-            'heap/HandleHeap.h',
+            'heap/HandleSet.h',
             'heap/HandleStack.h',
             'heap/HandleTypes.h',
             'heap/Heap.h',
             'heap/HandleStack.h',
             'heap/HandleTypes.h',
             'heap/Heap.h',
+            'heap/HeapBlock.h',
+            'heap/HeapRootVisitor.h',
+            'heap/ListableHandler.h',
             'heap/Local.h',
             'heap/LocalScope.h',
             'heap/Local.h',
             'heap/LocalScope.h',
+            'heap/MachineStackMarker.h',
+            'heap/MarkedAllocator.h',
+            'heap/MarkedBlock.h',
+            'heap/MarkedBlockSet.h',
+            'heap/MarkedSpace.h',
+            'heap/MarkStack.h',
+            'heap/PassWeak.h',
+            'heap/SlotVisitor.h',
             'heap/Strong.h',
             'heap/Strong.h',
+            'heap/StrongInlines.h',
+            'heap/TinyBloomFilter.h',
+            'heap/UnconditionalFinalizer.h',
+            'heap/VTableSpectrum.h',
             'heap/Weak.h',
             'heap/Weak.h',
-            'config.h',
+            'heap/WeakBlock.h',
+            'heap/WeakHandleOwner.h',
+            'heap/WeakImpl.h',
+            'heap/WeakReferenceHarvester.h',
+            'heap/WeakSet.h',
+            'heap/WeakSetInlines.h',
+            'heap/WriteBarrierSupport.h',
             'debugger/Debugger.h',
             'debugger/DebuggerActivation.h',
             'debugger/DebuggerCallFrame.h',
             'debugger/Debugger.h',
             'debugger/DebuggerActivation.h',
             'debugger/DebuggerCallFrame.h',
+            'interpreter/AbstractPC.h',
+            'interpreter/CachedCall.h',
             'interpreter/CallFrame.h',
             'interpreter/CallFrame.h',
+            'interpreter/CallFrameClosure.h',
             'interpreter/Interpreter.h',
             'interpreter/Register.h',
             'interpreter/RegisterFile.h',
             'interpreter/Interpreter.h',
             'interpreter/Register.h',
             'interpreter/RegisterFile.h',
+            'jit/CompactJITCodeMap.h',
             'jit/ExecutableAllocator.h',
             'jit/ExecutableAllocator.h',
+            'jit/HostCallReturnValue.h',
+            'jit/JIT.h',
             'jit/JITCode.h',
             'jit/JITCode.h',
+            'jit/JITCompilationEffort.h',
+            'jit/JITDriver.h',
+            'jit/JITExceptions.h',
+            'jit/JITInlineMethods.h',
+            'jit/JITStubCall.h',
             'jit/JITStubs.h',
             'jit/JITStubs.h',
+            'jit/JITWriteBarrier.h',
+            'jit/JSInterfaceJIT.h',
+            'jit/SpecializedThunkJIT.h',
             'jit/ThunkGenerators.h',
             'jit/ThunkGenerators.h',
+            'parser/ASTBuilder.h',
+            'parser/Lexer.h',
+            'parser/NodeConstructors.h',
+            'parser/NodeInfo.h',
+            'parser/Nodes.h',
+            'parser/Parser.h',
+            'parser/ParserArena.h',
+            'parser/ParserTokens.h',
             'parser/ResultType.h',
             'parser/SourceCode.h',
             'parser/SourceProvider.h',
             'parser/SourceProviderCache.h',
             'parser/ResultType.h',
             'parser/SourceCode.h',
             'parser/SourceProvider.h',
             'parser/SourceProviderCache.h',
+            'parser/SourceProviderCacheItem.h',
+            'parser/SyntaxChecker.h',
             'profiler/CallIdentifier.h',
             'profiler/Profile.h',
             'profiler/CallIdentifier.h',
             'profiler/Profile.h',
+            'profiler/ProfileGenerator.h',
             'profiler/ProfileNode.h',
             'profiler/Profiler.h',
             'runtime/ArgList.h',
             'profiler/ProfileNode.h',
             'profiler/Profiler.h',
             'runtime/ArgList.h',
+            'runtime/Arguments.h',
+            'runtime/ArrayConstructor.h',
             'runtime/ArrayPrototype.h',
             'runtime/ArrayPrototype.h',
+            'runtime/BatchedTransitionOptimizer.h',
+            'runtime/BigInteger.h',
+            'runtime/BooleanConstructor.h',
             'runtime/BooleanObject.h',
             'runtime/BooleanObject.h',
+            'runtime/BooleanPrototype.h',
             'runtime/CachedTranscendentalFunction.h',
             'runtime/CallData.h',
             'runtime/ClassInfo.h',
             'runtime/CachedTranscendentalFunction.h',
             'runtime/CallData.h',
             'runtime/ClassInfo.h',
+            'runtime/CodeSpecializationKind.h',
             'runtime/CommonIdentifiers.h',
             'runtime/CommonIdentifiers.h',
+            'runtime/CommonSlowPaths.h',
             'runtime/Completion.h',
             'runtime/ConstructData.h',
             'runtime/Completion.h',
             'runtime/ConstructData.h',
+            'runtime/DateConstructor.h',
+            'runtime/DateConversion.h',
             'runtime/DateInstance.h',
             'runtime/DateInstanceCache.h',
             'runtime/DateInstance.h',
             'runtime/DateInstanceCache.h',
+            'runtime/DatePrototype.h',
             'runtime/Error.h',
             'runtime/Error.h',
+            'runtime/ErrorConstructor.h',
+            'runtime/ErrorInstance.h',
+            'runtime/ErrorPrototype.h',
             'runtime/ExceptionHelpers.h',
             'runtime/ExceptionHelpers.h',
+            'runtime/Executable.h',
+            'runtime/ExecutionHarness.h',
             'runtime/FunctionConstructor.h',
             'runtime/FunctionPrototype.h',
             'runtime/GCActivityCallback.h',
             'runtime/FunctionConstructor.h',
             'runtime/FunctionPrototype.h',
             'runtime/GCActivityCallback.h',
+            'runtime/GetterSetter.h',
             'runtime/Identifier.h',
             'runtime/InitializeThreading.h',
             'runtime/InternalFunction.h',
             'runtime/Identifier.h',
             'runtime/InitializeThreading.h',
             'runtime/InternalFunction.h',
+            'runtime/Intrinsic.h',
+            'runtime/JSActivation.h',
             'runtime/JSAPIValueWrapper.h',
             'runtime/JSArray.h',
             'runtime/JSAPIValueWrapper.h',
             'runtime/JSArray.h',
-            'runtime/JSByteArray.h',
+            'runtime/JSBoundFunction.h',
             'runtime/JSCell.h',
             'runtime/JSCell.h',
+            'runtime/JSChunk.h',
+            'runtime/JSDateMath.h',
+            'runtime/JSExportMacros.h',
             'runtime/JSFunction.h',
             'runtime/JSGlobalData.h',
             'runtime/JSGlobalObject.h',
             'runtime/JSFunction.h',
             'runtime/JSGlobalData.h',
             'runtime/JSGlobalObject.h',
+            'runtime/JSGlobalObjectFunctions.h',
+            'runtime/JSGlobalThis.h',
             'runtime/JSLock.h',
             'runtime/JSLock.h',
-            'runtime/JSNumberCell.h',
+            'runtime/JSNotAnObject.h',
             'runtime/JSObject.h',
             'runtime/JSObject.h',
-            'runtime/JSObjectWithGlobalObject.h',
+            'runtime/JSONObject.h',
+            'runtime/JSPropertyNameIterator.h',
+            'runtime/JSStaticScopeObject.h',
             'runtime/JSString.h',
             'runtime/JSString.h',
+            'runtime/JSStringBuilder.h',
+            'runtime/JSStringJoiner.h',
             'runtime/JSType.h',
             'runtime/JSTypeInfo.h',
             'runtime/JSValue.h',
             'runtime/JSValueInlineMethods.h',
             'runtime/JSVariableObject.h',
             'runtime/JSWrapperObject.h',
             'runtime/JSType.h',
             'runtime/JSTypeInfo.h',
             'runtime/JSValue.h',
             'runtime/JSValueInlineMethods.h',
             'runtime/JSVariableObject.h',
             'runtime/JSWrapperObject.h',
+            'runtime/LiteralParser.h',
             'runtime/Lookup.h',
             'runtime/Lookup.h',
+            'runtime/MatchResult.h',
             'runtime/MathObject.h',
             'runtime/MemoryStatistics.h',
             'runtime/MathObject.h',
             'runtime/MemoryStatistics.h',
+            'runtime/NativeErrorConstructor.h',
+            'runtime/NativeErrorPrototype.h',
+            'runtime/NumberConstructor.h',
             'runtime/NumberObject.h',
             'runtime/NumberPrototype.h',
             'runtime/NumericStrings.h',
             'runtime/NumberObject.h',
             'runtime/NumberPrototype.h',
             'runtime/NumericStrings.h',
+            'runtime/ObjectConstructor.h',
             'runtime/ObjectPrototype.h',
             'runtime/Operations.h',
             'runtime/ObjectPrototype.h',
             'runtime/Operations.h',
+            'runtime/Options.h',
             'runtime/PropertyDescriptor.h',
             'runtime/PropertyMapHashTable.h',
             'runtime/PropertyNameArray.h',
             'runtime/PropertyDescriptor.h',
             'runtime/PropertyMapHashTable.h',
             'runtime/PropertyNameArray.h',
             'runtime/Protect.h',
             'runtime/PutPropertySlot.h',
             'runtime/RegExp.h',
             'runtime/Protect.h',
             'runtime/PutPropertySlot.h',
             'runtime/RegExp.h',
-            'runtime/RegExpKey.h',
             'runtime/RegExpCache.h',
             'runtime/RegExpCache.h',
+            'runtime/RegExpCachedResult.h',
+            'runtime/RegExpConstructor.h',
+            'runtime/RegExpKey.h',
+            'runtime/RegExpMatchesArray.h',
             'runtime/RegExpObject.h',
             'runtime/RegExpObject.h',
-            'runtime/RopeImpl.h',
+            'runtime/RegExpPrototype.h',
+            'runtime/SamplingCounter.h',
             'runtime/ScopeChain.h',
             'runtime/ScopeChain.h',
+            'runtime/ScopeChainMark.h',
             'runtime/SmallStrings.h',
             'runtime/SmallStrings.h',
+            'runtime/StorageBarrier.h',
+            'runtime/StrictEvalActivation.h',
+            'runtime/StringConstructor.h',
             'runtime/StringObject.h',
             'runtime/StringObject.h',
-            'runtime/StringObjectThatMasqueradesAsUndefined.h',
             'runtime/StringPrototype.h',
             'runtime/StringPrototype.h',
+            'runtime/StringRecursionChecker.h',
             'runtime/Structure.h',
             'runtime/StructureChain.h',
             'runtime/StructureTransitionTable.h',
             'runtime/SymbolTable.h',
             'runtime/Terminator.h',
             'runtime/TimeoutChecker.h',
             'runtime/Structure.h',
             'runtime/StructureChain.h',
             'runtime/StructureTransitionTable.h',
             'runtime/SymbolTable.h',
             'runtime/Terminator.h',
             'runtime/TimeoutChecker.h',
+            'runtime/Tracing.h',
+            'runtime/Uint16WithFraction.h',
             'runtime/UString.h',
             'runtime/UStringBuilder.h',
             'runtime/UString.h',
             'runtime/UStringBuilder.h',
+            'runtime/UStringConcatenate.h',
             'runtime/WeakGCMap.h',
             'runtime/WeakRandom.h',
             'runtime/WriteBarrier.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/Yarr.h',
+            'yarr/YarrCanonicalizeUCS2.h',
             'yarr/YarrInterpreter.h',
             'yarr/YarrInterpreter.h',
+            'yarr/YarrJIT.h',
+            'yarr/YarrParser.h',
             'yarr/YarrPattern.h',
             'yarr/YarrPattern.h',
+            'yarr/YarrSyntaxChecker.h',
         ],
         'javascriptcore_files': [
         ],
         'javascriptcore_files': [
-            'API/APIShims.h',
             'API/JSBase.cpp',
             'API/JSCallbackConstructor.cpp',
             'API/JSBase.cpp',
             'API/JSCallbackConstructor.cpp',
-            'API/JSCallbackConstructor.h',
             'API/JSCallbackFunction.cpp',
             'API/JSCallbackFunction.cpp',
-            'API/JSCallbackFunction.h',
             'API/JSCallbackObject.cpp',
             'API/JSCallbackObject.cpp',
-            'API/JSCallbackObject.h',
-            'API/JSCallbackObjectFunctions.h',
             'API/JSClassRef.cpp',
             'API/JSClassRef.cpp',
-            'API/JSClassRef.h',
             'API/JSContextRef.cpp',
             'API/JSObjectRef.cpp',
             'API/JSProfilerPrivate.cpp',
             'API/JSStringRef.cpp',
             'API/JSStringRefBSTR.cpp',
             'API/JSContextRef.cpp',
             'API/JSObjectRef.cpp',
             'API/JSProfilerPrivate.cpp',
             'API/JSStringRef.cpp',
             'API/JSStringRefBSTR.cpp',
-            'API/JSStringRefBSTR.h',
             'API/JSStringRefCF.cpp',
             'API/JSValueRef.cpp',
             'API/JSWeakObjectMapRefPrivate.cpp',
             'API/OpaqueJSString.cpp',
             'API/JSStringRefCF.cpp',
             'API/JSValueRef.cpp',
             'API/JSWeakObjectMapRefPrivate.cpp',
             'API/OpaqueJSString.cpp',
-            '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.cpp',
-            'assembler/ARMAssembler.h',
             'assembler/ARMv7Assembler.cpp',
             '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.cpp',
-            'assembler/MacroAssemblerARM.h',
-            'assembler/MacroAssemblerARMv7.h',
-            'assembler/MacroAssemblerMIPS.h',
-            'assembler/MacroAssemblerX86.h',
-            'assembler/MacroAssemblerX86Common.h',
-            'assembler/MacroAssemblerX86_64.h',
-            'assembler/RepatchBuffer.h',
-            'assembler/X86Assembler.h',
+            'assembler/MacroAssemblerSH4.cpp',
+            'bytecode/CallLinkInfo.cpp',
+            'bytecode/CallLinkStatus.cpp',
             'bytecode/CodeBlock.cpp',
             'bytecode/CodeBlock.cpp',
-            'bytecode/CodeBlock.h',
-            'bytecode/EvalCodeCache.h',
-            'bytecode/Instruction.h',
+            'bytecode/DFGExitProfile.cpp',
+            'bytecode/ExecutionCounter.cpp',
+            'bytecode/GetByIdStatus.cpp',
             'bytecode/JumpTable.cpp',
             'bytecode/JumpTable.cpp',
-            'bytecode/JumpTable.h',
+            'bytecode/LazyOperandValueProfile.cpp',
+            'bytecode/MethodCallLinkInfo.cpp',
+            'bytecode/MethodCallLinkStatus.cpp',
+            'bytecode/MethodOfGettingAValueProfile.cpp',
             'bytecode/Opcode.cpp',
             'bytecode/Opcode.cpp',
+            'bytecode/PolymorphicPutByIdList.cpp',
+            'bytecode/PredictedType.cpp',
+            'bytecode/PutByIdStatus.cpp',
             'bytecode/SamplingTool.cpp',
             'bytecode/SamplingTool.cpp',
-            'bytecode/SamplingTool.h',
             'bytecode/StructureStubInfo.cpp',
             'bytecode/StructureStubInfo.cpp',
-            'bytecode/StructureStubInfo.h',
             'bytecompiler/BytecodeGenerator.cpp',
             'bytecompiler/BytecodeGenerator.cpp',
-            'bytecompiler/BytecodeGenerator.h',
-            'bytecompiler/Label.h',
-            'bytecompiler/LabelScope.h',
             'bytecompiler/NodesCodegen.cpp',
             'bytecompiler/NodesCodegen.cpp',
-            'bytecompiler/RegisterID.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/DebuggerActivation.cpp',
             'debugger/DebuggerCallFrame.cpp',
             'debugger/Debugger.cpp',
             'debugger/DebuggerActivation.cpp',
             'debugger/DebuggerCallFrame.cpp',
-            'dfg/DFGAliasTracker.h',
+            'dfg/DFGAbstractState.cpp',
+            'dfg/DFGAssemblyHelpers.cpp',
             'dfg/DFGByteCodeParser.cpp',
             'dfg/DFGByteCodeParser.cpp',
-            'dfg/DFGByteCodeParser.h',
-            'dfg/DFGGenerationInfo.h',
+            'dfg/DFGCapabilities.cpp',
+            'dfg/DFGCFAPhase.cpp',
+            'dfg/DFGCorrectableJumpPoint.cpp',
+            'dfg/DFGCSEPhase.cpp',
+            'dfg/DFGDriver.cpp',
+            'dfg/DFGFixupPhase.cpp',
             'dfg/DFGGraph.cpp',
             'dfg/DFGGraph.cpp',
-            'dfg/DFGGraph.h',
-            'dfg/DFGJITCodeGenerator.cpp',
-            'dfg/DFGJITCodeGenerator.h',
             'dfg/DFGJITCompiler.cpp',
             'dfg/DFGJITCompiler.cpp',
-            'dfg/DFGJITCompiler.h',
-            'dfg/DFGNode.h',
-            'dfg/DFGNonSpeculativeJIT.cpp',
-            'dfg/DFGNonSpeculativeJIT.h',
+            'dfg/DFGNodeFlags.cpp',
             'dfg/DFGOperations.cpp',
             'dfg/DFGOperations.cpp',
-            'dfg/DFGOperations.h',
-            'dfg/DFGRegisterBank.h',
-            'dfg/DFGScoreBoard.h',
+            'dfg/DFGOSREntry.cpp',
+            'dfg/DFGOSRExit.cpp',
+            'dfg/DFGOSRExitCompiler.cpp',
+            'dfg/DFGOSRExitCompiler32_64.cpp',
+            'dfg/DFGOSRExitCompiler64.cpp',
+            'dfg/DFGPhase.cpp',
+            'dfg/DFGPredictionPropagationPhase.cpp',
+            'dfg/DFGRedundantPhiEliminationPhase.cpp',
+            'dfg/DFGRepatch.cpp',
             'dfg/DFGSpeculativeJIT.cpp',
             'dfg/DFGSpeculativeJIT.cpp',
-            'dfg/DFGSpeculativeJIT.h',
-            'icu/unicode/parseerr.h',
-            'icu/unicode/platform.h',
-            'icu/unicode/putil.h',
-            'icu/unicode/uchar.h',
-            'icu/unicode/ucnv.h',
-            'icu/unicode/ucnv_err.h',
-            'icu/unicode/ucol.h',
-            'icu/unicode/uconfig.h',
-            'icu/unicode/uenum.h',
-            'icu/unicode/uiter.h',
-            'icu/unicode/uloc.h',
-            'icu/unicode/umachine.h',
-            'icu/unicode/unorm.h',
-            'icu/unicode/urename.h',
-            'icu/unicode/uset.h',
-            'icu/unicode/ustring.h',
-            'icu/unicode/utf.h',
-            'icu/unicode/utf16.h',
-            'icu/unicode/utf8.h',
-            'icu/unicode/utf_old.h',
-            'icu/unicode/utypes.h',
-            'icu/unicode/uversion.h',
-            'interpreter/CachedCall.h',
+            'dfg/DFGSpeculativeJIT32_64.cpp',
+            'dfg/DFGSpeculativeJIT64.cpp',
+            'dfg/DFGThunks.cpp',
+            'dfg/DFGVirtualRegisterAllocationPhase.cpp',
+            'heap/ConservativeRoots.cpp',
+            'heap/CopiedSpace.cpp',
+            'heap/DFGCodeBlocks.cpp',
+            'heap/HandleSet.cpp',
+            'heap/HandleStack.cpp',
+            'heap/BlockAllocator.cpp',
+            'heap/Heap.cpp',
+            'heap/MachineStackMarker.cpp',
+            'heap/MarkedAllocator.cpp',
+            'heap/MarkedBlock.cpp',
+            'heap/MarkedSpace.cpp',
+            'heap/MarkStack.cpp',
+            'heap/VTableSpectrum.cpp',
+            'heap/WeakBlock.cpp',
+            'heap/WeakHandleOwner.cpp',
+            'heap/WeakSet.cpp',
+            'heap/WriteBarrierSupport.cpp',
+            'interpreter/AbstractPC.cpp',
             'interpreter/CallFrame.cpp',
             'interpreter/CallFrame.cpp',
-            'interpreter/CallFrameClosure.h',
             'interpreter/Interpreter.cpp',
             'interpreter/RegisterFile.cpp',
             'jit/ExecutableAllocator.cpp',
             'jit/ExecutableAllocatorFixedVMPool.cpp',
             'interpreter/Interpreter.cpp',
             'interpreter/RegisterFile.cpp',
             'jit/ExecutableAllocator.cpp',
             'jit/ExecutableAllocatorFixedVMPool.cpp',
+            'jit/HostCallReturnValue.cpp',
             'jit/JIT.cpp',
             'jit/JIT.cpp',
-            'jit/JIT.h',
             'jit/JITArithmetic.cpp',
             'jit/JITArithmetic32_64.cpp',
             'jit/JITCall.cpp',
             'jit/JITCall32_64.cpp',
             'jit/JITArithmetic.cpp',
             'jit/JITArithmetic32_64.cpp',
             'jit/JITCall.cpp',
             'jit/JITCall32_64.cpp',
-            'jit/JITInlineMethods.h',
+            'jit/JITExceptions.cpp',
             'jit/JITOpcodes.cpp',
             'jit/JITOpcodes32_64.cpp',
             'jit/JITPropertyAccess.cpp',
             'jit/JITPropertyAccess32_64.cpp',
             'jit/JITOpcodes.cpp',
             'jit/JITOpcodes32_64.cpp',
             'jit/JITPropertyAccess.cpp',
             'jit/JITPropertyAccess32_64.cpp',
-            'jit/JITStubCall.h',
             'jit/JITStubs.cpp',
             'jit/JITStubs.cpp',
-            'jit/JSInterfaceJIT.h',
-            'jit/SpecializedThunkJIT.h',
             'jit/ThunkGenerators.cpp',
             'jit/ThunkGenerators.cpp',
-            'os-win32/WinMain.cpp',
-            'os-win32/inttypes.h',
-            'os-win32/stdbool.h',
-            'os-win32/stdint.h',
-            'parser/ASTBuilder.h',
-            'parser/JSParser.cpp',
-            'parser/JSParser.h',
             'parser/Lexer.cpp',
             'parser/Lexer.cpp',
-            'parser/Lexer.h',
-            'parser/NodeConstructors.h',
-            'parser/NodeInfo.h',
             'parser/Nodes.cpp',
             'parser/Nodes.cpp',
-            'parser/Nodes.h',
             'parser/Parser.cpp',
             'parser/Parser.cpp',
-            'parser/Parser.h',
             'parser/ParserArena.cpp',
             'parser/ParserArena.cpp',
-            'parser/ParserArena.h',
             'parser/SourceProviderCache.cpp',
             'parser/SourceProviderCache.cpp',
-            'parser/SourceProviderCacheItem.h',
-            'parser/SyntaxChecker.h',
             'profiler/Profile.cpp',
             'profiler/ProfileGenerator.cpp',
             'profiler/Profile.cpp',
             'profiler/ProfileGenerator.cpp',
-            'profiler/ProfileGenerator.h',
             'profiler/ProfileNode.cpp',
             'profiler/Profiler.cpp',
             'profiler/ProfileNode.cpp',
             'profiler/Profiler.cpp',
-            '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/Arguments.cpp',
             'runtime/ArgList.cpp',
             'runtime/Arguments.cpp',
-            'runtime/Arguments.h',
             'runtime/ArrayConstructor.cpp',
             'runtime/ArrayConstructor.cpp',
-            'runtime/ArrayConstructor.h',
             'runtime/ArrayPrototype.cpp',
             'runtime/ArrayPrototype.cpp',
-            'runtime/BatchedTransitionOptimizer.h',
             'runtime/BooleanConstructor.cpp',
             'runtime/BooleanConstructor.cpp',
-            'runtime/BooleanConstructor.h',
             'runtime/BooleanObject.cpp',
             'runtime/BooleanPrototype.cpp',
             'runtime/BooleanObject.cpp',
             'runtime/BooleanPrototype.cpp',
-            'runtime/BooleanPrototype.h',
             'runtime/CallData.cpp',
             'runtime/CommonIdentifiers.cpp',
             'runtime/Completion.cpp',
             'runtime/ConstructData.cpp',
             'runtime/DateConstructor.cpp',
             'runtime/CallData.cpp',
             'runtime/CommonIdentifiers.cpp',
             'runtime/Completion.cpp',
             'runtime/ConstructData.cpp',
             'runtime/DateConstructor.cpp',
-            'runtime/DateConstructor.h',
             'runtime/DateConversion.cpp',
             'runtime/DateConversion.cpp',
-            'runtime/DateConversion.h',
             'runtime/DateInstance.cpp',
             'runtime/DatePrototype.cpp',
             'runtime/DateInstance.cpp',
             'runtime/DatePrototype.cpp',
-            'runtime/DatePrototype.h',
             'runtime/Error.cpp',
             'runtime/ErrorConstructor.cpp',
             'runtime/Error.cpp',
             'runtime/ErrorConstructor.cpp',
-            'runtime/ErrorConstructor.h',
             'runtime/ErrorInstance.cpp',
             'runtime/ErrorInstance.cpp',
-            'runtime/ErrorInstance.h',
             'runtime/ErrorPrototype.cpp',
             'runtime/ErrorPrototype.cpp',
-            'runtime/ErrorPrototype.h',
             'runtime/ExceptionHelpers.cpp',
             'runtime/Executable.cpp',
             'runtime/ExceptionHelpers.cpp',
             'runtime/Executable.cpp',
-            'runtime/Executable.h',
             'runtime/FunctionConstructor.cpp',
             'runtime/FunctionPrototype.cpp',
             'runtime/GCActivityCallback.cpp',
             'runtime/GCActivityCallbackCF.cpp',
             'runtime/GetterSetter.cpp',
             'runtime/FunctionConstructor.cpp',
             'runtime/FunctionPrototype.cpp',
             'runtime/GCActivityCallback.cpp',
             'runtime/GCActivityCallbackCF.cpp',
             'runtime/GetterSetter.cpp',
-            'runtime/GetterSetter.h',
             'runtime/Identifier.cpp',
             'runtime/InitializeThreading.cpp',
             'runtime/InternalFunction.cpp',
             'runtime/Identifier.cpp',
             'runtime/InitializeThreading.cpp',
             'runtime/InternalFunction.cpp',
-            'runtime/JSAPIValueWrapper.cpp',
             'runtime/JSActivation.cpp',
             'runtime/JSActivation.cpp',
-            'runtime/JSActivation.h',
+            'runtime/JSAPIValueWrapper.cpp',
             'runtime/JSArray.cpp',
             'runtime/JSArray.cpp',
-            'runtime/JSByteArray.cpp',
+            'runtime/JSBoundFunction.cpp',
             'runtime/JSCell.cpp',
             'runtime/JSCell.cpp',
+            'runtime/JSChunk.cpp',
+            'runtime/JSDateMath.cpp',
             'runtime/JSFunction.cpp',
             'runtime/JSGlobalData.cpp',
             'runtime/JSGlobalObject.cpp',
             'runtime/JSGlobalObjectFunctions.cpp',
             'runtime/JSFunction.cpp',
             'runtime/JSGlobalData.cpp',
             'runtime/JSGlobalObject.cpp',
             'runtime/JSGlobalObjectFunctions.cpp',
-            'runtime/JSGlobalObjectFunctions.h',
+            'runtime/JSGlobalThis.cpp',
             'runtime/JSLock.cpp',
             'runtime/JSNotAnObject.cpp',
             'runtime/JSLock.cpp',
             'runtime/JSNotAnObject.cpp',
-            'runtime/JSNotAnObject.h',
-            'runtime/JSNumberCell.cpp',
-            'runtime/JSONObject.cpp',
-            'runtime/JSONObject.h',
             'runtime/JSObject.cpp',
             'runtime/JSObject.cpp',
-            'runtime/JSObjectWithGlobalObject.cpp',
+            'runtime/JSONObject.cpp',
             'runtime/JSPropertyNameIterator.cpp',
             'runtime/JSPropertyNameIterator.cpp',
-            'runtime/JSPropertyNameIterator.h',
             'runtime/JSStaticScopeObject.cpp',
             'runtime/JSStaticScopeObject.cpp',
-            'runtime/JSStaticScopeObject.h',
             'runtime/JSString.cpp',
             'runtime/JSString.cpp',
-            'runtime/JSStringBuilder.h',
+            'runtime/JSStringJoiner.cpp',
             'runtime/JSValue.cpp',
             'runtime/JSVariableObject.cpp',
             'runtime/JSWrapperObject.cpp',
             'runtime/JSValue.cpp',
             'runtime/JSVariableObject.cpp',
             'runtime/JSWrapperObject.cpp',
-            'runtime/JSZombie.cpp',
-            'runtime/JSZombie.h',
             'runtime/LiteralParser.cpp',
             'runtime/LiteralParser.cpp',
-            'runtime/LiteralParser.h',
             'runtime/Lookup.cpp',
             'runtime/MathObject.cpp',
             'runtime/MemoryStatistics.cpp',
             'runtime/NativeErrorConstructor.cpp',
             'runtime/Lookup.cpp',
             'runtime/MathObject.cpp',
             'runtime/MemoryStatistics.cpp',
             'runtime/NativeErrorConstructor.cpp',
-            'runtime/NativeErrorConstructor.h',
             'runtime/NativeErrorPrototype.cpp',
             'runtime/NativeErrorPrototype.cpp',
-            'runtime/NativeErrorPrototype.h',
             'runtime/NumberConstructor.cpp',
             'runtime/NumberConstructor.cpp',
-            'runtime/NumberConstructor.h',
             'runtime/NumberObject.cpp',
             'runtime/NumberPrototype.cpp',
             'runtime/ObjectConstructor.cpp',
             'runtime/NumberObject.cpp',
             'runtime/NumberPrototype.cpp',
             'runtime/ObjectConstructor.cpp',
-            'runtime/ObjectConstructor.h',
             'runtime/ObjectPrototype.cpp',
             'runtime/Operations.cpp',
             'runtime/ObjectPrototype.cpp',
             'runtime/Operations.cpp',
+            'runtime/Options.cpp',
             'runtime/PropertyDescriptor.cpp',
             'runtime/PropertyNameArray.cpp',
             'runtime/PropertySlot.cpp',
             'runtime/RegExp.cpp',
             'runtime/RegExpCache.cpp',
             'runtime/PropertyDescriptor.cpp',
             'runtime/PropertyNameArray.cpp',
             'runtime/PropertySlot.cpp',
             'runtime/RegExp.cpp',
             'runtime/RegExpCache.cpp',
+            'runtime/RegExpCachedResult.cpp',
             'runtime/RegExpConstructor.cpp',
             'runtime/RegExpConstructor.cpp',
-            'runtime/RegExpConstructor.h',
-            'runtime/RegExpMatchesArray.h',
+            'runtime/RegExpMatchesArray.cpp',
             'runtime/RegExpObject.cpp',
             'runtime/RegExpPrototype.cpp',
             'runtime/RegExpObject.cpp',
             'runtime/RegExpPrototype.cpp',
-            'runtime/RegExpPrototype.h',
-            'runtime/RopeImpl.cpp',
+            'runtime/SamplingCounter.cpp',
             'runtime/ScopeChain.cpp',
             'runtime/ScopeChain.cpp',
-            'runtime/ScopeChainMark.h',
             'runtime/SmallStrings.cpp',
             'runtime/StrictEvalActivation.cpp',
             'runtime/SmallStrings.cpp',
             'runtime/StrictEvalActivation.cpp',
-            'runtime/StrictEvalActivation.h',
             'runtime/StringConstructor.cpp',
             'runtime/StringConstructor.cpp',
-            'runtime/StringConstructor.h',
             'runtime/StringObject.cpp',
             'runtime/StringPrototype.cpp',
             'runtime/StringRecursionChecker.cpp',
             'runtime/StringObject.cpp',
             'runtime/StringPrototype.cpp',
             'runtime/StringRecursionChecker.cpp',
-            'runtime/StringRecursionChecker.h',
             'runtime/Structure.cpp',
             'runtime/StructureChain.cpp',
             'runtime/TimeoutChecker.cpp',
             'runtime/Structure.cpp',
             'runtime/StructureChain.cpp',
             'runtime/TimeoutChecker.cpp',
-            'runtime/Tracing.d',
-            'runtime/Tracing.h',
             'runtime/UString.cpp',
             'runtime/UString.cpp',
-            'runtime/UStringConcatenate.h',
-            'wtf/Assertions.cpp',
-            'wtf/ByteArray.cpp',
-            'wtf/CryptographicallyRandomNumber.cpp',
-            'wtf/CurrentTime.cpp',
-            'wtf/DateMath.cpp',
-            'wtf/DecimalNumber.cpp',
-            'wtf/DynamicAnnotations.cpp',
-            'wtf/DynamicAnnotations.h',
-            'wtf/FastMalloc.cpp',
-            'wtf/HashTable.cpp',
-            'wtf/MD5.cpp',
-            'wtf/MainThread.cpp',
-            'wtf/MallocZoneSupport.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/RandomNumberSeed.h',
-            'wtf/RefCountedLeakCounter.cpp',
-            'wtf/SHA1.cpp',
-            'wtf/SHA1.h',
-            'wtf/SegmentedVector.h',
-            'wtf/SizeLimits.cpp',
-            'wtf/StackBounds.cpp',
-            'wtf/StringExtras.cpp',
-            'wtf/TCPackedCache.h',
-            'wtf/TCPageMap.h',
-            'wtf/TCSpinLock.h',
-            'wtf/TCSystemAlloc.cpp',
-            'wtf/TCSystemAlloc.h',
-            'wtf/ThreadFunctionInvocation.h',
-            'wtf/ThreadIdentifierDataPthreads.cpp',
-            'wtf/ThreadIdentifierDataPthreads.h',
-            'wtf/ThreadSpecificWin.cpp',
-            'wtf/Threading.cpp',
-            'wtf/ThreadingNone.cpp',
-            'wtf/ThreadingPthreads.cpp',
-            'wtf/ThreadingWin.cpp',
-            'wtf/TypeTraits.cpp',
-            '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/CString.cpp',
-            'wtf/text/StringBuilder.cpp',
-            'wtf/text/StringImpl.cpp',
-            'wtf/text/StringStatics.cpp',
-            'wtf/text/WTFString.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/icu/CollatorICU.cpp',
-            'wtf/unicode/qt4/UnicodeQt4.h',
-            'wtf/unicode/wince/UnicodeWinCE.cpp',
-            'wtf/unicode/wince/UnicodeWinCE.h',
-            'wtf/url/api/ParsedURL.cpp',
-            'wtf/url/api/ParsedURL.h',
-            'wtf/url/api/URLString.h',
-            'wtf/url/src/RawURLBuffer.h',
-            'wtf/url/src/URLBuffer.h',
-            'wtf/url/src/URLCharacterTypes.cpp',
-            'wtf/url/src/URLCharacterTypes.h',
-            'wtf/url/src/URLComponent.h',
-            'wtf/url/src/URLEscape.cpp',
-            'wtf/url/src/URLEscape.h',
-            'wtf/url/src/URLParser.h',
-            'wtf/url/src/URLQueryCanonicalizer.h',
-            'wtf/url/src/URLSegments.cpp',
-            'wtf/url/src/URLSegments.h',
-            'wtf/win/MainThreadWin.cpp',
-            'wtf/win/OwnPtrWin.cpp',
-            'wtf/wince/FastMallocWinCE.h',
-            'wtf/wince/MemoryManager.cpp',
-            'wtf/wince/MemoryManager.h',
-            'wtf/wx/MainThreadWx.cpp',
-            'wtf/wx/StringWx.cpp',
+            'tools/CodeProfile.cpp',
+            'tools/CodeProfiling.cpp',
+            'yarr/YarrCanonicalizeUCS2.cpp',
             'yarr/YarrInterpreter.cpp',
             'yarr/YarrJIT.cpp',
             'yarr/YarrInterpreter.cpp',
             'yarr/YarrJIT.cpp',
-            'yarr/YarrJIT.h',
-            'yarr/YarrParser.h',
             'yarr/YarrPattern.cpp',
             'yarr/YarrSyntaxChecker.cpp',
             'yarr/YarrPattern.cpp',
             'yarr/YarrSyntaxChecker.cpp',
-            'yarr/YarrSyntaxChecker.h',
         ],
         'javascriptcore_derived_source_files': [
             '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/Lexer.lut.h',
         ],
         'javascriptcore_derived_source_files': [
             '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/Lexer.lut.h',
index 275f35cda6843e1eda7d8cc41da4cb0cff43e390..3a450075a1343e59e7b1eda11a5f7cd803c865aa 100644 (file)
@@ -42,66 +42,39 @@ __ZN3WTF10StringImpl6createEPKtj
 __ZN3WTF12isMainThreadEv
 __ZN3WTF10StringImplD1Ev
 __ZN3WTF10StringImplD2Ev
 __ZN3WTF12isMainThreadEv
 __ZN3WTF10StringImplD1Ev
 __ZN3WTF10StringImplD2Ev
+__ZN3WTF6String6numberEy
+__ZN3WTF6String6formatEPKcz
+__ZN3WTF6VectorIcLm256EE4growEm
+__ZN3WTF13tryFastMallocEm
+__ZN3WTF15ThreadConditionC1Ev
+__ZN3WTF10StringImpl11reverseFindEtj
+__ZNK3WTF6String9substringEjj
+__ZN3WTF10StringImpl9substringEjj
+__ZN3WTF7CString16newUninitializedEmRPc
+__ZN3WTF7CString11mutableDataEv
+__ZN3WTF7CString18copyBufferIfNeededEv
 __ZN3WTF5Mutex4lockEv
 __ZN3WTF5Mutex4lockEv
-__ZNK3WTF6String14threadsafeCopyEv
-__ZNK3WTF10StringImpl14threadsafeCopyEv
 __ZN3WTF5Mutex6unlockEv
 __ZN3WTF5Mutex6unlockEv
+__ZN3WTF10StringImpl12sharedBufferEv
 __ZN3WTF10StringImpl8endsWithEPS0_b
 __ZN3WTF10StringImpl8endsWithEPS0_b
-__ZN3WTF13tryFastMallocEm
-__ZN3WTF7CString16newUninitializedEmRPc
-__ZN3WTF15ThreadConditionC1Ev
 __ZN3WTF12createThreadEPFPvS0_ES0_PKc
 __ZN3WTF12createThreadEPFPvS0_ES0_PKc
+__ZN3WTF12createThreadEPFvPvES0_PKc
 __ZN3WTF20createThreadInternalEPFPvS0_ES0_PKc
 __ZN3WTFL35establishIdentifierForPthreadHandleERKP17_opaque_pthread_t
 __ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E6rehashEi
 __ZN3WTF20createThreadInternalEPFPvS0_ES0_PKc
 __ZN3WTFL35establishIdentifierForPthreadHandleERKP17_opaque_pthread_t
 __ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E6rehashEi
-__ZN3WTF15ThreadCondition6signalEv
 __ZN3WTFL16threadEntryPointEPv
 __ZN3WTF31initializeCurrentThreadInternalEPKc
 __ZN3WTF20ThreadIdentifierData10initializeEj
 __ZN3WTF20ThreadIdentifierData23initializeKeyOnceHelperEv
 __ZN3WTF5MutexD1Ev
 __ZN3WTFL16threadEntryPointEPv
 __ZN3WTF31initializeCurrentThreadInternalEPKc
 __ZN3WTF20ThreadIdentifierData10initializeEj
 __ZN3WTF20ThreadIdentifierData23initializeKeyOnceHelperEv
 __ZN3WTF5MutexD1Ev
-__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
 __ZNK3WTF6String15stripWhiteSpaceEv
 __ZN3WTF10StringImpl15stripWhiteSpaceEv
 __ZN3WTF6String29charactersWithNullTerminationEv
 __ZN3WTF10StringImpl34createWithTerminatingNullCharacterERKS0_
 __ZN3WTF13currentThreadEv
 __ZN3WTF20ThreadIdentifierData10identifierEv
 __ZNK3WTF6String15stripWhiteSpaceEv
 __ZN3WTF10StringImpl15stripWhiteSpaceEv
-_JSStringCreateWithCFString
-_JSStringRetain
-_JSStringRelease
-__ZN3WTF6String6numberEi
+__ZN3WTF6StringC1EPKt
+__ZN3WTF6StringC2EPKt
 __ZN3WTF16callOnMainThreadEPFvPvES0_
 __ZN3WTF5DequeINS_19FunctionWithContextELm0EE14expandCapacityEv
 __ZN3WTF37scheduleDispatchFunctionsOnMainThreadEv
 __ZN3WTF16callOnMainThreadEPFvPvES0_
 __ZN3WTF5DequeINS_19FunctionWithContextELm0EE14expandCapacityEv
 __ZN3WTF37scheduleDispatchFunctionsOnMainThreadEv
@@ -109,31 +82,40 @@ __ZN3WTF15ThreadCondition4waitERNS_5MutexE
 __ZN3WTF6String8fromUTF8EPKc
 __ZN3WTF6String8fromUTF8EPKcm
 __ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b
 __ZN3WTF6String8fromUTF8EPKc
 __ZN3WTF6String8fromUTF8EPKcm
 __ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b
+__ZN3WTF15ThreadCondition6signalEv
 __ZN3WTF7CStringC1EPKc
 __ZN3WTF7CStringC1EPKc
+__ZN3WTF7CString4initEPKcm
+__ZNK3WTF6String4utf8Eb
+__ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
+__ZN3WTF7CStringC1EPKcm
 __ZN3WTF11fastReallocEPvm
 __ZN3WTF11fastReallocEPvm
+__ZN3WTF12AtomicString3addEPKc
+__ZN3WTF9HashTableIPNS_10StringImplES2_NS_17IdentityExtractorIS2_EENS_10StringHashENS_10HashTraitsIS2_EES7_E6rehashEi
+__ZN3WTF12AtomicString3addEPKtj
+__ZN3WTF10StringImpl4findEtj
+__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i
+__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
 -[WTFMainThreadCaller call]
 __ZN3WTF31dispatchFunctionsFromMainThreadEv
 -[WTFMainThreadCaller call]
 __ZN3WTF31dispatchFunctionsFromMainThreadEv
-__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i
-__ZN3WTF25TCMalloc_Central_FreeList11ShrinkCacheEib
 __ZN3WTF15ThreadCondition9broadcastEv
 __ZN3WTF15ThreadCondition9broadcastEv
-__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
-__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
-__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
-__ZN3WTF20ThreadIdentifierData8destructEPv
-__ZN3WTF31clearPthreadHandleForIdentifierEj
+__ZN3WTF15ThreadCondition9timedWaitERNS_5MutexEd
 __ZN3WTF12detachThreadEj
 __ZN3WTFL26pthreadHandleForIdentifierEj
 __ZN3WTF12detachThreadEj
 __ZN3WTFL26pthreadHandleForIdentifierEj
-__ZN3WTF14FastMallocZone4sizeEP14_malloc_zone_tPKv
-__ZN3WTF10StringImpl4findEtj
-___initializeScavenger_block_invoke_1
-__ZN3WTF23waitForThreadCompletionEjPPv
-__ZN3WTF22cancelCallOnMainThreadEPFvPvES0_
-__ZN3WTF6StringC1EPKt
-__ZN3WTF6StringC2EPKt
+__ZN3WTF20ThreadIdentifierData8destructEPv
+__ZN3WTF31clearPthreadHandleForIdentifierEj
+__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
+__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
+__ZN3WTF25TCMalloc_Central_FreeList11ShrinkCacheEib
+__ZN3WTFL10timerFiredEP16__CFRunLoopTimerPv
+__ZNK3WTF6String5lowerEv
+__ZN3WTF10StringImpl5lowerEv
 __ZNK3WTF6String5splitEtRNS_6VectorIS0_Lm0EEE
 __ZNK3WTF6String5splitERKS0_bRNS_6VectorIS0_Lm0EEE
 __ZN3WTF10StringImpl4findEPS0_j
 __ZN3WTF6VectorINS_6StringELm0EE14expandCapacityEm
 __ZNK3WTF6String5splitEtRNS_6VectorIS0_Lm0EEE
 __ZNK3WTF6String5splitERKS0_bRNS_6VectorIS0_Lm0EEE
 __ZN3WTF10StringImpl4findEPS0_j
 __ZN3WTF6VectorINS_6StringELm0EE14expandCapacityEm
+__ZN3WTF6StringC1EPKcj
+__ZN3WTF12AtomicString11addSlowCaseEPNS_10StringImplE
+__ZN3WTF12AtomicString6removeEPNS_10StringImplE
 _JSGlobalContextCreate
 __ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
 __ZN3JSCL17createJSLockCountEv
 _JSGlobalContextCreate
 __ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
 __ZN3JSCL17createJSLockCountEv
@@ -286,7 +268,6 @@ __ZN3JSC12X86Assembler7addl_irEiNS_12X86Registers10RegisterIDE
 __ZN3JSC14MacroAssembler4jumpENS_22AbstractMacroAssemblerINS_12X86AssemblerEE5LabelE
 __ZN3WTF15deleteAllValuesIPN3JSC4Yarr18PatternDisjunctionELm4EEEvRKNS_6VectorIT_XT0_EEE
 __ZN3WTF15deleteAllValuesIPN3JSC4Yarr14CharacterClassELm0EEEvRKNS_6VectorIT_XT0_EEE
 __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
 __ZN3JSC14ErrorPrototypeC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
 __ZN3JSC14ErrorPrototypeC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
 __ZN3JSC13ErrorInstanceC2EPNS_12JSGlobalDataEPNS_9StructureE
@@ -330,9 +311,8 @@ _JSGlobalContextRetain
 __ZN3JSC14MachineThreads16addCurrentThreadEv
 __ZN3JSC6JSLockC1EPNS_9ExecStateE
 __ZN3JSC4Heap7protectENS_7JSValueE
 __ZN3JSC14MachineThreads16addCurrentThreadEv
 __ZN3JSC6JSLockC1EPNS_9ExecStateE
 __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
 __ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE
+_JSStringCreateWithCFString
 _JSValueMakeFromJSONString
 __ZNK14OpaqueJSString7ustringEv
 __ZN3JSC7UStringC1EPKtj
 _JSValueMakeFromJSONString
 __ZNK14OpaqueJSString7ustringEv
 __ZN3JSC7UStringC1EPKtj
@@ -343,11 +323,12 @@ __ZN3WTF13StringBuilder6appendEPKtj
 __ZN3WTF13StringBuilder19appendUninitializedEj
 __ZN3WTF13StringBuilder14allocateBufferEPKtj
 __ZN3WTF13StringBuilder11shrinkToFitEv
 __ZN3WTF13StringBuilder19appendUninitializedEj
 __ZN3WTF13StringBuilder14allocateBufferEPKtj
 __ZN3WTF13StringBuilder11shrinkToFitEv
-__ZN3WTF13StringBuilder11reifyStringEv
-__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
+__ZNK3WTF13StringBuilder11reifyStringEv
+__ZNK3WTF13StringBuilder9canShrinkEv
 __ZN3JSC7JSArray4pushEPNS_9ExecStateENS_7JSValueE
 __ZN3JSC7JSArray20increaseVectorLengthEj
 __ZN3WTF14tryFastReallocEPvm
 __ZN3JSC7JSArray4pushEPNS_9ExecStateENS_7JSValueE
 __ZN3JSC7JSArray20increaseVectorLengthEj
 __ZN3WTF14tryFastReallocEPvm
+_JSStringRelease
 _JSValueIsNull
 _JSValueIsUndefined
 _JSValueIsBoolean
 _JSValueIsNull
 _JSValueIsUndefined
 _JSValueIsBoolean
@@ -375,17 +356,12 @@ _JSValueToStringCopy
 __ZNK3JSC7JSValue8toStringEPNS_9ExecStateE
 __ZN14OpaqueJSString6createERKN3JSC7UStringE
 _JSStringCopyCFString
 __ZNK3JSC7JSValue8toStringEPNS_9ExecStateE
 __ZN14OpaqueJSString6createERKN3JSC7UStringE
 _JSStringCopyCFString
-_JSObjectCopyPropertyNames
-__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC8JSObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC9Structure16getPropertyNamesERNS_12JSGlobalDataERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC9ExecState20objectPrototypeTableEPS0_
-__ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
-_JSPropertyNameArrayGetCount
-_JSPropertyNameArrayRelease
 _JSGlobalContextRelease
 __ZN3JSC4Heap9unprotectENS_7JSValueE
 _JSGlobalContextRelease
 __ZN3JSC4Heap9unprotectENS_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
 __ZN3JSC10HandleHeap4growEv
 __ZN3JSC10HandleHeap4growEv
+__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
 __ZN3JSC37DefaultGCActivityCallbackPlatformData7triggerEP16__CFRunLoopTimerPv
 __ZN3JSC4Heap17collectAllGarbageEv
 __ZN3JSC12JSGlobalData23recompileAllJSFunctionsEv
 __ZN3JSC37DefaultGCActivityCallbackPlatformData7triggerEP16__CFRunLoopTimerPv
 __ZN3JSC4Heap17collectAllGarbageEv
 __ZN3JSC12JSGlobalData23recompileAllJSFunctionsEv
@@ -411,7 +387,10 @@ __ZN3JSC10HandleHeap19finalizeWeakHandlesEv
 __ZN3JSC11MarkedSpace5resetEv
 __ZN3JSC11MarkedSpace5sweepEv
 __ZN3JSC11MarkedBlock5sweepEv
 __ZN3JSC11MarkedSpace5resetEv
 __ZN3JSC11MarkedSpace5sweepEv
 __ZN3JSC11MarkedBlock5sweepEv
-__ZN3JSC9StructureD1Ev
+__ZN3JSC14JSGlobalObjectD1Ev
+__ZN3JSC14JSGlobalObjectD2Ev
+__ZN3WTF9HashTableINS_6RefPtrI21OpaqueJSWeakObjectMapEES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E15deallocateTableEPS3_i
+__ZN3WTF9HashTableINS_6RefPtrI21OpaqueJSWeakObjectMapEES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
 __ZN3JSC8JSStringD1Ev
 __ZN3JSC10JSFunctionD1Ev
 __ZN3JSC14ArrayPrototypeD1Ev
 __ZN3JSC8JSStringD1Ev
 __ZN3JSC10JSFunctionD1Ev
 __ZN3JSC14ArrayPrototypeD1Ev
@@ -419,6 +398,20 @@ __ZN3JSC7JSArrayD2Ev
 __ZN3JSC13DatePrototypeD1Ev
 __ZN3JSC13JSFinalObjectD1Ev
 __ZN3JSC7JSArrayD1Ev
 __ZN3JSC13DatePrototypeD1Ev
 __ZN3JSC13JSFinalObjectD1Ev
 __ZN3JSC7JSArrayD1Ev
+__ZN3JSC9StructureD1Ev
+__ZN3JSC16NativeExecutableD1Ev
+__ZN3JSC20NativeErrorPrototypeD1Ev
+__ZN3JSC10MathObjectD1Ev
+__ZN3JSC10JSONObjectD1Ev
+__ZN3JSC17FunctionPrototypeD1Ev
+__ZN3JSC17ObjectConstructorD1Ev
+__ZN3JSC19FunctionConstructorD1Ev
+__ZN3JSC16ArrayConstructorD1Ev
+__ZN3JSC17StringConstructorD1Ev
+__ZN3JSC18BooleanConstructorD1Ev
+__ZN3JSC17NumberConstructorD1Ev
+__ZN3JSC15DateConstructorD1Ev
+__ZN3JSC16ErrorConstructorD1Ev
 __ZN3JSC14ScopeChainNodeD1Ev
 __ZN3JSC15ObjectPrototypeD1Ev
 __ZN3JSC15StringPrototypeD1Ev
 __ZN3JSC14ScopeChainNodeD1Ev
 __ZN3JSC15ObjectPrototypeD1Ev
 __ZN3JSC15StringPrototypeD1Ev
@@ -430,94 +423,25 @@ __ZN3JSC6RegExpD1Ev
 __ZN3JSC14ErrorPrototypeD1Ev
 __ZN3JSC17RegExpConstructorD1Ev
 __ZN3JSC22NativeErrorConstructorD1Ev
 __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
 __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
+__ZN3WTFL43initializeMainThreadToProcessMainThreadOnceEv
+__ZN3WTF47initializeMainThreadToProcessMainThreadPlatformEv
+__ZN3WTF5equalEPKNS_10StringImplEPKc
+__ZN3WTF17equalIgnoringCaseEPNS_10StringImplEPKc
+__ZN3WTF12AtomicString4initEv
+__ZN3WTF6String6appendERKS0_
+__ZN3WTF6StringC1EPKtj
+__ZN3WTF18charactersToDoubleEPKtmPbS2_
+__ZN3WTF6strtodEPKcPPc
+__ZN3WTF10StringImpl22containsOnlyWhitespaceEv
+__ZN3WTF10StringImpl11reverseFindEPS0_j
+__ZN3WTF17equalIgnoringCaseEPNS_10StringImplES1_
 __ZN3JSC12JSGlobalData12createLeakedENS_15ThreadStackTypeE
 __ZN3JSC12JSGlobalData12createLeakedENS_15ThreadStackTypeE
-__ZN3WTF10StringImpl5adoptERNS_12StringBufferE
-__ZN3WTF10StringImpl7replaceEtt
-__ZNK3WTF6String16removeCharactersEPFbtE
-__ZN3WTF10StringImpl16removeCharactersEPFbtE
-__ZN3WTF10StringImpl4findEPFbtEj
 __ZN3JSC24JSObjectWithGlobalObjectC2ERNS_12JSGlobalDataEPNS_14JSGlobalObjectEPNS_9StructureE
 __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
 __ZN3JSC8evaluateEPNS_9ExecStateEPNS_14ScopeChainNodeERKNS_10SourceCodeENS_7JSValueE
 __ZN3JSC17ProgramExecutableC1EPNS_9ExecStateERKNS_10SourceCodeE
 __ZN3JSC11Interpreter7executeEPNS_17ProgramExecutableEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectE
@@ -533,75 +457,19 @@ __ZN3JSC8JSParserC2EPNS_5LexerEPNS_12JSGlobalDataEPNS_18FunctionParametersEbbPNS
 __ZN3JSC8JSParser9pushScopeEv
 __ZN3JSC8JSParser4nextENS_5Lexer7LexTypeE
 __ZN3JSC5Lexer3lexEPNS_11JSTokenDataEPNS_11JSTokenInfoENS0_7LexTypeEb
 __ZN3JSC8JSParser9pushScopeEv
 __ZN3JSC8JSParser4nextENS_5Lexer7LexTypeE
 __ZN3JSC5Lexer3lexEPNS_11JSTokenDataEPNS_11JSTokenInfoENS0_7LexTypeEb
-__ZN3WTF15SegmentedVectorIN3JSC10IdentifierELm64EE6appendIS2_EEvRKT_
 __ZN3JSC8JSParser12parseProgramEv
 __ZNK3JSC19SourceProviderCache8byteSizeEv
 __ZN3WTF6VectorIPN3JSC20ParserArenaDeletableELm0EE15reserveCapacityEm
 __ZN3JSC8JSParser19parseSourceElementsILNS0_18SourceElementsModeE0ENS_10ASTBuilderEEENT0_14SourceElementsERS4_
 __ZN3JSC8JSParser14parseStatementINS_10ASTBuilderEEENT_9StatementERS3_RPKNS_10IdentifierE
 __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
-__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
+__ZN3JSC6Parser16didFinishParsingEPNS_14SourceElementsEPNS_15ParserArenaDataIN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEEEPNS3_INS5_IPNS_16FunctionBodyNodeELm0EEEEEjiiRNS4_7HashSetINS4_6RefPtrINS4_10StringImplEEENS_17IdentifierRepHashENS4_10HashTraitsISM_EEEE
+__ZN3JSC11ParserArenaD1Ev
+__ZN3JSC5Lexer5clearEv
+__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
 __ZN3JSC11ParserArena14derefWithArenaEN3WTF10PassRefPtrINS_21ParserArenaRefCountedEEE
 __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
-__ZN3JSC14SourceElements6appendEPNS_13StatementNodeE
-__ZNK3JSC13StatementNode16isEmptyStatementEv
-__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14expandCapacityEm
-__ZN3JSC8JSParser21parseConstDeclarationINS_10ASTBuilderEEENT_9StatementERS3_
-__ZN3WTF6VectorISt4pairIPKN3JSC10IdentifierEjELm0EE15reserveCapacityEm
-__ZN3JSC8JSParser25parseAssignmentExpressionINS_10ASTBuilderEEENT_10ExpressionERS3_
-__ZN3JSC8JSParser21parseMemberExpressionINS_10ASTBuilderEEENT_10ExpressionERS3_
-__ZN3JSC5Lexer10scanRegExpERPKNS_10IdentifierES4_t
-__ZN3JSC4Yarr11checkSyntaxERKNS_7UStringE
-__ZN3JSC4Yarr6ParserINS0_13SyntaxCheckerEE5parseEv
-__ZN3JSC4Yarr6ParserINS0_13SyntaxCheckerEE11parseEscapeILb1ENS3_28CharacterClassParserDelegateEEEbRT0_
-__ZN3JSC8JSParser20parseReturnStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
-__ZN3WTF6VectorIiLm0EE14expandCapacityEm
-__ZN3JSC8JSParser19parseVarDeclarationINS_13SyntaxCheckerEEENT_9StatementERS3_
-__ZN3JSC8JSParser17parseFunctionInfoILNS0_20FunctionRequirementsE0ELb0ENS_13SyntaxCheckerEEEbRT1_RPKNS_10IdentifierERNS4_19FormalParameterListERNS4_12FunctionBodyERiSE_SE_
-__ZN3JSC8JSParser19parseWhileStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
-__ZN3JSC10ASTBuilder20makeFunctionCallNodeEPNS_14ExpressionNodeEPNS_13ArgumentsNodeEiii
-__ZNK3JSC11ResolveNode10isLocationEv
-__ZNK3JSC11ResolveNode13isResolveNodeEv
-__ZN3WTF6VectorISt4pairIiiELm0EE14expandCapacityEm
-__ZN3JSC8JSParser22parseContinueStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
-__ZN3JSC8JSParser17parseTryStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
-__ZN3JSC6Parser16didFinishParsingEPNS_14SourceElementsEPNS_15ParserArenaDataIN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEEEPNS3_INS5_IPNS_16FunctionBodyNodeELm0EEEEEjiiRNS4_7HashSetINS4_6RefPtrINS4_10StringImplEEENS_17IdentifierRepHashENS4_10HashTraitsISM_EEEE
-__ZN3JSC11ParserArenaD1Ev
-__ZN3JSC5Lexer5clearEv
-__ZN3JSC11ProgramNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS6_IPNS_16FunctionBodyNodeELm0EEERNS5_7HashSetINS5_6RefPtrINS5_10StringImplEEENS_17IdentifierRepHashENS5_10HashTraitsISL_EEEERKNS_10SourceCodeEji
-__ZN3JSC9ScopeNodeC2EPNS_12JSGlobalDataERKNS_10SourceCodeEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS9_IPNS_16FunctionBodyNodeELm0EEERNS8_7HashSetINS8_6RefPtrINS8_10StringImplEEENS_17IdentifierRepHashENS8_10HashTraitsISO_EEEEji
 __ZN3JSC11ParserArena10removeLastEv
 __ZN3JSC11ParserArena10removeLastEv
+__ZN3JSC13StatementNode6setLocEii
 __ZN3JSC11ParserArena5resetEv
 __ZN3WTF6VectorIN3JSC10IdentifierELm64EE14shrinkCapacityEm
 __ZN3JSC9CodeBlockC2EPNS_16ScriptExecutableENS_8CodeTypeEPNS_14JSGlobalObjectEN3WTF10PassRefPtrINS_14SourceProviderEEEjPNS6_7HashMapINS6_6RefPtrINS6_10StringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS6_10HashTraitsISD_EENS_26SymbolTableIndexHashTraitsEEEb
 __ZN3JSC11ParserArena5resetEv
 __ZN3WTF6VectorIN3JSC10IdentifierELm64EE14shrinkCapacityEm
 __ZN3JSC9CodeBlockC2EPNS_16ScriptExecutableENS_8CodeTypeEPNS_14JSGlobalObjectEN3WTF10PassRefPtrINS_14SourceProviderEEEjPNS6_7HashMapINS6_6RefPtrINS6_10StringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS6_10HashTraitsISD_EENS_26SymbolTableIndexHashTraitsEEEb
@@ -610,16 +478,7 @@ __ZN3JSC17BytecodeGeneratorC2EPNS_11ProgramNodeEPNS_14ScopeChainNodeEPN3WTF7Hash
 __ZN3JSC17BytecodeGenerator10emitOpcodeENS_8OpcodeIDE
 __ZN3WTF6VectorIN3JSC11InstructionELm0EE15reserveCapacityEm
 __ZN3WTF15SegmentedVectorIN3JSC10RegisterIDELm32EE13ensureSegmentEmm
 __ZN3JSC17BytecodeGenerator10emitOpcodeENS_8OpcodeIDE
 __ZN3WTF6VectorIN3JSC11InstructionELm0EE15reserveCapacityEm
 __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
 __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
@@ -629,48 +488,6 @@ __ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDENS_7JSValueE
 __ZN3JSC17BytecodeGenerator16addConstantValueENS_7JSValueE
 __ZN3WTF9HashTableIPvSt4pairIS1_jENS_18PairFirstExtractorIS3_EENS_7PtrHashIS1_EENS_14PairHashTraitsIN3JSC24EncodedJSValueHashTraitsENS_10HashTraitsIjEEEESA_E6expandEv
 __ZN3WTF6VectorIN3JSC12WriteBarrierINS1_7UnknownEEELm0EE14expandCapacityEm
 __ZN3JSC17BytecodeGenerator16addConstantValueENS_7JSValueE
 __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
-__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
 __ZN3JSC9CodeBlock11shrinkToFitEv
 __ZN3WTF6VectorIN3JSC11InstructionELm0EE14shrinkCapacityEm
 __ZN3JSC17BytecodeGenerator16emitUnaryNoDstOpENS_8OpcodeIDEPNS_10RegisterIDE
 __ZN3JSC9CodeBlock11shrinkToFitEv
 __ZN3WTF6VectorIN3JSC11InstructionELm0EE14shrinkCapacityEm
@@ -678,32 +495,16 @@ __ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC10IdentifierELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC12WriteBarrierINS1_18FunctionExecutableEEELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC12WriteBarrierINS1_7UnknownEEELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC10IdentifierELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC12WriteBarrierINS1_18FunctionExecutableEEELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC12WriteBarrierINS1_7UnknownEEELm0EE14shrinkCapacityEm
-__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14shrinkCapacityEm
-__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14shrinkCapacityEm
-__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14shrinkCapacityEm
-__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14shrinkCapacityEm
 __ZN3JSC15ParserArenaDataIN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEED1Ev
 __ZN3JSC15ParserArenaDataIN3WTF6VectorIPNS_16FunctionBodyNodeELm0EEEED1Ev
 __ZN3JSC14SourceElementsD1Ev
 __ZN3JSC15ParserArenaDataIN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEED1Ev
 __ZN3JSC15ParserArenaDataIN3WTF6VectorIPNS_16FunctionBodyNodeELm0EEEED1Ev
 __ZN3JSC14SourceElementsD1Ev
-__ZThn16_N3JSC16FunctionBodyNodeD0Ev
-__ZN3JSC16FunctionBodyNodeD0Ev
 __ZN3JSC3JIT14privateCompileEPNS_21MacroAssemblerCodePtrE
 __ZN3JSC3JIT22privateCompileMainPassEv
 __ZN3JSC3JIT13emit_op_enterEPNS_11InstructionE
 __ZN3JSC3JIT11emit_op_movEPNS_11InstructionE
 __ZN3JSC3JIT14privateCompileEPNS_21MacroAssemblerCodePtrE
 __ZN3JSC3JIT22privateCompileMainPassEv
 __ZN3JSC3JIT13emit_op_enterEPNS_11InstructionE
 __ZN3JSC3JIT11emit_op_movEPNS_11InstructionE
-__ZN3JSC3JIT18emit_op_new_regexpEPNS_11InstructionE
-__ZN3JSC11JITStubCall4callEj
-__ZN3WTF6VectorIN3JSC10CallRecordELm0EE15reserveCapacityEm
-__ZN3JSC3JIT12emit_op_callEPNS_11InstructionE
-__ZN3JSC3JIT13compileOpCallENS_8OpcodeIDEPNS_11InstructionEj
-__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEm
-__ZN3JSC3JIT23emit_op_call_put_resultEPNS_11InstructionE
-__ZN3JSC3JIT17emit_op_new_arrayEPNS_11InstructionE
 __ZN3JSC3JIT11emit_op_endEPNS_11InstructionE
 __ZN3JSC3JIT22privateCompileLinkPassEv
 __ZN3JSC3JIT23privateCompileSlowCasesEv
 __ZN3JSC3JIT11emit_op_endEPNS_11InstructionE
 __ZN3JSC3JIT22privateCompileLinkPassEv
 __ZN3JSC3JIT23privateCompileSlowCasesEv
-__ZN3JSC3JIT16emitSlow_op_callEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT21compileOpCallSlowCaseEPNS_11InstructionERPNS_13SlowCaseEntryEjNS_8OpcodeIDE
 __ZN3WTF6VectorIN3JSC18MethodCallLinkInfoELm0EE4growEm
 __ZN3JSC17BytecodeGenerator18dumpsGeneratedCodeEv
 __ZN3JSC4Heap29reportExtraMemoryCostSlowCaseEm
 __ZN3WTF6VectorIN3JSC18MethodCallLinkInfoELm0EE4growEm
 __ZN3JSC17BytecodeGenerator18dumpsGeneratedCodeEv
 __ZN3JSC4Heap29reportExtraMemoryCostSlowCaseEm
@@ -714,717 +515,1171 @@ __ZN3JSC12RegisterFile12globalObjectEv
 __ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE
 __ZN3JSC12RegisterFile15setGlobalObjectEPNS_14JSGlobalObjectE
 _ctiTrampoline
 __ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE
 __ZN3JSC12RegisterFile15setGlobalObjectEPNS_14JSGlobalObjectE
 _ctiTrampoline
-_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_
+__ZN3WTF15SegmentedVectorIN3JSC10IdentifierELm64EE6appendIS2_EEvRKT_
+__ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
+__ZN3JSC8JSParser31parseExpressionOrLabelStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC5Lexer16nextTokenIsColonEv
 __ZN3JSC8JSParser15parseExpressionINS_10ASTBuilderEEENT_10ExpressionERS3_
 __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
+__ZN3JSC8JSParser25parseAssignmentExpressionINS_10ASTBuilderEEENT_10ExpressionERS3_
+__ZN3JSC8JSParser21parseMemberExpressionINS_10ASTBuilderEEENT_10ExpressionERS3_
+__ZN3JSC11ParserArena20allocateFreeablePoolEv
+__ZN3JSCL19isNonASCIIIdentPartEi
+__ZN3JSC11ParserArena16allocateFreeableEm
+__ZN3JSC14SourceElements6appendEPNS_13StatementNodeE
+__ZNK3JSC13StatementNode16isEmptyStatementEv
+__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14expandCapacityEm
+__ZN3JSC17ExprStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitNodeEPNS_10RegisterIDEPNS_4NodeE
+__ZN3JSC11ResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11registerForERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator11emitResolveEPNS_10RegisterIDERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator18findScopedPropertyERKNS_10IdentifierERiRmbRbRPNS_8JSObjectE
 __ZN3JSC17BytecodeGenerator11emitResolveEPNS_10RegisterIDERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator18findScopedPropertyERKNS_10IdentifierERiRmbRbRPNS_8JSObjectE
-__ZNK3JSC16JSVariableObject16isVariableObjectEv
-__ZN3JSC17BytecodeGenerator16emitGetScopedVarEPNS_10RegisterIDEmiNS_7JSValueE
-__ZN3JSC17BytecodeGenerator15emitMethodCheckEv
-__ZN3JSC17BytecodeGenerator11emitGetByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
-__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC17GlobalResolveInfoELm0EE14expandCapacityEm
 __ZN3JSC17BytecodeGenerator11addConstantERKNS_10IdentifierE
 __ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEmPKS2_
 __ZN3WTF6VectorIN3JSC10IdentifierELm0EE15reserveCapacityEm
 __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
+__ZN3JSC17BytecodeGenerator11emitGetByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14expandCapacityEm
+__ZN3JSC3JIT22emit_op_resolve_globalEPNS_11InstructionEb
 __ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEmPKS2_
 __ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEmPKS2_
-__ZN3WTF6VectorIN3JSC10CallRecordELm0EE14expandCapacityEmPKS2_
-__ZN3JSC3JIT11emit_op_retEPNS_11InstructionE
-__ZN3JSC3JIT24emitSlow_op_method_checkEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEm
+__ZN3JSC3JIT17emit_op_get_by_idEPNS_11InstructionE
+__ZN3JSC3JIT21compileGetByIdHotPathEiiPNS_10IdentifierEj
+__ZN3JSC3JIT26emitSlow_op_resolve_globalEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC20MacroAssemblerX86_648storePtrENS_22AbstractMacroAssemblerINS_12X86AssemblerEE13TrustedImmPtrENS3_15ImplicitAddressE
+__ZN3JSC11JITStubCall4callEj
+__ZN3WTF6VectorIN3JSC10CallRecordELm0EE15reserveCapacityEm
+__ZN3JSC3JIT21emitSlow_op_get_by_idEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC3JIT22compileGetByIdSlowCaseEiiPNS_10IdentifierERPNS_13SlowCaseEntryEb
 __ZN3JSC11JITStubCall4callEv
 __ZN3JSC3JIT22compileGetByIdSlowCaseEiiPNS_10IdentifierERPNS_13SlowCaseEntryEb
 __ZN3JSC11JITStubCall4callEv
-_cti_register_file_check
-_cti_op_get_by_id_method_check
-__ZNK3JSC7JSValue3getEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+_cti_op_resolve_global
+__ZN3JSC15ObjectPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__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_
+__ZN3JSC28createUndefinedVariableErrorEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC11makeUStringIPKcNS_7UStringEEES3_T_T0_
+__ZN3WTF13tryMakeStringIPKcN3JSC7UStringEEENS_10PassRefPtrINS_10StringImplEEET_T0_
+__ZN3JSC20createReferenceErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC13ErrorInstance6createEPNS_12JSGlobalDataEPNS_9StructureERKNS_7UStringE
+__ZN3JSC13ErrorInstanceC2EPNS_12JSGlobalDataEPNS_9StructureERKNS_7UStringE
+__ZN3JSCL23returnToThrowTrampolineEPNS_12JSGlobalDataENS_16ReturnAddressPtrERS2_
+_ctiVMThrowTrampoline
+_cti_vm_throw
+__ZN3JSC11Interpreter14throwExceptionERPNS_9ExecStateERNS_7JSValueEj
+__ZNK3JSC13ErrorInstance15isErrorInstanceEv
+__ZNK3JSC8JSObject13exceptionTypeEv
+__ZN3JSC9CodeBlock24handlerForBytecodeOffsetEj
+__ZN3JSC11Interpreter15unwindCallFrameERPNS_9ExecStateENS_7JSValueERjRPNS_9CodeBlockE
+_ctiOpThrowNotCaught
+__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
+__ZNK3JSC8JSObject11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSC14ErrorPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
-__ZNK3WTF12AtomicString5lowerEv
-__ZNK3JSC8JSObject24getPropertySpecificValueEPNS_9ExecStateERKNS_10IdentifierERPNS_6JSCellE
-__ZN3JSC27ctiPatchCallByReturnAddressEPNS_9CodeBlockENS_16ReturnAddressPtrENS_11FunctionPtrE
-__ZN3JSC3JIT8linkCallEPNS_10JSFunctionEPNS_9CodeBlockES4_NS_21MacroAssemblerCodePtrEPNS_12CallLinkInfoEiPNS_12JSGlobalDataE
-_cti_op_get_by_id
+__ZN3JSC10JSFunction11getCallDataERNS_8CallDataE
+__ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
+__ZN3JSC11Interpreter11executeCallEPNS_9ExecStateEPNS_8JSObjectENS_8CallTypeERKNS_8CallDataENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL22errorProtoFuncToStringEPNS_9ExecStateE
+__ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZNK3JSC8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3WTF13tryMakeStringIN3JSC7UStringEPKcS2_EENS_10PassRefPtrINS_10StringImplEEET_T0_T1_
+__ZN3JSC7toInt32Ed
+__ZN3JSC11NewExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13CallArgumentsC2ERNS_17BytecodeGeneratorEPNS_13ArgumentsNodeE
+__ZN3JSC17BytecodeGenerator13emitConstructEPNS_10RegisterIDES2_RNS_13CallArgumentsEjjj
+__ZN3JSC16ArgumentListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC10StringNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3WTF9HashTableIPNS_10StringImplESt4pairIS2_PN3JSC8JSStringEENS_18PairFirstExtractorIS7_EENS4_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS6_EEEESD_E6rehashEi
+__ZN3WTF6VectorIN3JSC12CallLinkInfoELm0EE14expandCapacityEm
+__ZN3JSC3JIT17emit_op_constructEPNS_11InstructionE
+__ZN3JSC3JIT13compileOpCallENS_8OpcodeIDEPNS_11InstructionEj
+__ZN3WTF6VectorIcLm128EE15reserveCapacityEm
+__ZN3WTF6VectorIN3JSC10CallRecordELm0EE14expandCapacityEmPKS2_
+__ZN3JSC3JIT23emit_op_call_put_resultEPNS_11InstructionE
+__ZN3JSC3JIT21emitSlow_op_constructEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT21compileOpCallSlowCaseEPNS_11InstructionERPNS_13SlowCaseEntryEjNS_8OpcodeIDE
+_cti_op_construct_NotJSConstruct
+__ZN3JSC17StringConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithStringConstructorEPNS_9ExecStateE
+__ZN3JSC12StringObjectC1EPNS_9ExecStateEPNS_9StructureERKNS_7UStringE
+__ZN3JSC12StringObjectC2EPNS_9ExecStateEPNS_9StructureERKNS_7UStringE
+__ZN3JSC11BooleanNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEb
+__ZN3JSC9BlockNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9ArrayNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitNewArrayEPNS_10RegisterIDEPNS_11ElementNodeE
+__ZN3JSC3JIT17emit_op_new_arrayEPNS_11InstructionE
 _cti_op_new_array
 __ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureERKNS_7ArgListE
 _cti_op_new_array
 __ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureERKNS_7ArgListE
-__ZN3JSC18FunctionExecutable11discardCodeEv
-__ZN3JSC17FunctionCodeBlockD0Ev
-__ZN3JSC9CodeBlockD2Ev
-__ZN3JSC17StructureStubInfo5derefEv
-__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_
 __ZN3JSC8JSParser17parseFunctionInfoILNS0_20FunctionRequirementsE0ELb0ENS_10ASTBuilderEEEbRT1_RPKNS_10IdentifierERNS4_19FormalParameterListERNS4_12FunctionBodyERiSE_SE_
-__ZN3JSC10ASTBuilder14makeAssignNodeEPNS_14ExpressionNodeENS_8OperatorES2_bbiii
-__ZN3JSC8JSParser19parseBreakStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
-__ZN3JSC17ExprStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC13AssignDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZNK3JSC14ExpressionNode6isPureERNS_17BytecodeGeneratorE
-__ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC12FuncExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator25emitNewFunctionExpressionEPNS_10RegisterIDEPNS_12FuncExprNodeE
-__ZN3JSC18FunctionExecutableC1EPNS_12JSGlobalDataERKNS_10IdentifierERKNS_10SourceCodeEbPNS_18FunctionParametersEbii
-__ZN3WTF6VectorIN3JSC12WriteBarrierINS1_18FunctionExecutableEEELm0EE14expandCapacityEm
-__ZN3JSC17BytecodeGenerator11emitPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
-__ZN3JSC3JIT17emit_op_get_by_idEPNS_11InstructionE
+__ZN3JSC8JSParser19parseSourceElementsILNS0_18SourceElementsModeE0ENS_13SyntaxCheckerEEENT0_14SourceElementsERS4_
+__ZN3JSC8JSParser14parseStatementINS_13SyntaxCheckerEEENT_9StatementERS3_RPKNS_10IdentifierE
+__ZN3JSC8JSParser15parseExpressionINS_13SyntaxCheckerEEENT_10ExpressionERS3_
+__ZN3JSC8JSParser25parseAssignmentExpressionINS_13SyntaxCheckerEEENT_10ExpressionERS3_
+__ZN3JSC8JSParser21parseMemberExpressionINS_13SyntaxCheckerEEENT_10ExpressionERS3_
+__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEb
+__ZN3JSC8JSParser5ScopeD1Ev
+__ZN3JSC5Lexer10sourceCodeEiii
+__ZN3JSC16FunctionBodyNode13finishParsingERKNS_10SourceCodeEPNS_13ParameterNodeERKNS_10IdentifierE
+__ZN3JSC16FunctionBodyNode13finishParsingEN3WTF10PassRefPtrINS_18FunctionParametersEEERKNS_10IdentifierE
+__ZN3JSC10ASTBuilder20makeFunctionCallNodeEPNS_14ExpressionNodeEPNS_13ArgumentsNodeEiii
+__ZNK3JSC14ExpressionNode10isLocationEv
+__ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12FuncExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator25emitNewFunctionExpressionEPNS_10RegisterIDEPNS_12FuncExprNodeE
+__ZN3JSC18FunctionExecutableC1EPNS_12JSGlobalDataERKNS_10IdentifierERKNS_10SourceCodeEbPNS_18FunctionParametersEbii
+__ZN3WTF6VectorIN3JSC12WriteBarrierINS1_18FunctionExecutableEEELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator8emitCallEPNS_10RegisterIDES2_RNS_13CallArgumentsEjjj
+__ZN3JSC17BytecodeGenerator8emitCallENS_8OpcodeIDEPNS_10RegisterIDES3_RNS_13CallArgumentsEjjj
+__ZThn16_N3JSC16FunctionBodyNodeD0Ev
+__ZN3JSC16FunctionBodyNodeD0Ev
 __ZN3JSC3JIT20emit_op_new_func_expEPNS_11InstructionE
 __ZN3JSC3JIT20emit_op_new_func_expEPNS_11InstructionE
-__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
-__ZN3JSC9Structure22materializePropertyMapERNS_12JSGlobalDataE
-__ZN3WTF9HashTableISt4pairINS_6RefPtrINS_10StringImplEEEjES1_IS5_PN3JSC7JSValueEENS_18PairFirstExtractorIS9_EENS6_24StructureTransitionTable4HashENS_14PairHashTraitsINSC_10HashTraitsENS_10HashTraitsIS8_EEEESF_E6rehashEi
+__ZN3JSC3JIT12emit_op_callEPNS_11InstructionE
+__ZN3JSC3JIT16emitSlow_op_callEPNS_11InstructionERPNS_13SlowCaseEntryE
 _cti_op_new_func_exp
 _cti_op_new_func_exp
-_cti_op_put_by_id
-__ZN3JSC8JSParser20parseSwitchStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
-__ZN3JSC8JSParser18parseSwitchClausesINS_13SyntaxCheckerEEENT_10ClauseListERS3_
-__ZN3WTF6VectorIPvLm0EE14expandCapacityEm
-__ZN3JSC8JSParser17parseForStatementINS_10ASTBuilderEEENT_9StatementERS3_
-__ZN3JSC8JSParser19parseVarDeclarationINS_10ASTBuilderEEENT_9StatementERS3_
-__ZN3JSC8JSParser21parseDoWhileStatementINS_10ASTBuilderEEENT_9StatementERS3_
-__ZNK3JSC19BracketAccessorNode10isLocationEv
-__ZNK3JSC19BracketAccessorNode21isBracketAccessorNodeEv
-__ZN3JSC10ASTBuilder14makeBinaryNodeEiSt4pairIPNS_14ExpressionNodeENS0_12BinaryOpInfoEES5_
-__ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC16PropertyListNode12emitBytecodeERNS_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
+__ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_18FunctionExecutableEPNS_14ScopeChainNodeE
+__ZN3JSC10JSFunctionC2EPNS_9ExecStateEPNS_18FunctionExecutableEPNS_14ScopeChainNodeE
+_cti_vm_lazyLinkCall
+__ZN3JSC18FunctionExecutable22compileForCallInternalEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC6Parser5parseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EEPNS_14JSGlobalObjectEPNS_8DebuggerEPNS_9ExecStateERKNS_10SourceCodeEPNS_18FunctionParametersENS_18JSParserStrictnessEPPNS_8JSObjectE
+__ZN3JSC8JSParser19parseSourceElementsILNS0_18SourceElementsModeE1ENS_10ASTBuilderEEENT0_14SourceElementsERS4_
+__ZN3JSC8JSParser19parseThrowStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__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
+__ZN3JSC16FunctionBodyNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC9ScopeNode15singleStatementEv
+__ZNK3JSC9BlockNode7isBlockEv
+__ZNK3JSC13StatementNode12isReturnNodeEv
+__ZN3JSC17BytecodeGenerator10emitReturnEPNS_10RegisterIDE
+__ZN3JSC3JIT13emit_op_throwEPNS_11InstructionE
+__ZN3JSC11JITStubCall11addArgumentEjNS_12X86Registers10RegisterIDE
+__ZN3JSC3JIT11emit_op_retEPNS_11InstructionE
+_cti_op_throw
+__ZNK3JSC8JSString8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE
+__ZN3JSC12StringObjectC1ERNS_12JSGlobalDataEPNS_9StructureEPNS_8JSStringE
+__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC15StringPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC17BytecodeGenerator8emitMoveEPNS_10RegisterIDES2_
+__ZN3JSCL20isNonASCIIIdentStartEi
+__ZN3JSC10NumberNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEd
+__ZN3WTF9HashTableIdSt4pairIdN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsIdEENSA_IS3_EEEESB_E6expandEv
+__ZN3JSC7UString6numberEj
+__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateEPNS_14JSGlobalObjectE
+__ZN3JSC15constructNumberEPNS_9ExecStateEPNS_14JSGlobalObjectENS_7JSValueE
+__ZN3JSC15NumberPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12StringObjectC1EPNS_9ExecStateEPNS_9StructureE
+__ZN3JSC5Lexer7record8Ei
+__ZN3JSC8NullNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC18FunctionExecutable11discardCodeEv
+__ZN3JSC17FunctionCodeBlockD0Ev
+__ZN3JSC9CodeBlockD2Ev
+__ZN3JSC15WeakHandleOwner26isReachableFromOpaqueRootsENS_6HandleINS_7UnknownEEEPvRNS_9MarkStackE
+__ZN3JSC12RegisterFile17GlobalObjectOwner8finalizeENS_6HandleINS_7UnknownEEEPv
+__ZN3JSC13ErrorInstanceD1Ev
+__ZN3JSC12StringObjectD1Ev
+__ZN3JSC12NumberObjectD1Ev
+__ZN3JSC17ProgramExecutableD1Ev
+__ZN3JSC16ProgramCodeBlockD0Ev
+__ZN3JSC19SourceProviderCacheD1Ev
+__ZN3WTF20deleteAllPairSecondsIPN3JSC23SourceProviderCacheItemEKNS_7HashMapIiS3_NS_7IntHashIjEENS_10HashTraitsIiEENS7_IS3_EEEEEEvRT0_
+__ZN3JSC17StructureStubInfo5derefEv
+__ZN3JSC18FunctionExecutableD1Ev
+__ZN3WTFeqERKNS_12AtomicStringEPKc
+_JSClassCreate
+__ZN13OpaqueJSClass6createEPK17JSClassDefinition
+__ZN13OpaqueJSClassC2EPK17JSClassDefinitionPS_
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_P19StaticFunctionEntryENS_18PairFirstExtractorIS7_EENS_10StringHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSC_IS6_EEEESD_E6expandEv
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_P16StaticValueEntryENS_18PairFirstExtractorIS7_EENS_10StringHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSC_IS6_EEEESD_E6expandEv
+_JSClassRetain
+_JSObjectMake
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEEC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEP13OpaqueJSClassPv
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE4initEPNS_9ExecStateE
+__ZN13OpaqueJSClass9prototypeEPN3JSC9ExecStateE
+__ZN13OpaqueJSClass11contextDataEPN3JSC9ExecStateE
+__ZN3WTF9HashTableIP13OpaqueJSClassSt4pairIS2_P24OpaqueJSClassContextDataENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS5_EEEESD_E6expandEv
+__ZN24OpaqueJSClassContextDataC2ERN3JSC12JSGlobalDataEP13OpaqueJSClass
+_JSClassRelease
+_JSObjectSetProperty
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8JSParser16parseIfStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZNK3JSC15DotAccessorNode10isLocationEv
+__ZNK3JSC14ExpressionNode13isResolveNodeEv
+__ZNK3JSC14ExpressionNode21isBracketAccessorNodeEv
+__ZN3JSC9CodeBlock25createRareDataIfNecessaryEv
+__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14expandCapacityEm
+__ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator8newLabelEv
 __ZN3JSC17BytecodeGenerator8newLabelEv
-__ZN3JSC17BytecodeGenerator20emitGetPropertyNamesEPNS_10RegisterIDES2_S2_S2_PNS_5LabelE
-__ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
+__ZNK3JSC14ExpressionNode26hasConditionContextCodegenEv
+__ZN3WTF6VectorIN3JSC19ExpressionRangeInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC19FunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15emitMethodCheckEv
 __ZN3JSC17BytecodeGenerator9emitLabelEPNS_5LabelE
 __ZN3WTF6VectorIjLm0EE15reserveCapacityEm
 __ZN3JSC17BytecodeGenerator9emitLabelEPNS_5LabelE
 __ZN3WTF6VectorIjLm0EE15reserveCapacityEm
-__ZN3WTF6VectorIN3JSC12ForInContextELm0EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14shrinkCapacityEm
+__ZN3JSC3JIT14emit_op_jfalseEPNS_11InstructionE
+__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common19RelationalConditionENS_12X86Registers10RegisterIDES4_
+__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14expandCapacityEmPKS2_
+__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14expandCapacityEm
+__ZN3JSC3JIT20emit_op_method_checkEPNS_11InstructionE
+__ZN3WTF6VectorIN3JSC25MethodCallCompilationInfoELm0EE14expandCapacityEm
+__ZN3JSC3JIT18emitSlow_op_jfalseEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC23MacroAssemblerX86Common12branchTest32ENS0_15ResultConditionENS_12X86Registers10RegisterIDENS_22AbstractMacroAssemblerINS_12X86AssemblerEE12TrustedImm32E
+__ZN3JSC3JIT24emitSlow_op_method_checkEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3WTF6VectorIN3JSC32CallReturnOffsetToBytecodeOffsetELm0EE15reserveCapacityEm
+_cti_op_get_by_id
+__ZNK3JSC7JSValue3getEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+_cti_op_jtrue
+__ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
+_cti_op_get_by_id_method_check
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE20staticFunctionGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSC18JSCallbackFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPFPK13OpaqueJSValuePK15OpaqueJSContextPS5_SB_mPKS7_PS7_ERKNS_10IdentifierE
+_cti_op_call_NotJSFunction
+__ZN3JSC18JSCallbackFunction11getCallDataERNS_8CallDataE
+__ZN3JSC18JSCallbackFunction4callEPNS_9ExecStateE
+__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
+_JSObjectGetPrivate
+_JSValueMakeUndefined
+__ZN3JSC6JSLock12DropAllLocksD1Ev
+__ZN3WTF6String6appendEPKtj
+__ZN3JSC15WeakHandleOwnerD2Ev
+__ZN3JSC8JSParser24parseFunctionDeclarationINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC8JSParser17parseFunctionInfoILNS0_20FunctionRequirementsE1ELb1ENS_10ASTBuilderEEEbRT1_RPKNS_10IdentifierERNS4_19FormalParameterListERNS4_12FunctionBodyERiSE_SE_
+__ZN3JSC8JSParser16parseIfStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3WTF7HashSetINS_6RefPtrINS_10StringImplEEEN3JSC17IdentifierRepHashENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3JSC8JSParser31parseExpressionOrLabelStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser19parseVarDeclarationINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser5Scope15declareVariableEPKNS_10IdentifierE
+__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
+__ZN3JSC19SourceProviderCache3addEiN3WTF10PassOwnPtrINS_23SourceProviderCacheItemEEEj
+__ZN3WTF9HashTableIiSt4pairIiPN3JSC23SourceProviderCacheItemEENS_18PairFirstExtractorIS5_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIiEENSB_IS4_EEEESC_E6expandEv
+__ZN3WTF6VectorIPN3JSC16FunctionBodyNodeELm0EE15reserveCapacityEm
+__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
+__ZN3JSC17BytecodeGenerator12addGlobalVarERKNS_10IdentifierEbRPNS_10RegisterIDE
+__ZN3JSC18FunctionExecutableC1EPNS_9ExecStateERKNS_10IdentifierERKNS_10SourceCodeEbPNS_18FunctionParametersEbii
+__ZN3JSC12FuncDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC14JSGlobalObject15copyGlobalsFromERNS_12RegisterFileE
+__ZNK3WTF12AtomicString5lowerEv
+__ZN3JSC41constructFunctionSkippingEvalEnabledCheckEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
+__ZN3WTF13StringBuilder6appendEPKcj
+__ZNK3JSC21UStringSourceProvider6lengthEv
+__ZN3JSC18FunctionExecutable14fromGlobalCodeERKNS_10IdentifierEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPPNS_8JSObjectE
+__ZNK3JSC21UStringSourceProvider4dataEv
+__ZN3JSC8JSParser16declareParameterEPKNS_10IdentifierE
+__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEm
+__ZN3JSC10JSFunction18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC9Structure22materializePropertyMapERNS_12JSGlobalDataE
+__ZNK3JSC11ResolveNode10isLocationEv
+__ZNK3JSC11ResolveNode13isResolveNodeEv
+__ZN3JSC17BytecodeGenerator12addParameterERKNS_10IdentifierEi
+__ZN3JSC23FunctionCallResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC16JSVariableObject16isVariableObjectEv
+__ZN3JSC17BytecodeGenerator16emitGetScopedVarEPNS_10RegisterIDEmiNS_7JSValueE
+__ZN3JSC3JIT22emit_op_get_global_varEPNS_11InstructionE
+__ZN3JSC8JSParser19parseVarDeclarationINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3WTF6VectorISt4pairIPKN3JSC10IdentifierEjELm0EE15reserveCapacityEm
+__ZN3JSC9ScopeNode8capturesERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator6addVarERKNS_10IdentifierEbRPNS_10RegisterIDE
+__ZNK3JSC14JSGlobalObject14isDynamicScopeERb
 __ZN3JSC16VarStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator15isLocalConstantERKNS_10IdentifierE
 __ZN3JSC16VarStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator15isLocalConstantERKNS_10IdentifierE
-__ZN3WTF6VectorIN3JSC17GlobalResolveInfoELm0EE14expandCapacityEm
-__ZN3JSC11DoWhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17AssignBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZNK3JSC11ResolveNode6isPureERNS_17BytecodeGeneratorE
-__ZN3JSC17BytecodeGenerator7isLocalERKNS_10IdentifierE
+_cti_register_file_check
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE17staticValueGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3WTF9HashTableISt4pairINS_6RefPtrINS_10StringImplEEEjES1_IS5_PN3JSC7JSValueEENS_18PairFirstExtractorIS9_EENS6_24StructureTransitionTable4HashENS_14PairHashTraitsINSC_10HashTraitsENS_10HashTraitsIS8_EEEESF_E6rehashEi
+_JSValueMakeString
 __ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC19BracketAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator22willResolveToArgumentsERKNS_10IdentifierE
-__ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_
-__ZN3JSC17BytecodeGenerator12emitPutByValEPNS_10RegisterIDES2_S2_
-__ZNK3JSC14ExpressionNode26hasConditionContextCodegenEv
-__ZN3JSC15StrictEqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_
-__ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC3JIT20emit_op_convert_thisEPNS_11InstructionE
+__ZN3JSC23MacroAssemblerX86Common11branchTest8ENS0_15ResultConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS4_12TrustedImm32E
+__ZN3JSC3JIT24emitSlow_op_convert_thisEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC8JSObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC14JSGlobalObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC9MarkStack14MarkStackArrayIPNS_6JSCellEE6appendERKS3_
+__ZN3JSC10JSFunction13visitChildrenERNS_9MarkStackE
+__ZN3JSC18FunctionExecutable13visitChildrenERNS_9MarkStackE
+__ZN3JSC14ScopeChainNode13visitChildrenERNS_9MarkStackE
+__ZN3JSC12RegExpObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC15JSWrapperObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC7JSArray13visitChildrenERNS_9MarkStackE
+__ZN3JSC22NativeErrorConstructor13visitChildrenERNS_9MarkStackE
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE13visitChildrenERNS_9MarkStackE
+__ZN3JSC9WeakGCMapISt4pairIN3WTF6RefPtrINS2_10StringImplEEEjENS_9StructureENS_24StructureTransitionTable26WeakGCMapFinalizerCallbackENS8_4HashENS8_10HashTraitsEE8finalizeENS_6HandleINS_7UnknownEEEPv
+__ZN3JSC9WeakGCMapISt4pairIN3WTF6RefPtrINS2_10StringImplEEEjENS_9StructureENS_24StructureTransitionTable26WeakGCMapFinalizerCallbackENS8_4HashENS8_10HashTraitsEED0Ev
+__ZN3JSC9WeakGCMapISt4pairIN3WTF6RefPtrINS2_10StringImplEEEjENS_9StructureENS_24StructureTransitionTable26WeakGCMapFinalizerCallbackENS8_4HashENS8_10HashTraitsEED1Ev
+__ZN3WTF7HashMapISt4pairINS_6RefPtrINS_10StringImplEEEjEPN3JSC7JSValueENS6_24StructureTransitionTable4HashENS9_10HashTraitsENS_10HashTraitsIS8_EEE4takeERKS5_
+__ZN3JSC20JSCallbackObjectData8finalizeENS_6HandleINS_7UnknownEEEPv
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEED1Ev
+__ZN3JSC20JSCallbackObjectDataD0Ev
+__ZN3JSC18JSCallbackFunctionD1Ev
+__ZN3WTF10StringImpl23reverseFindIgnoringCaseEPS0_j
+__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
+__ZN3WTF6VectorIiLm0EE14expandCapacityEm
+__ZN3JSC8JSParser20parseReturnStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC5Lexer10scanRegExpERPKNS_10IdentifierES4_t
+__ZN3JSC4Yarr11checkSyntaxERKNS_7UStringE
+__ZN3JSC4Yarr6ParserINS0_13SyntaxCheckerEE5parseEv
+__ZN3JSC8JSParser17parseTryStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser17parseForStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3WTF6VectorISt4pairIiiELm0EE14expandCapacityEm
+__ZN3JSC8JSParser24parseFunctionDeclarationINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser17parseFunctionInfoILNS0_20FunctionRequirementsE1ELb1ENS_13SyntaxCheckerEEEbRT1_RPKNS_10IdentifierERNS4_19FormalParameterListERNS4_12FunctionBodyERiSE_SE_
+_JSValueToBoolean
+__ZN3WTF21charactersToIntStrictEPKtmPbi
+__ZN3JSC8JSParser17parseForStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC10ASTBuilder14makeBinaryNodeEiSt4pairIPNS_14ExpressionNodeENS0_12BinaryOpInfoEES5_
+__ZN3JSC10ASTBuilder15makePostfixNodeEPNS_14ExpressionNodeENS_8OperatorEiii
+__ZN3JSC10ASTBuilder14makeAssignNodeEPNS_14ExpressionNodeENS_8OperatorES2_bbiii
+__ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
+__ZN3JSC19BracketAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC10NumberNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator22willResolveToArgumentsERKNS_10IdentifierE
+__ZNK3JSC11ResolveNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator7isLocalERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC18PostfixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator10emitPreIncEPNS_10RegisterIDE
+__ZN3JSC12BinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC14ExpressionNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator12emitBinaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_NS_12OperandTypesE
+__ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC3JIT11emit_op_jmpEPNS_11InstructionE
+__ZN3JSC3JIT18emit_op_get_by_valEPNS_11InstructionE
+__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common19RelationalConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS5_13TrustedImmPtrE
+__ZN3JSC12X86Assembler23X86InstructionFormatter11oneByteOp64ENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDES4_ii
+__ZN3JSC3JIT15emit_op_pre_incEPNS_11InstructionE
+__ZN3JSC3JIT16emitTimeoutCheckEv
+__ZN3JSC3JIT13emit_op_jlessEPNS_11InstructionE
+__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
+__ZN3JSC21roundUpAllocationSizeEmm
+__ZN3JSC3JIT19emitSlow_op_pre_incEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT17emitSlow_op_jlessEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC12X86Assembler7movq_rrENS_12X86Registers10RegisterIDENS1_13XMMRegisterIDE
+__ZN3JSC23MacroAssemblerX86Common12branchDoubleENS0_15DoubleConditionENS_12X86Registers13XMMRegisterIDES3_
+__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_12X86Registers10RegisterIDE
+__ZN3JSC10ASTBuilder11makeAddNodeEPNS_14ExpressionNodeES2_b
+__ZNK3JSC14ExpressionNode8isNumberEv
+__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14expandCapacityEmPKS3_
+__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE15reserveCapacityEm
+__ZN3JSC13AssignDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC7AddNode5isAddEv
+__ZN3JSC12BinaryOpNode10emitStrcatERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_PNS_21ReadModifyResolveNodeE
+__ZNK3JSC14ExpressionNode5isAddEv
+__ZNK3JSC10StringNode8isStringEv
+__ZNK3JSC14ExpressionNode8isStringEv
+__ZN3JSC17BytecodeGenerator15emitToPrimitiveEPNS_10RegisterIDES2_
+__ZN3JSC17BytecodeGenerator10emitStrcatEPNS_10RegisterIDES2_i
+__ZN3JSC17BytecodeGenerator11emitPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC10IfElseNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC3JIT20emit_op_to_primitiveEPNS_11InstructionE
+__ZN3JSC3JIT14emit_op_strcatEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_put_by_idEPNS_11InstructionE
+__ZN3JSC3JIT24emitSlow_op_to_primitiveEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT21emitSlow_op_put_by_idEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_strcat
+_cti_op_put_by_id
+__ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE
+__ZNK3JSC8JSString19resolveRopeSlowCaseEPNS_9ExecStateEPt
+__ZNK3JSC18EmptyStatementNode16isEmptyStatementEv
+__ZN3JSC8JSParser17parseTryStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator20emitInitLazyRegisterEPNS_10RegisterIDE
+__ZNK3JSC13LogicalOpNode26hasConditionContextCodegenEv
+__ZN3JSC13LogicalOpNode30emitBytecodeInConditionContextERNS_17BytecodeGeneratorEPNS_5LabelES4_b
+__ZNK3JSC14ExpressionNode6isNullEv
+__ZNK3JSC10StringNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17TypeOfResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11emitUnaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_
+__ZN3JSC17BytecodeGenerator19emitResolveWithBaseEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC7TryNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC20EvalFunctionCallNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitCallEvalEPNS_10RegisterIDES2_RNS_13CallArgumentsEjjj
+__ZN3JSC17BytecodeGenerator9emitCatchEPNS_10RegisterIDEPNS_5LabelES4_
+__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator16emitPushNewScopeEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3WTF6VectorIN3JSC18ControlFlowContextELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator21emitResolveBaseForPutEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator15emitResolveBaseEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator12emitPopScopeEv
+__ZN3JSC9EqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_
+__ZN3JSC3JIT21emit_op_init_lazy_regEPNS_11InstructionE
+__ZN3JSC3JIT25emit_op_create_activationEPNS_11InstructionE
+__ZN3JSC20MacroAssemblerX86_6413branchTestPtrENS_23MacroAssemblerX86Common15ResultConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS5_12TrustedImm32E
+__ZN3JSC3JIT11emit_op_neqEPNS_11InstructionE
+__ZN3JSC12X86Assembler6orl_irEiNS_12X86Registers10RegisterIDE
+__ZN3JSC3JIT13emit_op_jtrueEPNS_11InstructionE
+__ZN3JSC3JIT25emit_op_resolve_with_baseEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_call_evalEPNS_11InstructionE
+__ZN3JSC3JIT13emit_op_catchEPNS_11InstructionE
+__ZN3JSC20MacroAssemblerX86_647loadPtrENS_22AbstractMacroAssemblerINS_12X86AssemblerEE15ImplicitAddressENS_12X86Registers10RegisterIDE
+__ZN3JSC3JIT22emit_op_push_new_scopeEPNS_11InstructionE
+__ZN3JSC3JIT20emit_op_resolve_baseEPNS_11InstructionE
+__ZN3JSC3JIT15emit_op_resolveEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_pop_scopeEPNS_11InstructionE
+__ZN3JSC3JIT10emit_op_eqEPNS_11InstructionE
+__ZN3JSC3JIT27emit_op_tear_off_activationEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_neqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT17emitSlow_op_jtrueEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT21emitSlow_op_call_evalEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT14emitSlow_op_eqEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_push_activation
+__ZN3JSC12JSActivationC1EPNS_9ExecStateEPNS_18FunctionExecutableE
+_cti_op_typeof
+__ZN3JSC20jsTypeStringForValueEPNS_9ExecStateENS_7JSValueE
+_cti_op_eq
+_cti_op_resolve_with_base
+__ZN3JSC12JSActivation18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+_cti_op_call_eval
+__ZN3JSC11Interpreter8callEvalEPNS_9ExecStateEPNS_12RegisterFileEPNS_8RegisterEii
+__ZN3JSC14EvalExecutableC1EPNS_9ExecStateERKNS_10SourceCodeEb
+__ZN3JSC14EvalExecutable15compileInternalEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC6Parser5parseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_14JSGlobalObjectEPNS_8DebuggerEPNS_9ExecStateERKNS_10SourceCodeEPNS_18FunctionParametersENS_18JSParserStrictnessEPPNS_8JSObjectE
+__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
+__ZN3WTF7HashMapINS_6RefPtrINS_10StringImplEEEN3JSC12WriteBarrierINS4_14EvalExecutableEEENS_10StringHashENS_10HashTraitsIS3_EENS9_IS7_EEE3setEPS2_RKS7_
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_N3JSC12WriteBarrierINS5_14EvalExecutableEEEENS_18PairFirstExtractorIS9_EENS_10StringHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSE_IS8_EEEESF_E6expandEv
+__ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
+__ZN3JSC11Interpreter7executeEPNS_14EvalExecutableEPNS_9ExecStateEPNS_8JSObjectEiPNS_14ScopeChainNodeE
+_cti_op_resolve
+_JSValueMakeBoolean
+__ZN3JSC8JSParser20parseReturnStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC10ASTBuilder11makeDivNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC14ExpressionNode14stripUnaryPlusEv
+__ZNK3JSC10NumberNode8isNumberEv
+__ZN3JSC15StrictEqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC10ReturnNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13LogicalOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSCeqERKNS_7UStringEPKc
+__ZN3JSC23CallFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator25emitJumpIfNotFunctionCallEPNS_10RegisterIDEPNS_5LabelE
+__ZNK3JSC10ReturnNode12isReturnNodeEv
+__ZNK3JSC14SourceElements15singleStatementEv
+__ZN3JSC3JIT16emit_op_stricteqEPNS_11InstructionE
+__ZN3JSC3JIT17compileOpStrictEqEPNS_11InstructionENS0_21CompileOpStrictEqTypeE
+__ZN3JSC3JIT11emit_op_divEPNS_11InstructionE
+__ZN3JSC23MacroAssemblerX86Common4moveENS_22AbstractMacroAssemblerINS_12X86AssemblerEE12TrustedImm32ENS_12X86Registers10RegisterIDE
+__ZN3JSC12X86Assembler11cvtsi2sd_rrENS_12X86Registers10RegisterIDENS1_13XMMRegisterIDE
+__ZN3JSC3JIT16emit_op_jneq_ptrEPNS_11InstructionE
+__ZN3JSC3JIT20emitSlow_op_stricteqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT15emitSlow_op_divEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_stricteq
+__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
+__ZN3JSC4Yarr13YarrGenerator19jumpIfCharNotEqualsEti
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDES4_ii
+__ZN3JSC12X86Assembler7subl_irEiNS_12X86Registers10RegisterIDE
+__ZN3JSC4Yarr13YarrGenerator13backtrackTermEm
+__ZN3JSC4Yarr13YarrGenerator20backtrackTermDefaultEm
+__ZN3JSC17BytecodeGenerator13emitNewRegExpEPNS_10RegisterIDEN3WTF10PassRefPtrINS_6RegExpEEE
+__ZN3JSC17BytecodeGenerator9addRegExpEN3WTF10PassRefPtrINS_6RegExpEEE
+__ZNK3JSC14ExpressionNode10isSubtractEv
+__ZN3JSC3JIT18emit_op_new_regexpEPNS_11InstructionE
+__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+_cti_op_new_regexp
+__ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateE
+__ZNK3JSC7JSValue14toThisJSStringEPNS_9ExecStateE
+__ZN3JSC9ExecState8argumentEi
+__ZN3JSC6JSCell11getCallDataERNS_8CallDataE
+__ZN3WTF6RefPtrINS_10StringImplEEaSERKS2_
+__ZN3JSC6RegExp5matchERKNS_7UStringEiPN3WTF6VectorIiLm32EEE
+__ZN3JSC4Yarr7executeERNS0_13YarrCodeBlockEPKtjjPi
+__ZN3JSC3JIT11emit_op_addEPNS_11InstructionE
+_cti_op_add
+_cti_op_tear_off_activation
+__ZN3JSC9JITThunks15tryCacheGetByIDEPNS_9ExecStateEPNS_9CodeBlockENS_16ReturnAddressPtrENS_7JSValueERKNS_10IdentifierERKNS_12PropertySlotEPNS_17StructureStubInfoE
+__ZN3JSC3JIT33privateCompilePatchGetArrayLengthENS_16ReturnAddressPtrE
+__ZNK3JSC8JSObject24getPropertySpecificValueEPNS_9ExecStateERKNS_10IdentifierERPNS_6JSCellE
+__ZN3JSC27ctiPatchCallByReturnAddressEPNS_9CodeBlockENS_16ReturnAddressPtrENS_11FunctionPtrE
+__ZN3JSC3JIT8linkCallEPNS_10JSFunctionEPNS_9CodeBlockES4_NS_21MacroAssemblerCodePtrEPNS_12CallLinkInfoEiPNS_12JSGlobalDataE
+__ZN3JSC3JIT20patchMethodCallProtoERNS_12JSGlobalDataEPNS_9CodeBlockERNS_18MethodCallLinkInfoEPNS_10JSFunctionEPNS_9StructureEPNS_8JSObjectENS_16ReturnAddressPtrE
+__ZN3JSC9JITThunks15tryCachePutByIDEPNS_9ExecStateEPNS_9CodeBlockENS_16ReturnAddressPtrENS_7JSValueERKNS_15PutPropertySlotEPNS_17StructureStubInfoEb
+_cti_op_get_by_id_generic
+_cti_op_put_by_id_generic
+__ZN3JSC14StructureChainC1ERNS_12JSGlobalDataEPNS_9StructureES4_
+__ZN3JSC14StructureChainC2ERNS_12JSGlobalDataEPNS_9StructureES4_
+__ZN3JSC3JIT26privateCompileGetByIdChainEPNS_17StructureStubInfoEPNS_9StructureEPNS_14StructureChainEmRKNS_10IdentifierERKNS_12PropertySlotEmNS_16ReturnAddressPtrEPNS_9ExecStateE
+__ZN3JSC3JIT13testPrototypeENS_7JSValueERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListE
+__ZN3JSC3JIT22compileGetDirectOffsetEPNS_8JSObjectENS_12X86Registers10RegisterIDEm
+_cti_op_get_by_id_proto_list
+__ZN3JSC3JIT30privateCompileGetByIdChainListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureEPNS_14StructureChainEmRKNS_10IdentifierERKNS_12PropertySlotEmPNS_9ExecStateE
+__ZNK3JSC14LogicalNotNode26hasConditionContextCodegenEv
+__ZN3JSC11UnaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC14StructureChain13visitChildrenERNS_9MarkStackE
+__ZN3JSC12RegExpObjectD1Ev
+__ZN3JSC21UStringSourceProviderD0Ev
+__ZN3JSC14EvalExecutableD1Ev
+__ZN3JSC13EvalCodeBlockD0Ev
+__ZN3JSC14ExecutablePool13systemReleaseERNS0_10AllocationE
+__ZN3WTF11OSAllocator8decommitEPvm
+__ZN3JSC12JSActivationD1Ev
+__ZN3JSC19SourceProviderCache5clearEv
+__ZNK3WTF6String8toDoubleEPbS1_
+__ZN3JSC8JSParser5Scope19restoreFunctionInfoEPKNS_23SourceProviderCacheItemE
+__ZN3JSC5Lexer9setOffsetEi
+_JSStringCreateWithCharacters
+__ZN3WTF6VectorItLm0EE14expandCapacityEmPKt
+__ZN3WTF10StringImpl7replaceEtt
+__ZN3JSC14StructureChainD1Ev
+__ZN3WTF10StringImpl7replaceEPS0_S1_
+__ZNK3WTF6String5toIntEPb
+__ZN3WTF10StringImpl5toIntEPb
+__ZN3WTF15charactersToIntEPKtmPb
+__ZN3WTF6String6numberEi
+__ZN3WTF6String6numberEt
+__ZNK3WTF6String18simplifyWhiteSpaceEv
+__ZN3WTF10StringImpl18simplifyWhiteSpaceEv
+_JSValueMakeNumber
+__ZN3JSC13LiteralParser5Lexer9lexNumberERNS1_18LiteralParserTokenE
+__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateE
+__ZN3WTF10StringImpl5adoptERNS_12StringBufferE
+__ZNK3WTF6String8foldCaseEv
+__ZN3WTF10StringImpl8foldCaseEv
+__ZN3WTF14FastMallocZone4sizeEP14_malloc_zone_tPKv
+__ZNK3WTF6String7toFloatEPbS1_
+__ZN3WTF10StringImpl7toFloatEPbS1_
+__ZN3WTF17charactersToFloatEPKtmPbS2_
+__ZN3JSC17ReadModifyDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC7UString6numberEi
+__ZN3JSC3JIT15emitSlow_op_addEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT28compileBinaryArithOpSlowCaseENS_8OpcodeIDERPNS_13SlowCaseEntryEjjjNS_12OperandTypesEbb
+__ZNK3JSC7UString5asciiEv
+__ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
+_cti_op_less
+__ZN3JSC8jsStringEPNS_9ExecStateERKNS_7UStringE
+_cti_op_get_by_val
+__ZN3WTF10StringImpl5upperEv
+__ZN3JSC10ASTBuilder14makePrefixNodeEPNS_14ExpressionNodeENS_8OperatorEiii
+__ZN3JSC17PrefixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC4Yarr22YarrPatternConstructor25atomBuiltInCharacterClassENS0_23BuiltInCharacterClassIDEb
+__ZN3JSC4Yarr13YarrGenerator12atEndOfInputEv
+__ZN3JSC4Yarr13YarrGenerator13readCharacterEiNS_12X86Registers10RegisterIDE
+__ZN3JSC4Yarr13YarrGenerator19matchCharacterClassENS_12X86Registers10RegisterIDERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListEPKNS0_14CharacterClassE
+__ZN3JSC14MacroAssembler4pokeENS_12X86Registers10RegisterIDEi
+__ZN3JSC21ReadModifyResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC3JIT20compileBinaryArithOpENS_8OpcodeIDEjjjNS_12OperandTypesE
+__ZN3JSC23MacroAssemblerX86Common4moveENS_12X86Registers10RegisterIDES2_
+__ZN3JSCL20stringProtoFuncMatchEPNS_9ExecStateE
+__ZNK3JSC17RegExpConstructor14arrayOfMatchesEPNS_9ExecStateE
+__ZN3JSC18RegExpMatchesArrayC2EPNS_9ExecStateEPNS_24RegExpConstructorPrivateE
+__ZN3JSC7JSArrayC2ERNS_12JSGlobalDataEPNS_9StructureEjNS_17ArrayCreationModeE
+__ZN3JSC7JSArray15setSubclassDataEPv
+__ZN3JSC18RegExpMatchesArrayD1Ev
+__ZNK3JSC7JSArray12subclassDataEv
+__ZN3WTF10StringImpl16findIgnoringCaseEPKcj
+__ZN3WTF14numberToStringEdPt
+__ZN3WTF4dtoaILb1ELb0ELb0ELb1EEEvPcdiRbRiRj
+__ZNK3WTF13DecimalNumber15toStringDecimalEPtj
+__ZN3WTF10StringImpl8toDoubleEPbS1_
+__ZN3WTF6VectorIjLm16EE6resizeEm
+__ZN3WTFL7multaddERNS_6BigIntEii
+__ZN3WTFL4multERNS_6BigIntERKS0_
+__ZN3WTF6VectorIjLm16EEaSERKS1_
+__ZN3WTF6String6numberEd
+__ZN3JSC17BytecodeGenerator16emitPutScopedVarEmiPNS_10RegisterIDENS_7JSValueE
+__ZN3JSC3JIT22emit_op_put_global_varEPNS_11InstructionE
+__ZN3JSC3JIT11emit_op_subEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_subEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateE
+__ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
+__ZNK3JSC8JSString8toNumberEPNS_9ExecStateE
+__ZN3JSC10jsToNumberERKNS_7UStringE
+__ZN3JSCL19jsStrDecimalLiteralERPKtS1_
+__ZN3WTF22cancelCallOnMainThreadEPFvPvES0_
+__ZN3WTF22isMainThreadOrGCThreadEv
+__ZNK3JSC8JSString9toBooleanEPNS_9ExecStateE
+__ZN3WTF10StringImpl4findEPFbtEj
+__ZN3WTF10StringImpl4findEPKcj
+__ZN3WTF6String26fromUTF8WithLatin1FallbackEPKcm
+__ZN3WTF10fastStrDupEPKc
+__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPN3WTF10StringImplE
+_JSStringRetain
+___initializeScavenger_block_invoke_1
+__ZN3WTF23waitForThreadCompletionEj
+__ZN3WTF23waitForThreadCompletionEjPPv
+_JSObjectCopyPropertyNames
+__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC8JSObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC9Structure16getPropertyNamesERNS_12JSGlobalDataERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC9ExecState20objectPrototypeTableEPS0_
+_JSPropertyNameArrayGetCount
+_JSPropertyNameArrayRelease
+__Z22TCMalloc_SystemReleasePvm
+__Z21TCMalloc_SystemCommitPvm
+__ZN3WTF6VectorIPvLm0EE14expandCapacityEm
+__ZN3JSC3JIT15emit_op_jlesseqEPNS_11InstructionEb
+__ZN3JSC3JIT16emit_op_jnlesseqEPNS_11InstructionE
+__ZN3JSC3JIT19emitSlow_op_jlesseqEPNS_11InstructionERPNS_13SlowCaseEntryEb
+__ZN3JSC3JIT20emitSlow_op_jnlesseqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC19ReverseBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC3JIT14emit_op_jnlessEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_jnlessEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3WTF6String8truncateEj
+_cti_op_get_by_id_self_fail
+__ZN3JSC3JIT29privateCompileGetByIdSelfListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureERKNS_10IdentifierERKNS_12PropertySlotEm
+_cti_op_get_by_id_custom_stub
+__ZN3JSC10ASTBuilder12makeMultNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT11emit_op_mulEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_mulEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3WTF13StringBuilder15reserveCapacityEj
+__ZN3WTF17equalIgnoringCaseEPKtPKcj
+__ZN3WTF4dtoaEPcdRbRiRj
+__ZNK3WTF13DecimalNumber28bufferLengthForStringDecimalEv
+__ZN3JSC3JIT19patchPutByIdReplaceEPNS_9CodeBlockEPNS_17StructureStubInfoEPNS_9StructureEmNS_16ReturnAddressPtrEb
+__ZN3JSC10Identifier5equalEPKN3WTF10StringImplEPKc
+__ZN3JSC8JSParser19parseBreakStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser17parseFunctionInfoILNS0_20FunctionRequirementsE0ELb0ENS_13SyntaxCheckerEEEbRT1_RPKNS_10IdentifierERNS4_19FormalParameterListERNS4_12FunctionBodyERiSE_SE_
+__ZN3JSC8JSParser21parseConstDeclarationINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC18ConstStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13ConstDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13ConstDeclNode14emitCodeSingleERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator16constRegisterForERKNS_10IdentifierE
+__ZN3JSC21ThrowableBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+_cti_op_call_arityCheck
+_cti_op_in
+__ZN3JSC12JSActivation13visitChildrenERNS_9MarkStackE
+__ZNK3JSC12JSActivation14isDynamicScopeERb
+__ZN3JSC3JIT22emit_op_get_scoped_varEPNS_11InstructionE
+__ZN3JSC8JSParser19parseBreakStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC15ConditionalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9BreakNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11breakTargetERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator14emitJumpScopesEPNS_5LabelEi
+__ZN3JSCL20stringProtoFuncSplitEPNS_9ExecStateE
+__ZN3JSC11jsSubstringEPNS_12JSGlobalDataERKNS_7UStringEjj
+__ZN3JSC7JSArray3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC7JSArray11putSlowCaseEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC10ASTBuilder11makeSubNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC10MathObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL16mathProtoFuncAbsEPNS_9ExecStateE
+_cti_op_lesseq
+__ZN3JSC7UString6numberEd
+__ZN3JSC9CodeBlock14visitAggregateERNS_9MarkStackE
+__ZN3JSC13EvalCodeCache14visitAggregateERNS_9MarkStackE
+__ZN3JSC17StructureStubInfo14visitAggregateERNS_9MarkStackE
+_cti_op_resolve_base
+__ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC16PropertyListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitNewObjectEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator17emitDirectPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC3JIT18emit_op_new_objectEPNS_11InstructionE
+_cti_op_new_object
+_cti_op_put_by_id_direct
+__ZN3JSC14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL21arrayProtoFuncForEachEPNS_9ExecStateE
+__ZN3JSC11Interpreter20prepareForRepeatCallEPNS_18FunctionExecutableEPNS_9ExecStateEPNS_10JSFunctionEiPNS_14ScopeChainNodeE
+__ZNK3JSC19BracketAccessorNode10isLocationEv
+__ZNK3JSC19BracketAccessorNode21isBracketAccessorNodeEv
+__ZN3JSC17AssignBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitPutByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC3JIT18emit_op_put_by_valEPNS_11InstructionE
+__ZN3JSC3JIT22emitSlow_op_put_by_valEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC11Interpreter7executeERNS_16CallFrameClosureE
+__ZN3JSC3JIT16patchGetByIdSelfEPNS_9CodeBlockEPNS_17StructureStubInfoEPNS_9StructureEmNS_16ReturnAddressPtrE
+_cti_op_put_by_val
+__ZN3JSC11Interpreter13endRepeatCallERNS_16CallFrameClosureE
+__ZN3JSC3JIT22emit_op_put_scoped_varEPNS_11InstructionE
+_cti_op_is_string
+_cti_op_is_number
+__ZN3JSC20globalFuncParseFloatEPNS_9ExecStateE
+__ZN3WTF6VectorIcLm32EE14expandCapacityEm
+_cti_op_to_primitive
+__ZN3JSCL22objectProtoFuncValueOfEPNS_9ExecStateE
+__ZN3JSCL22arrayProtoFuncToStringEPNS_9ExecStateE
+_cti_op_jless
+__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateE
+__ZN3JSC18globalFuncParseIntEPNS_9ExecStateE
+__ZN3JSCL8parseIntERKNS_7UStringEi
+__ZN3JSC15TypeOfValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC3JIT26privateCompileGetByIdProtoEPNS_17StructureStubInfoEPNS_9StructureES4_RKNS_10IdentifierERKNS_12PropertySlotEmNS_16ReturnAddressPtrEPNS_9ExecStateE
+_cti_op_sub
+__ZN3WTF6String6appendEc
+__ZN3JSCL18arrayProtoFuncPushEPNS_9ExecStateE
+__ZN3JSCL18arrayProtoFuncSortEPNS_9ExecStateE
+__ZN3JSC7JSArray4sortEPNS_9ExecStateE
+__ZN3JSC7JSArray17compactForSortingEv
+__ZN3JSC4Heap18pushTempSortVectorEPN3WTF6VectorISt4pairINS_7JSValueENS_7UStringEELm0EEE
+__ZN3WTF6VectorIPNS0_ISt4pairIN3JSC7JSValueENS2_7UStringEELm0EEELm0EE15reserveCapacityEm
+__ZN3JSCL27compareByStringPairForQSortEPKvS1_
+__ZN3WTF16codePointCompareEPKNS_10StringImplES2_
+__ZN3JSC4Heap17popTempSortVectorEPN3WTF6VectorISt4pairINS_7JSValueENS_7UStringEELm0EEE
+__ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateE
+__ZN3WTF6VectorItLm64EE17tryExpandCapacityEm
+__ZN3JSC15JSStringBuilder5buildEPNS_9ExecStateE
+__ZN3JSC17BytecodeGenerator15emitNewFunctionEPNS_10RegisterIDEPNS_16FunctionBodyNodeE
+__ZN3JSC17BytecodeGenerator23emitNewFunctionInternalEPNS_10RegisterIDEjb
+__ZN3JSC3JIT16emit_op_new_funcEPNS_11InstructionE
+_cti_op_new_func
+__ZN3JSC3JIT17emit_op_nstricteqEPNS_11InstructionE
+__ZN3JSC3JIT21emitSlow_op_nstricteqEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_nstricteq
+__ZN3JSC14LogicalNotNode30emitBytecodeInConditionContextERNS_17BytecodeGeneratorEPNS_5LabelES4_b
+__ZN3JSC3JIT18emit_op_jmp_scopesEPNS_11InstructionE
+_cti_op_negate
+__ZN3JSCL16mathProtoFuncMaxEPNS_9ExecStateE
+__ZN3WTF15ThreadConditionD1Ev
+__ZN3JSCL23stringProtoFuncToStringEPNS_9ExecStateE
+__ZN3JSC24ApplyFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC14ExpressionNode13isSimpleArrayEv
+__ZN3JSC17BytecodeGenerator26emitJumpIfNotFunctionApplyEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC17BytecodeGenerator29uncheckedRegisterForArgumentsEv
+__ZN3JSC17BytecodeGenerator15emitLoadVarargsEPNS_10RegisterIDES2_S2_
+__ZN3JSC17BytecodeGenerator15emitCallVarargsEPNS_10RegisterIDES2_S2_S2_jjj
+__ZN3JSC3JIT20emit_op_load_varargsEPNS_11InstructionE
+__ZN3JSC3JIT20emit_op_call_varargsEPNS_11InstructionE
+__ZN3JSC3JIT20compileOpCallVarargsEPNS_11InstructionE
+__ZN3JSC3JIT24emit_op_create_argumentsEPNS_11InstructionE
+__ZN3JSC3JIT24emitSlow_op_load_varargsEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT24emitSlow_op_call_varargsEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT28compileOpCallVarargsSlowCaseEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_call_jitCompile
+__ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
+__ZN3JSC16BooleanPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL24booleanProtoFuncToStringEPNS_9ExecStateE
+__ZN3JSC17BytecodeGenerator18pushFinallyContextEPNS_5LabelEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator17popFinallyContextEv
+__ZN3JSC17BytecodeGenerator19highestUsedRegisterEv
+__ZN3JSC17BytecodeGenerator18emitJumpSubroutineEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC17BytecodeGenerator20emitSubroutineReturnEPNS_10RegisterIDE
+__ZN3JSC3JIT11emit_op_jsrEPNS_11InstructionE
+__ZN3WTF6VectorIN3JSC3JIT7JSRInfoELm0EE14expandCapacityEm
+__ZN3JSC3JIT12emit_op_sretEPNS_11InstructionE
+__ZN3JSC10throwErrorEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC12hasErrorInfoEPNS_9ExecStateEPNS_8JSObjectE
+__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEj
+__ZN3JSC12addErrorInfoEPNS_9ExecStateEPNS_8JSObjectEiRKNS_10SourceCodeE
+__ZN3JSC12addErrorInfoEPNS_12JSGlobalDataEPNS_8JSObjectEiRKNS_10SourceCodeE
+__ZN3JSC8JSObject17putWithAttributesEPNS_12JSGlobalDataERKNS_10IdentifierENS_7JSValueEj
+_cti_op_push_new_scope
+__ZN3JSC19JSStaticScopeObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12JSActivation3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+_cti_op_pop_scope
+__ZN3JSC19JSStaticScopeObjectD1Ev
+__ZN3JSC14InstanceOfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator20emitCheckHasInstanceEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitInstanceOfEPNS_10RegisterIDES2_S2_S2_
+__ZN3JSC3JIT26emit_op_check_has_instanceEPNS_11InstructionE
+__ZN3JSC3JIT18emit_op_instanceofEPNS_11InstructionE
+__ZN3JSC3JIT30emitSlow_op_check_has_instanceEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT22emitSlow_op_instanceofEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC14throwTypeErrorEPNS_9ExecStateE
+__ZN3JSC4Yarr12digitsCreateEv
+__ZN3WTF16VectorBufferBaseIcE14allocateBufferEm
+__ZN3JSC4Yarr13YarrGenerator24matchCharacterClassRangeENS_12X86Registers10RegisterIDERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListES8_PKNS0_14CharacterRangeEjPjPKtj
+__ZN3JSC23MacroAssemblerX86Common4jumpEv
+__ZN3JSC23MacroAssemblerX86Common8branch32ENS0_19RelationalConditionENS_12X86Registers10RegisterIDES3_
+__ZN3JSC4Yarr13YarrGenerator17BacktrackingState6linkToENS_22AbstractMacroAssemblerINS_12X86AssemblerEE5LabelEPNS_14MacroAssemblerE
+__ZN3JSC4Yarr22YarrPatternConstructor23setupDisjunctionOffsetsEPNS0_18PatternDisjunctionEjj
+__ZN3JSC4Yarr13YarrGenerator17BacktrackingState24takeBacktracksToJumpListERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListEPNS_14MacroAssemblerE
+__ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE
+_cti_timeout_check
+__ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
+__ZN3JSC22createNotAnObjectErrorEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC11makeUStringIPKcNS_7UStringES2_EES3_T_T0_T1_
+__ZN3WTF13tryMakeStringIPKcN3JSC7UStringES2_EENS_10PassRefPtrINS_10StringImplEEET_T0_T1_
+__ZN3JSC15createTypeErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC10throwErrorEPNS_9ExecStateEPNS_8JSObjectE
+__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC9CodeBlock32expressionRangeForBytecodeOffsetEjRiS1_S1_
+__ZN3JSC11makeUStringINS_7UStringEPKcS1_S3_EES1_T_T0_T1_T2_
+__ZN3WTF13tryMakeStringIN3JSC7UStringEPKcS2_S4_EENS_10PassRefPtrINS_10StringImplEEET_T0_T1_T2_
+__ZN3JSC13JSNotAnObjectD1Ev
+__ZN3JSCL18mathProtoFuncRoundEPNS_9ExecStateE
+__ZN3JSCL18mathProtoFuncFloorEPNS_9ExecStateE
+__ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE
+__ZN3JSC26createNotAConstructorErrorEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE
+__ZNK3JSC8JSObject9classNameEv
+__ZNK3JSC14ExpressionNode11isCommaNodeEv
+__ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9CommaNodeD1Ev
+__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEm
+__ZN3JSC10ASTBuilder11makeModNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT11emit_op_modEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_modEPNS_11InstructionERPNS_13SlowCaseEntryE
+__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
+__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm32EEELm32EE14expandCapacityEmPKS4_
+__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm32EEELm32EE15reserveCapacityEm
+__ZN3JSC16throwSyntaxErrorEPNS_9ExecStateE
+_cti_op_load_varargs
+__ZN3WTF13tryFastCallocEmm
+__ZN3JSC17BytecodeGenerator10emitPreDecEPNS_10RegisterIDE
+__ZN3JSC3JIT15emit_op_pre_decEPNS_11InstructionE
+__ZN3JSC3JIT19emitSlow_op_pre_decEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_pre_dec
+__ZN3WTF10StringImpl16findIgnoringCaseEPS0_j
+__ZN3JSC5Lexer19getUnicodeCharacterEv
+__ZN3JSCL23numberProtoFuncToStringEPNS_9ExecStateE
+__ZN3JSC12JSGlobalData15getHostFunctionEPFPvPNS_9ExecStateEEPFNS_21MacroAssemblerCodePtrEPS0_PNS_14ExecutablePoolEE
+__ZN3JSC9JITThunks16hostFunctionStubEPNS_12JSGlobalDataEPFPvPNS_9ExecStateEEPFNS_21MacroAssemblerCodePtrES2_PNS_14ExecutablePoolEE
+__ZN3JSC18sqrtThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
+__ZN3JSC19SpecializedThunkJIT8finalizeENS_21MacroAssemblerCodePtrE
+__ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEiRKNS_10IdentifierEPNS_16NativeExecutableE
+__ZN3JSC10JSFunctionC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEiRKNS_10IdentifierEPNS_16NativeExecutableE
+__ZN3JSC3JIT11emit_op_notEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_notEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC17powThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
+__ZN3JSC12X86Assembler7cmpl_imEiiNS_12X86Registers10RegisterIDE
+__ZN3JSC23MacroAssemblerX86Common26branchConvertDoubleToInt32ENS_12X86Registers13XMMRegisterIDENS1_10RegisterIDERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListES2_
+__ZN3JSC19SpecializedThunkJIT11returnInt32ENS_12X86Registers10RegisterIDE
+__ZN3JSC19SpecializedThunkJIT12returnDoubleENS_12X86Registers13XMMRegisterIDE
+__ZN3JSC19SpecializedThunkJITD1Ev
+__ZN3JSC10ASTBuilder14makeDeleteNodeEPNS_14ExpressionNodeEiii
+__ZN3JSC13DeleteDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitDeleteByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC3JIT17emit_op_del_by_idEPNS_11InstructionE
+_cti_op_del_by_id
+__ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC17ObjectConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC9Structure27despecifyFunctionTransitionERNS_12JSGlobalDataEPS0_RKNS_10IdentifierE
+__ZN3JSC13PropertyTableC2ERNS_12JSGlobalDataEPNS_6JSCellERKS0_
+__ZNK3WTF6String6toUIntEPb
+__ZN3WTF10StringImpl6toUIntEPb
+__ZN3WTF16charactersToUIntEPKtmPb
+__ZN3JSC8JSParser20parseSwitchStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser18parseSwitchClausesINS_13SyntaxCheckerEEENT_10ClauseListERS3_
+__ZN3JSC15ObjectPrototype18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC8JSParser20parseSwitchStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC8JSParser18parseSwitchClausesINS_10ASTBuilderEEENT_10ClauseListERS3_
+__ZN3JSC10SwitchNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13CaseBlockNode20emitBytecodeForBlockERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_
+__ZN3JSC13CaseBlockNode18tryOptimizedSwitchERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERiS7_
+__ZN3JSCL17processClauseListEPNS_14ClauseListNodeERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERNS_10SwitchKindERbRiSB_
+__ZN3JSC3JIT14emit_op_bitandEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_bitandEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC12RegExpObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC15RegExpPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL19regExpProtoFuncTestEPNS_9ExecStateE
+__ZN3JSC12RegExpObject4testEPNS_9ExecStateE
+__ZN3JSC12RegExpObject5matchEPNS_9ExecStateE
+__ZN3JSC3JIT20emit_op_resolve_skipEPNS_11InstructionE
+_cti_op_resolve_skip
+__ZN3WTFeqERKNS_12AtomicStringERKNS_6VectorItLm0EEE
+__ZN3WTF11OSAllocator18releaseDecommittedEPvm
+__ZN3WTF12AtomicString16fromUTF8InternalEPKcS2_
+__ZN3WTF7Unicode36calculateStringHashAndLengthFromUTF8EPKcS2_RjS3_
+__ZN3JSC17BytecodeGenerator11beginSwitchEPNS_10RegisterIDENS_10SwitchInfo10SwitchTypeE
+__ZN3WTF6VectorIN3JSC10SwitchInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator9endSwitchEjPN3WTF6RefPtrINS_5LabelEEEPPNS_14ExpressionNodeEPS3_ii
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14expandCapacityEm
+__ZN3JSC15StringJumpTableC1ERKS0_
+__ZN3JSC3JIT21emit_op_switch_stringEPNS_11InstructionE
+__ZN3WTF6VectorIN3JSC12SwitchRecordELm0EE14expandCapacityEm
+_cti_op_switch_string
+__ZN3JSC10ASTBuilder13makeBitOrNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT13emit_op_bitorEPNS_11InstructionE
+__ZN3JSC3JIT17emitSlow_op_bitorEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZNK3WTF6String5splitERKS0_RNS_6VectorIS0_Lm0EEE
+__ZN3JSC8JSParser19parseWhileStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser19parseWhileStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC9WhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF10StringImpl7replaceEtPS0_
+__ZN3JSC3JIT31privateCompilePutByIdTransitionEPNS_17StructureStubInfoEPNS_9StructureES4_mPNS_14StructureChainENS_16ReturnAddressPtrEb
+_cti_op_put_by_id_fail
+__ZN3JSC17BytecodeGenerator11emitPostIncEPNS_10RegisterIDES2_
+__ZN3JSC3JIT16emit_op_post_incEPNS_11InstructionE
+__ZN3JSC3JIT20emitSlow_op_post_incEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSCL23createPrototypePropertyERNS_12JSGlobalDataEPNS_14JSGlobalObjectEPNS_10JSFunctionE
+__ZNK3JSC8NullNode6isNullEv
+__ZN3JSC3JIT17emit_op_jneq_nullEPNS_11InstructionE
+_cti_op_convert_this
+_cti_vm_lazyLinkConstruct
+__ZN3JSC18FunctionExecutable27compileForConstructInternalEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC3JIT18emit_op_get_calleeEPNS_11InstructionE
+__ZN3JSC3JIT19emit_op_create_thisEPNS_11InstructionE
+_cti_op_create_this
+__ZN3JSC16ArrayConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL29constructWithArrayConstructorEPNS_9ExecStateE
+__ZN3JSCL27constructArrayWithSizeQuirkEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC3JIT16emit_op_jeq_nullEPNS_11InstructionE
+__ZN3JSC3JIT16emit_op_neq_nullEPNS_11InstructionE
+__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14expandCapacityEm
+__ZNK3JSC5Label4bindEii
+__ZN3WTF6VectorIiLm0EEC2ERKS1_
+__ZN3JSC3JIT18emit_op_switch_immEPNS_11InstructionE
+__ZN3WTF6VectorIN3JSC17CodeLocationLabelELm0EE14expandCapacityEm
+_cti_op_switch_imm
+__ZN3JSCL26stringProtoFuncToLowerCaseEPNS_9ExecStateE
+__ZN3JSC8JSString17substringFromRopeEPNS_9ExecStateEjj
+__ZN3WTF6String6removeEji
+__ZN3WTF6String6insertERKS0_j
+__ZN3WTF6String6insertEPKtjj
+__ZN3JSCL26stringProtoFuncToUpperCaseEPNS_9ExecStateE
+__ZN3JSCL26stringProtoFuncLastIndexOfEPNS_9ExecStateE
+__ZNK3JSC7JSValue20toIntegerPreserveNaNEPNS_9ExecStateE
+__ZN3WTFeqERKNS_7CStringES2_
+__ZN3WTF10StringImpl4fillEt
+__ZN3WTF22charactersToUIntStrictEPKtmPbi
+__ZNK3WTF6String5upperEv
+__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
+__ZN3JSC23createNotAFunctionErrorEPNS_9ExecStateENS_7JSValueE
+_cti_op_jmp_scopes
+__ZNK3WTF6String6latin1Ev
+__ZN3JSC3JIT30privateCompileGetByIdProtoListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureES6_RKNS_10IdentifierERKNS_12PropertySlotEmPNS_9ExecStateE
+__ZN3JSC3JIT15emit_op_eq_nullEPNS_11InstructionE
+__ZN3WTF6VectorISt4pairIiiELm8EE14expandCapacityEm
+__ZN3WTF7Unicode18equalUTF16WithUTF8EPKtS2_PKcS4_
+__ZN3WTF11emptyStringEv
+__ZN3WTF6String6numberEj
+__ZN3JSC14PostfixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureEjNS_17ArrayCreationModeE
+__ZN3JSC10Identifier4fromEPNS_9ExecStateEj
+__ZN3JSC3JIT22compileGetDirectOffsetENS_12X86Registers10RegisterIDES2_PNS_9StructureEm
+__ZN3WTF6VectorIN3JSC14ExecutablePool10AllocationELm2EE15reserveCapacityEm
+__ZN3JSC4Yarr12spacesCreateEv
+__ZN3WTF10StringImpl4costEv
+__ZN3JSC17BytecodeGenerator22emitGetArgumentsLengthEPNS_10RegisterIDES2_
+__ZN3JSC3JIT28emit_op_get_arguments_lengthEPNS_11InstructionE
+__ZN3JSC3JIT26emit_op_tear_off_argumentsEPNS_11InstructionE
+__ZN3JSC3JIT32emitSlow_op_get_arguments_lengthEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC27ctiPatchCallByReturnAddressEPNS_9CodeBlockENS_16ReturnAddressPtrENS_21MacroAssemblerCodePtrE
+__ZN3WTF6VectorIN3JSC4Yarr11PatternTermELm0EE14expandCapacityEmPKS3_
+__ZN3JSC4Yarr13YarrGenerator29generateAssertionWordBoundaryEm
+__ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_12X86Registers10RegisterIDES3_ii
+__ZN3JSCL21stringProtoFuncSearchEPNS_9ExecStateE
+__ZN3JSC17StringConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC26fromCharCodeThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
+__ZN3JSCL12charToStringERNS_19SpecializedThunkJITEPNS_12JSGlobalDataENS_12X86Registers10RegisterIDES5_S5_
+__ZN3JSCL18stringFromCharCodeEPNS_9ExecStateE
+__ZNK3JSC8JSObject14isGlobalObjectEv
+__ZNK3WTF6String16removeCharactersEPFbtE
+__ZN3WTF10StringImpl16removeCharactersEPFbtE
+_JSContextGetGlobalContext
+_JSWeakObjectMapCreate
+__ZN3JSC14JSGlobalObject17weakMapsFinalizerEv
+_JSWeakObjectMapGet
+_JSWeakObjectMapSet
+__ZN3WTF9HashTableIPvSt4pairIS1_PN3JSC7JSValueEENS_18PairFirstExtractorIS6_EENS_7PtrHashIS1_EENS_14PairHashTraitsINS_10HashTraitsIS1_EENSC_IS5_EEEESD_E6rehashEi
+__ZN3JSC4Yarr6ParserINS0_13SyntaxCheckerEE11parseEscapeILb1ENS3_28CharacterClassParserDelegateEEEbRT0_
+__ZN3JSC8JSParser22parseContinueStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser21parseDoWhileStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC9ForInNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator20emitGetPropertyNamesEPNS_10RegisterIDES2_S2_S2_PNS_5LabelE
+__ZN3WTF6VectorIN3JSC12ForInContextELm0EE14expandCapacityEm
+__ZN3JSC11DoWhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator20emitNextPropertyNameEPNS_10RegisterIDES2_S2_S2_S2_PNS_5LabelE
 __ZN3JSC17BytecodeGenerator20emitNextPropertyNameEPNS_10RegisterIDES2_S2_S2_S2_PNS_5LabelE
-__ZN3JSC3JIT18emit_op_new_objectEPNS_11InstructionE
 __ZN3JSC3JIT18emit_op_get_pnamesEPNS_11InstructionE
 __ZN3JSC3JIT18emit_op_get_pnamesEPNS_11InstructionE
-__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14expandCapacityEmPKS2_
-__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14expandCapacityEm
-__ZN3JSC3JIT11emit_op_jmpEPNS_11InstructionE
-__ZN3JSC3JIT22emit_op_resolve_globalEPNS_11InstructionEb
 __ZN3JSC3JIT20emit_op_get_by_pnameEPNS_11InstructionE
 __ZN3JSC3JIT20emit_op_get_by_pnameEPNS_11InstructionE
-__ZN3JSC12X86Assembler23X86InstructionFormatter11oneByteOp64ENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDES4_ii
-__ZN3JSC3JIT18emit_op_get_by_valEPNS_11InstructionE
-__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common19RelationalConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS5_13TrustedImmPtrE
-__ZN3JSC3JIT18emit_op_put_by_valEPNS_11InstructionE
-__ZN3JSC3JIT16emit_op_stricteqEPNS_11InstructionE
-__ZN3JSC3JIT17compileOpStrictEqEPNS_11InstructionENS0_21CompileOpStrictEqTypeE
-__ZN3JSC12X86Assembler6orl_irEiNS_12X86Registers10RegisterIDE
-__ZN3JSC3JIT16emitTimeoutCheckEv
-__ZN3JSC3JIT13emit_op_jtrueEPNS_11InstructionE
-__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common19RelationalConditionENS_12X86Registers10RegisterIDES4_
 __ZN3JSC3JIT18emit_op_next_pnameEPNS_11InstructionE
 __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
 __ZN3JSC3JIT24emitSlow_op_get_by_pnameEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC11JITStubCall11addArgumentEjNS_12X86Registers10RegisterIDE
-__ZN3JSC3JIT22emitSlow_op_get_by_valEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC9JITThunks7ctiStubEPNS_12JSGlobalDataEPFNS_21MacroAssemblerCodePtrES2_PNS_14ExecutablePoolEE
-__ZN3WTF9HashTableIPFN3JSC21MacroAssemblerCodePtrEPNS1_12JSGlobalDataEPNS1_14ExecutablePoolEESt4pairIS8_S2_ENS_18PairFirstExtractorISA_EENS_7PtrHashIS8_EENS_14PairHashTraitsINS_10HashTraitsIS8_EENSG_IS2_EEEESH_E6expandEv
-__ZN3JSC3JIT27stringGetByValStubGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
-__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
 __ZN3JSC9Structure22toDictionaryTransitionERNS_12JSGlobalDataEPS0_NS0_14DictionaryKindE
 _cti_op_get_pnames
 __ZN3JSC22JSPropertyNameIterator6createEPNS_9ExecStateEPNS_8JSObjectE
 __ZN3WTF6VectorIN3JSC10IdentifierELm20EE14expandCapacityEm
 _cti_has_property
-_cti_op_resolve_global
-_cti_op_get_by_val
-_cti_op_put_by_val
-__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC8JSParser20parseSwitchStatementINS_10ASTBuilderEEENT_9StatementERS3_
-__ZN3JSC8JSParser18parseSwitchClausesINS_10ASTBuilderEEENT_10ClauseListERS3_
-__ZN3JSC10SwitchNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC13CaseBlockNode20emitBytecodeForBlockERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_
-__ZN3JSC13CaseBlockNode18tryOptimizedSwitchERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERiS7_
-__ZN3JSCL17processClauseListEPNS_14ClauseListNodeERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERNS_10SwitchKindERbRiSB_
-__ZNK3JSC14ExpressionNode8isNumberEv
-__ZNK3JSC10StringNode8isStringEv
-__ZN3JSC17BytecodeGenerator11beginSwitchEPNS_10RegisterIDENS_10SwitchInfo10SwitchTypeE
-__ZN3WTF6VectorIN3JSC10SwitchInfoELm0EE14expandCapacityEm
-__ZN3JSC17BytecodeGenerator9endSwitchEjPN3WTF6RefPtrINS_5LabelEEEPPNS_14ExpressionNodeEPS3_ii
-__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14expandCapacityEm
-__ZNK3JSC13StatementNode12isReturnNodeEv
-__ZN3JSC15StringJumpTableC1ERKS0_
-__ZN3JSC3JIT21emit_op_switch_stringEPNS_11InstructionE
-__ZN3WTF6VectorIN3JSC12SwitchRecordELm0EE14expandCapacityEm
-_cti_op_switch_string
-__ZN3JSC9JITThunks15tryCacheGetByIDEPNS_9ExecStateEPNS_9CodeBlockENS_16ReturnAddressPtrENS_7JSValueERKNS_10IdentifierERKNS_12PropertySlotEPNS_17StructureStubInfoE
-_cti_op_get_by_id_self_fail
-__ZN3JSC3JIT29privateCompileGetByIdSelfListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureERKNS_10IdentifierERKNS_12PropertySlotEm
-_cti_op_get_by_id_custom_stub
-__ZN3JSC8JSParser16parseIfStatementINS_10ASTBuilderEEENT_9StatementERS3_
-__ZN3JSC5Lexer19getUnicodeCharacterEv
-__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm0EE14expandCapacityEm
-__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14expandCapacityEmPKS3_
-__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE15reserveCapacityEm
 __ZN3JSC9Structure26flattenDictionaryStructureERNS_12JSGlobalDataEPNS_8JSObjectE
 __ZN3JSC9Structure26flattenDictionaryStructureERNS_12JSGlobalDataEPNS_8JSObjectE
-__ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE
-__ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE
-__ZN3JSC11BooleanNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEb
-__ZN3JSC10NumberNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEd
-__ZN3WTF9HashTableIdSt4pairIdN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsIdEENSA_IS3_EEEESB_E6expandEv
-__ZN3JSC11NewExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator13emitConstructEPNS_10RegisterIDES2_RNS_13CallArgumentsEjjj
-__ZN3JSC10IfElseNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC12BinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZNK3JSC10NumberNode6isPureERNS_17BytecodeGeneratorE
-__ZN3JSC17BytecodeGenerator12emitBinaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_NS_12OperandTypesE
-__ZN3JSC3JIT14emit_op_jfalseEPNS_11InstructionE
-__ZN3JSC3JIT17emit_op_constructEPNS_11InstructionE
-__ZN3JSC3JIT14emit_op_jnlessEPNS_11InstructionE
-__ZN3JSC3JIT18emitSlow_op_jfalseEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT21emitSlow_op_constructEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT18emitSlow_op_jnlessEPNS_11InstructionERPNS_13SlowCaseEntryE
-__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
 _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
 __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
 __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
 _JSValueProtect
-_JSValueMakeUndefined
-_cti_op_jless
-__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
+__ZN3WTF10StringImpl19characterStartingAtEj
 __ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSCL27objectProtoFuncDefineGetterEPNS_9ExecStateE
 __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_
 __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_
 __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
 __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
-__ZN3JSC12BinaryOpNode10emitStrcatERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_PNS_21ReadModifyResolveNodeE
-__ZNK3JSC14ExpressionNode8isStringEv
-__ZN3JSC17BytecodeGenerator15emitToPrimitiveEPNS_10RegisterIDES2_
-__ZN3JSC17BytecodeGenerator10emitStrcatEPNS_10RegisterIDES2_i
-__ZN3JSC3JIT11emit_op_addEPNS_11InstructionE
-__ZN3JSC3JIT20emit_op_to_primitiveEPNS_11InstructionE
-__ZN3JSC3JIT14emit_op_strcatEPNS_11InstructionE
-__ZN3JSC3JIT24emitSlow_op_to_primitiveEPNS_11InstructionERPNS_13SlowCaseEntryE
-_JSValueMakeString
-_cti_op_jtrue
-__ZNK3JSC8JSString9toBooleanEPNS_9ExecStateE
-_cti_op_strcat
-__ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE
-__ZNK3JSC8JSString19resolveRopeSlowCaseEPNS_9ExecStateEPt
-__ZN3JSC8RopeImpl20destructNonRecursiveEv
-__ZN3JSC8RopeImpl23derefFibersNonRecursiveERN3WTF6VectorIPS0_Lm32EEE
-_cti_op_construct_NotJSConstruct
 __ZN3JSC17ObjectConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL30constructWithObjectConstructorEPNS_9ExecStateE
 __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
 __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
 __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
-__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateE
-_cti_op_add
-__ZN3JSC10ASTBuilder12makeMultNodeEPNS_14ExpressionNodeES2_b
-__ZN3JSC14ExpressionNode14stripUnaryPlusEv
-__ZN3JSC17BytecodeGenerator20emitInitLazyRegisterEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator29uncheckedRegisterForArgumentsEv
 __ZN3JSC17BytecodeGenerator20emitGetArgumentByValEPNS_10RegisterIDES2_S2_
 __ZN3JSC17BytecodeGenerator20emitGetArgumentByValEPNS_10RegisterIDES2_S2_
-__ZN3JSC17BytecodeGenerator22emitGetArgumentsLengthEPNS_10RegisterIDES2_
-__ZN3JSC3JIT21emit_op_init_lazy_regEPNS_11InstructionE
-__ZN3JSC3JIT11emit_op_mulEPNS_11InstructionE
 __ZN3JSC3JIT27emit_op_get_argument_by_valEPNS_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
 __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
 __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
 __ZN3JSCL20arrayProtoFuncSpliceEPNS_9ExecStateE
-__ZNK3JSC8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE
-__ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
-__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureEjNS_17ArrayCreationModeE
 __ZN3JSC7JSArray9setLengthEj
 __ZN3JSCL11getPropertyEPNS_9ExecStateEPNS_8JSObjectEj
 __ZN3JSC7JSArray9setLengthEj
 __ZN3JSCL11getPropertyEPNS_9ExecStateEPNS_8JSObjectEj
-__ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateE
-__ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
-__ZN3JSC15JSStringBuilder5buildEPNS_9ExecStateE
-__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_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_
 __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
+__ZN3WTF9HashTableIjSt4pairIjPN3JSC16FunctionBodyNodeEENS_18PairFirstExtractorIS5_EENS_7IntHashIjEENS_14PairHashTraitsINS_29UnsignedWithZeroKeyHashTraitsIjEENS_10HashTraitsIS4_EEEESC_E6rehashEi
+__ZN3JSC17BytecodeGenerator19emitLazyNewFunctionEPNS_10RegisterIDEPNS_16FunctionBodyNodeE
 _JSObjectMakeArray
 _JSObjectMakeArray
-_JSValueMakeBoolean
 __ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
 _JSValueUnprotect
 __ZN3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6expandEv
 __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_
 __ZN3JSC8JSParser22parseContinueStatementINS_10ASTBuilderEEENT_9StatementERS3_
-__ZN3JSC8JSParser19parseBreakStatementINS_10ASTBuilderEEENT_9StatementERS3_
-__ZN3JSC17BytecodeGenerator15emitNewFunctionEPNS_10RegisterIDEPNS_16FunctionBodyNodeE
-__ZN3JSC15TypeOfValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSCeqERKNS_7UStringEPKc
 __ZN3WTF6VectorIPN3JSC14ExpressionNodeELm8EE14expandCapacityEm
 __ZN3WTF6VectorINS_6RefPtrIN3JSC5LabelEEELm8EE14expandCapacityEm
 __ZN3WTF6VectorIPN3JSC14ExpressionNodeELm8EE14expandCapacityEm
 __ZN3WTF6VectorINS_6RefPtrIN3JSC5LabelEEELm8EE14expandCapacityEm
-__ZN3JSC19ReverseBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC12ContinueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator14continueTargetERKNS_10IdentifierE
 __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
 __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
 _cti_op_is_function
 __ZN3JSC16jsIsFunctionTypeENS_7JSValueE
-__ZN3JSC3JIT33privateCompilePatchGetArrayLengthENS_16ReturnAddressPtrE
-__ZN3JSC14StructureChainC1ERNS_12JSGlobalDataEPNS_9StructureES4_
-__ZN3JSC14StructureChainC2ERNS_12JSGlobalDataEPNS_9StructureES4_
-__ZN3JSC3JIT31privateCompilePutByIdTransitionEPNS_17StructureStubInfoEPNS_9StructureES4_mPNS_14StructureChainENS_16ReturnAddressPtrEb
-__ZN3JSC3JIT13testPrototypeENS_7JSValueERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListE
-__ZN3JSC3JIT26privateCompileGetByIdChainEPNS_17StructureStubInfoEPNS_9StructureEPNS_14StructureChainEmRKNS_10IdentifierERKNS_12PropertySlotEmNS_16ReturnAddressPtrEPNS_9ExecStateE
-__ZN3JSC17BytecodeGenerator10emitPreDecEPNS_10RegisterIDE
-__ZN3JSC3JIT15emit_op_pre_decEPNS_11InstructionE
-__ZN3JSC23MacroAssemblerX86Common4moveENS_12X86Registers10RegisterIDES2_
-__ZN3JSC3JIT19emitSlow_op_pre_decEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_get_by_id_proto_list
-__ZN3JSC3JIT30privateCompileGetByIdChainListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureEPNS_14StructureChainEmRKNS_10IdentifierERKNS_12PropertySlotEmPNS_9ExecStateE
-__ZN3WTF13StringBuilder15reserveCapacityEj
-__ZN3WTF4dtoaEPcdRbRiRj
-__ZNK3WTF13DecimalNumber28bufferLengthForStringDecimalEv
-__ZN3JSC18globalFuncParseIntEPNS_9ExecStateE
-__ZN3JSC7toInt32Ed
-__ZN3JSCL8parseIntERKNS_7UStringEi
-_cti_op_nstricteq
 __ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __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
 _cti_op_not
-__ZN3WTF13tryFastCallocEmm
-__ZN3WTF9ByteArray6createEm
-__ZN3JSC3JIT22emit_op_get_scoped_varEPNS_11InstructionE
-__ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateE
-__ZNK3JSC7JSValue14toThisJSStringEPNS_9ExecStateE
-__ZN3JSC9ExecState8argumentEi
-__ZN3JSC6JSCell11getCallDataERNS_8CallDataE
-__ZN3WTF6RefPtrINS_10StringImplEEaSERKS2_
 __ZNK3JSC7UString20substringSharingImplEjj
 __ZN3JSC4Heap8allocateEm
 __ZNK3JSC7UString20substringSharingImplEjj
 __ZN3JSC4Heap8allocateEm
-__ZN3JSC24ApplyFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZNK3JSC14ExpressionNode13isSimpleArrayEv
-__ZN3JSC17BytecodeGenerator26emitJumpIfNotFunctionApplyEPNS_10RegisterIDEPNS_5LabelE
-__ZNK3JSC12JSActivation14isDynamicScopeERb
-__ZN3JSC17BytecodeGenerator15emitLoadVarargsEPNS_10RegisterIDES2_S2_
-__ZN3JSC17BytecodeGenerator15emitCallVarargsEPNS_10RegisterIDES2_S2_S2_jjj
-__ZN3JSC3JIT20emit_op_load_varargsEPNS_11InstructionE
-__ZN3JSC3JIT20emit_op_call_varargsEPNS_11InstructionE
-__ZN3JSC3JIT20compileOpCallVarargsEPNS_11InstructionE
-__ZN3JSC3JIT24emitSlow_op_load_varargsEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT24emitSlow_op_call_varargsEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT28compileOpCallVarargsSlowCaseEPNS_11InstructionERPNS_13SlowCaseEntryE
 _cti_op_create_arguments_no_params
 __ZN3JSCL20arrayProtoFuncConcatEPNS_9ExecStateE
 _cti_op_create_arguments_no_params
 __ZN3JSCL20arrayProtoFuncConcatEPNS_9ExecStateE
-_cti_op_load_varargs
 __ZN3JSC7JSArray15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
 __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
 __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
 __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
 _JSObjectDeletePrivateProperty
-__ZN3WTF6VectorIjLm16EE6resizeEm
-__ZN3WTFL7multaddERNS_6BigIntEii
-__ZN3WTFL4multERNS_6BigIntERKS0_
-__ZN3WTF6VectorIjLm16EEaSERKS1_
-__ZN3JSC4Yarr22YarrPatternConstructor23setupDisjunctionOffsetsEPNS0_18PatternDisjunctionEjj
-__ZN3JSC23MacroAssemblerX86Common4jumpEv
-__ZN3WTF6VectorIN3JSC4Yarr11PatternTermELm0EE14expandCapacityEmPKS3_
 __ZN3JSC4Yarr18PatternDisjunction17addNewAlternativeEv
 __ZN3JSC4Yarr22YarrPatternConstructor15copyDisjunctionEPNS0_18PatternDisjunctionEb
 __ZN3WTF6VectorIPN3JSC4Yarr18PatternDisjunctionELm4EE14expandCapacityEm
 __ZN3WTF6VectorIN3JSC4Yarr13YarrGenerator17BacktrackingState19ReturnAddressRecordELm4EE14expandCapacityEm
 __ZN3JSCL19regExpProtoFuncExecEPNS_9ExecStateE
 __ZN3JSC12RegExpObject4execEPNS_9ExecStateE
 __ZN3JSC4Yarr18PatternDisjunction17addNewAlternativeEv
 __ZN3JSC4Yarr22YarrPatternConstructor15copyDisjunctionEPNS0_18PatternDisjunctionEb
 __ZN3WTF6VectorIPN3JSC4Yarr18PatternDisjunctionELm4EE14expandCapacityEm
 __ZN3WTF6VectorIN3JSC4Yarr13YarrGenerator17BacktrackingState19ReturnAddressRecordELm4EE14expandCapacityEm
 __ZN3JSCL19regExpProtoFuncExecEPNS_9ExecStateE
 __ZN3JSC12RegExpObject4execEPNS_9ExecStateE
-__ZNK3JSC17RegExpConstructor14arrayOfMatchesEPNS_9ExecStateE
-__ZN3JSC18RegExpMatchesArrayC2EPNS_9ExecStateEPNS_24RegExpConstructorPrivateE
-__ZN3JSC7JSArrayC2ERNS_12JSGlobalDataEPNS_9StructureEjNS_17ArrayCreationModeE
-__ZN3JSC7JSArray15setSubclassDataEPv
 __ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZNK3JSC7JSArray12subclassDataEv
 __ZN3JSC18RegExpMatchesArray17fillArrayInstanceEPNS_9ExecStateE
 __ZN3JSC18RegExpMatchesArray17fillArrayInstanceEPNS_9ExecStateE
-__ZN3JSCL20stringProtoFuncMatchEPNS_9ExecStateE
-__ZN3JSC4Yarr22YarrPatternConstructor25atomBuiltInCharacterClassENS0_23BuiltInCharacterClassIDEb
-__ZN3JSC4Yarr12spacesCreateEv
 __ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateE
 __ZN3JSCL6decodeEPNS_9ExecStateEPKcb
 __ZN3WTF6VectorItLm64EE9tryAppendItEEbPKT_m
 __ZN3WTF7Unicode18UTF8SequenceLengthEc
 __ZN3WTF7Unicode18decodeUTF8SequenceEPKc
 __ZN3WTF6VectorItLm64EE18tryReserveCapacityEm
 __ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateE
 __ZN3JSCL6decodeEPNS_9ExecStateEPKcb
 __ZN3WTF6VectorItLm64EE9tryAppendItEEbPKT_m
 __ZN3WTF7Unicode18UTF8SequenceLengthEc
 __ZN3WTF7Unicode18decodeUTF8SequenceEPKc
 __ZN3WTF6VectorItLm64EE18tryReserveCapacityEm
-__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateE
 __ZN3JSC16globalFuncEscapeEPNS_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
 __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
 __ZN3JSC7JSArray19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC10Identifier4fromEPNS_9ExecStateEj
-__ZN3JSC7UString6numberEj
 __ZN3JSC17PropertyNameArray3addEPN3WTF10StringImplE
 __ZN3JSC9ExecState19arrayPrototypeTableEPS0_
 __ZN3JSC17PropertyNameArray3addEPN3WTF10StringImplE
 __ZN3JSC9ExecState19arrayPrototypeTableEPS0_
-__ZN3JSC3JIT22emit_op_put_scoped_varEPNS_11InstructionE
-__ZN3JSC12JSGlobalData15getHostFunctionEPFPvPNS_9ExecStateEEPFNS_21MacroAssemblerCodePtrEPS0_PNS_14ExecutablePoolEE
-__ZN3JSC9JITThunks16hostFunctionStubEPNS_12JSGlobalDataEPFPvPNS_9ExecStateEEPFNS_21MacroAssemblerCodePtrES2_PNS_14ExecutablePoolEE
 __ZN3JSC20charAtThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
 __ZN3JSCL14stringCharLoadERNS_19SpecializedThunkJITE
 __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
 __ZN3JSCL21stringProtoFuncCharAtEPNS_9ExecStateE
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm16EE14expandCapacityEm
+__ZN3WTF6VectorINS_6RefPtrIN3JSC10RegisterIDEEELm16EE14expandCapacityEm
 __ZN3WTF14FastMallocZone9forceLockEP14_malloc_zone_t
 __ZN3WTF14FastMallocZone11forceUnlockEP14_malloc_zone_t
 __ZN3WTF14FastMallocZone9forceLockEP14_malloc_zone_t
 __ZN3WTF14FastMallocZone11forceUnlockEP14_malloc_zone_t
+__ZN3JSC3JIT30emit_op_resolve_global_dynamicEPNS_11InstructionE
+__ZN3JSC3JIT34emitSlow_op_resolve_global_dynamicEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3WTF6VectorIN3JSC11StringRangeELm16EE14expandCapacityEmPKS2_
+__ZN3WTF6VectorIN3JSC11StringRangeELm16EE15reserveCapacityEm
+__ZN3WTF6VectorIN3JSC7UStringELm16EE14expandCapacityEmPKS2_
+__ZN3WTF6VectorIN3JSC7UStringELm16EE15reserveCapacityEm
+__ZN3JSC10ASTBuilder17makeLeftShiftNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT14emit_op_lshiftEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_lshiftEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_lshift
+_cti_op_bitor
 __ZN3WTF6VectorIPN3JSC9StructureELm8EE14expandCapacityEm
 __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
 _cti_op_get_by_id_proto_list_full
 __ZN3WTF6VectorIN3JSC4Yarr13YarrGenerator6YarrOpELm128EE14expandCapacityEmPKS4_
 __ZN3WTF6VectorIN3JSC4Yarr13YarrGenerator6YarrOpELm128EE15reserveCapacityEm
-__ZN3JSCL26stringProtoFuncLastIndexOfEPNS_9ExecStateE
-__ZNK3JSC7JSValue20toIntegerPreserveNaNEPNS_9ExecStateE
 __ZN3JSC17RegExpConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL30constructWithRegExpConstructorEPNS_9ExecStateE
 __ZN3JSC15constructRegExpEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListE
 __ZN3JSC17RegExpConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL30constructWithRegExpConstructorEPNS_9ExecStateE
 __ZN3JSC15constructRegExpEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListE
-__ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
-__ZN3JSC16BooleanPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC3JIT22compileGetDirectOffsetENS_12X86Registers10RegisterIDES2_PNS_9StructureEm
-__ZN3JSC3JIT15emit_op_resolveEPNS_11InstructionE
+__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 _JSWeakObjectMapRemove
 __ZN3WTF7HashMapIPvPN3JSC7JSValueENS_7PtrHashIS1_EENS_10HashTraitsIS1_EENS7_IS4_EEE4takeERKS1_
 _JSObjectSetPrivate
 _JSWeakObjectMapRemove
 __ZN3WTF7HashMapIPvPN3JSC7JSValueENS_7PtrHashIS1_EENS_10HashTraitsIS1_EENS7_IS4_EEE4takeERKS1_
 _JSObjectSetPrivate
-_cti_op_put_by_id_fail
+_JSValueIsEqual
+__ZN3JSC7JSValue13equalSlowCaseEPNS_9ExecStateES0_S0_
 __ZN3JSC4Heap16allocateSlowCaseEm
 __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_
 __ZN3JSC9WeakGCMapIPvNS_8JSObjectENS_33DefaultWeakGCMapFinalizerCallbackIS1_S2_EEN3WTF7PtrHashIS1_EENS5_10HashTraitsIS1_EEE8finalizeENS_6HandleINS_7UnknownEEES1_
-__ZN3JSC20JSCallbackObjectData8finalizeENS_6HandleINS_7UnknownEEEPv
-__ZN3WTF7HashMapISt4pairINS_6RefPtrINS_10StringImplEEEjEPN3JSC7JSValueENS6_24StructureTransitionTable4HashENS9_10HashTraitsENS_10HashTraitsIS8_EEE4takeERKS5_
-__ZN3JSC12RegExpObjectD1Ev
-__ZN3JSC12JSActivationD1Ev
-__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEED1Ev
-__ZN3JSC20JSCallbackObjectDataD0Ev
-_JSClassRelease
-__ZN3JSC15WeakHandleOwnerD2Ev
-__ZN3JSC14ExecutablePool13systemReleaseERNS0_10AllocationE
-__ZN3WTF11OSAllocator8decommitEPvm
-__ZN3JSC18RegExpMatchesArrayD1Ev
 __ZN3JSC22JSPropertyNameIteratorD1Ev
 __ZN3JSC22JSPropertyNameIteratorD1Ev
-__ZN3JSC14StructureChainD1Ev
-__ZN3JSC18JSCallbackFunctionD1Ev
-__ZN3JSC9WeakGCMapISt4pairIN3WTF6RefPtrINS2_10StringImplEEEjENS_9StructureENS_24StructureTransitionTable26WeakGCMapFinalizerCallbackENS8_4HashENS8_10HashTraitsEE8finalizeENS_6HandleINS_7UnknownEEEPv
-__ZN3JSC9WeakGCMapISt4pairIN3WTF6RefPtrINS2_10StringImplEEEjENS_9StructureENS_24StructureTransitionTable26WeakGCMapFinalizerCallbackENS8_4HashENS8_10HashTraitsEED0Ev
-__ZN3JSC9WeakGCMapISt4pairIN3WTF6RefPtrINS2_10StringImplEEEjENS_9StructureENS_24StructureTransitionTable26WeakGCMapFinalizerCallbackENS8_4HashENS8_10HashTraitsEED1Ev
-__ZN3JSC18FunctionExecutableD1Ev
+_JSStringGetMaximumUTF8CStringSize
+_JSStringGetUTF8CString
+__ZN3JSC10ASTBuilder14makeBitAndNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC10ASTBuilder18makeRightShiftNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT14emit_op_rshiftEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_rshiftEPNS_11InstructionERPNS_13SlowCaseEntryE
 _cti_op_put_by_id_transition_realloc
 _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
+__ZNK3WTF6String5splitEtbRNS_6VectorIS0_Lm0EEE
+__ZN3JSC24charCodeAtThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
+_cti_op_get_by_val_string
+__ZN3JSC17StringConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callStringConstructorEPNS_9ExecStateE
+__ZN3WTF6String6appendEt
 _cti_op_is_undefined
 _cti_op_is_undefined
-__ZN3JSC21ReadModifyResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17NumberConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC13jsAddSlowCaseEPNS_9ExecStateENS_7JSValueES2_
 __ZNK3JSC8JSString11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZN3JSC17NumberConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC13jsAddSlowCaseEPNS_9ExecStateENS_7JSValueES2_
 __ZNK3JSC8JSString11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
-__ZN3JSC3JIT19patchPutByIdReplaceEPNS_9CodeBlockEPNS_17StructureStubInfoEPNS_9StructureEmNS_16ReturnAddressPtrEb
 _cti_op_get_by_id_getter_stub
 _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
 __ZN3JSC9Structure24removePropertyTransitionERNS_12JSGlobalDataEPS0_RKNS_10IdentifierERm
 __ZN3JSC9Structure6removeERKNS_10IdentifierE
 __ZN3WTF6VectorIjLm0EE14expandCapacityEm
@@ -1432,41 +1687,25 @@ __ZN3JSC9Structure31removePropertyWithoutTransitionERNS_12JSGlobalDataERKNS_10Id
 __ZN3JSC12GetterSetter13visitChildrenERNS_9MarkStackE
 __ZN3JSC9Arguments13visitChildrenERNS_9MarkStackE
 __ZN3JSC14JSGlobalObject17WeakMapsFinalizer8finalizeENS_6HandleINS_7UnknownEEEPv
 __ZN3JSC12GetterSetter13visitChildrenERNS_9MarkStackE
 __ZN3JSC9Arguments13visitChildrenERNS_9MarkStackE
 __ZN3JSC14JSGlobalObject17WeakMapsFinalizer8finalizeENS_6HandleINS_7UnknownEEEPv
-__ZN3JSC12StringObjectD1Ev
 __ZN3JSC9ArgumentsD1Ev
 __ZN3JSC9ArgumentsD2Ev
 __ZN3JSC9ArgumentsD1Ev
 __ZN3JSC9ArgumentsD2Ev
-__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
+__ZNK3JSC19JSStaticScopeObject14isDynamicScopeERb
+__ZN3JSC19globalFuncEncodeURIEPNS_9ExecStateE
+__ZN3JSCL6encodeEPNS_9ExecStateEPKc
+__ZNK3JSC7UString4utf8Eb
+__ZN3JSCL17arrayProtoFuncMapEPNS_9ExecStateE
 _JSStringIsEqualToUTF8CString
 _JSStringIsEqualToUTF8CString
-__ZN3JSC12RegisterFile17GlobalObjectOwner8finalizeENS_6HandleINS_7UnknownEEEPv
 __ZN3JSC12GetterSetterD1Ev
 __ZN3JSC12GetterSetterD1Ev
-__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEm
-__ZNK3WTF6String18simplifyWhiteSpaceEv
-__ZN3WTF10StringImpl18simplifyWhiteSpaceEv
 __ZN3JSC22JSPropertyNameIterator13visitChildrenERNS_9MarkStackE
 __ZN3JSC22JSPropertyNameIterator13visitChildrenERNS_9MarkStackE
-__ZN3WTFL43initializeMainThreadToProcessMainThreadOnceEv
-__ZN3WTF47initializeMainThreadToProcessMainThreadPlatformEv
-__ZN3WTF6String6numberEd
-__ZN3WTF10StringImpl5upperEv
-__ZN3WTF6String6removeEji
-__ZN3WTF6String6insertERKS0_j
-__ZN3WTF6String6insertEPKtjj
-__ZN3WTF10StringImpl7replaceEPS0_S1_
-__ZNK3WTF6String5splitEtbRNS_6VectorIS0_Lm0EEE
+__ZNK3WTF6String19characterStartingAtEj
+__ZN3JSC10ASTBuilder14makeBitXOrNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT14emit_op_bitxorEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_bitxorEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_bitxor
+__ZN3JSC8JSParser21parseDoWhileStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSCL16mathProtoFuncMinEPNS_9ExecStateE
+__ZN3JSCL21arrayProtoFuncReverseEPNS_9ExecStateE
+__ZN3JSC17ProgramExecutable13visitChildrenERNS_9MarkStackE
 __ZN3JSC12JSGlobalData18createContextGroupENS_15ThreadStackTypeE
 __ZN3JSC12JSGlobalData22clearBuiltinStructuresEv
 __ZN3JSC4Heap7destroyEv
 __ZN3JSC12JSGlobalData18createContextGroupENS_15ThreadStackTypeE
 __ZN3JSC12JSGlobalData22clearBuiltinStructuresEv
 __ZN3JSC4Heap7destroyEv
@@ -1502,7 +1741,6 @@ _JSReportExtraMemoryCost
 _JSValueIsObject
 _JSValueMakeNull
 _JSObjectSetPrototype
 _JSValueIsObject
 _JSValueMakeNull
 _JSObjectSetPrototype
-_JSStringCreateWithCharacters
 _JSValueGetType
 __ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEE3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 _JSGarbageCollect
 _JSValueGetType
 __ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEE3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 _JSGarbageCollect
@@ -1513,36 +1751,19 @@ __ZN3WTF13StringBuilder6appendEc
 _JSEvaluateScript
 __ZNK3JSC14JSGlobalObject17supportsProfilingEv
 __ZNK3JSC14JSGlobalObject22supportsRichSourceInfoEv
 _JSEvaluateScript
 __ZNK3JSC14JSGlobalObject17supportsProfilingEv
 __ZNK3JSC14JSGlobalObject22supportsRichSourceInfoEv
-__ZN3JSC8JSParser19parseThrowStatementINS_10ASTBuilderEEENT_9StatementERS3_
-__ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC3JIT13emit_op_throwEPNS_11InstructionE
-_cti_op_throw
-__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateEPNS_14JSGlobalObjectE
 __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
 __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
-_JSValueIsEqual
-__ZN3JSC7JSValue13equalSlowCaseEPNS_9ExecStateES0_S0_
-__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC10throwErrorEPNS_9ExecStateENS_7JSValueE
-__ZNK3JSC8JSString8toNumberEPNS_9ExecStateE
-__ZN3JSC10jsToNumberERKNS_7UStringE
 _JSStringGetLength
 _JSStringGetCharactersPtr
 _JSStringGetLength
 _JSStringGetCharactersPtr
-_JSStringGetMaximumUTF8CStringSize
-_JSStringGetUTF8CString
 _JSValueIsStrictEqual
 _JSValueIsStrictEqual
-__ZN3JSC21UStringSourceProviderD0Ev
 _JSCheckScriptSyntax
 __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
 __ZN3JSC17ProgramExecutable11checkSyntaxEPNS_9ExecStateE
 __ZN3WTF6VectorIN3JSC9LabelInfoELm0EE14expandCapacityEmPKS2_
 __ZN3WTF6VectorIN3JSC9LabelInfoELm0EE15reserveCapacityEm
 __ZN3JSC17createSyntaxErrorEPNS_14JSGlobalObjectERKNS_7UStringE
 _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
 _JSObjectCallAsConstructor
 __ZN3JSC9constructEPNS_9ExecStateENS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
 __ZN3JSC11Interpreter16executeConstructEPNS_9ExecStateEPNS_8JSObjectENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
-__ZN3JSC15ObjectPrototype18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 _JSObjectSetPropertyAtIndex
 _JSObjectMakeFunction
 __ZN3JSC17constructFunctionEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
 _JSObjectSetPropertyAtIndex
 _JSObjectMakeFunction
 __ZN3JSC17constructFunctionEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
@@ -1580,51 +1801,13 @@ __ZN3JSCL18regExpObjectSourceEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3WTF13tryMakeStringIPKcN3JSC7UStringEPcEENS_10PassRefPtrINS_10StringImplEEET_T0_T1_
 __ZN13OpaqueJSClassD1Ev
 __ZN13OpaqueJSClassD2Ev
 __ZN3WTF13tryMakeStringIPKcN3JSC7UStringEPcEENS_10PassRefPtrINS_10StringImplEEET_T0_T1_
 __ZN13OpaqueJSClassD1Ev
 __ZN13OpaqueJSClassD2Ev
-__ZN3JSC20EvalFunctionCallNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator12emitCallEvalEPNS_10RegisterIDES2_RNS_13CallArgumentsEjjj
-__ZN3JSC3JIT25emit_op_resolve_with_baseEPNS_11InstructionE
-__ZN3JSC3JIT17emit_op_call_evalEPNS_11InstructionE
-__ZN3JSC3JIT21emitSlow_op_call_evalEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_resolve_with_base
-__ZN3JSC12JSActivation18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-_cti_op_call_eval
-__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
-__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
 __ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEE20staticFunctionGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC17ProgramExecutable13visitChildrenERNS_9MarkStackE
 __ZN3JSC19JSStaticScopeObject13visitChildrenERNS_9MarkStackE
 __ZN3JSC19JSStaticScopeObject13visitChildrenERNS_9MarkStackE
-__ZN3JSC14EvalExecutableD1Ev
-__ZN3JSC13EvalCodeBlockD0Ev
 __ZN3JSC12DateInstanceD1Ev
 __ZN3JSC21JSCallbackConstructorD1Ev
 __ZN3JSC12DateInstanceD1Ev
 __ZN3JSC21JSCallbackConstructorD1Ev
-__ZN3JSC17TypeOfResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC3JIT20emit_op_resolve_baseEPNS_11InstructionE
-__ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
-_cti_op_resolve
 __ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEE17staticValueGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEE17staticValueGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-_cti_op_resolve_base
-_cti_op_typeof
-__ZN3JSC20jsTypeStringForValueEPNS_9ExecStateENS_7JSValueE
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE11getCallDataERNS_8CallDataE
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE11getCallDataERNS_8CallDataE
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-_cti_op_push_new_scope
-__ZN3JSC19JSStaticScopeObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC12JSActivation3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-_cti_op_pop_scope
-__ZN3JSCL20isNonASCIIIdentStartEi
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE4callEPNS_9ExecStateE
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE16getConstructDataERNS_13ConstructDataE
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE9constructEPNS_9ExecStateE
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE4callEPNS_9ExecStateE
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE16getConstructDataERNS_13ConstructDataE
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE9constructEPNS_9ExecStateE
@@ -1632,7 +1815,6 @@ _cti_op_instanceof
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE11hasInstanceEPNS_9ExecStateENS_7JSValueES5_
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 _JSPropertyNameAccumulatorAddName
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE11hasInstanceEPNS_9ExecStateENS_7JSValueES5_
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 _JSPropertyNameAccumulatorAddName
-__ZN3JSC17ObjectConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSCL41objectConstructorGetOwnPropertyDescriptorEPNS_9ExecStateE
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC18PropertyDescriptor15setConfigurableEb
 __ZN3JSCL41objectConstructorGetOwnPropertyDescriptorEPNS_9ExecStateE
 __ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC18PropertyDescriptor15setConfigurableEb
@@ -1641,85 +1823,43 @@ __ZNK3JSC18PropertyDescriptor20isAccessorDescriptorEv
 __ZNK3JSC18PropertyDescriptor8writableEv
 __ZNK3JSC18PropertyDescriptor10enumerableEv
 __ZNK3JSC18PropertyDescriptor12configurableEv
 __ZNK3JSC18PropertyDescriptor8writableEv
 __ZNK3JSC18PropertyDescriptor10enumerableEv
 __ZNK3JSC18PropertyDescriptor12configurableEv
-__ZN3JSC20createReferenceErrorEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC12hasErrorInfoEPNS_9ExecStateEPNS_8JSObjectE
-__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEj
-__ZN3JSC12addErrorInfoEPNS_9ExecStateEPNS_8JSObjectEiRKNS_10SourceCodeE
 __ZN3JSC8JSObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
 __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
 __ZN3JSC3JIT19emit_op_to_jsnumberEPNS_11InstructionE
 __ZN3JSC3JIT23emitSlow_op_to_jsnumberEPNS_11InstructionERPNS_13SlowCaseEntryE
 _cti_op_to_jsnumber
 __ZNK3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE8toNumberEPNS_9ExecStateE
-__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE
 __ZNK3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE9classNameEv
 __ZNK3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE9classNameEv
-__ZN3JSC17StringConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL21callStringConstructorEPNS_9ExecStateE
 __ZNK3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE8toStringEPNS_9ExecStateE
 __ZNK3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE8toStringEPNS_9ExecStateE
-_cti_op_sub
 __ZN3JSC21JSCallbackConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL19constructJSCallbackEPNS_9ExecStateE
 __ZN3JSC21JSCallbackConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL19constructJSCallbackEPNS_9ExecStateE
-_cti_op_to_primitive
-__ZN3JSCL22objectProtoFuncValueOfEPNS_9ExecStateE
-_cti_op_jmp_scopes
 __ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
 __ZN3JSC16createRangeErrorEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
 __ZN3JSC16createRangeErrorEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC9Structure27despecifyFunctionTransitionERNS_12JSGlobalDataEPS0_RKNS_10IdentifierE
-__ZN3JSC13PropertyTableC2ERNS_12JSGlobalDataEPNS_6JSCellERKS0_
 _cti_op_mul
 _cti_op_mul
-__ZNK3JSC8JSObject9classNameEv
 __ZN3JSC12RegisterFile21releaseExcessCapacityEv
 __ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEED1Ev
 __ZN3JSC12RegisterFile21releaseExcessCapacityEv
 __ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEED1Ev
-__ZN3JSC19JSStaticScopeObjectD1Ev
-__ZN3JSC12NumberObjectD1Ev
 _JSObjectHasProperty
 _JSObjectGetPrototype
 __ZN3JSC8JSObject15unwrappedObjectEv
 __ZN3JSC11createErrorEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC12JSGlobalData6createENS_15ThreadStackTypeE
 __ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_10JSFunctionEj
 _JSObjectHasProperty
 _JSObjectGetPrototype
 __ZN3JSC8JSObject15unwrappedObjectEv
 __ZN3JSC11createErrorEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC12JSGlobalData6createENS_15ThreadStackTypeE
 __ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_10JSFunctionEj
-__ZNK3JSC7UString4utf8Eb
 __ZN3JSC12JSGlobalData13startSamplingEv
 __ZN3JSC11Interpreter13startSamplingEv
 __ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateE
 __ZN3JSC21gregorianDateTimeToMSEPNS_9ExecStateERKNS_17GregorianDateTimeEdb
 __ZN3JSCL30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateE
 __ZN3JSC12JSGlobalData13startSamplingEv
 __ZN3JSC11Interpreter13startSamplingEv
 __ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateE
 __ZN3JSC21gregorianDateTimeToMSEPNS_9ExecStateERKNS_17GregorianDateTimeEdb
 __ZN3JSCL30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateE
-_cti_op_negate
 __ZN3JSC12JSGlobalData12stopSamplingEv
 __ZN3JSC11Interpreter12stopSamplingEv
 __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
 __ZN3WTF9HashTableIjSt4pairIjN3JSC12WriteBarrierINS2_7UnknownEEEENS_18PairFirstExtractorIS6_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSC_IS5_EEEESD_E6rehashEi
-__ZN3JSC3JIT11emit_op_neqEPNS_11InstructionE
-__ZN3JSC3JIT15emitSlow_op_neqEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE
 __ZN3JSC11Interpreter14dumpSampleDataEPNS_9ExecStateE
 __ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE
 __ZN3JSC11Interpreter14dumpSampleDataEPNS_9ExecStateE
-__ZN3JSCL22arrayProtoFuncToStringEPNS_9ExecStateE
 __ZN3JSC16ArrayConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL20callArrayConstructorEPNS_9ExecStateE
 __ZN3JSC16ArrayConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL20callArrayConstructorEPNS_9ExecStateE
-__ZN3JSC10ASTBuilder11makeModNodeEPNS_14ExpressionNodeES2_b
-__ZN3JSC3JIT11emit_op_modEPNS_11InstructionE
-__ZN3JSC3JIT15emitSlow_op_modEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC17NumberConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL21callNumberConstructorEPNS_9ExecStateE
 __ZN3JSC17NumberConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL21callNumberConstructorEPNS_9ExecStateE
-__ZN3JSCL16mathProtoFuncAbsEPNS_9ExecStateE
 __ZN3JSCL28numberConstructorPosInfinityEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSCL28numberConstructorPosInfinityEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL18mathProtoFuncFloorEPNS_9ExecStateE
 _cti_op_mod
 _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
 __ZN3JSC3JIT13linkConstructEPNS_10JSFunctionEPNS_9CodeBlockES4_NS_21MacroAssemblerCodePtrEPNS_12CallLinkInfoEiPNS_12JSGlobalDataE
 __ZN3JSC14EvalExecutable13visitChildrenERNS_9MarkStackE
 __ZN3JSC17NumberConstructor16getConstructDataERNS_13ConstructDataE
@@ -1738,63 +1878,34 @@ __ZN3JSCL25numberConstructorNaNValueEPNS_9ExecStateENS_7JSValueERKNS_10Identifie
 __ZN3JSCL28numberConstructorNegInfinityEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSC18BooleanConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL22callBooleanConstructorEPNS_9ExecStateE
 __ZN3JSCL28numberConstructorNegInfinityEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSC18BooleanConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL22callBooleanConstructorEPNS_9ExecStateE
-__ZN3JSC8JSString17substringFromRopeEPNS_9ExecStateEjj
 __ZN3WTF6VectorIN3JSC8JSString12RopeIterator8WorkItemELm16EE14expandCapacityEmPKS4_
 __ZN3WTF6VectorIN3JSC8JSString12RopeIterator8WorkItemELm16EE15reserveCapacityEm
 __ZN3JSC10JSFunction14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3WTF6VectorIN3JSC8JSString12RopeIterator8WorkItemELm16EE14expandCapacityEmPKS4_
 __ZN3WTF6VectorIN3JSC8JSString12RopeIterator8WorkItemELm16EE15reserveCapacityEm
 __ZN3JSC10JSFunction14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSCL24booleanProtoFuncToStringEPNS_9ExecStateE
 __ZN3JSC18globalFuncUnescapeEPNS_9ExecStateE
 __ZN3JSC18globalFuncUnescapeEPNS_9ExecStateE
-__ZN3WTF6VectorItLm64EE17tryExpandCapacityEm
 __ZNK3WTF13DecimalNumber19toStringExponentialEPtj
 __ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
 __ZNK3WTF13DecimalNumber19toStringExponentialEPtj
 __ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
-__ZN3JSCL21arrayProtoFuncReverseEPNS_9ExecStateE
-__ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC9CommaNodeD1Ev
 __ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateEj
 __ZN3JSC19FunctionConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL32constructWithFunctionConstructorEPNS_9ExecStateE
 __ZN3JSC17constructFunctionEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListE
 __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
 __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_
 __ZN3JSCltERKNS_7UStringES2_
-__ZN3JSCL27compareByStringPairForQSortEPKvS1_
-__ZN3WTF16codePointCompareEPKNS_10StringImplES2_
 __ZN3JSC7JSArray4sortEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
 __ZN3JSC7JSArray4sortEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
-__ZN3JSC11Interpreter20prepareForRepeatCallEPNS_18FunctionExecutableEPNS_9ExecStateEPNS_10JSFunctionEiPNS_14ScopeChainNodeE
 __ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE6insertEi
 __ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE6insertEi
-__ZN3JSC11Interpreter13endRepeatCallERNS_16CallFrameClosureE
-__ZN3JSC11Interpreter7executeERNS_16CallFrameClosureE
 __ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE7balanceEi
 __ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE7balanceEi
-__ZNK3JSC14ExpressionNode11isCommaNodeEv
 __ZNK3JSC7SubNode10isSubtractEv
 __ZN3JSC17BytecodeGenerator17argumentNumberForERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator27setIsNumericCompareFunctionEb
 __ZN3JSC7JSArray11sortNumericEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
 __ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateE
 __ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
 __ZNK3JSC7SubNode10isSubtractEv
 __ZN3JSC17BytecodeGenerator17argumentNumberForERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator27setIsNumericCompareFunctionEb
 __ZN3JSC7JSArray11sortNumericEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
 __ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateE
 __ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
-__ZN3JSC24charCodeAtThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
 __ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZNK3JSC8NullNode6isNullEv
-__ZN3JSC3JIT15emit_op_eq_nullEPNS_11InstructionE
-_cti_op_is_number
 __ZNK3JSC7JSValue16synthesizeObjectEPNS_9ExecStateE
 __ZN3JSC36constructBooleanFromImmediateBooleanEPNS_9ExecStateEPNS_14JSGlobalObjectENS_7JSValueE
 __ZNK3JSC7JSValue16synthesizeObjectEPNS_9ExecStateE
 __ZN3JSC36constructBooleanFromImmediateBooleanEPNS_9ExecStateEPNS_14JSGlobalObjectENS_7JSValueE
-__ZN3JSC14throwTypeErrorEPNS_9ExecStateE
 __ZN3JSCL27dateProtoFuncGetUTCFullYearEPNS_9ExecStateE
 __ZNK3JSC12DateInstance29calculateGregorianDateTimeUTCEPNS_9ExecStateE
 __ZN3JSC23MacroAssemblerX86Common4moveENS_22AbstractMacroAssemblerINS_12X86AssemblerEE13TrustedImmPtrENS_12X86Registers10RegisterIDE
 __ZN3JSCL27dateProtoFuncGetUTCFullYearEPNS_9ExecStateE
 __ZNK3JSC12DateInstance29calculateGregorianDateTimeUTCEPNS_9ExecStateE
 __ZN3JSC23MacroAssemblerX86Common4moveENS_22AbstractMacroAssemblerINS_12X86AssemblerEE13TrustedImmPtrENS_12X86Registers10RegisterIDE
@@ -1827,12 +1938,13 @@ __ZN3JSCL7dateUTCEPNS_9ExecStateE
 __ZN3JSC15globalFuncIsNaNEPNS_9ExecStateE
 _cti_op_is_object
 __ZN3JSC14jsIsObjectTypeENS_7JSValueE
 __ZN3JSC15globalFuncIsNaNEPNS_9ExecStateE
 _cti_op_is_object
 __ZN3JSC14jsIsObjectTypeENS_7JSValueE
-_cti_op_less
-__ZN3JSCL19jsStrDecimalLiteralERPKtS1_
-__ZN3WTF6VectorIcLm32EE14expandCapacityEm
 __ZN3JSCL20dateProtoFuncGetYearEPNS_9ExecStateE
 _cti_op_pre_inc
 __ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateE
 __ZN3JSCL20dateProtoFuncGetYearEPNS_9ExecStateE
 _cti_op_pre_inc
 __ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateE
+__ZN3JSCL17arrayProtoFuncPopEPNS_9ExecStateE
+__ZN3JSC7JSArray3popEv
+__ZN3JSCL19arrayProtoFuncShiftEPNS_9ExecStateE
+__ZN3JSC7JSArray10shiftCountEPNS_9ExecStateEi
 __ZN3JSCL28dateProtoFuncSetMilliSecondsEPNS_9ExecStateE
 __ZN3JSCL23setNewValueFromTimeArgsEPNS_9ExecStateEib
 __ZN3JSCL31dateProtoFuncSetUTCMillisecondsEPNS_9ExecStateE
 __ZN3JSCL28dateProtoFuncSetMilliSecondsEPNS_9ExecStateE
 __ZN3JSCL23setNewValueFromTimeArgsEPNS_9ExecStateEib
 __ZN3JSCL31dateProtoFuncSetUTCMillisecondsEPNS_9ExecStateE
@@ -1856,7 +1968,6 @@ __ZN3JSC17BytecodeGenerator13emitPushScopeEPNS_10RegisterIDE
 __ZN3JSC3JIT18emit_op_push_scopeEPNS_11InstructionE
 _cti_op_push_scope
 __ZN3JSC17DeleteResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC3JIT18emit_op_push_scopeEPNS_11InstructionE
 _cti_op_push_scope
 __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
 __ZN3JSC3JIT26emit_op_ret_object_or_thisEPNS_11InstructionE
 __ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZN3WTF9HashTableIPNS_10StringImplES2_NS_17IdentityExtractorIS2_EENS_7PtrHashIS2_EENS_10HashTraitsIS2_EES8_E6expandEv
@@ -1868,71 +1979,32 @@ __ZN3JSC19FunctionConstructor11getCallDataERNS_8CallDataE
 __ZN3JSC15DateConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL25numberConstructorMaxValueEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSCL25numberConstructorMinValueEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __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
 _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
 __ZN3JSC10ASTBuilder18makeBitwiseNotNodeEPNS_14ExpressionNodeE
 __ZN3JSC3JIT14emit_op_bitnotEPNS_11InstructionE
 __ZN3JSC3JIT18emitSlow_op_bitnotEPNS_11InstructionERPNS_13SlowCaseEntryE
 _cti_op_jlesseq
 _cti_op_bitnot
-__ZN3JSC12StringObjectC1EPNS_9ExecStateEPNS_9StructureE
 __ZN3WTF6VectorIjLm16EE15reserveCapacityEm
 __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
 _cti_op_rshift
 __ZN3JSC10ASTBuilder19makeURightShiftNodeEPNS_14ExpressionNodeES2_b
 __ZN3JSC3JIT15emit_op_urshiftEPNS_11InstructionE
 __ZN3JSC3JIT19emitSlow_op_urshiftEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3WTF6VectorIPNS_14StringImplBaseELm32EE14expandCapacityEm
 _cti_op_urshift
 _cti_op_urshift
-__ZN3JSC3JIT16emit_op_neq_nullEPNS_11InstructionE
-__ZN3JSC10ASTBuilder14makeBitAndNodeEPNS_14ExpressionNodeES2_b
-__ZN3JSC3JIT14emit_op_bitandEPNS_11InstructionE
-__ZN3JSC3JIT18emitSlow_op_bitandEPNS_11InstructionERPNS_13SlowCaseEntryE
 _cti_op_bitand
 _cti_op_bitand
-__ZN3JSC10ASTBuilder13makeBitOrNodeEPNS_14ExpressionNodeES2_b
-__ZN3JSC3JIT13emit_op_bitorEPNS_11InstructionE
-__ZN3JSC3JIT17emitSlow_op_bitorEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_bitor
-__ZN3JSC10ASTBuilder14makeBitXOrNodeEPNS_14ExpressionNodeES2_b
-__ZN3JSC3JIT14emit_op_bitxorEPNS_11InstructionE
-__ZN3JSC3JIT18emitSlow_op_bitxorEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_bitxor
 _cti_op_div
 __ZN3JSCL23callFunctionConstructorEPNS_9ExecStateE
 __ZN3JSC10JSFunction12lengthGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSC10JSFunction15argumentsGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZNK3JSC11Interpreter17retrieveArgumentsEPNS_9ExecStateEPNS_10JSFunctionE
 __ZN3JSCL21callFunctionPrototypeEPNS_9ExecStateE
 _cti_op_div
 __ZN3JSCL23callFunctionConstructorEPNS_9ExecStateE
 __ZN3JSC10JSFunction12lengthGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSC10JSFunction15argumentsGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZNK3JSC11Interpreter17retrieveArgumentsEPNS_9ExecStateEPNS_10JSFunctionE
 __ZN3JSCL21callFunctionPrototypeEPNS_9ExecStateE
-__ZNK3JSC14ExpressionNode10isLocationEv
-__ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC23createNotAFunctionErrorEPNS_9ExecStateENS_7JSValueE
 __ZN3JSC10JSFunction19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZNK3JSC9CommaNode11isCommaNodeEv
 __ZN3JSC10JSFunction19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZNK3JSC9CommaNode11isCommaNodeEv
-__ZN3JSC20globalFuncParseFloatEPNS_9ExecStateE
-__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14expandCapacityEm
-__ZNK3JSC5Label4bindEii
-__ZN3WTF6VectorIiLm0EEC2ERKS1_
-__ZN3JSC3JIT18emit_op_switch_immEPNS_11InstructionE
-__ZN3WTF6VectorIN3JSC17CodeLocationLabelELm0EE14expandCapacityEm
-_cti_op_switch_imm
 __ZN3JSC18globalFuncIsFiniteEPNS_9ExecStateE
 __ZN3JSC18globalFuncIsFiniteEPNS_9ExecStateE
-__ZN3JSC28createUndefinedVariableErrorEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC11makeUStringIPKcNS_7UStringEEES3_T_T0_
-__ZN3WTF13tryMakeStringIPKcN3JSC7UStringEEENS_10PassRefPtrINS_10StringImplEEET_T0_
+__ZN3JSCL19stringProtoFuncTrimEPNS_9ExecStateE
+__ZN3JSCL10trimStringEPNS_9ExecStateENS_7JSValueEi
+__ZN3JSC15isStrWhiteSpaceEt
 __ZN3JSC15AssignErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator23emitThrowReferenceErrorERKNS_7UStringE
 __ZN3JSC3JIT29emit_op_throw_reference_errorEPNS_11InstructionE
 __ZN3JSC15AssignErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator23emitThrowReferenceErrorERKNS_7UStringE
 __ZN3JSC3JIT29emit_op_throw_reference_errorEPNS_11InstructionE
@@ -1947,11 +2019,8 @@ __ZN3JSCL17mathProtoFuncCeilEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncCosEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncExpEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncLogEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncCosEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncExpEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncLogEPNS_9ExecStateE
-__ZN3JSCL16mathProtoFuncMaxEPNS_9ExecStateE
-__ZN3JSCL16mathProtoFuncMinEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncPowEPNS_9ExecStateE
 __ZN3JSCL19mathProtoFuncRandomEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncPowEPNS_9ExecStateE
 __ZN3JSCL19mathProtoFuncRandomEPNS_9ExecStateE
-__ZN3JSCL18mathProtoFuncRoundEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncSinEPNS_9ExecStateE
 __ZN3JSCL17mathProtoFuncSqrtEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncTanEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncSinEPNS_9ExecStateE
 __ZN3JSCL17mathProtoFuncSqrtEPNS_9ExecStateE
 __ZN3JSCL16mathProtoFuncTanEPNS_9ExecStateE
@@ -1962,39 +2031,25 @@ __ZN3JSC9ExecState22objectConstructorTableEPS0_
 _cti_to_object
 __ZN3JSC9ExecState20numberPrototypeTableEPS0_
 __ZNK3JSC15DotAccessorNode17isDotAccessorNodeEv
 _cti_to_object
 __ZN3JSC9ExecState20numberPrototypeTableEPS0_
 __ZNK3JSC15DotAccessorNode17isDotAccessorNodeEv
-__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPN3WTF10StringImplE
 __ZNK3JSC14ExpressionNode17isDotAccessorNodeEv
 __ZN3JSC9ExecState22stringConstructorTableEPS0_
 __ZN3JSCL26stringFromCharCodeSlowCaseEPNS_9ExecStateE
 __ZN3JSCL25stringProtoFuncCharCodeAtEPNS_9ExecStateE
 __ZNK3JSC12JSActivation12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC14ExpressionNode17isDotAccessorNodeEv
 __ZN3JSC9ExecState22stringConstructorTableEPS0_
 __ZN3JSCL26stringFromCharCodeSlowCaseEPNS_9ExecStateE
 __ZN3JSCL25stringProtoFuncCharCodeAtEPNS_9ExecStateE
 __ZNK3JSC12JSActivation12toThisObjectEPNS_9ExecStateE
-__ZN3JSCL26stringProtoFuncToLowerCaseEPNS_9ExecStateE
-__ZN3JSCL26stringProtoFuncToUpperCaseEPNS_9ExecStateE
 __ZN3JSC12StringObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZN3JSC9ExecState11stringTableEPS0_
 __ZN3JSC12StringObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __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_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
 __ZN3JSC17RegExpConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC12RegExpObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSCL21regExpObjectLastIndexEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC4Yarr12digitsCreateEv
 __ZN3WTF6VectorIN3JSC4Yarr12ByteCompiler21ParenthesesStackEntryELm0EE14expandCapacityEm
 __ZN3JSC4Yarr12ByteCompiler16closeAlternativeEi
 __ZN3WTF6VectorIN3JSC4Yarr8ByteTermELm0EE14expandCapacityEmPKS3_
 __ZN3WTF6VectorIPN3JSC4Yarr15ByteDisjunctionELm0EE14expandCapacityEm
 __ZN3WTF6VectorIN3JSC4Yarr12ByteCompiler21ParenthesesStackEntryELm0EE14expandCapacityEm
 __ZN3JSC4Yarr12ByteCompiler16closeAlternativeEi
 __ZN3WTF6VectorIN3JSC4Yarr8ByteTermELm0EE14expandCapacityEmPKS3_
 __ZN3WTF6VectorIPN3JSC4Yarr15ByteDisjunctionELm0EE14expandCapacityEm
-__ZN3JSC3JIT16emit_op_jeq_nullEPNS_11InstructionE
 __ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC4Yarr11Interpreter20backtrackParenthesesERNS0_8ByteTermEPNS1_18DisjunctionContextE
 __ZN3JSC4Yarr11YarrPattern21newlineCharacterClassEv
 __ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC4Yarr11Interpreter20backtrackParenthesesERNS0_8ByteTermEPNS1_18DisjunctionContextE
 __ZN3JSC4Yarr11YarrPattern21newlineCharacterClassEv
@@ -2005,13 +2060,10 @@ __ZN3JSC4Yarr15nonspacesCreateEv
 __ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EE14expandCapacityEmPKS5_
 __ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EE14expandCapacityEm
 __ZN3JSC4Yarr15nondigitsCreateEv
 __ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EE14expandCapacityEmPKS5_
 __ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EE14expandCapacityEm
 __ZN3JSC4Yarr15nondigitsCreateEv
-__ZN3JSC4Yarr13YarrGenerator29generateAssertionWordBoundaryEm
 __ZN3JSCL24setRegExpObjectLastIndexEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
 __ZN3JSC9ExecState11regExpTableEPS0_
 __ZN3JSC9ExecState20regExpPrototypeTableEPS0_
 __ZN3JSCL24setRegExpObjectLastIndexEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
 __ZN3JSC9ExecState11regExpTableEPS0_
 __ZN3JSC9ExecState20regExpPrototypeTableEPS0_
-__ZN3JSC8JSParser21parseDoWhileStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
 __ZN3JSC9LabelNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC9LabelNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC14PostfixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3WTF6VectorIiLm0EE15reserveCapacityEm
 __ZN3JSC3JIT19emit_op_switch_charEPNS_11InstructionE
 _cti_op_switch_char
 __ZN3WTF6VectorIiLm0EE15reserveCapacityEm
 __ZN3JSC3JIT19emit_op_switch_charEPNS_11InstructionE
 _cti_op_switch_char
@@ -2020,14 +2072,11 @@ __ZNK3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EE
 __ZN3JSCL20stringProtoFuncSliceEPNS_9ExecStateE
 _cti_op_get_by_id_proto_fail
 __ZN3JSCL28arrayProtoFuncToLocaleStringEPNS_9ExecStateE
 __ZN3JSCL20stringProtoFuncSliceEPNS_9ExecStateE
 _cti_op_get_by_id_proto_fail
 __ZN3JSCL28arrayProtoFuncToLocaleStringEPNS_9ExecStateE
-__ZN3JSCL17arrayProtoFuncPopEPNS_9ExecStateE
-__ZN3JSC7JSArray3popEv
 __ZN3JSC16ErrorConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL29constructWithErrorConstructorEPNS_9ExecStateE
 __ZN3JSCL22compareNumbersForQSortEPKvS1_
 __ZN3JSCL25dateProtoFuncToDateStringEPNS_9ExecStateE
 __ZN3JSCL25dateProtoFuncToTimeStringEPNS_9ExecStateE
 __ZN3JSC16ErrorConstructor16getConstructDataERNS_13ConstructDataE
 __ZN3JSCL29constructWithErrorConstructorEPNS_9ExecStateE
 __ZN3JSCL22compareNumbersForQSortEPKvS1_
 __ZN3JSCL25dateProtoFuncToDateStringEPNS_9ExecStateE
 __ZN3JSCL25dateProtoFuncToTimeStringEPNS_9ExecStateE
-_cti_op_get_by_val_string
 __ZN3JSCL27dateProtoFuncToLocaleStringEPNS_9ExecStateE
 __ZN3JSCL16formatLocaleDateEPNS_9ExecStateEPNS_12DateInstanceEdNS_20LocaleDateTimeFormatE
 __ZN3JSCL31dateProtoFuncToLocaleDateStringEPNS_9ExecStateE
 __ZN3JSCL27dateProtoFuncToLocaleStringEPNS_9ExecStateE
 __ZN3JSCL16formatLocaleDateEPNS_9ExecStateEPNS_12DateInstanceEdNS_20LocaleDateTimeFormatE
 __ZN3JSCL31dateProtoFuncToLocaleDateStringEPNS_9ExecStateE
@@ -2036,8 +2085,6 @@ __ZN3JSCL20callErrorConstructorEPNS_9ExecStateE
 __ZN3JSC17RegExpConstructor11getCallDataERNS_8CallDataE
 __ZN3JSCL21callRegExpConstructorEPNS_9ExecStateE
 __ZNK3JSC8JSObject15isErrorInstanceEv
 __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
 __ZN3JSC12JSActivation14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator14emitPutByIndexEPNS_10RegisterIDEjS2_
 __ZN3JSC3JIT20emit_op_put_by_indexEPNS_11InstructionE
@@ -2048,7 +2095,6 @@ __ZN3JSC17DeleteBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10Register
 __ZN3JSC17BytecodeGenerator15emitDeleteByValEPNS_10RegisterIDES2_S2_
 _cti_op_del_by_val
 __ZN3JSC9Arguments14deletePropertyEPNS_9ExecStateEj
 __ZN3JSC17BytecodeGenerator15emitDeleteByValEPNS_10RegisterIDES2_S2_
 _cti_op_del_by_val
 __ZN3JSC9Arguments14deletePropertyEPNS_9ExecStateEj
-__ZN3JSC14LogicalNotNode30emitBytecodeInConditionContextERNS_17BytecodeGeneratorEPNS_5LabelES4_b
 _cti_op_tear_off_arguments
 __ZN3JSC9Arguments3putEPNS_9ExecStateEjNS_7JSValueE
 __ZN3JSCL29objectProtoFuncHasOwnPropertyEPNS_9ExecStateE
 _cti_op_tear_off_arguments
 __ZN3JSC9Arguments3putEPNS_9ExecStateEjNS_7JSValueE
 __ZN3JSCL29objectProtoFuncHasOwnPropertyEPNS_9ExecStateE
@@ -2076,21 +2122,14 @@ __ZNK3JSC17RegExpConstructor14getLeftContextEPNS_9ExecStateE
 __ZN3JSCL29regExpConstructorRightContextEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZNK3JSC17RegExpConstructor15getRightContextEPNS_9ExecStateE
 __ZN3WTF6VectorIiLm32EE15reserveCapacityEm
 __ZN3JSCL29regExpConstructorRightContextEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZNK3JSC17RegExpConstructor15getRightContextEPNS_9ExecStateE
 __ZN3WTF6VectorIiLm32EE15reserveCapacityEm
-__ZN3WTF6VectorIN3JSC11StringRangeELm16EE14expandCapacityEmPKS2_
-__ZN3WTF6VectorIN3JSC11StringRangeELm16EE15reserveCapacityEm
-__ZN3WTF6VectorIN3JSC7UStringELm16EE14expandCapacityEmPKS2_
-__ZN3WTF6VectorIN3JSC7UStringELm16EE15reserveCapacityEm
 __ZN3JSCL24regExpConstructorDollar1EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSCL24regExpConstructorDollar2EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3WTF6VectorIPNS0_IN3JSC5LabelELm32EEELm32EE14expandCapacityEmPKS4_
 __ZN3WTF6VectorIPNS0_IN3JSC5LabelELm32EEELm32EE15reserveCapacityEm
 __ZN3JSC8JSString16replaceCharacterEPNS_9ExecStateEtRKNS_7UStringE
 __ZN3JSCL24regExpConstructorDollar1EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSCL24regExpConstructorDollar2EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3WTF6VectorIPNS0_IN3JSC5LabelELm32EEELm32EE14expandCapacityEmPKS4_
 __ZN3WTF6VectorIPNS0_IN3JSC5LabelELm32EEELm32EE15reserveCapacityEm
 __ZN3JSC8JSString16replaceCharacterEPNS_9ExecStateEtRKNS_7UStringE
-__ZN3JSCL19arrayProtoFuncShiftEPNS_9ExecStateE
-__ZN3JSC7JSArray10shiftCountEPNS_9ExecStateEi
 __ZN3JSCL21arrayProtoFuncUnShiftEPNS_9ExecStateE
 __ZN3JSC7JSArray12unshiftCountEPNS_9ExecStateEi
 __ZN3JSC7JSArray26increaseVectorPrefixLengthEj
 __ZN3JSCL21arrayProtoFuncUnShiftEPNS_9ExecStateE
 __ZN3JSC7JSArray12unshiftCountEPNS_9ExecStateEi
 __ZN3JSC7JSArray26increaseVectorPrefixLengthEj
-__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm16EE14expandCapacityEm
 __ZN3JSCL21stringProtoFuncConcatEPNS_9ExecStateE
 __ZN3JSCL24regExpConstructorDollar3EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSCL24regExpConstructorDollar4EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSCL21stringProtoFuncConcatEPNS_9ExecStateE
 __ZN3JSCL24regExpConstructorDollar3EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSCL24regExpConstructorDollar4EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
@@ -2109,7 +2148,6 @@ __ZN3JSCL29setRegExpConstructorMultilineEPNS_9ExecStateEPNS_8JSObjectENS_7JSValu
 __ZN3JSCL22regExpProtoFuncCompileEPNS_9ExecStateE
 __ZN3JSC14globalFuncEvalEPNS_9ExecStateE
 __ZN3JSC11Interpreter7executeEPNS_14EvalExecutableEPNS_9ExecStateEPNS_8JSObjectEPNS_14ScopeChainNodeE
 __ZN3JSCL22regExpProtoFuncCompileEPNS_9ExecStateE
 __ZN3JSC14globalFuncEvalEPNS_9ExecStateE
 __ZN3JSC11Interpreter7executeEPNS_14EvalExecutableEPNS_9ExecStateEPNS_8JSObjectEPNS_14ScopeChainNodeE
-__ZNK3JSC19JSStaticScopeObject14isDynamicScopeERb
 __ZN3JSC9Arguments3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC17ConservativeRoots4growEv
 __ZN3JSCL27objectProtoFuncDefineSetterEPNS_9ExecStateE
 __ZN3JSC9Arguments3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC17ConservativeRoots4growEv
 __ZN3JSCL27objectProtoFuncDefineSetterEPNS_9ExecStateE
@@ -2134,8 +2172,6 @@ __ZN3JSCL21stringProtoFuncStrikeEPNS_9ExecStateE
 __ZN3JSCL18stringProtoFuncSubEPNS_9ExecStateE
 __ZN3JSCL18stringProtoFuncSupEPNS_9ExecStateE
 __ZN3JSC18PostfixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSCL18stringProtoFuncSubEPNS_9ExecStateE
 __ZN3JSCL18stringProtoFuncSupEPNS_9ExecStateE
 __ZN3JSC18PostfixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC19globalFuncEncodeURIEPNS_9ExecStateE
-__ZN3JSCL6encodeEPNS_9ExecStateEPKc
 __ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSCL35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateE
 __ZNK3JSC8JSObject20propertyIsEnumerableEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSCL35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateE
 __ZNK3JSC8JSObject20propertyIsEnumerableEPNS_9ExecStateERKNS_10IdentifierE
@@ -2148,11 +2184,7 @@ __ZN3WTF6VectorISt4pairIPN3JSC14ExpressionNodeENS2_10ASTBuilder12BinaryOpInfoEEL
 __ZN3WTF6VectorISt4pairIPN3JSC14ExpressionNodeENS2_10ASTBuilder12BinaryOpInfoEELm10EE15reserveCapacityEm
 __ZN3WTF6VectorISt4pairIiiELm10EE14expandCapacityEm
 __ZN3JSC29callHostFunctionAsConstructorEPNS_9ExecStateE
 __ZN3WTF6VectorISt4pairIPN3JSC14ExpressionNodeENS2_10ASTBuilder12BinaryOpInfoEELm10EE15reserveCapacityEm
 __ZN3WTF6VectorISt4pairIiiELm10EE14expandCapacityEm
 __ZN3JSC29callHostFunctionAsConstructorEPNS_9ExecStateE
-__ZN3JSC3JIT30emit_op_resolve_global_dynamicEPNS_11InstructionE
-__ZN3JSC3JIT34emitSlow_op_resolve_global_dynamicEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZNK3JSC9ArrayNode13isSimpleArrayEv
 __ZNK3JSC9ArrayNode13isSimpleArrayEv
-__ZN3JSCL17arrayProtoFuncMapEPNS_9ExecStateE
-__ZN3JSCL21arrayProtoFuncForEachEPNS_9ExecStateE
 __ZN3JSCL20arrayProtoFuncFilterEPNS_9ExecStateE
 __ZN3JSCL19arrayProtoFuncEveryEPNS_9ExecStateE
 __ZN3JSCL18arrayProtoFuncSomeEPNS_9ExecStateE
 __ZN3JSCL20arrayProtoFuncFilterEPNS_9ExecStateE
 __ZN3JSCL19arrayProtoFuncEveryEPNS_9ExecStateE
 __ZN3JSCL18arrayProtoFuncSomeEPNS_9ExecStateE
@@ -2160,56 +2192,305 @@ __ZN3JSCL21arrayProtoFuncIndexOfEPNS_9ExecStateE
 __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
 __ZN3JSCL25arrayProtoFuncLastIndexOfEPNS_9ExecStateE
 __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
 __ZN3JSCL25arrayProtoFuncLastIndexOfEPNS_9ExecStateE
-__ZNK3WTF6String7toFloatEPbS1_
-__ZN3WTF10StringImpl7toFloatEPbS1_
-__ZN3WTF17charactersToFloatEPKtmPbS2_
-__ZNK3JSC7UString5asciiEv
-__ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
-__ZN3WTF10StringImpl8toDoubleEPbS1_
-__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateE
-__ZN3WTF10StringImpl4findEPKcj
-__ZN3WTF6String26fromUTF8WithLatin1FallbackEPKcm
-__ZN3WTF10fastStrDupEPKc
-__ZN3WTF17equalIgnoringCaseEPKtPKcj
-__ZN3JSC10Identifier5equalEPKN3WTF10StringImplEPKc
-__ZN3JSC11JSByteArray15createStructureERNS_12JSGlobalDataENS_7JSValueEPKNS_9ClassInfoE
-__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE
-__ZN3JSC11JSByteArrayC2EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE
-__ZN3JSC11JSByteArrayD1Ev
-_cti_op_get_by_val_byte_array
-__ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC11JSByteArray3putEPNS_9ExecStateEjNS_7JSValueE
-_cti_op_put_by_val_byte_array
-__ZN3JSC16throwSyntaxErrorEPNS_9ExecStateE
-__ZN3WTF10StringImpl16findIgnoringCaseEPS0_j
-__ZNK3WTF6String6toUIntEPb
-__ZN3WTF10StringImpl6toUIntEPb
-__ZN3WTF16charactersToUIntEPKtmPb
-__ZN3WTFeqERKNS_12AtomicStringERKNS_6VectorItLm0EEE
-__ZN3WTF12AtomicString16fromUTF8InternalEPKcS2_
-__ZN3WTF7Unicode36calculateStringHashAndLengthFromUTF8EPKcS2_RjS3_
-__ZNK3WTF6String5splitERKS0_RNS_6VectorIS0_Lm0EEE
-__ZN3WTF10StringImpl7replaceEtPS0_
-__ZN3WTFeqERKNS_7CStringES2_
-__ZN3WTF10StringImpl6secureEtNS0_21LastCharacterBehaviorE
-__ZNK3WTF6String5upperEv
-__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
-__ZNK3WTF6String6latin1Ev
-__ZN3WTF6VectorIN3JSC14ExecutablePool10AllocationELm2EE15reserveCapacityEm
-__ZN3WTF6String6numberEj
-__ZNK3JSC8JSObject14isGlobalObjectEv
-__ZN3WTF10StringImpl19characterStartingAtEj
-__ZN3WTF6String6appendEt
-__ZNK3WTF6String19characterStartingAtEj
-__ZN3JSC11JSByteArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3WTF20equalIgnoringNullityEPNS_10StringImplES1_
 _cti_op_get_by_id_array_fail
 __ZN3JSC17PrefixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3WTF20equalIgnoringNullityEPNS_10StringImplES1_
 _cti_op_get_by_id_array_fail
 __ZN3JSC17PrefixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3WTF21CrossThreadRefCountedINS_16OwnFastMallocPtrIKtEEE5derefEv
 __ZN3JSC12JSGlobalData10ClientDataD2Ev
 __ZN3JSC8DebuggerD2Ev
 __ZN3WTF14ThreadSpecificINS_13WTFThreadDataEE7destroyEPv
 __ZN3WTF13WTFThreadDataD1Ev
 __ZN3WTF17AtomicStringTable7destroyEPS0_
 __ZN3JSC15IdentifierTableD1Ev
 __ZN3JSC12JSGlobalData10ClientDataD2Ev
 __ZN3JSC8DebuggerD2Ev
 __ZN3WTF14ThreadSpecificINS_13WTFThreadDataEE7destroyEPv
 __ZN3WTF13WTFThreadDataD1Ev
 __ZN3WTF17AtomicStringTable7destroyEPS0_
 __ZN3JSC15IdentifierTableD1Ev
+_cti_op_is_boolean
+__ZN3JSC18RegExpMatchesArray14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC15WeakHandleOwner8finalizeENS_6HandleINS_7UnknownEEEPv
+__ZN3WTF9dayInYearEdi
+__ZN3WTF18monthFromDayInYearEib
+__ZN3WTF23dayInMonthFromDayInYearEib
+__ZNK3JSC4Heap11objectCountEv
+__ZNK3JSC11MarkedSpace11objectCountEv
+__ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
+__ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
+__ZN3JSC9Structure22getterSetterTransitionERNS_12JSGlobalDataEPS0_
+__ZN3JSCL28objectProtoFuncIsPrototypeOfEPNS_9ExecStateE
+__ZN3JSCL21functionProtoFuncCallEPNS_9ExecStateE
+__ZNK3JSC7ArgList8getSliceEiRS0_
+__ZN3JSCL36objectConstructorGetOwnPropertyNamesEPNS_9ExecStateE
+__ZN3JSCL31objectConstructorGetPrototypeOfEPNS_9ExecStateE
+__ZN3JSC22NativeErrorConstructor11getCallDataERNS_8CallDataE
+__ZN3JSC10JSONObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3WTF10StringImpl23defaultWritingDirectionEPb
+__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC23throwStackOverflowErrorEPNS_9ExecStateE
+__ZN3JSCL23arrayConstructorIsArrayEPNS_9ExecStateE
+__ZN3JSCL21objectConstructorKeysEPNS_9ExecStateE
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
+__ZN3JSCL24dateProtoFuncToISOStringEPNS_9ExecStateE
+_cti_op_get_by_id_string_fail
+__ZN3JSC22StringRecursionChecker11emptyStringEv
+__ZN3JSC22StringRecursionChecker23throwStackOverflowErrorEv
+__ZN3JSC9ExecState9jsonTableEPS0_
+__ZN3JSC10JSFunction12callerGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_10JSFunctionE
+__ZN3WTF27releaseFastMallocFreeMemoryEv
+__ZN3JSC17BytecodeGenerator21emitComplexJumpScopesEPNS_5LabelEPNS_18ControlFlowContextES4_
+__ZN3JSCL22functionProtoFuncApplyEPNS_9ExecStateE
+__ZN3JSC7JSArray11fillArgListEPNS_9ExecStateERNS_20MarkedArgumentBufferE
+__ZN3JSC9CodeBlock16createActivationEPNS_9ExecStateE
+__ZN3JSCL22JSONProtoFuncStringifyEPNS_9ExecStateE
+_cti_op_put_by_id_direct_fail
+__ZN3JSCL18JSONProtoFuncParseEPNS_9ExecStateE
+__ZN3JSC6Walker4walkENS_7JSValueE
+__ZN3WTF6VectorIN3JSC5LocalINS1_7JSArrayEEELm16EE14expandCapacityEm
+__ZN3WTF6VectorIjLm16EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC11WalkerStateELm16EE14expandCapacityEm
+__ZN3JSC11HandleStack4growEv
+__ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateEjNS_7JSValueE
+__ZNK3JSC27PropertyNameForFunctionCall5valueEPNS_9ExecStateE
+__ZN3WTF13StringBuilder6resizeEj
+__ZN3JSC8JSParser17parseFunctionInfoILNS0_20FunctionRequirementsE1ELb0ENS_13SyntaxCheckerEEEbRT1_RPKNS_10IdentifierERNS4_19FormalParameterListERNS4_12FunctionBodyERiSE_SE_
+__ZN3JSCL19dateProtoFuncToJSONEPNS_9ExecStateE
+__ZN3JSC9ExecState9dateTableEPS0_
+__ZN3JSC10Identifier4fromEPNS_9ExecStateEd
+__ZN3WTF6VectorIN3JSC11Stringifier6HolderELm16EE15reserveCapacityEm
+__ZN3JSCL23objectConstructorCreateEPNS_9ExecStateE
+__ZN3JSCL16definePropertiesEPNS_9ExecStateEPNS_8JSObjectES3_
+__ZN3JSCL20toPropertyDescriptorEPNS_9ExecStateENS_7JSValueERNS_18PropertyDescriptorE
+__ZN3WTF6VectorIN3JSC18PropertyDescriptorELm0EE14expandCapacityEm
+__ZNK3JSC18PropertyDescriptor16isDataDescriptorEv
+__ZN3JSC8JSObject17defineOwnPropertyEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorEb
+__ZN3JSCL13putDescriptorEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERNS_18PropertyDescriptorEjRKS7_
+__ZNK3JSC18PropertyDescriptor19isGenericDescriptorEv
+__ZN3JSC18PropertyDescriptor9setGetterENS_7JSValueE
+__ZNK3JSC18PropertyDescriptor6getterEv
+__ZNK3JSC18PropertyDescriptor6setterEv
+__ZN3JSC18PropertyDescriptor11setWritableEb
+__ZN3JSC18PropertyDescriptor9setSetterENS_7JSValueE
+__ZN3JSCL33objectConstructorDefinePropertiesEPNS_9ExecStateE
+__ZNK3JSC18PropertyDescriptor7equalToEPNS_9ExecStateERKS0_
+__ZNK3JSC18PropertyDescriptor15attributesEqualERKS0_
+__ZNK3JSC18PropertyDescriptor22attributesWithOverrideERKS0_
+__ZN3JSCL31objectConstructorDefinePropertyEPNS_9ExecStateE
+__ZN3JSC7JSArray24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC9Arguments19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC9ExecState21booleanPrototypeTableEPS0_
+__ZN3JSC9ExecState20dateConstructorTableEPS0_
+__ZN3JSC9ExecState22regExpConstructorTableEPS0_
+__ZN3JSC9ExecState19errorPrototypeTableEPS0_
+__ZN3JSC12JSActivation18getArgumentsGetterEv
+__ZN3JSC12JSActivation15argumentsGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL20arrayProtoFuncReduceEPNS_9ExecStateE
+__ZN3JSCL25arrayProtoFuncReduceRightEPNS_9ExecStateE
+__ZN3JSC3JIT27emit_op_convert_this_strictEPNS_11InstructionE
+__ZN3JSC3JIT31emitSlow_op_convert_this_strictEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC9Arguments33createStrictModeCalleeIfNecessaryEPNS_9ExecStateE
+__ZN3JSC23createTypeErrorFunctionEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC18PropertyDescriptor21setAccessorDescriptorENS_7JSValueES1_j
+__ZN3JSC9Arguments24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC27StrictModeTypeErrorFunction11getCallDataERNS_8CallDataE
+__ZN3JSC27StrictModeTypeErrorFunction18callThrowTypeErrorEPNS_9ExecStateE
+__ZN3JSC14throwTypeErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC9Arguments33createStrictModeCallerIfNecessaryEPNS_9ExecStateE
+_cti_op_resolve_base_strict_put
+__ZN3JSC37createErrorForInvalidGlobalAssignmentEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC19JSStaticScopeObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC20StrictEvalActivationC1EPNS_9ExecStateE
+__ZN3JSC15PrefixErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC16PostfixErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC10JSFunction24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSCL35createDescriptorForThrowingPropertyEPNS_9ExecStateERNS_18PropertyDescriptorEPKc
+__ZN3JSC20StrictEvalActivationD1Ev
+__ZN3JSC27StrictModeTypeErrorFunctionD1Ev
+__ZN3JSC9Arguments15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
+_cti_op_loop_if_lesseq
+__ZN3JSC23MacroAssemblerX86Common12branchTest32ENS0_15ResultConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS4_12TrustedImm32E
+__ZN3JSC23MacroAssemblerX86Common8branch32ENS0_19RelationalConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS4_12TrustedImm32E
+__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_12X86Registers10RegisterIDEi
+__ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EEC2ERKS6_
+__ZN3JSCL31dateProtoFuncToLocaleTimeStringEPNS_9ExecStateE
+__ZN3JSCL20dateProtoFuncSetYearEPNS_9ExecStateE
+__ZN3JSCL26dateProtoFuncSetUTCSecondsEPNS_9ExecStateE
+__ZN3JSC21DebuggerStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15DeleteValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC28globalFuncEncodeURIComponentEPNS_9ExecStateE
+__ZN3JSC15createEvalErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3WTF6String6numberEx
+__ZN3JSC14ArrayPrototype24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC13DatePrototype24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC15StringPrototype24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC12StringObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC8JSString27getStringPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC15RegExpPrototype24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC12RegExpObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC17NumberConstructor24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC17RegExpConstructor24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC10MathObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC18RegExpMatchesArray24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSCL8callDateEPNS_9ExecStateE
+__ZN3JSCL26callNativeErrorConstructorEPNS_9ExecStateE
+__ZN3JSC17BytecodeGenerator35emitThrowExpressionTooDeepExceptionEv
+__ZN3JSC22createOutOfMemoryErrorEPNS_14JSGlobalObjectE
+__ZN3JSC11createErrorEPNS_14JSGlobalObjectERKNS_7UStringE
+__ZN3JSC13UnaryPlusNode14stripUnaryPlusEv
+__ZN3JSCL29objectProtoFuncToLocaleStringEPNS_9ExecStateE
+__ZN3WTF6VectorIN3JSC8JSParser14ScopeLabelInfoELm2EE14expandCapacityEm
+__ZN3JSCL34objectConstructorPreventExtensionsEPNS_9ExecStateE
+__ZN3JSC10JSFunction17preventExtensionsERNS_12JSGlobalDataE
+__ZN3JSC8JSObject17preventExtensionsERNS_12JSGlobalDataE
+__ZN3JSC9Structure27preventExtensionsTransitionERNS_12JSGlobalDataEPS0_
+__ZN3JSCL21objectConstructorSealEPNS_9ExecStateE
+__ZN3JSC8JSObject4sealERNS_12JSGlobalDataE
+__ZN3JSC9Structure8isSealedERNS_12JSGlobalDataE
+__ZN3JSC9Structure14sealTransitionERNS_12JSGlobalDataEPS0_
+__ZN3JSCL23objectConstructorFreezeEPNS_9ExecStateE
+__ZN3JSC8JSObject6freezeERNS_12JSGlobalDataE
+__ZN3JSC9Structure8isFrozenERNS_12JSGlobalDataE
+__ZN3JSC9Structure16freezeTransitionERNS_12JSGlobalDataEPS0_
+__ZN3JSCL25objectConstructorIsSealedEPNS_9ExecStateE
+__ZN3JSCL25objectConstructorIsFrozenEPNS_9ExecStateE
+__ZN3JSCL29objectConstructorIsExtensibleEPNS_9ExecStateE
+__ZN3JSC4Yarr25CharacterClassConstructor9addSortedERN3WTF6VectorItLm0EEEt
+__ZNK3JSC19JSStaticScopeObject12toThisObjectEPNS_9ExecStateE
+__ZN3JSCL23stringProtoFuncTrimLeftEPNS_9ExecStateE
+__ZN3JSCL24stringProtoFuncTrimRightEPNS_9ExecStateE
+__ZN3WTF6VectorIcLm0EE14expandCapacityEm
+__ZN3JSCL28stringProtoFuncLocaleCompareEPNS_9ExecStateE
+__ZN3WTF8Collator11userDefaultEv
+__ZNK3WTF8Collator7collateEPKtmS2_m
+__ZNK3WTF8Collator14createCollatorEv
+__ZN3WTF8CollatorD1Ev
+__ZN3WTF8Collator15releaseCollatorEv
+__ZN3JSC3JIT30emit_op_ensure_property_existsEPNS_11InstructionE
+_cti_op_ensure_property_exists
+__ZNK3JSC20StrictEvalActivation12toThisObjectEPNS_9ExecStateE
+__ZN3JSC15IdentifierArena21makeNumericIdentifierEPNS_12JSGlobalDataEd
+__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC6JSCell3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3WTF16codePointCompareERKNS_6StringES2_
+__ZN3JSC3JIT25emit_op_profile_will_callEPNS_11InstructionE
+__ZN3JSC3JIT24emit_op_profile_did_callEPNS_11InstructionE
+__ZN3JSC8Profiler8profilerEv
+__ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC16ProfileGenerator6createEPNS_9ExecStateERKNS_7UStringEj
+__ZN3JSC16ProfileGeneratorC2EPNS_9ExecStateERKNS_7UStringEj
+__ZN3JSC7Profile6createERKNS_7UStringEj
+__ZN3JSC7ProfileC2ERKNS_7UStringEj
+__ZN3JSC11ProfileNodeC1EPNS_9ExecStateERKNS_14CallIdentifierEPS0_S6_
+__ZN3JSC16ProfileGenerator24addParentForConsoleStartEPNS_9ExecStateE
+__ZN3JSC8Profiler20createCallIdentifierEPNS_9ExecStateENS_7JSValueERKNS_7UStringEi
+__ZN3JSC10JSFunction21calculatedDisplayNameEPNS_9ExecStateE
+__ZN3JSC10JSFunction11displayNameEPNS_9ExecStateE
+__ZN3JSC11ProfileNode10insertNodeEN3WTF10PassRefPtrIS0_EE
+__ZN3WTF6VectorINS_6RefPtrIN3JSC16ProfileGeneratorEEELm0EE14expandCapacityEm
+_cti_op_profile_did_call
+__ZN3JSC8Profiler10didExecuteEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC16ProfileGenerator10didExecuteEPNS_9ExecStateERKNS_14CallIdentifierE
+__ZN3JSC11ProfileNode10didExecuteEv
+_cti_op_profile_will_call
+__ZN3JSC8Profiler11willExecuteEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC16ProfileGenerator11willExecuteEPNS_9ExecStateERKNS_14CallIdentifierE
+__ZN3JSC11ProfileNode11willExecuteEPNS_9ExecStateERKNS_14CallIdentifierE
+__ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC16ProfileGenerator13stopProfilingEv
+__ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
+__ZNK3JSC11ProfileNode25traverseNextNodePostOrderEv
+__ZN3JSC11ProfileNode13stopProfilingEv
+__ZN3JSC11ProfileNode11removeChildEPS0_
+__ZN3JSC11ProfileNode8addChildEN3WTF10PassRefPtrIS0_EE
+__ZN3JSC8Debugger23recompileAllJSFunctionsEPNS_12JSGlobalDataE
+__ZN3WTF9HashTableIPN3JSC18FunctionExecutableES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC7ProfileD0Ev
+__ZN3WTF10RefCountedIN3JSC11ProfileNodeEE5derefEv
+__ZN3JSC8Profiler11willExecuteEPNS_9ExecStateERKNS_7UStringEi
+__ZN3JSC8Profiler10didExecuteEPNS_9ExecStateERKNS_7UStringEi
+__ZNK3JSC16ProfileGenerator5titleEv
+__ZN3JSC8Profiler13stopProfilingEPNS_14JSGlobalObjectE
+__ZN3JSC34createTerminatedExecutionExceptionEPNS_12JSGlobalDataE
+__ZNK3JSC24TerminatedExecutionError13exceptionTypeEv
+__ZN3JSC24TerminatedExecutionErrorD1Ev
+__ZN3WTF5Mutex7tryLockEv
+__ZN3WTF6String6numberEm
+__ZN3WTF5yieldEv
+__ZN3WTF8CollatorC1EPKc
+__ZN3WTF8Collator18setOrderLowerFirstEb
+__ZN3JSC10JSONObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC9Structure27despecifyDictionaryFunctionERNS_12JSGlobalDataERKNS_10IdentifierE
+__ZN3JSC17ObjectConstructor24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC15ObjectPrototype24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC17StringConstructor24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC16BooleanPrototype24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC15NumberPrototype24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC15DateConstructor24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC14ErrorPrototype24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC16ArrayConstructor24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSCL7dateNowEPNS_9ExecStateE
+__ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
+__ZN3WTF9HashTableIPN3JSC14JSGlobalObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC7UString6numberEl
+__ZN3JSC3JIT13emit_op_debugEPNS_11InstructionE
+_cti_op_debug
+__ZN3JSC11Interpreter5debugEPNS_9ExecStateENS_11DebugHookIDEii
+__ZNK3JSC14SourceProvider13startPositionEv
+__ZN3WTF9HashTableIPN3JSC18FunctionExecutableES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_
+__ZN3WTF9HashTableIPN3JSC14SourceProviderESt4pairIS3_PNS1_9ExecStateEENS_18PairFirstExtractorIS7_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSD_IS6_EEEESE_E4findIS3_NS_22IdentityHashTranslatorIS3_S7_SB_EEEENS_17HashTableIteratorIS3_S7_S9_SB_SG_SE_EERKT_
+__ZN3WTF9HashTableIPN3JSC14SourceProviderESt4pairIS3_PNS1_9ExecStateEENS_18PairFirstExtractorIS7_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSD_IS6_EEEESE_E6expandEv
+__ZNK3JSC17DebuggerCallFrame4typeEv
+__ZNK3JSC17DebuggerCallFrame22calculatedFunctionNameEv
+__ZN3JSC12JSActivation19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZNK3JSC12JSActivation18isActivationObjectEv
+__ZNK3JSC17DebuggerCallFrame10thisObjectEv
+__ZN3WTF28setMainThreadCallbacksPausedEb
+__ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_7JSValueE
+__ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
+__ZN3JSC14JSGlobalObject11disableEvalEv
+__ZN3WTF6VectorIN3JSC14ExecutablePool10AllocationELm2EE14expandCapacityEm
+__ZNK3WTF6String8toIntPtrEPb
+__ZN3WTF10StringImpl8toIntPtrEPb
+__ZN3WTF18charactersToIntPtrEPKtmPb
+__ZNK3JSC8JSObject18isActivationObjectEv
+_cti_op_construct_jitCompile
+__ZN3WTF10StringImpl7replaceEjjPS0_
+__ZNK3JSC4Heap8capacityEv
+__ZNK3JSC11MarkedSpace8capacityEv
+__ZNK3JSC4Heap4sizeEv
+__ZN3WTF29cryptographicallyRandomValuesEPvm
+__ZN3WTF6VectorIN3JSC8JSParser5ScopeELm10EE15reserveCapacityEm
+__ZN3JSC8JSString16getIndexSlowCaseEPNS_9ExecStateEj
+__ZNK3WTF6String12toUIntStrictEPbi
+__ZN3WTF10StringImpl12toUIntStrictEPbi
+__ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
+__ZNK3WTF6String8toUInt64EPb
+__ZN3WTF10StringImpl8toUInt64EPb
+__ZN3WTF18charactersToUInt64EPKtmPb
+__ZN3WTF3MD5C1Ev
+__ZN3WTF3MD58addBytesEPKhm
+__ZN3WTF3MD58checksumERNS_6VectorIhLm16EEE
+__ZN3WTFL12MD5TransformEPjPKj
+__ZN3WTF6String6numberEl
+__ZN3JSC4Heap17globalObjectCountEv
+__ZN3JSC4Heap20protectedObjectCountEv
+__ZN3JSC4Heap25protectedObjectTypeCountsEv
+__ZN3JSC11TypeCounterclEPNS_6JSCellE
+__ZN3WTF9HashTableIPN3JSC6JSCellES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3WTF9HashTableIPKcSt4pairIS2_jENS_18PairFirstExtractorIS4_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSA_IjEEEESB_E6expandEv
+__ZNK3JSC6JSCell17isAPIValueWrapperEv
+__ZNK3JSC6JSCell22isPropertyNameIteratorEv
+__ZN3JSC4Heap16objectTypeCountsEv
+__ZN3WTF9HashTableIPN3JSC6JSCellES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_17HashTableIteratorIS3_S3_S5_S7_S9_S9_EERKT_
+__ZN3WTF20fastMallocStatisticsEv
+__ZN3JSC22globalMemoryStatisticsEv
+__ZN3JSC12RegisterFile18committedByteCountEv
+__ZN3JSC19ExecutableAllocator18committedByteCountEv
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_N3JSC14OffsetLocationEENS_18PairFirstExtractorIS7_EENS_10StringHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSC_IS6_EEEESD_E4findIPS2_NS_29RefPtrHashMapRawKeyTranslatorISI_S7_SF_SA_EEEENS_17HashTableIteratorIS3_S7_S9_SA_SF_SD_EERKT_
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_N3JSC14OffsetLocationEENS_18PairFirstExtractorIS7_EENS_10StringHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSC_IS6_EEEESD_E4findIS3_NS_22IdentityHashTranslatorIS3_S7_SA_EEEENS_17HashTableIteratorIS3_S7_S9_SA_SF_SD_EERKT_
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_N3JSC14OffsetLocationEENS_18PairFirstExtractorIS7_EENS_10StringHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSC_IS6_EEEESD_E6expandEv
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_N3JSC14OffsetLocationEENS_18PairFirstExtractorIS7_EENS_10StringHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSC_IS6_EEEESD_EC2ERKSG_
+__ZN3JSC9Arguments11fillArgListEPNS_9ExecStateERNS_20MarkedArgumentBufferE
+__ZN3WTF6VectorIiLm8EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC10ASTBuilder14AssignmentInfoELm10EE14expandCapacityEm
+_cti_op_put_by_id_direct_generic
+__ZN3WTF9HashTableIPN3JSC16FunctionBodyNodeESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E4findIS3_NS_22IdentityHashTranslatorIS3_S5_S9_EEEENS_17HashTableIteratorIS3_S5_S7_S9_SE_SC_EERKT_
+__ZN3WTF9HashTableIPN3JSC16FunctionBodyNodeESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6expandEv
index ed4cf2e2730a10fda48e3a1a58dcfe5d92f681b9..4a8ecd42feb47b58bc0f598612fe2926a6961baa 100644 (file)
-# JavaScriptCore - Qt4 build info
-
-include(../common.pri)
-
-VPATH += $$PWD
-
-# Use a config-specific target to prevent parallel builds file clashes on Mac
-mac: CONFIG(debug, debug|release): JAVASCRIPTCORE_TARGET = jscored
-else: JAVASCRIPTCORE_TARGET = jscore
-
-# Output in JavaScriptCore/<config>
-CONFIG(debug, debug|release) : JAVASCRIPTCORE_DESTDIR = debug
-else: JAVASCRIPTCORE_DESTDIR = release
-
-CONFIG(standalone_package) {
-    isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$PWD/generated
-} else {
-    isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$OUTPUT_DIR/JavaScriptCore/generated
-}
-
-JAVASCRIPTCORE_INCLUDEPATH = \
-    $$PWD \
-    $$PWD/.. \
-    $$PWD/../ThirdParty \
-    $$PWD/assembler \
-    $$PWD/bytecode \
-    $$PWD/bytecompiler \
-    $$PWD/heap \
-    $$PWD/dfg \
-    $$PWD/debugger \
-    $$PWD/interpreter \
-    $$PWD/jit \
-    $$PWD/parser \
-    $$PWD/profiler \
-    $$PWD/runtime \
-    $$PWD/wtf \
-    $$PWD/wtf/gobject \
-    $$PWD/wtf/symbian \
-    $$PWD/wtf/unicode \
-    $$PWD/yarr \
-    $$PWD/API \
-    $$PWD/ForwardingHeaders \
-    $$JSC_GENERATED_SOURCES_DIR
-
-symbian {
-    PREPEND_INCLUDEPATH = $$JAVASCRIPTCORE_INCLUDEPATH $$PREPEND_INCLUDEPATH
-} else {
-    INCLUDEPATH = $$JAVASCRIPTCORE_INCLUDEPATH $$INCLUDEPATH
-}
-
-symbian {
-    LIBS += -lhal
-    INCLUDEPATH *= $$MW_LAYER_SYSTEMINCLUDE
-}
-
-win32-*: DEFINES += _HAS_TR1=0
-
-DEFINES += BUILDING_JavaScriptCore BUILDING_WTF
-
-# CONFIG += text_breaking_with_icu
-
-contains (CONFIG, text_breaking_with_icu) {
-    DEFINES += WTF_USE_QT_ICU_TEXT_BREAKING=1
+# -------------------------------------------------------------------
+# This file contains shared rules used both when building
+# JavaScriptCore itself, and by targets that use JavaScriptCore.
+#
+# See 'Tools/qmake/README' for an overview of the build system
+# -------------------------------------------------------------------
+
+SOURCE_DIR = $${ROOT_WEBKIT_DIR}/Source/JavaScriptCore
+
+JAVASCRIPTCORE_GENERATED_SOURCES_DIR = $${ROOT_BUILD_DIR}/Source/JavaScriptCore/$${GENERATED_SOURCES_DESTDIR}
+
+INCLUDEPATH += \
+    $$SOURCE_DIR \
+    $$SOURCE_DIR/.. \
+    $$SOURCE_DIR/../WTF \
+    $$SOURCE_DIR/assembler \
+    $$SOURCE_DIR/bytecode \
+    $$SOURCE_DIR/bytecompiler \
+    $$SOURCE_DIR/heap \
+    $$SOURCE_DIR/dfg \
+    $$SOURCE_DIR/debugger \
+    $$SOURCE_DIR/interpreter \
+    $$SOURCE_DIR/jit \
+    $$SOURCE_DIR/llint \
+    $$SOURCE_DIR/parser \
+    $$SOURCE_DIR/profiler \
+    $$SOURCE_DIR/runtime \
+    $$SOURCE_DIR/tools \
+    $$SOURCE_DIR/yarr \
+    $$SOURCE_DIR/API \
+    $$SOURCE_DIR/ForwardingHeaders \
+    $$JAVASCRIPTCORE_GENERATED_SOURCES_DIR
+
+win32-* {
+    LIBS += -lwinmm
+
+    win32-g++* {
+        LIBS += -lpthreadGC2
+    } else:win32-msvc* {
+        LIBS += -lpthreadVC2
+    }
 }
 
 wince* {
     INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/ce-compat
 }
 
 wince* {
     INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/ce-compat
-    INCLUDEPATH += $$PWD/../JavaScriptCore/os-win32
+    INCLUDEPATH += $$SOURCE_DIR/os-win32
 }
 }
-
-
-defineTest(prependJavaScriptCoreLib) {
-    # Argument is the relative path to JavaScriptCore.pro's qmake output
-    pathToJavaScriptCoreOutput = $$ARGS/$$JAVASCRIPTCORE_DESTDIR
-
-    win32-msvc*|wince* {
-        LIBS = -l$$JAVASCRIPTCORE_TARGET $$LIBS
-        LIBS = -L$$pathToJavaScriptCoreOutput $$LIBS
-        POST_TARGETDEPS += $${pathToJavaScriptCoreOutput}$${QMAKE_DIR_SEP}$${JAVASCRIPTCORE_TARGET}.lib
-    } else:symbian {
-        LIBS = -l$${JAVASCRIPTCORE_TARGET}.lib $$LIBS
-        # 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
-        POST_TARGETDEPS += $${pathToJavaScriptCoreOutput}$${QMAKE_DIR_SEP}$${JAVASCRIPTCORE_TARGET}.lib
-    } else {
-        # 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
-        POST_TARGETDEPS += $${pathToJavaScriptCoreOutput}$${QMAKE_DIR_SEP}lib$${JAVASCRIPTCORE_TARGET}.a
-    }
-
-    win32-* {
-        LIBS += -lwinmm
-    }
-
-    # The following line is to prevent qmake from adding jscore to libQtWebKit's prl dependencies.
-    # The compromise we have to accept by disabling explicitlib is to drop support to link QtWebKit and QtScript
-    # statically in applications (which isn't used often because, among other things, of licensing obstacles).
-    CONFIG -= explicitlib
-
-    export(QMAKE_LIBDIR)
-    export(LIBS)
-    export(POST_TARGETDEPS)
-    export(CONFIG)
-
-    return(true)
-}
-
index 3e0caf8df920b5de0aa9b7a3b187ae2dcaba22ff..393728f9910d83e6d778a172c6d7aa771295ace4 100644 (file)
-# JavaScriptCore - qmake build info
-CONFIG += building-libs
-include($$PWD/../WebKit.pri)
-include(JavaScriptCore.pri)
+# -------------------------------------------------------------------
+# Main project file for JavaScriptSource
+#
+# See 'Tools/qmake/README' for an overview of the build system
+# -------------------------------------------------------------------
 
 
-TEMPLATE = lib
-CONFIG += staticlib
-# Don't use JavaScriptCore as the target name. qmake would create a JavaScriptCore.vcproj for msvc
-# which already exists as a directory
-TARGET = $$JAVASCRIPTCORE_TARGET
-DESTDIR = $$JAVASCRIPTCORE_DESTDIR
-QT += core
-QT -= gui
+TEMPLATE = subdirs
+CONFIG += ordered
 
 
-CONFIG += depend_includepath
+derived_sources.file = DerivedSources.pri
+target.file = Target.pri
 
 
-contains(QT_CONFIG, embedded):CONFIG += embedded
+SUBDIRS += derived_sources target
 
 
-# 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
-contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
-unix:contains(QT_CONFIG, reduce_relocations):CONFIG += bsymbolic_functions
-
-CONFIG(QTDIR_build) {
-    # Remove the following 2 lines if you want debug information in JavaScriptCore
-    CONFIG -= separate_debug_info
-    CONFIG += no_debug_info
-}
-
-*-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2
-*-g++*:QMAKE_CXXFLAGS_RELEASE += -O3
-
-# Rules when JIT enabled (not disabled)
-!contains(DEFINES, ENABLE_JIT=0) {
-    linux*-g++*:greaterThan(QT_GCC_MAJOR_VERSION,3):greaterThan(QT_GCC_MINOR_VERSION,0) {
-        QMAKE_CXXFLAGS += -fno-stack-protector
-        QMAKE_CFLAGS += -fno-stack-protector
-    }
-}
-
-wince* {
-    SOURCES += $$QT_SOURCE_TREE/src/3rdparty/ce-compat/ce_time.c
-}
-
-include(yarr/yarr.pri)
-include(wtf/wtf.pri)
-
-INSTALLDEPS += all
-
-SOURCES += \
-    API/JSBase.cpp \
-    API/JSCallbackConstructor.cpp \
-    API/JSCallbackFunction.cpp \
-    API/JSCallbackObject.cpp \
-    API/JSClassRef.cpp \
-    API/JSContextRef.cpp \
-    API/JSObjectRef.cpp \
-    API/JSStringRef.cpp \
-    API/JSValueRef.cpp \
-    API/OpaqueJSString.cpp \
-    assembler/ARMAssembler.cpp \
-    assembler/ARMv7Assembler.cpp \
-    assembler/MacroAssemblerARM.cpp \
-    assembler/MacroAssemblerSH4.h \
-    assembler/MacroAssemblerSH4.cpp \
-    assembler/SH4Assembler.h \
-    bytecode/CodeBlock.cpp \
-    bytecode/JumpTable.cpp \
-    bytecode/Opcode.cpp \
-    bytecode/SamplingTool.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 \
-    dfg/DFGByteCodeParser.cpp \
-    dfg/DFGGraph.cpp \
-    dfg/DFGJITCodeGenerator.cpp \
-    dfg/DFGJITCompiler.cpp \
-    dfg/DFGNonSpeculativeJIT.cpp \
-    dfg/DFGOperations.cpp \
-    dfg/DFGSpeculativeJIT.cpp \
-    interpreter/CallFrame.cpp \
-    interpreter/Interpreter.cpp \
-    interpreter/RegisterFile.cpp \
-    jit/ExecutableAllocatorFixedVMPool.cpp \
-    jit/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/JITPropertyAccess.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/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/ErrorConstructor.cpp \
-    runtime/Error.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/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/RegExpConstructor.cpp \
-    runtime/RegExp.cpp \
-    runtime/RegExpObject.cpp \
-    runtime/RegExpPrototype.cpp \
-    runtime/RegExpCache.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/StructureChain.cpp \
-    runtime/Structure.cpp \
-    runtime/TimeoutChecker.cpp \
-    runtime/UString.cpp \
-    yarr/YarrJIT.cpp \
-
-*sh4* {
-    QMAKE_CXXFLAGS += -mieee -w
-    QMAKE_CFLAGS   += -mieee -w
-}
-
-# Generated files, simply list them for JavaScriptCore
-
-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
-}
+addStrictSubdirOrderBetween(derived_sources, target)
 
 
+jsc.file = jsc.pro
+jsc.makefile = Makefile.jsc
+SUBDIRS += jsc
index 6ba7e34798459e23254d790dc8b602b2c2a490f9..748acf9dc14baeb3b84203e46592012bc0d6f9b0 100644 (file)
@@ -1,4 +1,5 @@
-# Copyright (C) 2010 Apple Inc. All rights reserved.
+# Copyright (C) 2011 Apple Inc. All rights reserved.
+# Copyright (C) 2012 Sony Network Entertainment. 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,6 +28,15 @@ import operator
 
 keywordsText = open(sys.argv[1]).read()
 
 
 keywordsText = open(sys.argv[1]).read()
 
+# A second argument signifies that the output
+# should be redirected to a file
+redirect_to_file = len(sys.argv) > 2
+
+# Change stdout to point to the file if requested
+if redirect_to_file:
+    file_output = open(sys.argv[-1], "w")
+    sys.stdout = file_output
+
 # Observed weights of the most common keywords, rounded to 2.s.d
 keyWordWeights = {
     "catch": 0.01,
 # Observed weights of the most common keywords, rounded to 2.s.d
 keyWordWeights = {
     "catch": 0.01,
@@ -103,11 +113,12 @@ class Trie:
             return self
         if len(self.keys) != 1:
             return self
             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
+        # Python 3: for() loop for compatibility. Use next() when Python 2.6 is the baseline.
+        for (prefix, suffix) in self.keys.items():
+            res = Trie(self.prefix + prefix)
+            res.value = suffix.value
+            res.keys = suffix.keys
+            return res
 
     def fillOut(self, prefix=""):
         self.fullPrefix = prefix + self.prefix
 
     def fillOut(self, prefix=""):
         self.fullPrefix = prefix + self.prefix
@@ -121,12 +132,12 @@ class Trie:
         self.keys = [(trie.prefix, trie) for trie in sorted(self.keys.values(), key=operator.attrgetter('weight'), reverse=True)]
         self.weight = 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):
+    def printSubTreeAsC(self, typeName, indent):
         str = makePadding(indent)
 
         if self.value != None:
             print(str + "if (!isIdentPart(code[%d])) {" % (len(self.fullPrefix)))
         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 + "    internalShift<%d>();" % len(self.fullPrefix))
             print(str + "    if (shouldCreateIdentifier)")
             print(str + ("        data->ident = &m_globalData->propertyNames->%sKeyword;" % self.fullPrefix))
             print(str + "    return " + self.value + ";")
             print(str + "    if (shouldCreateIdentifier)")
             print(str + ("        data->ident = &m_globalData->propertyNames->%sKeyword;" % self.fullPrefix))
             print(str + "    return " + self.value + ";")
@@ -145,15 +156,17 @@ class Trie:
                 base = "code"
                 if baseIndex > 0:
                     base = "code + %d" % baseIndex
                 base = "code"
                 if baseIndex > 0:
                     base = "code + %d" % baseIndex
-                comparison = ("COMPARE_CHARACTERS%d(%s, " % (len(test), base)) + ", ".join(test) + ")"
+                comparison = ("COMPARE_%d%sS(%s, " % (len(test), typeName, base)) + ", ".join(test) + ")"
             if itemCount == 0:
                 print(str + "if (" + comparison + ") {")
             else:
             if itemCount == 0:
                 print(str + "if (" + comparison + ") {")
             else:
-                print(str + "else if (" + comparison + ") {")
+                print(str + "else if (" + comparison + ") {")
 
 
-            trie.printSubTreeAsC(indent + 4)
+            trie.printSubTreeAsC(typeName, indent + 4)
             itemCount = itemCount + 1
             itemCount = itemCount + 1
-            print(str + "}")
+
+            if itemCount == len(self.keys):
+                print(str + "}")
 
     def maxLength(self):
         max = len(self.fullPrefix)
 
     def maxLength(self):
         max = len(self.fullPrefix)
@@ -165,16 +178,33 @@ class Trie:
 
     def printAsC(self):
         print("namespace JSC {")
 
     def printAsC(self):
         print("namespace JSC {")
-        print("static ALWAYS_INLINE bool isIdentPart(int c);")
+        print("")
+        print("static ALWAYS_INLINE bool isIdentPart(LChar c);")
+        print("static ALWAYS_INLINE bool isIdentPart(UChar 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))
         # 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("")
+        print("template <>")
+        print("template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::parseKeyword(JSTokenData* data)")
+        print("{")
         print("    ASSERT(m_codeEnd - m_code >= maxTokenLength);")
         print("    ASSERT(m_codeEnd - m_code >= maxTokenLength);")
+        print("")
         print("    const UChar* code = m_code;")
         print("    const UChar* code = m_code;")
-        self.printSubTreeAsC(4)
+        self.printSubTreeAsC("UCHAR", 4)
         print("    return IDENT;")
         print("}")
         print("    return IDENT;")
         print("}")
+        print("")
+        print("template <>")
+        print("template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<LChar>::parseKeyword(JSTokenData* data)")
+        print("{")
+        print("    ASSERT(m_codeEnd - m_code >= maxTokenLength);")
+        print("")
+        print("    const LChar* code = m_code;")
+        self.printSubTreeAsC("CHAR", 4)
+        print("    return IDENT;")
         print("}")
         print("}")
+        print("")
+        print("} // namespace JSC")
 
 keywords = parseKeywords(keywordsText)
 trie = Trie("")
 
 keywords = parseKeywords(keywordsText)
 trie = Trie("")
@@ -184,47 +214,92 @@ trie.coalesce()
 trie.fillOut()
 print("// This file was generated by KeywordLookupGenerator.py.  Do not edit.")
 print("""
 trie.fillOut()
 print("// This file was generated by KeywordLookupGenerator.py.  Do not edit.")
 print("""
-
 #if CPU(NEEDS_ALIGNED_ACCESS)
 
 #if CPU(NEEDS_ALIGNED_ACCESS)
 
-#define COMPARE_CHARACTERS2(address, char1, char2) \
+#define COMPARE_2CHARS(address, char1, char2) \\
+    (((address)[0] == char1) && ((address)[1] == char2))
+#define COMPARE_4CHARS(address, char1, char2, char3, char4) \\
+    (COMPARE_2CHARS(address, char1, char2) && COMPARE_2CHARS((address) + 2, char3, char4))
+#define COMPARE_2UCHARS(address, char1, char2) \\
     (((address)[0] == char1) && ((address)[1] == 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))
+#define COMPARE_4UCHARS(address, char1, char2, char3, char4) \\
+    (COMPARE_2UCHARS(address, char1, char2) && COMPARE_2UCHARS((address) + 2, char3, char4))
 
 
-#else
+#else // CPU(NEEDS_ALIGNED_ACCESS)
 
 #if CPU(BIG_ENDIAN)
 
 #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))
+
+#define CHARPAIR_TOUINT16(a, b) \\
+    ((((uint16_t)(a)) << 8) + (uint16_t)(b))
+#define CHARQUAD_TOUINT32(a, b, c, d) \\
+    ((((uint32_t)(CHARPAIR_TOUINT16(a, b))) << 16) + CHARPAIR_TOUINT16(c, d))
+#define UCHARPAIR_TOUINT32(a, b) \\
+    ((((uint32_t)(a)) << 16) + (uint32_t)(b))
+#define UCHARQUAD_TOUINT64(a, b, c, d) \\
+    ((((uint64_t)(UCHARQUAD_TOUINT64(a, b))) << 32) + UCHARPAIR_TOUINT32(c, d))
+
+#else // CPU(BIG_ENDIAN)
+
+#define CHARPAIR_TOUINT16(a, b) \\
+    ((((uint16_t)(b)) << 8) + (uint16_t)(a))
+#define CHARQUAD_TOUINT32(a, b, c, d) \\
+    ((((uint32_t)(CHARPAIR_TOUINT16(c, d))) << 16) + CHARPAIR_TOUINT16(a, b))
+#define UCHARPAIR_TOUINT32(a, b) \\
+    ((((uint32_t)(b)) << 16) + (uint32_t)(a))
+#define UCHARQUAD_TOUINT64(a, b, c, d) \\
+    ((((uint64_t)(UCHARPAIR_TOUINT32(c, d))) << 32) + UCHARPAIR_TOUINT32(a, b))
+
+#endif // CPU(BIG_ENDIAN)
+
+
+#define COMPARE_2CHARS(address, char1, char2) \\
+    (((uint16_t*)(address))[0] == CHARPAIR_TOUINT16(char1, char2))
+#define COMPARE_2UCHARS(address, char1, char2) \\
+    (((uint32_t*)(address))[0] == UCHARPAIR_TOUINT32(char1, char2))
+
 #if CPU(X86_64)
 
 #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))
+#define COMPARE_4CHARS(address, char1, char2, char3, char4) \\
+    (((uint32_t*)(address))[0] == CHARQUAD_TOUINT32(char1, char2, char3, char4))
+#define COMPARE_4UCHARS(address, char1, char2, char3, char4) \\
+    (((uint64_t*)(address))[0] == UCHARQUAD_TOUINT64(char1, char2, char3, char4))
+
+#else // CPU(X86_64)
+
+#define COMPARE_4CHARS(address, char1, char2, char3, char4) \\
+    (COMPARE_2CHARS(address, char1, char2) && COMPARE_2CHARS((address) + 2, char3, char4))
+#define COMPARE_4UCHARS(address, char1, char2, char3, char4) \\
+    (COMPARE_2UCHARS(address, char1, char2) && COMPARE_2UCHARS((address) + 2, char3, char4))
+
+#endif // CPU(X86_64)
+
+#endif // CPU(NEEDS_ALIGNED_ACCESS)
+
+#define COMPARE_3CHARS(address, char1, char2, char3) \\
+    (COMPARE_2CHARS(address, char1, char2) && ((address)[2] == (char3)))
+#define COMPARE_3UCHARS(address, char1, char2, char3) \\
+    (COMPARE_2UCHARS(address, char1, char2) && ((address)[2] == (char3)))
+#define COMPARE_5CHARS(address, char1, char2, char3, char4, char5) \\
+    (COMPARE_4CHARS(address, char1, char2, char3, char4) && ((address)[4] == (char5)))
+#define COMPARE_5UCHARS(address, char1, char2, char3, char4, char5) \\
+    (COMPARE_4UCHARS(address, char1, char2, char3, char4) && ((address)[4] == (char5)))
+#define COMPARE_6CHARS(address, char1, char2, char3, char4, char5, char6) \\
+    (COMPARE_4CHARS(address, char1, char2, char3, char4) && COMPARE_2CHARS(address + 4, char5, char6))
+#define COMPARE_6UCHARS(address, char1, char2, char3, char4, char5, char6) \\
+    (COMPARE_4UCHARS(address, char1, char2, char3, char4) && COMPARE_2UCHARS(address + 4, char5, char6))
+#define COMPARE_7CHARS(address, char1, char2, char3, char4, char5, char6, char7) \\
+    (COMPARE_4CHARS(address, char1, char2, char3, char4) && COMPARE_4CHARS(address + 3, char4, char5, char6, char7))
+#define COMPARE_7UCHARS(address, char1, char2, char3, char4, char5, char6, char7) \\
+    (COMPARE_4UCHARS(address, char1, char2, char3, char4) && COMPARE_4UCHARS(address + 3, char4, char5, char6, char7))
+#define COMPARE_8CHARS(address, char1, char2, char3, char4, char5, char6, char7, char8) \\
+    (COMPARE_4CHARS(address, char1, char2, char3, char4) && COMPARE_4CHARS(address + 4, char5, char6, char7, char8))
+#define COMPARE_8UCHARS(address, char1, char2, char3, char4, char5, char6, char7, char8) \\
+    (COMPARE_4UCHARS(address, char1, char2, char3, char4) && COMPARE_4UCHARS(address + 4, char5, char6, char7, char8))
 """)
 
 trie.printAsC()
 """)
 
 trie.printAsC()
+
+# Close the redirected file if requested
+if (redirect_to_file):
+    file_output.close()
+    sys.stdout = sys.__stdout__
diff --git a/PlatformBlackBerry.cmake b/PlatformBlackBerry.cmake
new file mode 100644 (file)
index 0000000..abfae85
--- /dev/null
@@ -0,0 +1,5 @@
+LIST(INSERT JavaScriptCore_INCLUDE_DIRECTORIES 0
+    "${BLACKBERRY_THIRD_PARTY_DIR}/icu"
+)
+
+INSTALL(FILES "wtf/Forward.h" DESTINATION usr/include/browser/webkit/wtf)
diff --git a/PlatformEfl.cmake b/PlatformEfl.cmake
new file mode 100644 (file)
index 0000000..448834c
--- /dev/null
@@ -0,0 +1,22 @@
+LIST(APPEND JavaScriptCore_SOURCES
+    jit/ExecutableAllocatorFixedVMPool.cpp
+    jit/ExecutableAllocator.cpp
+)
+
+LIST(APPEND JavaScriptCore_LIBRARIES
+    ${ICU_I18N_LIBRARIES}
+)
+
+LIST(APPEND JavaScriptCore_INCLUDE_DIRECTORIES
+    ${ICU_INCLUDE_DIRS}
+)
+
+IF (ENABLE_GLIB_SUPPORT)
+  LIST(APPEND JavaScriptCore_INCLUDE_DIRECTORIES
+    ${JAVASCRIPTCORE_DIR}/wtf/gobject
+  )
+ENDIF ()
+
+LIST(APPEND JavaScriptCore_LINK_FLAGS
+    ${ECORE_LDFLAGS}
+)
diff --git a/PlatformWinCE.cmake b/PlatformWinCE.cmake
new file mode 100644 (file)
index 0000000..e1a43ff
--- /dev/null
@@ -0,0 +1,20 @@
+LIST(APPEND JavaScriptCore_SOURCES
+    jit/ExecutableAllocator.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 ()
diff --git a/Target.pri b/Target.pri
new file mode 100644 (file)
index 0000000..017f316
--- /dev/null
@@ -0,0 +1,256 @@
+# -------------------------------------------------------------------
+# Target file for the JavaScriptSource library
+#
+# See 'Tools/qmake/README' for an overview of the build system
+# -------------------------------------------------------------------
+
+TEMPLATE = lib
+TARGET = JavaScriptCore
+
+include(JavaScriptCore.pri)
+
+WEBKIT += wtf
+QT += core
+QT -= gui
+
+CONFIG += staticlib
+
+*-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2
+*-g++*:QMAKE_CXXFLAGS_RELEASE += -O3
+
+# Rules when JIT enabled (not disabled)
+!contains(DEFINES, ENABLE_JIT=0) {
+    linux*-g++*:greaterThan(QT_GCC_MAJOR_VERSION,3):greaterThan(QT_GCC_MINOR_VERSION,0) {
+        QMAKE_CXXFLAGS += -fno-stack-protector
+        QMAKE_CFLAGS += -fno-stack-protector
+    }
+}
+
+wince* {
+    SOURCES += $$QT_SOURCE_TREE/src/3rdparty/ce-compat/ce_time.c
+}
+
+include(yarr/yarr.pri)
+
+INSTALLDEPS += all
+
+SOURCES += \
+    API/JSBase.cpp \
+    API/JSCallbackConstructor.cpp \
+    API/JSCallbackFunction.cpp \
+    API/JSCallbackObject.cpp \
+    API/JSClassRef.cpp \
+    API/JSContextRef.cpp \
+    API/JSObjectRef.cpp \
+    API/JSStringRef.cpp \
+    API/JSValueRef.cpp \
+    API/OpaqueJSString.cpp \
+    assembler/ARMAssembler.cpp \
+    assembler/ARMv7Assembler.cpp \
+    assembler/MacroAssemblerARM.cpp \
+    assembler/MacroAssemblerSH4.cpp \
+    bytecode/CallLinkInfo.cpp \
+    bytecode/CallLinkStatus.cpp \
+    bytecode/CodeBlock.cpp \
+    bytecode/DFGExitProfile.cpp \
+    bytecode/ExecutionCounter.cpp \
+    bytecode/GetByIdStatus.cpp \
+    bytecode/JumpTable.cpp \
+    bytecode/LazyOperandValueProfile.cpp \
+    bytecode/MethodCallLinkInfo.cpp \
+    bytecode/MethodCallLinkStatus.cpp \
+    bytecode/MethodOfGettingAValueProfile.cpp \
+    bytecode/Opcode.cpp \
+    bytecode/PolymorphicPutByIdList.cpp \
+    bytecode/PredictedType.cpp \
+    bytecode/PutByIdStatus.cpp \
+    bytecode/SamplingTool.cpp \
+    bytecode/StructureStubInfo.cpp \
+    bytecompiler/BytecodeGenerator.cpp \
+    bytecompiler/NodesCodegen.cpp \
+    heap/CopiedSpace.cpp \
+    heap/ConservativeRoots.cpp \
+    heap/DFGCodeBlocks.cpp \
+    heap/WeakSet.cpp \
+    heap/WeakHandleOwner.cpp \
+    heap/WeakBlock.cpp \
+    heap/HandleSet.cpp \
+    heap/HandleStack.cpp \
+    heap/BlockAllocator.cpp \
+    heap/Heap.cpp \
+    heap/MachineStackMarker.cpp \
+    heap/MarkStack.cpp \
+    heap/MarkedAllocator.cpp \
+    heap/MarkedBlock.cpp \
+    heap/MarkedSpace.cpp \
+    heap/VTableSpectrum.cpp \
+    heap/WriteBarrierSupport.cpp \
+    debugger/DebuggerActivation.cpp \
+    debugger/DebuggerCallFrame.cpp \
+    debugger/Debugger.cpp \
+    dfg/DFGAbstractState.cpp \
+    dfg/DFGAssemblyHelpers.cpp \
+    dfg/DFGByteCodeParser.cpp \
+    dfg/DFGCapabilities.cpp \
+    dfg/DFGCFAPhase.cpp \
+    dfg/DFGCorrectableJumpPoint.cpp \
+    dfg/DFGCSEPhase.cpp \
+    dfg/DFGDriver.cpp \
+    dfg/DFGFixupPhase.cpp \
+    dfg/DFGGraph.cpp \
+    dfg/DFGJITCompiler.cpp \
+    dfg/DFGNodeFlags.cpp \
+    dfg/DFGOperations.cpp \
+    dfg/DFGOSREntry.cpp \
+    dfg/DFGOSRExit.cpp \
+    dfg/DFGOSRExitCompiler.cpp \
+    dfg/DFGOSRExitCompiler64.cpp \
+    dfg/DFGOSRExitCompiler32_64.cpp \
+    dfg/DFGPhase.cpp \
+    dfg/DFGPredictionPropagationPhase.cpp \
+    dfg/DFGRedundantPhiEliminationPhase.cpp \
+    dfg/DFGRepatch.cpp \
+    dfg/DFGSpeculativeJIT.cpp \
+    dfg/DFGSpeculativeJIT32_64.cpp \
+    dfg/DFGSpeculativeJIT64.cpp \
+    dfg/DFGThunks.cpp \
+    dfg/DFGVirtualRegisterAllocationPhase.cpp \
+    interpreter/AbstractPC.cpp \
+    interpreter/CallFrame.cpp \
+    interpreter/Interpreter.cpp \
+    interpreter/RegisterFile.cpp \
+    jit/ExecutableAllocatorFixedVMPool.cpp \
+    jit/ExecutableAllocator.cpp \
+    jit/HostCallReturnValue.cpp \
+    jit/JITArithmetic.cpp \
+    jit/JITArithmetic32_64.cpp \
+    jit/JITCall.cpp \
+    jit/JITCall32_64.cpp \
+    jit/JIT.cpp \
+    jit/JITExceptions.cpp \
+    jit/JITOpcodes.cpp \
+    jit/JITOpcodes32_64.cpp \
+    jit/JITPropertyAccess.cpp \
+    jit/JITPropertyAccess32_64.cpp \
+    jit/JITStubs.cpp \
+    jit/ThunkGenerators.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/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/ErrorConstructor.cpp \
+    runtime/Error.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/Options.cpp \
+    runtime/Identifier.cpp \
+    runtime/InitializeThreading.cpp \
+    runtime/InternalFunction.cpp \
+    runtime/JSActivation.cpp \
+    runtime/JSAPIValueWrapper.cpp \
+    runtime/JSArray.cpp \
+    runtime/JSCell.cpp \
+    runtime/JSDateMath.cpp \
+    runtime/JSFunction.cpp \
+    runtime/JSBoundFunction.cpp \
+    runtime/JSGlobalData.cpp \
+    runtime/JSGlobalObject.cpp \
+    runtime/JSGlobalObjectFunctions.cpp \
+    runtime/JSGlobalThis.cpp \
+    runtime/JSLock.cpp \
+    runtime/JSNotAnObject.cpp \
+    runtime/JSObject.cpp \
+    runtime/JSONObject.cpp \
+    runtime/JSPropertyNameIterator.cpp \
+    runtime/JSStaticScopeObject.cpp \
+    runtime/JSString.cpp \
+    runtime/JSStringJoiner.cpp \
+    runtime/JSValue.cpp \
+    runtime/JSVariableObject.cpp \
+    runtime/JSWrapperObject.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/RegExpConstructor.cpp \
+    runtime/RegExpCachedResult.cpp \
+    runtime/RegExpMatchesArray.cpp \
+    runtime/RegExp.cpp \
+    runtime/RegExpObject.cpp \
+    runtime/RegExpPrototype.cpp \
+    runtime/RegExpCache.cpp \
+    runtime/SamplingCounter.cpp \
+    runtime/ScopeChain.cpp \
+    runtime/SmallStrings.cpp \
+    runtime/StrictEvalActivation.cpp \
+    runtime/StringConstructor.cpp \
+    runtime/StringObject.cpp \
+    runtime/StringPrototype.cpp \
+    runtime/StringRecursionChecker.cpp \
+    runtime/StructureChain.cpp \
+    runtime/Structure.cpp \
+    runtime/TimeoutChecker.cpp \
+    runtime/UString.cpp \
+    tools/CodeProfile.cpp \
+    tools/CodeProfiling.cpp \
+    yarr/YarrJIT.cpp \
+
+*sh4* {
+    QMAKE_CXXFLAGS += -mieee -w
+    QMAKE_CFLAGS   += -mieee -w
+}
+
+lessThan(QT_GCC_MAJOR_VERSION, 5) {
+    # GCC 4.5 and before
+    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
+    }
+
+    # GCC 4.6 and after.
+    greaterThan(QT_GCC_MINOR_VERSION, 5) {
+        if (!contains(QMAKE_CXXFLAGS, -std=c++0x) && !contains(QMAKE_CXXFLAGS, -std=gnu++0x)) {
+            # We need to deactivate those warnings because some names conflicts with upcoming c++0x types (e.g.nullptr).
+            QMAKE_CFLAGS_WARN_ON += -Wno-c++0x-compat
+            QMAKE_CXXFLAGS_WARN_ON += -Wno-c++0x-compat
+            QMAKE_CFLAGS += -Wno-c++0x-compat
+            QMAKE_CXXFLAGS += -Wno-c++0x-compat
+        }
+    }
+}
index f86444d08b62d819a7de767d1d2479642aaef9bb..74809cadb8f525c18345ed19546452dacdaaa73e 100644 (file)
@@ -276,45 +276,46 @@ void ARMAssembler::dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID bas
             dtr_ur(isLoad, srcDst, base, ARMRegisters::S0 | transferFlag);
         }
     } else {
             dtr_ur(isLoad, srcDst, base, ARMRegisters::S0 | transferFlag);
         }
     } else {
-        offset = -offset;
-        if (offset <= 0xfff)
-            dtr_d(isLoad, srcDst, base, offset | transferFlag);
-        else if (offset <= 0xfffff) {
-            sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
-            dtr_d(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff) | transferFlag);
+        if (offset >= -0xfff)
+            dtr_d(isLoad, srcDst, base, -offset | transferFlag);
+        else if (offset >= -0xfffff) {
+            sub_r(ARMRegisters::S0, base, OP2_IMM | (-offset >> 12) | (10 << 8));
+            dtr_d(isLoad, srcDst, ARMRegisters::S0, (-offset & 0xfff) | transferFlag);
         } else {
             moveImm(offset, ARMRegisters::S0);
         } else {
             moveImm(offset, ARMRegisters::S0);
-            dtr_dr(isLoad, srcDst, base, ARMRegisters::S0 | transferFlag);
+            dtr_ur(isLoad, srcDst, base, ARMRegisters::S0 | transferFlag);
         }
     }
 }
 
         }
     }
 }
 
-void ARMAssembler::baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset)
+void ARMAssembler::baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset, bool bytes)
 {
     ARMWord op2;
 {
     ARMWord op2;
+    ARMWord transferFlag = bytes ? DT_BYTE : 0;
 
     ASSERT(scale >= 0 && scale <= 3);
     op2 = lsl(index, scale);
 
     if (offset >= 0 && offset <= 0xfff) {
         add_r(ARMRegisters::S0, base, op2);
 
     ASSERT(scale >= 0 && scale <= 3);
     op2 = lsl(index, scale);
 
     if (offset >= 0 && offset <= 0xfff) {
         add_r(ARMRegisters::S0, base, op2);
-        dtr_u(isLoad, srcDst, ARMRegisters::S0, offset);
+        dtr_u(isLoad, srcDst, ARMRegisters::S0, offset | transferFlag);
         return;
     }
     if (offset <= 0 && offset >= -0xfff) {
         add_r(ARMRegisters::S0, base, op2);
         return;
     }
     if (offset <= 0 && offset >= -0xfff) {
         add_r(ARMRegisters::S0, base, op2);
-        dtr_d(isLoad, srcDst, ARMRegisters::S0, -offset);
+        dtr_d(isLoad, srcDst, ARMRegisters::S0, (-offset & 0xfff) | transferFlag);
         return;
     }
 
     ldr_un_imm(ARMRegisters::S0, offset);
     add_r(ARMRegisters::S0, ARMRegisters::S0, op2);
         return;
     }
 
     ldr_un_imm(ARMRegisters::S0, offset);
     add_r(ARMRegisters::S0, ARMRegisters::S0, op2);
-    dtr_ur(isLoad, srcDst, base, ARMRegisters::S0);
+    dtr_ur(isLoad, srcDst, base, ARMRegisters::S0 | transferFlag);
 }
 
 void ARMAssembler::doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset)
 {
 }
 
 void ARMAssembler::doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset)
 {
-    if (offset & 0x3) {
+    // VFP cannot directly access memory that is not four-byte-aligned
+    if (!(offset & 0x3)) {
         if (offset <= 0x3ff && offset >= 0) {
             fdtr_u(isLoad, srcDst, base, offset >> 2);
             return;
         if (offset <= 0x3ff && offset >= 0) {
             fdtr_u(isLoad, srcDst, base, offset >> 2);
             return;
@@ -343,14 +344,15 @@ 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(JSGlobalData& globalData, ExecutablePool* allocator)
+PassRefPtr<ExecutableMemoryHandle> ARMAssembler::executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort)
 {
     // 64-bit alignment is required for next constant pool and JIT code as well
     m_buffer.flushWithoutBarrier(true);
     if (!m_buffer.isAligned(8))
         bkpt(0);
 
 {
     // 64-bit alignment is required for next constant pool and JIT code as well
     m_buffer.flushWithoutBarrier(true);
     if (!m_buffer.isAligned(8))
         bkpt(0);
 
-    char* data = reinterpret_cast<char*>(m_buffer.executableCopy(globalData, allocator));
+    RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData, ownerUID, effort);
+    char* data = reinterpret_cast<char*>(result->start());
 
     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.
@@ -370,9 +372,26 @@ void* ARMAssembler::executableCopy(JSGlobalData& globalData, ExecutablePool* all
         }
     }
 
         }
     }
 
-    return data;
+    return result;
 }
 
 }
 
+#if OS(LINUX) && COMPILER(RVCT)
+
+__asm void ARMAssembler::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
+
 } // namespace JSC
 
 #endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
 } // namespace JSC
 
 #endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
index 1a216fecefc3b5b339de97c98668358c61617632..dc2e557a33ed3a2fbb550dc252f4cda3a3da1dda 100644 (file)
@@ -30,6 +30,7 @@
 #if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
 
 #include "AssemblerBufferWithConstantPool.h"
 #if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
 
 #include "AssemblerBufferWithConstantPool.h"
+#include "JITCompilationEffort.h"
 #include <wtf/Assertions.h>
 namespace JSC {
 
 #include <wtf/Assertions.h>
 namespace JSC {
 
@@ -161,7 +162,6 @@ namespace JSC {
             VMOV_ARM = 0x0e100a10,
             VCVT_F64_S32 = 0x0eb80bc0,
             VCVT_S32_F64 = 0x0ebd0b40,
             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,
             VMRS_APSR = 0x0ef1fa10,
 #if WTF_ARM_ARCH_AT_LEAST(5)
             CLZ = 0x016f0f10,
@@ -173,6 +173,7 @@ namespace JSC {
             MOVW = 0x03000000,
             MOVT = 0x03400000,
 #endif
             MOVW = 0x03000000,
             MOVT = 0x03400000,
 #endif
+            NOP = 0xe1a00000,
         };
 
         enum {
         };
 
         enum {
@@ -545,12 +546,6 @@ namespace JSC {
             emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_S32_F64, (sd >> 1), 0, dm);
         }
 
             emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_S32_F64, (sd >> 1), 0, dm);
         }
 
-        void vcvtr_s32_f64_r(int sd, int dm, Condition cc = AL)
-        {
-            ASSERT(!(sd & 0x1)); // sd must be divisible by 2
-            emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVTR_S32_F64, (sd >> 1), 0, dm);
-        }
-
         void vmrs_apsr(Condition cc = AL)
         {
             m_buffer.putInt(static_cast<ARMWord>(cc) | VMRS_APSR);
         void vmrs_apsr(Condition cc = AL)
         {
             m_buffer.putInt(static_cast<ARMWord>(cc) | VMRS_APSR);
@@ -578,6 +573,11 @@ namespace JSC {
             m_buffer.putInt(OP_NOP_T2);
         }
 
             m_buffer.putInt(OP_NOP_T2);
         }
 
+        void nop()
+        {
+            m_buffer.putInt(NOP);
+        }
+
         void bx(int rm, Condition cc = AL)
         {
 #if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__)
         void bx(int rm, Condition cc = AL)
         {
 #if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__)
@@ -686,11 +686,9 @@ namespace JSC {
             return loadBranchTarget(ARMRegisters::pc, cc, useConstantPool);
         }
 
             return loadBranchTarget(ARMRegisters::pc, cc, useConstantPool);
         }
 
-        void* executableCopy(JSGlobalData&, ExecutablePool* allocator);
+        PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData&, void* ownerUID, JITCompilationEffort);
 
 
-#ifndef NDEBUG
         unsigned debugOffset() { return m_buffer.debugOffset(); }
         unsigned debugOffset() { return m_buffer.debugOffset(); }
-#endif
 
         // Patching helpers
 
 
         // Patching helpers
 
@@ -743,8 +741,8 @@ namespace JSC {
         static void* readPointer(void* from)
         {
             ARMWord* insn = reinterpret_cast<ARMWord*>(from);
         static void* readPointer(void* from)
         {
             ARMWord* insn = reinterpret_cast<ARMWord*>(from);
-            void* addr = reinterpret_cast<void*>(getLdrImmAddress(insn));
-            return *addr;
+            ARMWord* addr = getLdrImmAddress(insn);
+            return *reinterpret_cast<void**>(addr);
         }
         
         // Patch pointers
         }
         
         // Patch pointers
@@ -802,6 +800,11 @@ namespace JSC {
             patchPointerInternal(getAbsoluteJumpAddress(from), to);
         }
 
             patchPointerInternal(getAbsoluteJumpAddress(from), to);
         }
 
+        static void* readCallTarget(void* from)
+        {
+            return reinterpret_cast<void*>(readPointer(reinterpret_cast<void*>(getAbsoluteJumpAddress(from))));
+        }
+
         // Address operations
 
         static void* getRelocatedAddress(void* code, AssemblerLabel label)
         // Address operations
 
         static void* getRelocatedAddress(void* code, AssemblerLabel label)
@@ -855,7 +858,7 @@ namespace JSC {
         // 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);
-        void baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset);
+        void baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset, bool bytes = false);
         void doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset);
 
         // Constant pool hnadlers
         void doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset);
 
         // Constant pool hnadlers
@@ -867,6 +870,42 @@ namespace JSC {
             return AL | B | (offset & BRANCH_MASK);
         }
 
             return AL | B | (offset & BRANCH_MASK);
         }
 
+#if OS(LINUX) && COMPILER(RVCT)
+        static __asm void cacheFlush(void* code, size_t);
+#else
+        static void cacheFlush(void* code, size_t size)
+        {
+#if OS(LINUX) && COMPILER(GCC)
+            uintptr_t currentPage = reinterpret_cast<uintptr_t>(code) & ~(pageSize() - 1);
+            uintptr_t lastPage = (reinterpret_cast<uintptr_t>(code) + size) & ~(pageSize() - 1);
+            do {
+                asm volatile(
+                    "push    {r7}\n"
+                    "mov     r0, %0\n"
+                    "mov     r1, %1\n"
+                    "mov     r7, #0xf0000\n"
+                    "add     r7, r7, #0x2\n"
+                    "mov     r2, #0x0\n"
+                    "svc     0x0\n"
+                    "pop     {r7}\n"
+                    :
+                    : "r" (currentPage), "r" (currentPage + pageSize())
+                    : "r0", "r1", "r2");
+                currentPage += pageSize();
+            } while (lastPage >= currentPage);
+#elif OS(WINCE)
+            CacheRangeFlush(code, size, CACHE_SYNC_ALL);
+#elif OS(QNX) && ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+            UNUSED_PARAM(code);
+            UNUSED_PARAM(size);
+#elif OS(QNX)
+            msync(code, size, MS_INVALIDATE_ICACHE);
+#else
+#error "The cacheFlush support is missing on this platform."
+#endif
+        }
+#endif
+
     private:
         ARMWord RM(int reg)
         {
     private:
         ARMWord RM(int reg)
         {
index f5101c76b7e44c2f6f894a4958824a76a0e0fb3c..a8b55d182d669766041249f19d4d067276956cc9 100644 (file)
@@ -414,11 +414,6 @@ private:
 
 class ARMv7Assembler {
 public:
 
 class ARMv7Assembler {
 public:
-    ~ARMv7Assembler()
-    {
-        ASSERT(m_jumpsToLink.isEmpty());
-    }
-
     typedef ARMRegisters::RegisterID RegisterID;
     typedef ARMRegisters::FPSingleRegisterID FPSingleRegisterID;
     typedef ARMRegisters::FPDoubleRegisterID FPDoubleRegisterID;
     typedef ARMRegisters::RegisterID RegisterID;
     typedef ARMRegisters::FPSingleRegisterID FPSingleRegisterID;
     typedef ARMRegisters::FPDoubleRegisterID FPDoubleRegisterID;
@@ -467,26 +462,40 @@ public:
     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)
-            : m_from(from)
-            , m_to(to)
-            , m_type(type)
-            , m_linkType(LinkInvalid)
-            , m_condition(condition)
         {
         {
+            data.realTypes.m_from = from;
+            data.realTypes.m_to = to;
+            data.realTypes.m_type = type;
+            data.realTypes.m_linkType = LinkInvalid;
+            data.realTypes.m_condition = condition;
         }
         }
-        intptr_t from() const { return m_from; }
-        void setFrom(intptr_t from) { m_from = from; }
-        intptr_t to() const { return m_to; }
-        JumpType type() const { return m_type; }
-        JumpLinkType linkType() const { return m_linkType; }
-        void setLinkType(JumpLinkType linkType) { ASSERT(m_linkType == LinkInvalid); m_linkType = linkType; }
-        Condition condition() const { return m_condition; }
+        void operator=(const LinkRecord& other)
+        {
+            data.copyTypes.content[0] = other.data.copyTypes.content[0];
+            data.copyTypes.content[1] = other.data.copyTypes.content[1];
+            data.copyTypes.content[2] = other.data.copyTypes.content[2];
+        }
+        intptr_t from() const { return data.realTypes.m_from; }
+        void setFrom(intptr_t from) { data.realTypes.m_from = from; }
+        intptr_t to() const { return data.realTypes.m_to; }
+        JumpType type() const { return data.realTypes.m_type; }
+        JumpLinkType linkType() const { return data.realTypes.m_linkType; }
+        void setLinkType(JumpLinkType linkType) { ASSERT(data.realTypes.m_linkType == LinkInvalid); data.realTypes.m_linkType = linkType; }
+        Condition condition() const { return data.realTypes.m_condition; }
     private:
     private:
-        intptr_t m_from : 31;
-        intptr_t m_to : 31;
-        JumpType m_type : 8;
-        JumpLinkType m_linkType : 8;
-        Condition m_condition : 16;
+        union {
+            struct RealTypes {
+                intptr_t m_from : 31;
+                intptr_t m_to : 31;
+                JumpType m_type : 8;
+                JumpLinkType m_linkType : 8;
+                Condition m_condition : 16;
+            } realTypes;
+            struct CopyTypes {
+                uint32_t content[3];
+            } copyTypes;
+            COMPILE_ASSERT(sizeof(RealTypes) == sizeof(CopyTypes), LinkRecordCopyStructSizeEqualsRealStruct);
+        } data;
     };
 
 private:
     };
 
 private:
@@ -534,12 +543,18 @@ private:
         OP_BLX              = 0x4700,
         OP_BX               = 0x4700,
         OP_STR_reg_T1       = 0x5000,
         OP_BLX              = 0x4700,
         OP_BX               = 0x4700,
         OP_STR_reg_T1       = 0x5000,
+        OP_STRH_reg_T1      = 0x5200,
+        OP_STRB_reg_T1      = 0x5400,
+        OP_LDRSB_reg_T1     = 0x5600,
         OP_LDR_reg_T1       = 0x5800,
         OP_LDRH_reg_T1      = 0x5A00,
         OP_LDRB_reg_T1      = 0x5C00,
         OP_LDR_reg_T1       = 0x5800,
         OP_LDRH_reg_T1      = 0x5A00,
         OP_LDRB_reg_T1      = 0x5C00,
+        OP_LDRSH_reg_T1     = 0x5E00,
         OP_STR_imm_T1       = 0x6000,
         OP_LDR_imm_T1       = 0x6800,
         OP_STR_imm_T1       = 0x6000,
         OP_LDR_imm_T1       = 0x6800,
+        OP_STRB_imm_T1      = 0x7000,
         OP_LDRB_imm_T1      = 0x7800,
         OP_LDRB_imm_T1      = 0x7800,
+        OP_STRH_imm_T1      = 0x8000,
         OP_LDRH_imm_T1      = 0x8800,
         OP_STR_imm_T2       = 0x9000,
         OP_LDR_imm_T2       = 0x9800,
         OP_LDRH_imm_T1      = 0x8800,
         OP_STR_imm_T2       = 0x9000,
         OP_LDR_imm_T2       = 0x9800,
@@ -569,18 +584,28 @@ private:
         OP_SUB_reg_T2   = 0xEBA0,
         OP_SUB_S_reg_T2 = 0xEBB0,
         OP_CMP_reg_T2   = 0xEBB0,
         OP_SUB_reg_T2   = 0xEBA0,
         OP_SUB_S_reg_T2 = 0xEBB0,
         OP_CMP_reg_T2   = 0xEBB0,
+        OP_VMOV_CtoD    = 0xEC00,
+        OP_VMOV_DtoC    = 0xEC10,
+        OP_FSTS         = 0xED00,
         OP_VSTR         = 0xED00,
         OP_VSTR         = 0xED00,
+        OP_FLDS         = 0xED10,
         OP_VLDR         = 0xED10,
         OP_VLDR         = 0xED10,
-        OP_VMOV_StoC    = 0xEE00,
-        OP_VMOV_CtoS    = 0xEE10,
+        OP_VMOV_CtoS    = 0xEE00,
+        OP_VMOV_StoC    = 0xEE10,
         OP_VMUL_T2      = 0xEE20,
         OP_VADD_T2      = 0xEE30,
         OP_VSUB_T2      = 0xEE30,
         OP_VDIV         = 0xEE80,
         OP_VMUL_T2      = 0xEE20,
         OP_VADD_T2      = 0xEE30,
         OP_VSUB_T2      = 0xEE30,
         OP_VDIV         = 0xEE80,
+        OP_VABS_T2      = 0xEEB0,
         OP_VCMP         = 0xEEB0,
         OP_VCVT_FPIVFP  = 0xEEB0,
         OP_VCMP         = 0xEEB0,
         OP_VCVT_FPIVFP  = 0xEEB0,
+        OP_VMOV_T2      = 0xEEB0,
         OP_VMOV_IMM_T2  = 0xEEB0,
         OP_VMRS         = 0xEEB0,
         OP_VMOV_IMM_T2  = 0xEEB0,
         OP_VMRS         = 0xEEB0,
+        OP_VNEG_T2      = 0xEEB0,
+        OP_VSQRT_T1     = 0xEEB0,
+        OP_VCVTSD_T1    = 0xEEB0,
+        OP_VCVTDS_T1    = 0xEEB0,
         OP_B_T3a        = 0xF000,
         OP_B_T4a        = 0xF000,
         OP_AND_imm_T1   = 0xF000,
         OP_B_T3a        = 0xF000,
         OP_B_T4a        = 0xF000,
         OP_AND_imm_T1   = 0xF000,
@@ -592,27 +617,38 @@ private:
         OP_ADD_imm_T3   = 0xF100,
         OP_ADD_S_imm_T3 = 0xF110,
         OP_CMN_imm      = 0xF110,
         OP_ADD_imm_T3   = 0xF100,
         OP_ADD_S_imm_T3 = 0xF110,
         OP_CMN_imm      = 0xF110,
+        OP_ADC_imm      = 0xF140,
         OP_SUB_imm_T3   = 0xF1A0,
         OP_SUB_S_imm_T3 = 0xF1B0,
         OP_CMP_imm_T2   = 0xF1B0,
         OP_RSB_imm_T2   = 0xF1C0,
         OP_SUB_imm_T3   = 0xF1A0,
         OP_SUB_S_imm_T3 = 0xF1B0,
         OP_CMP_imm_T2   = 0xF1B0,
         OP_RSB_imm_T2   = 0xF1C0,
+        OP_RSB_S_imm_T2 = 0xF1D0,
         OP_ADD_imm_T4   = 0xF200,
         OP_MOV_imm_T3   = 0xF240,
         OP_SUB_imm_T4   = 0xF2A0,
         OP_MOVT         = 0xF2C0,
         OP_ADD_imm_T4   = 0xF200,
         OP_MOV_imm_T3   = 0xF240,
         OP_SUB_imm_T4   = 0xF2A0,
         OP_MOVT         = 0xF2C0,
+        OP_UBFX_T1      = 0xF3C0,
         OP_NOP_T2a      = 0xF3AF,
         OP_NOP_T2a      = 0xF3AF,
+        OP_STRB_imm_T3  = 0xF800,
+        OP_STRB_reg_T2  = 0xF800,
         OP_LDRB_imm_T3  = 0xF810,
         OP_LDRB_reg_T2  = 0xF810,
         OP_LDRB_imm_T3  = 0xF810,
         OP_LDRB_reg_T2  = 0xF810,
+        OP_STRH_imm_T3  = 0xF820,
+        OP_STRH_reg_T2  = 0xF820,
         OP_LDRH_reg_T2  = 0xF830,
         OP_LDRH_imm_T3  = 0xF830,
         OP_STR_imm_T4   = 0xF840,
         OP_STR_reg_T2   = 0xF840,
         OP_LDR_imm_T4   = 0xF850,
         OP_LDR_reg_T2   = 0xF850,
         OP_LDRH_reg_T2  = 0xF830,
         OP_LDRH_imm_T3  = 0xF830,
         OP_STR_imm_T4   = 0xF840,
         OP_STR_reg_T2   = 0xF840,
         OP_LDR_imm_T4   = 0xF850,
         OP_LDR_reg_T2   = 0xF850,
+        OP_STRB_imm_T2  = 0xF880,
         OP_LDRB_imm_T2  = 0xF890,
         OP_LDRB_imm_T2  = 0xF890,
+        OP_STRH_imm_T2  = 0xF8A0,
         OP_LDRH_imm_T2  = 0xF8B0,
         OP_STR_imm_T3   = 0xF8C0,
         OP_LDR_imm_T3   = 0xF8D0,
         OP_LDRH_imm_T2  = 0xF8B0,
         OP_STR_imm_T3   = 0xF8C0,
         OP_LDR_imm_T3   = 0xF8D0,
+        OP_LDRSB_reg_T2 = 0xF910,
+        OP_LDRSH_reg_T2 = 0xF930,
         OP_LSL_reg_T2   = 0xFA00,
         OP_LSR_reg_T2   = 0xFA20,
         OP_ASR_reg_T2   = 0xFA40,
         OP_LSL_reg_T2   = 0xFA00,
         OP_LSR_reg_T2   = 0xFA20,
         OP_ASR_reg_T2   = 0xFA40,
@@ -624,16 +660,26 @@ private:
     typedef enum {
         OP_VADD_T2b     = 0x0A00,
         OP_VDIVb        = 0x0A00,
     typedef enum {
         OP_VADD_T2b     = 0x0A00,
         OP_VDIVb        = 0x0A00,
+        OP_FLDSb        = 0x0A00,
         OP_VLDRb        = 0x0A00,
         OP_VMOV_IMM_T2b = 0x0A00,
         OP_VLDRb        = 0x0A00,
         OP_VMOV_IMM_T2b = 0x0A00,
+        OP_VMOV_T2b     = 0x0A40,
         OP_VMUL_T2b     = 0x0A00,
         OP_VMUL_T2b     = 0x0A00,
+        OP_FSTSb        = 0x0A00,
         OP_VSTRb        = 0x0A00,
         OP_VSTRb        = 0x0A00,
-        OP_VMOV_CtoSb   = 0x0A10,
         OP_VMOV_StoCb   = 0x0A10,
         OP_VMOV_StoCb   = 0x0A10,
+        OP_VMOV_CtoSb   = 0x0A10,
+        OP_VMOV_DtoCb   = 0x0A10,
+        OP_VMOV_CtoDb   = 0x0A10,
         OP_VMRSb        = 0x0A10,
         OP_VMRSb        = 0x0A10,
+        OP_VABS_T2b     = 0x0A40,
         OP_VCMPb        = 0x0A40,
         OP_VCVT_FPIVFPb = 0x0A40,
         OP_VCMPb        = 0x0A40,
         OP_VCVT_FPIVFPb = 0x0A40,
+        OP_VNEG_T2b     = 0x0A40,
         OP_VSUB_T2b     = 0x0A40,
         OP_VSUB_T2b     = 0x0A40,
+        OP_VSQRT_T1b    = 0x0A40,
+        OP_VCVTSD_T1b   = 0x0A40,
+        OP_VCVTDS_T1b   = 0x0A40,
         OP_NOP_T2b      = 0x8000,
         OP_B_T3b        = 0x8000,
         OP_B_T4b        = 0x9000,
         OP_NOP_T2b      = 0x8000,
         OP_B_T3b        = 0x8000,
         OP_B_T4b        = 0x9000,
@@ -699,6 +745,17 @@ private:
 
 public:
     
 
 public:
     
+    void adc(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+    {
+        // Rd can only be SP if Rn is also SP.
+        ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
+        ASSERT(rd != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
+        ASSERT(imm.isEncodedImm());
+
+        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADC_imm, rn, rd, imm);
+    }
+
     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
     void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
@@ -708,6 +765,7 @@ public:
         ASSERT(imm.isValid());
 
         if (rn == ARMRegisters::sp) {
         ASSERT(imm.isValid());
 
         if (rn == ARMRegisters::sp) {
+            ASSERT(!(imm.getUInt16() & 3));
             if (!(rd & 8) && imm.isUInt10()) {
                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, static_cast<uint8_t>(imm.getUInt10() >> 2));
                 return;
             if (!(rd & 8) && imm.isUInt10()) {
                 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, static_cast<uint8_t>(imm.getUInt10() >> 2));
                 return;
@@ -860,7 +918,7 @@ public:
         return m_formatter.label();
     }
 
         return m_formatter.label();
     }
 
-    void bkpt(uint8_t imm=0)
+    void bkpt(uint8_t imm = 0)
     {
         m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
     }
     {
         m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
     }
@@ -1126,6 +1184,30 @@ public:
         else
             m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
     }
         else
             m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
     }
+    
+    void ldrsb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
+    {
+        ASSERT(rn != ARMRegisters::pc);
+        ASSERT(!BadReg(rm));
+        ASSERT(shift <= 3);
+        
+        if (!shift && !((rt | rn | rm) & 8))
+            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRSB_reg_T1, rm, rn, rt);
+        else
+            m_formatter.twoWordOp12Reg4FourFours(OP_LDRSB_reg_T2, rn, FourFours(rt, 0, shift, rm));
+    }
+
+    void ldrsh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
+    {
+        ASSERT(rn != ARMRegisters::pc);
+        ASSERT(!BadReg(rm));
+        ASSERT(shift <= 3);
+        
+        if (!shift && !((rt | rn | rm) & 8))
+            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRSH_reg_T1, rm, rn, rt);
+        else
+            m_formatter.twoWordOp12Reg4FourFours(OP_LDRSH_reg_T2, rn, FourFours(rt, 0, shift, rm));
+    }
 
     void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
     {
 
     void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount)
     {
@@ -1353,6 +1435,124 @@ 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));
     }
 
+    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
+    ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
+    {
+        ASSERT(rt != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
+        ASSERT(imm.isUInt12());
+
+        if (!((rt | rn) & 8) && imm.isUInt7())
+            m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STRB_imm_T1, imm.getUInt7() >> 2, rn, rt);
+        else
+            m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRB_imm_T2, rn, rt, imm.getUInt12());
+    }
+
+    // If index is set, this is a regular offset or a pre-indexed store;
+    // if index is not set then is is a post-index store.
+    //
+    // If wback is set rn is updated - this is a pre or post index store,
+    // if wback is not set this is a regular offset memory access.
+    //
+    // (-255 <= offset <= 255)
+    // _reg = REG[rn]
+    // _tmp = _reg + offset
+    // MEM[index ? _tmp : _reg] = REG[rt]
+    // if (wback) REG[rn] = _tmp
+    ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
+    {
+        ASSERT(rt != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
+        ASSERT(index || wback);
+        ASSERT(!wback | (rt != rn));
+    
+        bool add = true;
+        if (offset < 0) {
+            add = false;
+            offset = -offset;
+        }
+        ASSERT((offset & ~0xff) == 0);
+        
+        offset |= (wback << 8);
+        offset |= (add   << 9);
+        offset |= (index << 10);
+        offset |= (1 << 11);
+        
+        m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRB_imm_T3, rn, rt, offset);
+    }
+
+    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
+    ALWAYS_INLINE void strb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
+    {
+        ASSERT(rn != ARMRegisters::pc);
+        ASSERT(!BadReg(rm));
+        ASSERT(shift <= 3);
+
+        if (!shift && !((rt | rn | rm) & 8))
+            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STRB_reg_T1, rm, rn, rt);
+        else
+            m_formatter.twoWordOp12Reg4FourFours(OP_STRB_reg_T2, rn, FourFours(rt, 0, shift, rm));
+    }
+    
+    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
+    ALWAYS_INLINE void strh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
+    {
+        ASSERT(rt != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
+        ASSERT(imm.isUInt12());
+        
+        if (!((rt | rn) & 8) && imm.isUInt7())
+            m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STRH_imm_T1, imm.getUInt7() >> 2, rn, rt);
+        else
+            m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRH_imm_T2, rn, rt, imm.getUInt12());
+    }
+    
+    // If index is set, this is a regular offset or a pre-indexed store;
+    // if index is not set then is is a post-index store.
+    //
+    // If wback is set rn is updated - this is a pre or post index store,
+    // if wback is not set this is a regular offset memory access.
+    //
+    // (-255 <= offset <= 255)
+    // _reg = REG[rn]
+    // _tmp = _reg + offset
+    // MEM[index ? _tmp : _reg] = REG[rt]
+    // if (wback) REG[rn] = _tmp
+    ALWAYS_INLINE void strh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
+    {
+        ASSERT(rt != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
+        ASSERT(index || wback);
+        ASSERT(!wback | (rt != rn));
+        
+        bool add = true;
+        if (offset < 0) {
+            add = false;
+            offset = -offset;
+        }
+        ASSERT(!(offset & ~0xff));
+        
+        offset |= (wback << 8);
+        offset |= (add   << 9);
+        offset |= (index << 10);
+        offset |= (1 << 11);
+        
+        m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STRH_imm_T3, rn, rt, offset);
+    }
+    
+    // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
+    ALWAYS_INLINE void strh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
+    {
+        ASSERT(rn != ARMRegisters::pc);
+        ASSERT(!BadReg(rm));
+        ASSERT(shift <= 3);
+        
+        if (!shift && !((rt | rn | rm) & 8))
+            m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STRH_reg_T1, rm, rn, rt);
+        else
+            m_formatter.twoWordOp12Reg4FourFours(OP_STRH_reg_T2, rn, FourFours(rt, 0, shift, rm));
+    }
+
     ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
     ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
@@ -1362,6 +1562,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()) {
+            ASSERT(!(imm.getUInt16() & 3));
             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
             return;
         } else if (!((rd | rn) & 8)) {
             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
             return;
         } else if (!((rd | rn) & 8)) {
@@ -1423,6 +1624,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()) {
+            ASSERT(!(imm.getUInt16() & 3));
             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
             return;
         } else if (!((rd | rn) & 8)) {
             m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
             return;
         } else if (!((rd | rn) & 8)) {
@@ -1438,6 +1640,16 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
     }
 
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm);
     }
 
+    ALWAYS_INLINE void sub_S(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
+    {
+        ASSERT(rd != ARMRegisters::pc);
+        ASSERT(rn != ARMRegisters::pc);
+        ASSERT(imm.isValid());
+        ASSERT(imm.isUInt12());
+
+        m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_S_imm_T2, rn, rd, imm);
+    }
+
     // Not allowed in an IT (if then) block?
     ALWAYS_INLINE void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
     // Not allowed in an IT (if then) block?
     ALWAYS_INLINE void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
@@ -1480,34 +1692,48 @@ public:
             m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
     }
 
             m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn);
     }
 
-    void vadd_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
+    ALWAYS_INLINE void ubfx(RegisterID rd, RegisterID rn, unsigned lsb, unsigned width)
+    {
+        ASSERT(lsb < 32);
+        ASSERT((width >= 1) && (width <= 32));
+        ASSERT((lsb + width) <= 32);
+        m_formatter.twoWordOp12Reg40Imm3Reg4Imm20Imm5(OP_UBFX_T1, rd, rn, (lsb & 0x1c) << 10, (lsb & 0x3) << 6, (width - 1) & 0x1f);
+    }
+
+    void vadd(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
     {
         m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm);
     }
 
     {
         m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm);
     }
 
-    void vcmp_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
+    void vcmp(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
     {
         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(4), rd, rm);
     }
 
     {
         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(4), rd, rm);
     }
 
-    void vcmpz_F64(FPDoubleRegisterID rd)
+    void vcmpz(FPDoubleRegisterID rd)
     {
         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0));
     }
 
     {
         m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0));
     }
 
-    void vcvt_F64_S32(FPDoubleRegisterID rd, FPSingleRegisterID rm)
+    void vcvt_signedToFloatingPoint(FPDoubleRegisterID rd, FPSingleRegisterID rm)
     {
         // boolean values are 64bit (toInt, unsigned, roundZero)
         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm);
     }
 
     {
         // boolean values are 64bit (toInt, unsigned, roundZero)
         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm);
     }
 
-    void vcvtr_S32_F64(FPSingleRegisterID rd, FPDoubleRegisterID rm)
+    void vcvt_floatingPointToSigned(FPSingleRegisterID rd, FPDoubleRegisterID rm)
     {
         // boolean values are 64bit (toInt, unsigned, roundZero)
         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, false, true), rd, rm);
     }
     {
         // boolean values are 64bit (toInt, unsigned, roundZero)
         m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, false, true), rd, rm);
     }
+    
+    void vcvt_floatingPointToUnsigned(FPSingleRegisterID rd, FPDoubleRegisterID rm)
+    {
+        // boolean values are 64bit (toInt, unsigned, roundZero)
+        m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, true, true), rd, rm);
+    }
 
 
-    void vdiv_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
+    void vdiv(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
     {
         m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm);
     }
     {
         m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm);
     }
@@ -1516,17 +1742,41 @@ public:
     {
         m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm);
     }
     {
         m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm);
     }
+    
+    void flds(FPSingleRegisterID rd, RegisterID rn, int32_t imm)
+    {
+        m_formatter.vfpMemOp(OP_FLDS, OP_FLDSb, false, rn, rd, imm);
+    }
 
     void vmov(RegisterID rd, FPSingleRegisterID rn)
     {
         ASSERT(!BadReg(rd));
 
     void vmov(RegisterID rd, FPSingleRegisterID rn)
     {
         ASSERT(!BadReg(rd));
-        m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rn, rd, VFPOperand(0));
+        m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rn, rd, VFPOperand(0));
     }
 
     void vmov(FPSingleRegisterID rd, RegisterID rn)
     {
         ASSERT(!BadReg(rn));
     }
 
     void vmov(FPSingleRegisterID rd, RegisterID rn)
     {
         ASSERT(!BadReg(rn));
-        m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rd, rn, VFPOperand(0));
+        m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rd, rn, VFPOperand(0));
+    }
+
+    void vmov(RegisterID rd1, RegisterID rd2, FPDoubleRegisterID rn)
+    {
+        ASSERT(!BadReg(rd1));
+        ASSERT(!BadReg(rd2));
+        m_formatter.vfpOp(OP_VMOV_DtoC, OP_VMOV_DtoCb, true, rd2, VFPOperand(rd1 | 16), rn);
+    }
+
+    void vmov(FPDoubleRegisterID rd, RegisterID rn1, RegisterID rn2)
+    {
+        ASSERT(!BadReg(rn1));
+        ASSERT(!BadReg(rn2));
+        m_formatter.vfpOp(OP_VMOV_CtoD, OP_VMOV_CtoDb, true, rn2, VFPOperand(rn1 | 16), rd);
+    }
+
+    void vmov(FPDoubleRegisterID rd, FPDoubleRegisterID rn)
+    {
+        m_formatter.vfpOp(OP_VMOV_T2, OP_VMOV_T2b, true, VFPOperand(0), rd, rn);
     }
 
     void vmrs(RegisterID reg = ARMRegisters::pc)
     }
 
     void vmrs(RegisterID reg = ARMRegisters::pc)
@@ -1535,7 +1785,7 @@ public:
         m_formatter.vfpOp(OP_VMRS, OP_VMRSb, false, VFPOperand(1), VFPOperand(0x10 | reg), VFPOperand(0));
     }
 
         m_formatter.vfpOp(OP_VMRS, OP_VMRSb, false, VFPOperand(1), VFPOperand(0x10 | reg), VFPOperand(0));
     }
 
-    void vmul_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
+    void vmul(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
     {
         m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm);
     }
     {
         m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm);
     }
@@ -1545,11 +1795,41 @@ public:
         m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm);
     }
 
         m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm);
     }
 
-    void vsub_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
+    void fsts(FPSingleRegisterID rd, RegisterID rn, int32_t imm)
+    {
+        m_formatter.vfpMemOp(OP_FSTS, OP_FSTSb, false, rn, rd, imm);
+    }
+
+    void vsub(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
     {
         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);
     }
 
+    void vabs(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
+    {
+        m_formatter.vfpOp(OP_VABS_T2, OP_VABS_T2b, true, VFPOperand(16), rd, rm);
+    }
+
+    void vneg(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
+    {
+        m_formatter.vfpOp(OP_VNEG_T2, OP_VNEG_T2b, true, VFPOperand(1), rd, rm);
+    }
+
+    void vsqrt(FPDoubleRegisterID rd, FPDoubleRegisterID rm)
+    {
+        m_formatter.vfpOp(OP_VSQRT_T1, OP_VSQRT_T1b, true, VFPOperand(17), rd, rm);
+    }
+    
+    void vcvtds(FPDoubleRegisterID rd, FPSingleRegisterID rm)
+    {
+        m_formatter.vfpOp(OP_VCVTDS_T1, OP_VCVTDS_T1b, false, VFPOperand(23), rd, rm);
+    }
+
+    void vcvtsd(FPSingleRegisterID rd, FPDoubleRegisterID rm)
+    {
+        m_formatter.vfpOp(OP_VCVTSD_T1, OP_VCVTSD_T1b, true, VFPOperand(23), rd, rm);
+    }
+
     void nop()
     {
         m_formatter.oneWordOp8Imm8(OP_NOP_T1, 0);
     void nop()
     {
         m_formatter.oneWordOp8Imm8(OP_NOP_T1, 0);
@@ -1620,29 +1900,29 @@ public:
         
         if (jumpType == JumpCondition) {
             // 2-byte conditional T1
         
         if (jumpType == JumpCondition) {
             // 2-byte conditional T1
-            const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT1)));
+            const uint16_t* jumpT1Location = reinterpret_cast_ptr<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 - JUMP_ENUM_SIZE(LinkJumpT3)));
+            const uint16_t* jumpT3Location = reinterpret_cast_ptr<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 - JUMP_ENUM_SIZE(LinkConditionalJumpT4)));
+            reinterpret_cast_ptr<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 - JUMP_ENUM_SIZE(LinkJumpT2)));
+            const uint16_t* jumpT2Location = reinterpret_cast_ptr<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 - JUMP_ENUM_SIZE(LinkJumpT4)));
+            const uint16_t* jumpT4Location = reinterpret_cast_ptr<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;
@@ -1681,25 +1961,25 @@ public:
     {
         switch (record.linkType()) {
         case LinkJumpT1:
     {
         switch (record.linkType()) {
         case LinkJumpT1:
-            linkJumpT1(record.condition(), reinterpret_cast<uint16_t*>(from), to);
+            linkJumpT1(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to);
             break;
         case LinkJumpT2:
             break;
         case LinkJumpT2:
-            linkJumpT2(reinterpret_cast<uint16_t*>(from), to);
+            linkJumpT2(reinterpret_cast_ptr<uint16_t*>(from), to);
             break;
         case LinkJumpT3:
             break;
         case LinkJumpT3:
-            linkJumpT3(record.condition(), reinterpret_cast<uint16_t*>(from), to);
+            linkJumpT3(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to);
             break;
         case LinkJumpT4:
             break;
         case LinkJumpT4:
-            linkJumpT4(reinterpret_cast<uint16_t*>(from), to);
+            linkJumpT4(reinterpret_cast_ptr<uint16_t*>(from), to);
             break;
         case LinkConditionalJumpT4:
             break;
         case LinkConditionalJumpT4:
-            linkConditionalJumpT4(record.condition(), reinterpret_cast<uint16_t*>(from), to);
+            linkConditionalJumpT4(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to);
             break;
         case LinkConditionalBX:
             break;
         case LinkConditionalBX:
-            linkConditionalBX(record.condition(), reinterpret_cast<uint16_t*>(from), to);
+            linkConditionalBX(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to);
             break;
         case LinkBX:
             break;
         case LinkBX:
-            linkBX(reinterpret_cast<uint16_t*>(from), to);
+            linkBX(reinterpret_cast_ptr<uint16_t*>(from), to);
             break;
         default:
             ASSERT_NOT_REACHED();
             break;
         default:
             ASSERT_NOT_REACHED();
@@ -1760,7 +2040,7 @@ public:
 
         linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to);
 
 
         linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to);
 
-        ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
+        cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t));
     }
     
     static void relinkCall(void* from, void* to)
     }
     
     static void relinkCall(void* from, void* to)
@@ -1770,6 +2050,11 @@ public:
 
         setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
     }
 
         setPointer(reinterpret_cast<uint16_t*>(from) - 1, to);
     }
+    
+    static void* readCallTarget(void* from)
+    {
+        return readPointer(reinterpret_cast<uint16_t*>(from) - 1);
+    }
 
     static void repatchInt32(void* where, int32_t value)
     {
 
     static void repatchInt32(void* where, int32_t value)
     {
@@ -1797,6 +2082,39 @@ public:
         return reinterpret_cast<void*>(readInt32(where));
     }
 
         return reinterpret_cast<void*>(readInt32(where));
     }
 
+    unsigned debugOffset() { return m_formatter.debugOffset(); }
+
+    static void cacheFlush(void* code, size_t size)
+    {
+#if OS(IOS)
+        sys_cache_control(kCacheFunctionPrepareForExecution, code, size);
+#elif OS(LINUX)
+        asm volatile(
+            "push    {r7}\n"
+            "mov     r0, %0\n"
+            "mov     r1, %1\n"
+            "movw    r7, #0x2\n"
+            "movt    r7, #0xf\n"
+            "movs    r2, #0x0\n"
+            "svc     0x0\n"
+            "pop     {r7}\n"
+            :
+            : "r" (code), "r" (reinterpret_cast<char*>(code) + size)
+            : "r0", "r1", "r2");
+#elif OS(WINCE)
+        CacheRangeFlush(code, size, CACHE_SYNC_ALL);
+#elif OS(QNX)
+#if !ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+        msync(code, size, MS_INVALIDATE_ICACHE);
+#else
+        UNUSED_PARAM(code);
+        UNUSED_PARAM(size);
+#endif
+#else
+#error "The cacheFlush support is missing on this platform."
+#endif
+    }
+
 private:
     // VFP operations commonly take one or more 5-bit operands, typically representing a
     // floating point register number.  This will commonly be encoded in the instruction
 private:
     // VFP operations commonly take one or more 5-bit operands, typically representing a
     // floating point register number.  This will commonly be encoded in the instruction
@@ -1856,6 +2174,7 @@ private:
             if (isRoundZero)
                 op |= 0x10;
         } else {
             if (isRoundZero)
                 op |= 0x10;
         } else {
+            ASSERT(!isRoundZero);
             // 'op' field in instruction is isUnsigned
             if (!isUnsigned)
                 op |= 0x10;
             // 'op' field in instruction is isUnsigned
             if (!isUnsigned)
                 op |= 0x10;
@@ -1875,7 +2194,7 @@ private:
         location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
         location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
 
         location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
         location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16);
 
-        ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
+        cacheFlush(location - 4, 4 * sizeof(uint16_t));
     }
     
     static int32_t readInt32(void* code)
     }
     
     static int32_t readInt32(void* code)
@@ -1901,8 +2220,9 @@ private:
         ASSERT(imm.isValid());
         ASSERT(imm.isUInt7());
         uint16_t* location = reinterpret_cast<uint16_t*>(code);
         ASSERT(imm.isValid());
         ASSERT(imm.isUInt7());
         uint16_t* location = reinterpret_cast<uint16_t*>(code);
+        location[0] &= ~((static_cast<uint16_t>(0x7f) >> 2) << 6);
         location[0] |= (imm.getUInt7() >> 2) << 6;
         location[0] |= (imm.getUInt7() >> 2) << 6;
-        ExecutableAllocator::cacheFlush(location, sizeof(uint16_t));
+        cacheFlush(location, sizeof(uint16_t));
     }
 
     static void setPointer(void* code, void* value)
     }
 
     static void setPointer(void* code, void* value)
@@ -2247,6 +2567,12 @@ private:
             m_buffer.putShort((reg2 << 12) | imm);
         }
 
             m_buffer.putShort((reg2 << 12) | imm);
         }
 
+        ALWAYS_INLINE void twoWordOp12Reg40Imm3Reg4Imm20Imm5(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm1, uint16_t imm2, uint16_t imm3)
+        {
+            m_buffer.putShort(op | reg1);
+            m_buffer.putShort((imm1 << 12) | (reg2 << 8) | (imm2 << 6) | imm3);
+        }
+
         // Formats up instructions of the pattern:
         //    111111111B11aaaa:bbbb222SA2C2cccc
         // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit.
         // Formats up instructions of the pattern:
         //    111111111B11aaaa:bbbb222SA2C2cccc
         // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit.
@@ -2284,9 +2610,7 @@ private:
         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(); }
 
-#ifndef NDEBUG
         unsigned debugOffset() { return m_buffer.debugOffset(); }
         unsigned debugOffset() { return m_buffer.debugOffset(); }
-#endif
 
     private:
         AssemblerBuffer m_buffer;
 
     private:
         AssemblerBuffer m_buffer;
index 7d9d0925c5ee42931c3f7568eec49d7dda05049f..e7cc70fc5e2add38caa3eeb98b8ea65a1a2ef25b 100644 (file)
 #ifndef AbstractMacroAssembler_h
 #define AbstractMacroAssembler_h
 
 #ifndef AbstractMacroAssembler_h
 #define AbstractMacroAssembler_h
 
+#include "AssemblerBuffer.h"
 #include "CodeLocation.h"
 #include "MacroAssemblerCodeRef.h"
 #include "CodeLocation.h"
 #include "MacroAssemblerCodeRef.h"
+#include <wtf/CryptographicallyRandomNumber.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/UnusedParam.h>
 
 #if ENABLE(ASSEMBLER)
 
 #include <wtf/Noncopyable.h>
 #include <wtf/UnusedParam.h>
 
 #if ENABLE(ASSEMBLER)
 
+
+#if PLATFORM(QT)
+#define ENABLE_JIT_CONSTANT_BLINDING 0
+#endif
+
+#ifndef ENABLE_JIT_CONSTANT_BLINDING
+#define ENABLE_JIT_CONSTANT_BLINDING 1
+#endif
+
 namespace JSC {
 
 class LinkBuffer;
 class RepatchBuffer;
 namespace JSC {
 
 class LinkBuffer;
 class RepatchBuffer;
+namespace DFG {
+class CorrectableJumpPoint;
+}
 
 template <class AssemblerType>
 class AbstractMacroAssembler {
 
 template <class AssemblerType>
 class AbstractMacroAssembler {
@@ -161,6 +175,19 @@ public:
             : m_value(value)
         {
         }
             : m_value(value)
         {
         }
+        
+        // This is only here so that TrustedImmPtr(0) does not confuse the C++
+        // overload handling rules.
+        explicit TrustedImmPtr(int value)
+            : m_value(0)
+        {
+            ASSERT_UNUSED(value, !value);
+        }
+
+        explicit TrustedImmPtr(size_t value)
+            : m_value(reinterpret_cast<void*>(value))
+        {
+        }
 
         intptr_t asIntptr()
         {
 
         intptr_t asIntptr()
         {
@@ -170,11 +197,19 @@ public:
         const void* m_value;
     };
 
         const void* m_value;
     };
 
-    struct ImmPtr : public TrustedImmPtr {
+    struct ImmPtr : 
+#if ENABLE(JIT_CONSTANT_BLINDING)
+        private TrustedImmPtr 
+#else
+        public TrustedImmPtr
+#endif
+    {
         explicit ImmPtr(const void* value)
             : TrustedImmPtr(value)
         {
         }
         explicit ImmPtr(const void* value)
             : TrustedImmPtr(value)
         {
         }
+
+        TrustedImmPtr asTrustedImmPtr() { return *this; }
     };
 
     // TrustedImm32:
     };
 
     // TrustedImm32:
@@ -216,7 +251,13 @@ public:
     };
 
 
     };
 
 
-    struct Imm32 : public TrustedImm32 {
+    struct Imm32 : 
+#if ENABLE(JIT_CONSTANT_BLINDING)
+        private TrustedImm32 
+#else
+        public TrustedImm32
+#endif
+    {
         explicit Imm32(int32_t value)
             : TrustedImm32(value)
         {
         explicit Imm32(int32_t value)
             : TrustedImm32(value)
         {
@@ -227,6 +268,8 @@ public:
         {
         }
 #endif
         {
         }
 #endif
+        const TrustedImm32& asTrustedImm32() const { return *this; }
+
     };
     
     // Section 2: MacroAssembler code buffer handles
     };
     
     // Section 2: MacroAssembler code buffer handles
@@ -244,6 +287,7 @@ public:
     class Label {
         template<class TemplateAssemblerType>
         friend class AbstractMacroAssembler;
     class Label {
         template<class TemplateAssemblerType>
         friend class AbstractMacroAssembler;
+        friend class DFG::CorrectableJumpPoint;
         friend class Jump;
         friend class MacroAssemblerCodeRef;
         friend class LinkBuffer;
         friend class Jump;
         friend class MacroAssemblerCodeRef;
         friend class LinkBuffer;
@@ -362,7 +406,7 @@ public:
         }
         
         Call(AssemblerLabel jmp, Flags flags)
         }
         
         Call(AssemblerLabel jmp, Flags flags)
-            : m_jmp(jmp)
+            : m_label(jmp)
             , m_flags(flags)
         {
         }
             , m_flags(flags)
         {
         }
@@ -374,10 +418,10 @@ public:
 
         static Call fromTailJump(Jump jump)
         {
 
         static Call fromTailJump(Jump jump)
         {
-            return Call(jump.m_jmp, Linkable);
+            return Call(jump.m_label, Linkable);
         }
 
         }
 
-        AssemblerLabel m_jmp;
+        AssemblerLabel m_label;
     private:
         Flags m_flags;
     };
     private:
         Flags m_flags;
     };
@@ -392,6 +436,7 @@ public:
         template<class TemplateAssemblerType>
         friend class AbstractMacroAssembler;
         friend class Call;
         template<class TemplateAssemblerType>
         friend class AbstractMacroAssembler;
         friend class Call;
+        friend class DFG::CorrectableJumpPoint;
         friend class LinkBuffer;
     public:
         Jump()
         friend class LinkBuffer;
     public:
         Jump()
@@ -401,14 +446,20 @@ public:
 #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)
 #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_label(jmp)
             , m_type(type)
             , m_condition(condition)
         {
         }
             , m_type(type)
             , m_condition(condition)
         {
         }
+#elif CPU(SH4)
+        Jump(AssemblerLabel jmp, SH4Assembler::JumpType type = SH4Assembler::JumpFar)
+            : m_label(jmp)
+            , m_type(type)
+        {
+        }
 #else
         Jump(AssemblerLabel jmp)    
 #else
         Jump(AssemblerLabel jmp)    
-            : m_jmp(jmp)
+            : m_label(jmp)
         {
         }
 #endif
         {
         }
 #endif
@@ -416,29 +467,49 @@ public:
         void link(AbstractMacroAssembler<AssemblerType>* masm) const
         {
 #if CPU(ARM_THUMB2)
         void link(AbstractMacroAssembler<AssemblerType>* masm) const
         {
 #if CPU(ARM_THUMB2)
-            masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label(), m_type, m_condition);
+            masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
+#elif CPU(SH4)
+            masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type);
 #else
 #else
-            masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label());
+            masm->m_assembler.linkJump(m_label, masm->m_assembler.label());
 #endif
         }
         
         void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) const
         {
 #if CPU(ARM_THUMB2)
 #endif
         }
         
         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);
+            masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition);
 #else
 #else
-            masm->m_assembler.linkJump(m_jmp, label.m_label);
+            masm->m_assembler.linkJump(m_label, label.m_label);
 #endif
         }
 
 #endif
         }
 
-        bool isSet() const { return m_jmp.isSet(); }
+        bool isSet() const { return m_label.isSet(); }
 
     private:
 
     private:
-        AssemblerLabel m_jmp;
+        AssemblerLabel m_label;
 #if CPU(ARM_THUMB2)
         ARMv7Assembler::JumpType m_type;
         ARMv7Assembler::Condition m_condition;
 #endif
 #if CPU(ARM_THUMB2)
         ARMv7Assembler::JumpType m_type;
         ARMv7Assembler::Condition m_condition;
 #endif
+#if CPU(SH4)
+        SH4Assembler::JumpType m_type;
+#endif
+    };
+
+    struct PatchableJump {
+        PatchableJump()
+        {
+        }
+
+        explicit PatchableJump(Jump jump)
+            : m_jump(jump)
+        {
+        }
+
+        operator Jump&() { return m_jump; }
+
+        Jump m_jump;
     };
 
     // JumpList:
     };
 
     // JumpList:
@@ -506,72 +577,50 @@ public:
         return Label(this);
     }
 
         return Label(this);
     }
 
-    ptrdiff_t differenceBetween(Label from, Jump to)
-    {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
-    }
-
-    ptrdiff_t differenceBetween(Label from, Call to)
-    {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
-    }
-
-    ptrdiff_t differenceBetween(Label from, Label to)
+    template<typename T, typename U>
+    static ptrdiff_t differenceBetween(T from, U to)
     {
         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
     }
 
     {
         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
     }
 
-    ptrdiff_t differenceBetween(Label from, DataLabelPtr to)
+    static ptrdiff_t differenceBetweenCodePtr(const MacroAssemblerCodePtr& a, const MacroAssemblerCodePtr& b)
     {
     {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
+        return reinterpret_cast<ptrdiff_t>(b.executableAddress()) - reinterpret_cast<ptrdiff_t>(a.executableAddress());
     }
 
     }
 
-    ptrdiff_t differenceBetween(Label from, DataLabel32 to)
-    {
-        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);
-    }
+    unsigned debugOffset() { return m_assembler.debugOffset(); }
 
 
-    ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
+    ALWAYS_INLINE static void cacheFlush(void* code, size_t size)
     {
     {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
+        AssemblerType::cacheFlush(code, size);
     }
     }
-
-    ptrdiff_t differenceBetween(DataLabelPtr from, DataLabelPtr to)
+protected:
+    AbstractMacroAssembler()
+        : m_randomSource(cryptographicallyRandomNumber())
     {
     {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
     }
 
     }
 
-    ptrdiff_t differenceBetween(DataLabelPtr from, Call to)
+    AssemblerType m_assembler;
+    
+    uint32_t random()
     {
     {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
+        return m_randomSource.getUint32();
     }
 
     }
 
-    // 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() { }
+    WeakRandom m_randomSource;
 
 
-#ifndef NDEBUG
-    unsigned debugOffset() { return m_assembler.debugOffset(); }
+#if ENABLE(JIT_CONSTANT_BLINDING)
+    static bool scratchRegisterForBlinding() { return false; }
+    static bool shouldBlindForSpecificArch(uint32_t) { return true; }
+    static bool shouldBlindForSpecificArch(uint64_t) { return true; }
 #endif
 
 #endif
 
-protected:
-    AssemblerType m_assembler;
-
     friend class LinkBuffer;
     friend class RepatchBuffer;
 
     static void linkJump(void* code, Jump jump, CodeLocationLabel target)
     {
     friend class LinkBuffer;
     friend class RepatchBuffer;
 
     static void linkJump(void* code, Jump jump, CodeLocationLabel target)
     {
-        AssemblerType::linkJump(code, jump.m_jmp, target.dataLocation());
+        AssemblerType::linkJump(code, jump.m_label, target.dataLocation());
     }
 
     static void linkPointer(void* code, AssemblerLabel label, void* value)
     }
 
     static void linkPointer(void* code, AssemblerLabel label, void* value)
@@ -586,7 +635,7 @@ protected:
 
     static unsigned getLinkerCallReturnOffset(Call call)
     {
 
     static unsigned getLinkerCallReturnOffset(Call call)
     {
-        return AssemblerType::getCallReturnOffset(call.m_jmp);
+        return AssemblerType::getCallReturnOffset(call.m_label);
     }
 
     static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination)
     }
 
     static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination)
@@ -618,6 +667,18 @@ protected:
     {
         return AssemblerType::readPointer(dataLabelPtr.dataLocation());
     }
     {
         return AssemblerType::readPointer(dataLabelPtr.dataLocation());
     }
+    
+    static void unreachableForPlatform()
+    {
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+        ASSERT_NOT_REACHED();
+#pragma clang diagnostic pop
+#else
+        ASSERT_NOT_REACHED();
+#endif
+    }
 };
 
 } // namespace JSC
 };
 
 } // namespace JSC
index b98503d0876e96bec8181eb9c261eedb07e059c5..d1deef2344af2dabac0e59a56b2193220309899e 100644 (file)
@@ -28,6 +28,8 @@
 
 #if ENABLE(ASSEMBLER)
 
 
 #if ENABLE(ASSEMBLER)
 
+#include "JITCompilationEffort.h"
+#include "JSGlobalData.h"
 #include "stdint.h"
 #include <string.h>
 #include <jit/ExecutableAllocator.h>
 #include "stdint.h"
 #include <string.h>
 #include <jit/ExecutableAllocator.h>
@@ -128,29 +130,24 @@ namespace JSC {
             return AssemblerLabel(m_index);
         }
 
             return AssemblerLabel(m_index);
         }
 
-        void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
+        PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort)
         {
             if (!m_index)
                 return 0;
 
         {
             if (!m_index)
                 return 0;
 
-            void* result = allocator->alloc(globalData, m_index);
+            RefPtr<ExecutableMemoryHandle> result = globalData.executableAllocator.allocate(globalData, m_index, ownerUID, effort);
 
             if (!result)
                 return 0;
 
 
             if (!result)
                 return 0;
 
-            ExecutableAllocator::makeWritable(result, m_index);
+            ExecutableAllocator::makeWritable(result->start(), result->sizeInBytes());
 
 
-            return memcpy(result, m_buffer, m_index);
+            memcpy(result->start(), m_buffer, m_index);
+            
+            return result.release();
         }
 
         }
 
-        void rewindToLabel(AssemblerLabel label)
-        {
-            m_index = label.m_offset;
-        }
-
-#ifndef NDEBUG
         unsigned debugOffset() { return m_index; }
         unsigned debugOffset() { return m_index; }
-#endif
 
     protected:
         void append(const char* data, int size)
 
     protected:
         void append(const char* data, int size)
index cd9ff9c0ef43aacd592e933fa19af15d3c6b75a7..e2ea261ee26c5673106a37cc30ad6d6075315033 100644 (file)
@@ -83,7 +83,7 @@ namespace JSC {
 */
 
 template <int maxPoolSize, int barrierSize, int maxInstructionSize, class AssemblerType>
 */
 
 template <int maxPoolSize, int barrierSize, int maxInstructionSize, class AssemblerType>
-class AssemblerBufferWithConstantPool: public AssemblerBuffer {
+class AssemblerBufferWithConstantPool : public AssemblerBuffer {
     typedef SegmentedVector<uint32_t, 512> LoadOffsets;
     using AssemblerBuffer::putIntegral;
     using AssemblerBuffer::putIntegralUnchecked;
     typedef SegmentedVector<uint32_t, 512> LoadOffsets;
     using AssemblerBuffer::putIntegral;
     using AssemblerBuffer::putIntegralUnchecked;
@@ -195,10 +195,10 @@ public:
         putIntegralUnchecked(value.low);
     }
 
         putIntegralUnchecked(value.low);
     }
 
-    void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
+    PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort)
     {
         flushConstantPool(false);
     {
         flushConstantPool(false);
-        return AssemblerBuffer::executableCopy(globalData, allocator);
+        return AssemblerBuffer::executableCopy(globalData, ownerUID, effort);
     }
 
     void putShortWithConstantInt(uint16_t insn, uint32_t constant, bool isReusable = false)
     }
 
     void putShortWithConstantInt(uint16_t insn, uint32_t constant, bool isReusable = false)
index 59b5a1e6110c5e6197b2144d2bb457b5b3917c1a..eff320d5748bdfb5ddbaf6e93aa71bcbadc03567 100644 (file)
 #define DUMP_LINK_STATISTICS 0
 #define DUMP_CODE 0
 
 #define DUMP_LINK_STATISTICS 0
 #define DUMP_CODE 0
 
-#include <MacroAssembler.h>
+#define GLOBAL_THUNK_ID reinterpret_cast<void*>(static_cast<intptr_t>(-1))
+#define REGEXP_CODE_ID reinterpret_cast<void*>(static_cast<intptr_t>(-2))
+
+#include "JITCompilationEffort.h"
+#include "MacroAssembler.h"
+#include <wtf/DataLog.h>
 #include <wtf/Noncopyable.h>
 
 namespace JSC {
 #include <wtf/Noncopyable.h>
 
 namespace JSC {
@@ -58,6 +63,7 @@ class LinkBuffer {
     typedef MacroAssemblerCodePtr CodePtr;
     typedef MacroAssembler::Label Label;
     typedef MacroAssembler::Jump Jump;
     typedef MacroAssemblerCodePtr CodePtr;
     typedef MacroAssembler::Label Label;
     typedef MacroAssembler::Jump Jump;
+    typedef MacroAssembler::PatchableJump PatchableJump;
     typedef MacroAssembler::JumpList JumpList;
     typedef MacroAssembler::Call Call;
     typedef MacroAssembler::DataLabelCompact DataLabelCompact;
     typedef MacroAssembler::JumpList JumpList;
     typedef MacroAssembler::Call Call;
     typedef MacroAssembler::DataLabelCompact DataLabelCompact;
@@ -69,49 +75,49 @@ class LinkBuffer {
 #endif
 
 public:
 #endif
 
 public:
-    LinkBuffer(JSGlobalData& globalData, MacroAssembler* masm, PassRefPtr<ExecutablePool> executablePool)
-        : m_executablePool(executablePool)
-        , m_size(0)
-        , m_code(0)
-        , m_assembler(masm)
-        , m_globalData(&globalData)
-#ifndef NDEBUG
-        , m_completed(false)
+    LinkBuffer(JSGlobalData& globalData, MacroAssembler* masm, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed)
+        : m_size(0)
+#if ENABLE(BRANCH_COMPACTION)
+        , m_initialSize(0)
 #endif
 #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)
         , m_code(0)
         , m_assembler(masm)
         , m_globalData(&globalData)
 #ifndef NDEBUG
         , m_completed(false)
+        , m_effort(effort)
 #endif
     {
 #endif
     {
-        linkCode();
+        linkCode(ownerUID, effort);
     }
 
     ~LinkBuffer()
     {
     }
 
     ~LinkBuffer()
     {
-        ASSERT(m_completed);
+        ASSERT(m_completed || (!m_executableMemory && m_effort == JITCompilationCanFail));
+    }
+    
+    bool didFailToAllocate() const
+    {
+        return !m_executableMemory;
     }
 
     }
 
+    bool isValid() const
+    {
+        return !didFailToAllocate();
+    }
+    
     // These methods are used to link or set values at code generation time.
 
     void link(Call call, FunctionPtr function)
     {
         ASSERT(call.isFlagSet(Call::Linkable));
     // These methods are used to link or set values at code generation time.
 
     void link(Call call, FunctionPtr function)
     {
         ASSERT(call.isFlagSet(Call::Linkable));
-        call.m_jmp = applyOffset(call.m_jmp);
+        call.m_label = applyOffset(call.m_label);
         MacroAssembler::linkCall(code(), call, function);
     }
     
     void link(Jump jump, CodeLocationLabel label)
     {
         MacroAssembler::linkCall(code(), call, function);
     }
     
     void link(Jump jump, CodeLocationLabel label)
     {
-        jump.m_jmp = applyOffset(jump.m_jmp);
+        jump.m_label = applyOffset(jump.m_label);
         MacroAssembler::linkJump(code(), jump, label);
     }
 
         MacroAssembler::linkJump(code(), jump, label);
     }
 
@@ -139,14 +145,19 @@ public:
     {
         ASSERT(call.isFlagSet(Call::Linkable));
         ASSERT(!call.isFlagSet(Call::Near));
     {
         ASSERT(call.isFlagSet(Call::Linkable));
         ASSERT(!call.isFlagSet(Call::Near));
-        return CodeLocationCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_jmp)));
+        return CodeLocationCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_label)));
     }
 
     CodeLocationNearCall locationOfNearCall(Call call)
     {
         ASSERT(call.isFlagSet(Call::Linkable));
         ASSERT(call.isFlagSet(Call::Near));
     }
 
     CodeLocationNearCall locationOfNearCall(Call call)
     {
         ASSERT(call.isFlagSet(Call::Linkable));
         ASSERT(call.isFlagSet(Call::Near));
-        return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_jmp)));
+        return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_label)));
+    }
+
+    CodeLocationLabel locationOf(PatchableJump jump)
+    {
+        return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), applyOffset(jump.m_jump.m_label)));
     }
 
     CodeLocationLabel locationOf(Label label)
     }
 
     CodeLocationLabel locationOf(Label label)
@@ -173,26 +184,21 @@ public:
     // the start of the code.
     unsigned returnAddressOffset(Call call)
     {
     // the start of the code.
     unsigned returnAddressOffset(Call call)
     {
-        call.m_jmp = applyOffset(call.m_jmp);
+        call.m_label = applyOffset(call.m_label);
         return MacroAssembler::getLinkerCallReturnOffset(call);
     }
 
         return MacroAssembler::getLinkerCallReturnOffset(call);
     }
 
-    // Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called
-    // once to complete generation of the code.  'finalizeCode()' is suited to situations
-    // where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is
-    // suited to adding to an existing allocation.
-    CodeRef finalizeCode()
+    uint32_t offsetOf(Label label)
     {
     {
-        performFinalization();
-
-        return CodeRef(m_code, m_executablePool, m_size);
+        return applyOffset(label.m_label).m_offset;
     }
 
     }
 
-    CodeLocationLabel finalizeCodeAddendum()
+    // Upon completion of all patching 'finalizeCode()' should be called once to complete generation of the code.
+    CodeRef finalizeCode()
     {
         performFinalization();
 
     {
         performFinalization();
 
-        return CodeLocationLabel(code());
+        return CodeRef(m_executableMemory);
     }
 
     CodePtr trampolineAt(Label label)
     }
 
     CodePtr trampolineAt(Label label)
@@ -200,12 +206,15 @@ 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;
     }
     void* debugAddress()
     {
         return m_code;
     }
-#endif
+    
+    size_t debugSize()
+    {
+        return m_size;
+    }
 
 private:
     template <typename T> T applyOffset(T src)
 
 private:
     template <typename T> T applyOffset(T src)
@@ -216,26 +225,30 @@ private:
         return src;
     }
     
         return src;
     }
     
-    // Keep this private! - the underlying code should only be obtained externally via 
-    // finalizeCode() or finalizeCodeAddendum().
+    // Keep this private! - the underlying code should only be obtained externally via finalizeCode().
     void* code()
     {
         return m_code;
     }
 
     void* code()
     {
         return m_code;
     }
 
-    void linkCode()
+    void linkCode(void* ownerUID, JITCompilationEffort effort)
     {
         ASSERT(!m_code);
 #if !ENABLE(BRANCH_COMPACTION)
     {
         ASSERT(!m_code);
 #if !ENABLE(BRANCH_COMPACTION)
-        m_code = m_assembler->m_assembler.executableCopy(*m_globalData, m_executablePool.get());
+        m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID, effort);
+        if (!m_executableMemory)
+            return;
+        m_code = m_executableMemory->start();
         m_size = m_assembler->m_assembler.codeSize();
         ASSERT(m_code);
 #else
         m_size = m_assembler->m_assembler.codeSize();
         ASSERT(m_code);
 #else
-        size_t initialSize = m_assembler->m_assembler.codeSize();
-        m_code = (uint8_t*)m_executablePool->alloc(*m_globalData, initialSize);
-        if (!m_code)
+        m_initialSize = m_assembler->m_assembler.codeSize();
+        m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID, effort);
+        if (!m_executableMemory)
             return;
             return;
-        ExecutableAllocator::makeWritable(m_code, initialSize);
+        m_code = (uint8_t*)m_executableMemory->start();
+        ASSERT(m_code);
+        ExecutableAllocator::makeWritable(m_code, m_initialSize);
         uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode();
         uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
         int readPtr = 0;
         uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode();
         uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
         int readPtr = 0;
@@ -248,9 +261,9 @@ 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;
-            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);
+            uint16_t* copySource = reinterpret_cast_ptr<uint16_t*>(inData + readPtr);
+            uint16_t* copyEnd = reinterpret_cast_ptr<uint16_t*>(inData + readPtr + regionSize);
+            uint16_t* copyDst = reinterpret_cast_ptr<uint16_t*>(outData + writePtr);
             ASSERT(!(regionSize % 2));
             ASSERT(!(readPtr % 2));
             ASSERT(!(writePtr % 2));
             ASSERT(!(regionSize % 2));
             ASSERT(!(readPtr % 2));
             ASSERT(!(writePtr % 2));
@@ -281,8 +294,8 @@ 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, initialSize - readPtr);
-        m_assembler->recordLinkOffsets(readPtr, initialSize, readPtr - writePtr);
+        memcpy(outData + writePtr, inData + readPtr, m_initialSize - readPtr);
+        m_assembler->recordLinkOffsets(readPtr, m_initialSize, readPtr - writePtr);
         
         for (unsigned i = 0; i < jumpCount; ++i) {
             uint8_t* location = outData + jumpsToLink[i].from();
         
         for (unsigned i = 0; i < jumpCount; ++i) {
             uint8_t* location = outData + jumpsToLink[i].from();
@@ -291,11 +304,11 @@ private:
         }
 
         jumpsToLink.clear();
         }
 
         jumpsToLink.clear();
-        m_size = writePtr + initialSize - readPtr;
-        m_executablePool->tryShrink(m_code, initialSize, m_size);
+        m_size = writePtr + m_initialSize - readPtr;
+        m_executableMemory->shrink(m_size);
 
 #if DUMP_LINK_STATISTICS
 
 #if DUMP_LINK_STATISTICS
-        dumpLinkStatistics(m_code, initialSize, m_size);
+        dumpLinkStatistics(m_code, m_initialSize, m_size);
 #endif
 #if DUMP_CODE
         dumpCode(m_code, m_size);
 #endif
 #if DUMP_CODE
         dumpCode(m_code, m_size);
@@ -307,11 +320,16 @@ private:
     {
 #ifndef NDEBUG
         ASSERT(!m_completed);
     {
 #ifndef NDEBUG
         ASSERT(!m_completed);
+        ASSERT(isValid());
         m_completed = true;
 #endif
 
         m_completed = true;
 #endif
 
+#if ENABLE(BRANCH_COMPACTION)
+        ExecutableAllocator::makeExecutable(code(), m_initialSize);
+#else
         ExecutableAllocator::makeExecutable(code(), m_size);
         ExecutableAllocator::makeExecutable(code(), m_size);
-        ExecutableAllocator::cacheFlush(code(), m_size);
+#endif
+        MacroAssembler::cacheFlush(code(), m_size);
     }
 
 #if DUMP_LINK_STATISTICS
     }
 
 #if DUMP_LINK_STATISTICS
@@ -323,13 +341,13 @@ private:
         linkCount++;
         totalInitialSize += initialSize;
         totalFinalSize += finalSize;
         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);
+        dataLog("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);
+        dataLog("\ttotal %u: orig %u, compact %u (delta %u, %.2f%%)\n", 
+                    linkCount, totalInitialSize, totalFinalSize, totalInitialSize - totalFinalSize,
+                    100.0 * (totalInitialSize - totalFinalSize) / totalInitialSize);
     }
 #endif
     
     }
 #endif
     
@@ -346,28 +364,49 @@ private:
         size_t tsize = size / sizeof(short);
         char nameBuf[128];
         snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
         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);
+        dataLog("\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++)
         
         for (unsigned i = 0; i < tsize; i++)
-            printf("\t.short\t0x%x\n", tcode[i]);
+            dataLog("\t.short\t0x%x\n", tcode[i]);
+#elif CPU(ARM_TRADITIONAL)
+        //   gcc -c jit.s
+        //   objdump -D jit.o
+        static unsigned codeCount = 0;
+        unsigned int* tcode = static_cast<unsigned int*>(code);
+        size_t tsize = size / sizeof(unsigned int);
+        char nameBuf[128];
+        snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
+        dataLog("\t.globl\t%s\n"
+                    "\t.align 4\n"
+                    "\t.code 32\n"
+                    "\t.text\n"
+                    "# %p\n"
+                    "%s:\n", nameBuf, code, nameBuf);
+
+        for (unsigned i = 0; i < tsize; i++)
+            dataLog("\t.long\t0x%x\n", tcode[i]);
 #endif
     }
 #endif
     
 #endif
     }
 #endif
     
-    RefPtr<ExecutablePool> m_executablePool;
+    RefPtr<ExecutableMemoryHandle> m_executableMemory;
     size_t m_size;
     size_t m_size;
+#if ENABLE(BRANCH_COMPACTION)
+    size_t m_initialSize;
+#endif
     void* m_code;
     MacroAssembler* m_assembler;
     JSGlobalData* m_globalData;
 #ifndef NDEBUG
     bool m_completed;
     void* m_code;
     MacroAssembler* m_assembler;
     JSGlobalData* m_globalData;
 #ifndef NDEBUG
     bool m_completed;
+    JITCompilationEffort m_effort;
 #endif
 };
 
 #endif
 };
 
index 4164fa9db0d9f92434e1ee146492f321bb3ef873..7212a182c6ca0d43cfe23279c5b1ed9e3d28b081 100644 (file)
@@ -32,6 +32,7 @@
 #if ENABLE(ASSEMBLER) && CPU(MIPS)
 
 #include "AssemblerBuffer.h"
 #if ENABLE(ASSEMBLER) && CPU(MIPS)
 
 #include "AssemblerBuffer.h"
+#include "JITCompilationEffort.h"
 #include <wtf/Assertions.h>
 #include <wtf/SegmentedVector.h>
 
 #include <wtf/Assertions.h>
 #include <wtf/SegmentedVector.h>
 
@@ -645,19 +646,17 @@ public:
         return m_buffer.codeSize();
     }
 
         return m_buffer.codeSize();
     }
 
-    void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
+    PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort)
     {
     {
-        void *result = m_buffer.executableCopy(globalData, allocator);
+        RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData, ownerUID, effort);
         if (!result)
             return 0;
 
         if (!result)
             return 0;
 
-        relocateJumps(m_buffer.data(), result);
-        return result;
+        relocateJumps(m_buffer.data(), result->start());
+        return result.release();
     }
 
     }
 
-#ifndef NDEBUG
     unsigned debugOffset() { return m_buffer.debugOffset(); }
     unsigned debugOffset() { return m_buffer.debugOffset(); }
-#endif
 
     static unsigned getCallReturnOffset(AssemblerLabel call)
     {
 
     static unsigned getCallReturnOffset(AssemblerLabel call)
     {
@@ -719,7 +718,7 @@ public:
         insn = insn - 6;
         int flushSize = linkWithOffset(insn, to);
 
         insn = insn - 6;
         int flushSize = linkWithOffset(insn, to);
 
-        ExecutableAllocator::cacheFlush(insn, flushSize);
+        cacheFlush(insn, flushSize);
     }
 
     static void relinkCall(void* from, void* to)
     }
 
     static void relinkCall(void* from, void* to)
@@ -731,7 +730,7 @@ public:
         else
             start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 4 * sizeof(MIPSWord));
 
         else
             start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 4 * sizeof(MIPSWord));
 
-        ExecutableAllocator::cacheFlush(start, size);
+        cacheFlush(start, size);
     }
 
     static void repatchInt32(void* from, int32_t to)
     }
 
     static void repatchInt32(void* from, int32_t to)
@@ -743,7 +742,7 @@ public:
         ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
         *insn = (*insn & 0xffff0000) | (to & 0xffff);
         insn--;
         ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
         *insn = (*insn & 0xffff0000) | (to & 0xffff);
         insn--;
-        ExecutableAllocator::cacheFlush(insn, 2 * sizeof(MIPSWord));
+        cacheFlush(insn, 2 * sizeof(MIPSWord));
     }
 
     static int32_t readInt32(void* from)
     }
 
     static int32_t readInt32(void* from)
@@ -753,7 +752,8 @@ public:
         int32_t result = (*insn & 0x0000ffff) << 16;
         insn++;
         ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
         int32_t result = (*insn & 0x0000ffff) << 16;
         insn++;
         ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
-        result |= *insn & 0x0000ffff
+        result |= *insn & 0x0000ffff;
+        return result;
     }
     
     static void repatchCompact(void* where, int32_t value)
     }
     
     static void repatchCompact(void* where, int32_t value)
@@ -768,7 +768,45 @@ public:
 
     static void* readPointer(void* from)
     {
 
     static void* readPointer(void* from)
     {
-        return static_cast<void*>(readInt32(from));
+        return reinterpret_cast<void*>(readInt32(from));
+    }
+
+    static void* readCallTarget(void* from)
+    {
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
+        insn -= 4;
+        ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
+        int32_t result = (*insn & 0x0000ffff) << 16;
+        insn++;
+        ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
+        result |= *insn & 0x0000ffff;
+        return reinterpret_cast<void*>(result);
+    }
+
+    static void cacheFlush(void* code, size_t size)
+    {
+#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));
+        //
+        // Modify "start" and "end" to avoid GCC 4.3.0-4.4.2 bug in
+        // mips_expand_synci_loop that may execute synci one more time.
+        // "start" points to the fisrt byte of the cache line.
+        // "end" points to the last byte of the line before the last cache line.
+        // Because size is always a multiple of 4, this is safe to set
+        // "end" to the last byte.
+        //
+        intptr_t start = reinterpret_cast<intptr_t>(code) & (-lineSize);
+        intptr_t end = ((reinterpret_cast<intptr_t>(code) + size - 1) & (-lineSize)) - 1;
+        __builtin___clear_cache(reinterpret_cast<char*>(start), reinterpret_cast<char*>(end));
+#else
+        intptr_t end = reinterpret_cast<intptr_t>(code) + size;
+        __builtin___clear_cache(reinterpret_cast<char*>(code), reinterpret_cast<char*>(end));
+#endif
+#else
+        _flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
+#endif
     }
 
 private:
     }
 
 private:
index c8506c74a72ab3b8d6e20720189ed8f29366175f..516ffac16f25152337af8a8a79a9da540a689ace 100644 (file)
@@ -60,7 +60,6 @@ typedef MacroAssemblerSH4 MacroAssemblerBase;
 #error "The MacroAssembler is not supported on this platform."
 #endif
 
 #error "The MacroAssembler is not supported on this platform."
 #endif
 
-
 namespace JSC {
 
 class MacroAssembler : public MacroAssemblerBase {
 namespace JSC {
 
 class MacroAssembler : public MacroAssemblerBase {
@@ -69,12 +68,88 @@ public:
     using MacroAssemblerBase::pop;
     using MacroAssemblerBase::jump;
     using MacroAssemblerBase::branch32;
     using MacroAssemblerBase::pop;
     using MacroAssemblerBase::jump;
     using MacroAssemblerBase::branch32;
-    using MacroAssemblerBase::branch16;
 #if CPU(X86_64)
     using MacroAssemblerBase::branchPtr;
     using MacroAssemblerBase::branchTestPtr;
 #endif
 #if CPU(X86_64)
     using MacroAssemblerBase::branchPtr;
     using MacroAssemblerBase::branchTestPtr;
 #endif
+    using MacroAssemblerBase::move;
+
+#if ENABLE(JIT_CONSTANT_BLINDING)
+    using MacroAssemblerBase::add32;
+    using MacroAssemblerBase::and32;
+    using MacroAssemblerBase::branchAdd32;
+    using MacroAssemblerBase::branchMul32;
+    using MacroAssemblerBase::branchSub32;
+    using MacroAssemblerBase::lshift32;
+    using MacroAssemblerBase::or32;
+    using MacroAssemblerBase::rshift32;
+    using MacroAssemblerBase::store32;
+    using MacroAssemblerBase::sub32;
+    using MacroAssemblerBase::urshift32;
+    using MacroAssemblerBase::xor32;
+#endif
 
 
+    // Utilities used by the DFG JIT.
+#if ENABLE(DFG_JIT)
+    using MacroAssemblerBase::invert;
+    
+    static DoubleCondition invert(DoubleCondition cond)
+    {
+        switch (cond) {
+        case DoubleEqual:
+            return DoubleNotEqualOrUnordered;
+        case DoubleNotEqual:
+            return DoubleEqualOrUnordered;
+        case DoubleGreaterThan:
+            return DoubleLessThanOrEqualOrUnordered;
+        case DoubleGreaterThanOrEqual:
+            return DoubleLessThanOrUnordered;
+        case DoubleLessThan:
+            return DoubleGreaterThanOrEqualOrUnordered;
+        case DoubleLessThanOrEqual:
+            return DoubleGreaterThanOrUnordered;
+        case DoubleEqualOrUnordered:
+            return DoubleNotEqual;
+        case DoubleNotEqualOrUnordered:
+            return DoubleEqual;
+        case DoubleGreaterThanOrUnordered:
+            return DoubleLessThanOrEqual;
+        case DoubleGreaterThanOrEqualOrUnordered:
+            return DoubleLessThan;
+        case DoubleLessThanOrUnordered:
+            return DoubleGreaterThanOrEqual;
+        case DoubleLessThanOrEqualOrUnordered:
+            return DoubleGreaterThan;
+        default:
+            ASSERT_NOT_REACHED();
+            return DoubleEqual; // make compiler happy
+        }
+    }
+    
+    static bool isInvertible(ResultCondition cond)
+    {
+        switch (cond) {
+        case Zero:
+        case NonZero:
+            return true;
+        default:
+            return false;
+        }
+    }
+    
+    static ResultCondition invert(ResultCondition cond)
+    {
+        switch (cond) {
+        case Zero:
+            return NonZero;
+        case NonZero:
+            return Zero;
+        default:
+            ASSERT_NOT_REACHED();
+            return Zero; // Make compiler happy for release builds.
+        }
+    }
+#endif
 
     // Platform agnostic onvenience functions,
     // described in terms of other macro assembly methods.
 
     // Platform agnostic onvenience functions,
     // described in terms of other macro assembly methods.
@@ -88,19 +163,24 @@ public:
         loadPtr(Address(stackPointerRegister, (index * sizeof(void*))), dest);
     }
 
         loadPtr(Address(stackPointerRegister, (index * sizeof(void*))), dest);
     }
 
+    Address addressForPoke(int index)
+    {
+        return Address(stackPointerRegister, (index * sizeof(void*)));
+    }
+    
     void poke(RegisterID src, int index = 0)
     {
     void poke(RegisterID src, int index = 0)
     {
-        storePtr(src, Address(stackPointerRegister, (index * sizeof(void*))));
+        storePtr(src, addressForPoke(index));
     }
 
     void poke(TrustedImm32 value, int index = 0)
     {
     }
 
     void poke(TrustedImm32 value, int index = 0)
     {
-        store32(value, Address(stackPointerRegister, (index * sizeof(void*))));
+        store32(value, addressForPoke(index));
     }
 
     void poke(TrustedImmPtr imm, int index = 0)
     {
     }
 
     void poke(TrustedImmPtr imm, int index = 0)
     {
-        storePtr(imm, Address(stackPointerRegister, (index * sizeof(void*))));
+        storePtr(imm, addressForPoke(index));
     }
 
 
     }
 
 
@@ -109,6 +189,10 @@ public:
     {
         branchPtr(cond, op1, imm).linkTo(target, this);
     }
     {
         branchPtr(cond, op1, imm).linkTo(target, this);
     }
+    void branchPtr(RelationalCondition cond, RegisterID op1, ImmPtr imm, Label target)
+    {
+        branchPtr(cond, op1, imm).linkTo(target, this);
+    }
 
     void branch32(RelationalCondition cond, RegisterID op1, RegisterID op2, Label target)
     {
 
     void branch32(RelationalCondition cond, RegisterID op1, RegisterID op2, Label target)
     {
@@ -119,27 +203,78 @@ public:
     {
         branch32(cond, op1, imm).linkTo(target, this);
     }
     {
         branch32(cond, op1, imm).linkTo(target, this);
     }
+    
+    void branch32(RelationalCondition cond, RegisterID op1, Imm32 imm, Label target)
+    {
+        branch32(cond, op1, imm).linkTo(target, this);
+    }
 
     void branch32(RelationalCondition cond, RegisterID left, Address right, Label target)
     {
         branch32(cond, left, right).linkTo(target, this);
     }
 
 
     void branch32(RelationalCondition cond, RegisterID left, Address right, Label target)
     {
         branch32(cond, left, right).linkTo(target, this);
     }
 
-    void branch16(RelationalCondition cond, BaseIndex left, RegisterID right, Label target)
+    Jump branch32(RelationalCondition cond, TrustedImm32 left, RegisterID right)
     {
     {
-        branch16(cond, left, right).linkTo(target, this);
+        return branch32(commute(cond), right, left);
     }
     }
-    
+
+    Jump branch32(RelationalCondition cond, Imm32 left, RegisterID right)
+    {
+        return branch32(commute(cond), right, left);
+    }
+
     void branchTestPtr(ResultCondition cond, RegisterID reg, Label target)
     {
         branchTestPtr(cond, reg).linkTo(target, this);
     }
 
     void branchTestPtr(ResultCondition cond, RegisterID reg, Label target)
     {
         branchTestPtr(cond, reg).linkTo(target, this);
     }
 
+#if !CPU(ARM_THUMB2)
+    PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
+    {
+        return PatchableJump(branchPtrWithPatch(cond, left, dataLabel, initialRightValue));
+    }
+
+    PatchableJump patchableJump()
+    {
+        return PatchableJump(jump());
+    }
+#endif
+
     void jump(Label target)
     {
         jump().linkTo(target, this);
     }
 
     void jump(Label target)
     {
         jump().linkTo(target, this);
     }
 
+    // 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 condition)
+    {
+        switch (condition) {
+        case Above:
+            return Below;
+        case AboveOrEqual:
+            return BelowOrEqual;
+        case Below:
+            return Above;
+        case BelowOrEqual:
+            return AboveOrEqual;
+        case GreaterThan:
+            return LessThan;
+        case GreaterThanOrEqual:
+            return LessThanOrEqual;
+        case LessThan:
+            return GreaterThan;
+        case LessThanOrEqual:
+            return GreaterThanOrEqual;
+        default:
+            break;
+        }
+
+        ASSERT(condition == Equal || condition == NotEqual);
+        return condition;
+    }
+    
 
     // Ptr methods
     // On 32-bit platforms (i.e. x86), these methods directly map onto their 32-bit equivalents.
 
     // Ptr methods
     // On 32-bit platforms (i.e. x86), these methods directly map onto their 32-bit equivalents.
@@ -165,6 +300,11 @@ public:
         add32(imm, src, dest);
     }
 
         add32(imm, src, dest);
     }
 
+    void addPtr(TrustedImm32 imm, AbsoluteAddress address)
+    {
+        add32(imm, address);
+    }
+    
     void andPtr(RegisterID src, RegisterID dest)
     {
         and32(src, dest);
     void andPtr(RegisterID src, RegisterID dest)
     {
         and32(src, dest);
@@ -180,6 +320,11 @@ public:
         or32(src, dest);
     }
 
         or32(src, dest);
     }
 
+    void orPtr(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        or32(op1, op2, dest);
+    }
+
     void orPtr(TrustedImmPtr imm, RegisterID dest)
     {
         or32(TrustedImm32(imm), dest);
     void orPtr(TrustedImmPtr imm, RegisterID dest)
     {
         or32(TrustedImm32(imm), dest);
@@ -226,7 +371,7 @@ public:
         load32(address, dest);
     }
 
         load32(address, dest);
     }
 
-    void loadPtr(void* address, RegisterID dest)
+    void loadPtr(const void* address, RegisterID dest)
     {
         load32(address, dest);
     }
     {
         load32(address, dest);
     }
@@ -241,6 +386,11 @@ public:
         return load32WithCompactAddressOffsetPatch(address, dest);
     }
 
         return load32WithCompactAddressOffsetPatch(address, dest);
     }
 
+    void move(ImmPtr imm, RegisterID dest)
+    {
+        move(Imm32(imm.asTrustedImmPtr()), dest);
+    }
+
     void comparePtr(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
         compare32(cond, left, right, dest);
     void comparePtr(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
         compare32(cond, left, right, dest);
@@ -265,6 +415,11 @@ public:
     {
         store32(TrustedImm32(imm), address);
     }
     {
         store32(TrustedImm32(imm), address);
     }
+    
+    void storePtr(ImmPtr imm, Address address)
+    {
+        store32(Imm32(imm.asTrustedImmPtr()), address);
+    }
 
     void storePtr(TrustedImmPtr imm, void* address)
     {
 
     void storePtr(TrustedImmPtr imm, void* address)
     {
@@ -276,7 +431,6 @@ public:
         return store32WithAddressOffsetPatch(src, address);
     }
 
         return store32WithAddressOffsetPatch(src, address);
     }
 
-
     Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right)
     {
         return branch32(cond, left, right);
     Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right)
     {
         return branch32(cond, left, right);
@@ -286,6 +440,11 @@ public:
     {
         return branch32(cond, left, TrustedImm32(right));
     }
     {
         return branch32(cond, left, TrustedImm32(right));
     }
+    
+    Jump branchPtr(RelationalCondition cond, RegisterID left, ImmPtr right)
+    {
+        return branch32(cond, left, Imm32(right.asTrustedImmPtr()));
+    }
 
     Jump branchPtr(RelationalCondition cond, RegisterID left, Address right)
     {
 
     Jump branchPtr(RelationalCondition cond, RegisterID left, Address right)
     {
@@ -306,7 +465,7 @@ public:
     {
         return branch32(cond, left, TrustedImm32(right));
     }
     {
         return branch32(cond, left, TrustedImm32(right));
     }
-
+    
     Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, TrustedImmPtr right)
     {
         return branch32(cond, left, TrustedImm32(right));
     Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, TrustedImmPtr right)
     {
         return branch32(cond, left, TrustedImm32(right));
@@ -332,7 +491,6 @@ public:
         return branchTest32(cond, address, mask);
     }
 
         return branchTest32(cond, address, mask);
     }
 
-
     Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         return branchAdd32(cond, src, dest);
     Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         return branchAdd32(cond, src, dest);
@@ -347,12 +505,527 @@ public:
     {
         return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask);
     }
     {
         return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask);
     }
+#else
+    
+#if ENABLE(JIT_CONSTANT_BLINDING)
+    using MacroAssemblerBase::addPtr;
+    using MacroAssemblerBase::andPtr;
+    using MacroAssemblerBase::branchSubPtr;
+    using MacroAssemblerBase::convertInt32ToDouble;
+    using MacroAssemblerBase::storePtr;
+    using MacroAssemblerBase::subPtr;
+    using MacroAssemblerBase::xorPtr;
+    
+    bool shouldBlindDouble(double value)
+    {
+        // Don't trust NaN or +/-Infinity
+        if (!isfinite(value))
+            return true;
+
+        // Try to force normalisation, and check that there's no change
+        // in the bit pattern
+        if (bitwise_cast<uintptr_t>(value * 1.0) != bitwise_cast<uintptr_t>(value))
+            return true;
+
+        value = abs(value);
+        // Only allow a limited set of fractional components
+        double scaledValue = value * 8;
+        if (scaledValue / 8 != value)
+            return true;
+        double frac = scaledValue - floor(scaledValue);
+        if (frac != 0.0)
+            return true;
+
+        return value > 0xff;
+    }
+    
+    bool shouldBlind(ImmPtr imm)
+    { 
+#if !defined(NDEBUG)
+        UNUSED_PARAM(imm);
+        // Debug always blind all constants, if only so we know
+        // if we've broken blinding during patch development.
+        return true;        
+#endif
+
+        // First off we'll special case common, "safe" values to avoid hurting
+        // performance too much
+        uintptr_t value = imm.asTrustedImmPtr().asIntptr();
+        switch (value) {
+        case 0xffff:
+        case 0xffffff:
+        case 0xffffffffL:
+        case 0xffffffffffL:
+        case 0xffffffffffffL:
+        case 0xffffffffffffffL:
+        case 0xffffffffffffffffL:
+            return false;
+        default: {
+            if (value <= 0xff)
+                return false;
+#if CPU(X86_64)
+            JSValue jsValue = JSValue::decode(reinterpret_cast<void*>(value));
+            if (jsValue.isInt32())
+                return shouldBlind(Imm32(jsValue.asInt32()));
+            if (jsValue.isDouble() && !shouldBlindDouble(jsValue.asDouble()))
+                return false;
+
+            if (!shouldBlindDouble(bitwise_cast<double>(value)))
+                return false;
+#endif 
+        }
+        }
+        return shouldBlindForSpecificArch(value);
+    }
+    
+    struct RotatedImmPtr {
+        RotatedImmPtr(uintptr_t v1, uint8_t v2)
+            : value(v1)
+            , rotation(v2)
+        {
+        }
+        TrustedImmPtr value;
+        TrustedImm32 rotation;
+    };
+    
+    RotatedImmPtr rotationBlindConstant(ImmPtr imm)
+    {
+        uint8_t rotation = random() % (sizeof(void*) * 8);
+        uintptr_t value = imm.asTrustedImmPtr().asIntptr();
+        value = (value << rotation) | (value >> (sizeof(void*) * 8 - rotation));
+        return RotatedImmPtr(value, rotation);
+    }
+    
+    void loadRotationBlindedConstant(RotatedImmPtr constant, RegisterID dest)
+    {
+        move(constant.value, dest);
+        rotateRightPtr(constant.rotation, dest);
+    }
+
+    void convertInt32ToDouble(Imm32 imm, FPRegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            RegisterID scratchRegister = scratchRegisterForBlinding();
+            loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister);
+            convertInt32ToDouble(scratchRegister, dest);
+        } else
+            convertInt32ToDouble(imm.asTrustedImm32(), dest);
+    }
+
+    void move(ImmPtr imm, RegisterID dest)
+    {
+        if (shouldBlind(imm))
+            loadRotationBlindedConstant(rotationBlindConstant(imm), dest);
+        else
+            move(imm.asTrustedImmPtr(), dest);
+    }
+
+    Jump branchPtr(RelationalCondition cond, RegisterID left, ImmPtr right)
+    {
+        if (shouldBlind(right)) {
+            RegisterID scratchRegister = scratchRegisterForBlinding();
+            loadRotationBlindedConstant(rotationBlindConstant(right), scratchRegister);
+            return branchPtr(cond, left, scratchRegister);
+        }
+        return branchPtr(cond, left, right.asTrustedImmPtr());
+    }
+    
+    void storePtr(ImmPtr imm, Address dest)
+    {
+        if (shouldBlind(imm)) {
+            RegisterID scratchRegister = scratchRegisterForBlinding();
+            loadRotationBlindedConstant(rotationBlindConstant(imm), scratchRegister);
+            storePtr(scratchRegister, dest);
+        } else
+            storePtr(imm.asTrustedImmPtr(), dest);
+    }
+
 #endif
 
 #endif
 
+#endif // !CPU(X86_64)
+
+#if ENABLE(JIT_CONSTANT_BLINDING)
+    bool shouldBlind(Imm32 imm)
+    { 
+#if !defined(NDEBUG)
+        UNUSED_PARAM(imm);
+        // Debug always blind all constants, if only so we know
+        // if we've broken blinding during patch development.
+        return true;
+#else
+
+        // First off we'll special case common, "safe" values to avoid hurting
+        // performance too much
+        uint32_t value = imm.asTrustedImm32().m_value;
+        switch (value) {
+        case 0xffff:
+        case 0xffffff:
+        case 0xffffffff:
+            return false;
+        default:
+            if (value <= 0xff)
+                return false;
+        }
+        return shouldBlindForSpecificArch(value);
+#endif
+    }
+
+    struct BlindedImm32 {
+        BlindedImm32(int32_t v1, int32_t v2)
+            : value1(v1)
+            , value2(v2)
+        {
+        }
+        TrustedImm32 value1;
+        TrustedImm32 value2;
+    };
+
+    uint32_t keyForConstant(uint32_t value, uint32_t& mask)
+    {
+        uint32_t key = random();
+        if (value <= 0xff)
+            mask = 0xff;
+        else if (value <= 0xffff)
+            mask = 0xffff;
+        else if (value <= 0xffffff)
+            mask = 0xffffff;
+        else
+            mask = 0xffffffff;
+        return key & mask;
+    }
+
+    uint32_t keyForConstant(uint32_t value)
+    {
+        uint32_t mask = 0;
+        return keyForConstant(value, mask);
+    }
+
+    BlindedImm32 xorBlindConstant(Imm32 imm)
+    {
+        uint32_t baseValue = imm.asTrustedImm32().m_value;
+        uint32_t key = keyForConstant(baseValue);
+        return BlindedImm32(baseValue ^ key, key);
+    }
+
+    BlindedImm32 additionBlindedConstant(Imm32 imm)
+    {
+        // The addition immediate may be used as a pointer offset. Keep aligned based on "imm".
+        static uint32_t maskTable[4] = { 0xfffffffc, 0xffffffff, 0xfffffffe, 0xffffffff };
+
+        uint32_t baseValue = imm.asTrustedImm32().m_value;
+        uint32_t key = keyForConstant(baseValue) & maskTable[baseValue & 3];
+        if (key > baseValue)
+            key = key - baseValue;
+        return BlindedImm32(baseValue - key, key);
+    }
+    
+    BlindedImm32 andBlindedConstant(Imm32 imm)
+    {
+        uint32_t baseValue = imm.asTrustedImm32().m_value;
+        uint32_t mask = 0;
+        uint32_t key = keyForConstant(baseValue, mask);
+        ASSERT((baseValue & mask) == baseValue);
+        return BlindedImm32(((baseValue & key) | ~key) & mask, ((baseValue & ~key) | key) & mask);
+    }
+    
+    BlindedImm32 orBlindedConstant(Imm32 imm)
+    {
+        uint32_t baseValue = imm.asTrustedImm32().m_value;
+        uint32_t mask = 0;
+        uint32_t key = keyForConstant(baseValue, mask);
+        ASSERT((baseValue & mask) == baseValue);
+        return BlindedImm32((baseValue & key) & mask, (baseValue & ~key) & mask);
+    }
+    
+    void loadXorBlindedConstant(BlindedImm32 constant, RegisterID dest)
+    {
+        move(constant.value1, dest);
+        xor32(constant.value2, dest);
+    }
+    
+    void add32(Imm32 imm, RegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            BlindedImm32 key = additionBlindedConstant(imm);
+            add32(key.value1, dest);
+            add32(key.value2, dest);
+        } else
+            add32(imm.asTrustedImm32(), dest);
+    }
+    
+    void addPtr(Imm32 imm, RegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            BlindedImm32 key = additionBlindedConstant(imm);
+            addPtr(key.value1, dest);
+            addPtr(key.value2, dest);
+        } else
+            addPtr(imm.asTrustedImm32(), dest);
+    }
+
+    void and32(Imm32 imm, RegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            BlindedImm32 key = andBlindedConstant(imm);
+            and32(key.value1, dest);
+            and32(key.value2, dest);
+        } else
+            and32(imm.asTrustedImm32(), dest);
+    }
+
+    void andPtr(Imm32 imm, RegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            BlindedImm32 key = andBlindedConstant(imm);
+            andPtr(key.value1, dest);
+            andPtr(key.value2, dest);
+        } else
+            andPtr(imm.asTrustedImm32(), dest);
+    }
+    
+    void and32(Imm32 imm, RegisterID src, RegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            if (src == dest)
+                return and32(imm.asTrustedImm32(), dest);
+            loadXorBlindedConstant(xorBlindConstant(imm), dest);
+            and32(src, dest);
+        } else
+            and32(imm.asTrustedImm32(), src, dest);
+    }
+
+    void move(Imm32 imm, RegisterID dest)
+    {
+        if (shouldBlind(imm))
+            loadXorBlindedConstant(xorBlindConstant(imm), dest);
+        else
+            move(imm.asTrustedImm32(), dest);
+    }
+    
+    void or32(Imm32 imm, RegisterID src, RegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            if (src == dest)
+                return or32(imm, dest);
+            loadXorBlindedConstant(xorBlindConstant(imm), dest);
+            or32(src, dest);
+        } else
+            or32(imm.asTrustedImm32(), src, dest);
+    }
+    
+    void or32(Imm32 imm, RegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            BlindedImm32 key = orBlindedConstant(imm);
+            or32(key.value1, dest);
+            or32(key.value2, dest);
+        } else
+            or32(imm.asTrustedImm32(), dest);
+    }
+    
+    void poke(Imm32 value, int index = 0)
+    {
+        store32(value, addressForPoke(index));
+    }
+    
+    void poke(ImmPtr value, int index = 0)
+    {
+        storePtr(value, addressForPoke(index));
+    }
+    
+    void store32(Imm32 imm, Address dest)
+    {
+        if (shouldBlind(imm)) {
+#if CPU(X86) || CPU(X86_64)
+            BlindedImm32 blind = xorBlindConstant(imm);
+            store32(blind.value1, dest);
+            xor32(blind.value2, dest);
+#else
+            if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
+                loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister);
+                store32(scratchRegister, dest);
+            } else {
+                // If we don't have a scratch register available for use, we'll just 
+                // place a random number of nops.
+                uint32_t nopCount = random() & 3;
+                while (nopCount--)
+                    nop();
+                store32(imm.asTrustedImm32(), dest);
+            }
+#endif
+        } else
+            store32(imm.asTrustedImm32(), dest);
+    }
+    
+    void sub32(Imm32 imm, RegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            BlindedImm32 key = additionBlindedConstant(imm);
+            sub32(key.value1, dest);
+            sub32(key.value2, dest);
+        } else
+            sub32(imm.asTrustedImm32(), dest);
+    }
+    
+    void subPtr(Imm32 imm, RegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            BlindedImm32 key = additionBlindedConstant(imm);
+            subPtr(key.value1, dest);
+            subPtr(key.value2, dest);
+        } else
+            subPtr(imm.asTrustedImm32(), dest);
+    }
+    
+    void xor32(Imm32 imm, RegisterID src, RegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            BlindedImm32 blind = xorBlindConstant(imm);
+            xor32(blind.value1, src, dest);
+            xor32(blind.value2, dest);
+        } else
+            xor32(imm.asTrustedImm32(), src, dest);
+    }
+    
+    void xor32(Imm32 imm, RegisterID dest)
+    {
+        if (shouldBlind(imm)) {
+            BlindedImm32 blind = xorBlindConstant(imm);
+            xor32(blind.value1, dest);
+            xor32(blind.value2, dest);
+        } else
+            xor32(imm.asTrustedImm32(), dest);
+    }
+
+    Jump branch32(RelationalCondition cond, RegisterID left, Imm32 right)
+    {
+        if (shouldBlind(right)) {
+            if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
+                loadXorBlindedConstant(xorBlindConstant(right), scratchRegister);
+                return branch32(cond, left, scratchRegister);
+            }
+            // If we don't have a scratch register available for use, we'll just 
+            // place a random number of nops.
+            uint32_t nopCount = random() & 3;
+            while (nopCount--)
+                nop();
+            return branch32(cond, left, right.asTrustedImm32());
+        }
+        
+        return branch32(cond, left, right.asTrustedImm32());
+    }
+
+    Jump branchAdd32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest)
+    {
+        if (src == dest) {
+            if (!scratchRegisterForBlinding()) {
+                // Release mode ASSERT, if this fails we will perform incorrect codegen.
+                CRASH();
+            }
+        }
+        if (shouldBlind(imm)) {
+            if (src == dest) {
+                if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
+                    move(src, scratchRegister);
+                    src = scratchRegister;
+                }
+            }
+            loadXorBlindedConstant(xorBlindConstant(imm), dest);
+            return branchAdd32(cond, src, dest);  
+        }
+        return branchAdd32(cond, src, imm.asTrustedImm32(), dest);            
+    }
+    
+    Jump branchMul32(ResultCondition cond, Imm32 imm, RegisterID src, RegisterID dest)
+    {
+        if (src == dest) {
+            if (!scratchRegisterForBlinding()) {
+                // Release mode ASSERT, if this fails we will perform incorrect codegen.
+                CRASH();
+            }
+        }
+        if (shouldBlind(imm)) {
+            if (src == dest) {
+                if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
+                    move(src, scratchRegister);
+                    src = scratchRegister;
+                }
+            }
+            loadXorBlindedConstant(xorBlindConstant(imm), dest);
+            return branchMul32(cond, src, dest);  
+        }
+        return branchMul32(cond, imm.asTrustedImm32(), src, dest);
+    }
+
+    // branchSub32 takes a scratch register as 32 bit platforms make use of this,
+    // with src == dst, and on x86-32 we don't have a platform scratch register.
+    Jump branchSub32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest, RegisterID scratch)
+    {
+        if (shouldBlind(imm)) {
+            ASSERT(scratch != dest);
+            ASSERT(scratch != src);
+            loadXorBlindedConstant(xorBlindConstant(imm), scratch);
+            return branchSub32(cond, src, scratch, dest);
+        }
+        return branchSub32(cond, src, imm.asTrustedImm32(), dest);            
+    }
+    
+    // Immediate shifts only have 5 controllable bits
+    // so we'll consider them safe for now.
+    TrustedImm32 trustedImm32ForShift(Imm32 imm)
+    {
+        return TrustedImm32(imm.asTrustedImm32().m_value & 31);
+    }
+
+    void lshift32(Imm32 imm, RegisterID dest)
+    {
+        lshift32(trustedImm32ForShift(imm), dest);
+    }
+    
+    void lshift32(RegisterID src, Imm32 amount, RegisterID dest)
+    {
+        lshift32(src, trustedImm32ForShift(amount), dest);
+    }
+    
+    void rshift32(Imm32 imm, RegisterID dest)
+    {
+        rshift32(trustedImm32ForShift(imm), dest);
+    }
+    
+    void rshift32(RegisterID src, Imm32 amount, RegisterID dest)
+    {
+        rshift32(src, trustedImm32ForShift(amount), dest);
+    }
+    
+    void urshift32(Imm32 imm, RegisterID dest)
+    {
+        urshift32(trustedImm32ForShift(imm), dest);
+    }
+    
+    void urshift32(RegisterID src, Imm32 amount, RegisterID dest)
+    {
+        urshift32(src, trustedImm32ForShift(amount), dest);
+    }
+#endif
 };
 
 } // namespace JSC
 
 };
 
 } // namespace JSC
 
+#else // ENABLE(ASSEMBLER)
+
+// If there is no assembler for this platform, at least allow code to make references to
+// some of the things it would otherwise define, albeit without giving that code any way
+// of doing anything useful.
+class MacroAssembler {
+private:
+    MacroAssembler() { }
+    
+public:
+    
+    enum RegisterID { NoRegister };
+    enum FPRegisterID { NoFPRegister };
+};
+
 #endif // ENABLE(ASSEMBLER)
 
 #endif // MacroAssembler_h
 #endif // ENABLE(ASSEMBLER)
 
 #endif // MacroAssembler_h
index b365dce7b47af88f21c3dc4eebe5ab5eed8dd309..829ec532e924b6a7db3f78dbb9b912e20eb23a03 100644 (file)
@@ -108,6 +108,11 @@ public:
         add32(ARMRegisters::S1, dest);
     }
 
         add32(ARMRegisters::S1, dest);
     }
 
+    void add32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.adds_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+    }
+
     void and32(RegisterID src, RegisterID dest)
     {
         m_assembler.ands_r(dest, dest, src);
     void and32(RegisterID src, RegisterID dest)
     {
         m_assembler.ands_r(dest, dest, src);
@@ -122,6 +127,15 @@ public:
             m_assembler.ands_r(dest, dest, w);
     }
 
             m_assembler.ands_r(dest, dest, w);
     }
 
+    void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true);
+        if (w & ARMAssembler::OP2_INV_IMM)
+            m_assembler.bics_r(dest, src, w & ~ARMAssembler::OP2_INV_IMM);
+        else
+            m_assembler.ands_r(dest, src, w);
+    }
+
     void lshift32(RegisterID shift_amount, RegisterID dest)
     {
         ARMWord w = ARMAssembler::getOp2(0x1f);
     void lshift32(RegisterID shift_amount, RegisterID dest)
     {
         ARMWord w = ARMAssembler::getOp2(0x1f);
@@ -136,6 +150,11 @@ public:
         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));
     }
 
+    void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.movs_r(dest, m_assembler.lsl(src, imm.m_value & 0x1f));
+    }
+
     void mul32(RegisterID src, RegisterID dest)
     {
         if (src == dest) {
     void mul32(RegisterID src, RegisterID dest)
     {
         if (src == dest) {
@@ -156,11 +175,6 @@ public:
         m_assembler.rsbs_r(srcDest, srcDest, ARMAssembler::getOp2(0));
     }
 
         m_assembler.rsbs_r(srcDest, srcDest, ARMAssembler::getOp2(0));
     }
 
-    void not32(RegisterID dest)
-    {
-        m_assembler.mvns_r(dest, dest);
-    }
-
     void or32(RegisterID src, RegisterID dest)
     {
         m_assembler.orrs_r(dest, dest, src);
     void or32(RegisterID src, RegisterID dest)
     {
         m_assembler.orrs_r(dest, dest, src);
@@ -171,6 +185,16 @@ public:
         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));
     }
 
+    void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        m_assembler.orrs_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+    }
+
+    void or32(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        m_assembler.orrs_r(dest, op1, op2);
+    }
+
     void rshift32(RegisterID shift_amount, RegisterID dest)
     {
         ARMWord w = ARMAssembler::getOp2(0x1f);
     void rshift32(RegisterID shift_amount, RegisterID dest)
     {
         ARMWord w = ARMAssembler::getOp2(0x1f);
@@ -179,10 +203,15 @@ 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(TrustedImm32 imm, RegisterID dest)
     {
     void rshift32(TrustedImm32 imm, RegisterID dest)
     {
-        m_assembler.movs_r(dest, m_assembler.asr(dest, imm.m_value & 0x1f));
+        rshift32(dest, imm, dest);
+    }
+
+    void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.movs_r(dest, m_assembler.asr(src, imm.m_value & 0x1f));
     }
     
     void urshift32(RegisterID shift_amount, RegisterID dest)
     }
     
     void urshift32(RegisterID shift_amount, RegisterID dest)
@@ -198,6 +227,11 @@ public:
     {
         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));
     }
+    
+    void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.movs_r(dest, m_assembler.lsr(src, imm.m_value & 0x1f));
+    }
 
     void sub32(RegisterID src, RegisterID dest)
     {
 
     void sub32(RegisterID src, RegisterID dest)
     {
@@ -222,6 +256,11 @@ public:
         sub32(ARMRegisters::S1, dest);
     }
 
         sub32(ARMRegisters::S1, dest);
     }
 
+    void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.subs_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+    }
+
     void xor32(RegisterID src, RegisterID dest)
     {
         m_assembler.eors_r(dest, dest, src);
     void xor32(RegisterID src, RegisterID dest)
     {
         m_assembler.eors_r(dest, dest, src);
@@ -229,7 +268,18 @@ public:
 
     void xor32(TrustedImm32 imm, RegisterID dest)
     {
 
     void xor32(TrustedImm32 imm, RegisterID dest)
     {
-        m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+        if (imm.m_value == -1)
+            m_assembler.mvns_r(dest, dest);
+        else
+            m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
+    }
+
+    void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        if (imm.m_value == -1)
+            m_assembler.mvns_r(dest, src);
+        else    
+            m_assembler.eors_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
     }
 
     void countLeadingZeros32(RegisterID src, RegisterID dest)
     }
 
     void countLeadingZeros32(RegisterID src, RegisterID dest)
@@ -248,6 +298,11 @@ public:
         m_assembler.dataTransfer32(true, dest, address.base, address.offset, true);
     }
 
         m_assembler.dataTransfer32(true, dest, address.base, address.offset, true);
     }
 
+    void load8(BaseIndex address, RegisterID dest)
+    {
+        m_assembler.baseIndexTransfer32(true, dest, address.base, address.index, static_cast<int>(address.scale), address.offset, true);
+    }
+
     void load32(ImplicitAddress address, RegisterID dest)
     {
         m_assembler.dataTransfer32(true, dest, address.base, address.offset);
     void load32(ImplicitAddress address, RegisterID dest)
     {
         m_assembler.dataTransfer32(true, dest, address.base, address.offset);
@@ -267,6 +322,11 @@ public:
     }
 #endif
 
     }
 #endif
 
+    void load16Unaligned(BaseIndex address, RegisterID dest)
+    {
+        load16(address, dest);
+    }
+
     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     {
         DataLabel32 dataLabel(this);
     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     {
         DataLabel32 dataLabel(this);
@@ -404,6 +464,13 @@ public:
         return branch32(cond, ARMRegisters::S1, right);
     }
 
         return branch32(cond, ARMRegisters::S1, right);
     }
 
+    Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
+    {
+        ASSERT(!(right.m_value & 0xFFFFFF00));
+        load8(left, ARMRegisters::S1);
+        return branch32(cond, ARMRegisters::S1, right);
+    }
+
     Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
     {
         m_assembler.cmp_r(left, right);
     Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
     {
         m_assembler.cmp_r(left, right);
@@ -416,7 +483,7 @@ public:
             m_assembler.ldr_un_imm(ARMRegisters::S0, right.m_value);
             m_assembler.cmp_r(left, ARMRegisters::S0);
         } else {
             m_assembler.ldr_un_imm(ARMRegisters::S0, right.m_value);
             m_assembler.cmp_r(left, ARMRegisters::S0);
         } else {
-            ARMWord tmp = m_assembler.getOp2(-right.m_value);
+            ARMWord tmp = (right.m_value == 0x80000000) ? ARMAssembler::INVALID_IMM : m_assembler.getOp2(-right.m_value);
             if (tmp != ARMAssembler::INVALID_IMM)
                 m_assembler.cmn_r(left, tmp);
             else
             if (tmp != ARMAssembler::INVALID_IMM)
                 m_assembler.cmn_r(left, tmp);
             else
@@ -455,23 +522,6 @@ public:
         return branch32(cond, ARMRegisters::S1, right);
     }
 
         return branch32(cond, ARMRegisters::S1, right);
     }
 
-    Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right)
-    {
-        UNUSED_PARAM(cond);
-        UNUSED_PARAM(left);
-        UNUSED_PARAM(right);
-        ASSERT_NOT_REACHED();
-        return jump();
-    }
-
-    Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
-    {
-        load16(left, ARMRegisters::S0);
-        move(right, ARMRegisters::S1);
-        m_assembler.cmp_r(ARMRegisters::S0, ARMRegisters::S1);
-        return m_assembler.jmp(ARMCondition(cond));
-    }
-
     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         load8(address, ARMRegisters::S1);
     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         load8(address, ARMRegisters::S1);
@@ -537,6 +587,13 @@ public:
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
+    Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        add32(src, imm, dest);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
     void mull32(RegisterID src1, RegisterID src2, RegisterID dest)
     {
         if (src1 == dest) {
     void mull32(RegisterID src1, RegisterID src2, RegisterID dest)
     {
         if (src1 == dest) {
@@ -586,6 +643,20 @@ public:
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
+    Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        sub32(src, imm, dest);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
+    Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        m_assembler.subs_r(dest, op1, op2);
+        return Jump(m_assembler.jmp(ARMCondition(cond)));
+    }
+
     Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
     Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
@@ -646,6 +717,12 @@ public:
         m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
     }
 
         m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
     }
 
+    void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
+    {
+        load8(left, ARMRegisters::S1);
+        compare32(cond, ARMRegisters::S1, right, dest);
+    }
+
     void test32(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
     {
         if (mask.m_value == -1)
     void test32(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
     {
         if (mask.m_value == -1)
@@ -775,20 +852,21 @@ public:
     }
 
     // Floating point operators
     }
 
     // Floating point operators
-    bool supportsFloatingPoint() const
+    static bool supportsFloatingPoint()
     {
         return s_isVFPPresent;
     }
 
     {
         return s_isVFPPresent;
     }
 
-    bool supportsFloatingPointTruncate() const
+    static bool supportsFloatingPointTruncate()
     {
     {
-        return s_isVFPPresent;
+        return false;
     }
 
     }
 
-    bool supportsFloatingPointSqrt() const
+    static bool supportsFloatingPointSqrt()
     {
         return s_isVFPPresent;
     }
     {
         return s_isVFPPresent;
     }
+    static bool supportsFloatingPointAbs() { return false; }
 
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
 
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
@@ -855,6 +933,11 @@ public:
     {
         m_assembler.vsqrt_f64_r(dest, src);
     }
     {
         m_assembler.vsqrt_f64_r(dest, src);
     }
+    
+    void absDouble(FPRegisterID, FPRegisterID)
+    {
+        ASSERT_NOT_REACHED();
+    }
 
     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
     {
 
     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
     {
@@ -891,17 +974,13 @@ 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 and INT_MAX).
+    // (specifically, in this case, INT_MIN).
     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     {
     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     {
-        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)));
+        UNUSED_PARAM(src);
+        UNUSED_PARAM(dest);
+        ASSERT_NOT_REACHED();
+        return jump();
     }
 
     // Convert 'src' to an integer, and places the resulting 'dest'.
     }
 
     // Convert 'src' to an integer, and places the resulting 'dest'.
@@ -940,6 +1019,11 @@ public:
         m_assembler.nop();
     }
 
         m_assembler.nop();
     }
 
+    static FunctionPtr readCallTarget(CodeLocationCall call)
+    {
+        return FunctionPtr(reinterpret_cast<void(*)()>(ARMAssembler::readCallTarget(call.dataLocation())));
+    }
+
 protected:
     ARMAssembler::Condition ARMCondition(RelationalCondition cond)
     {
 protected:
     ARMAssembler::Condition ARMCondition(RelationalCondition cond)
     {
@@ -1021,7 +1105,7 @@ private:
 
     static void linkCall(void* code, Call call, FunctionPtr function)
     {
 
     static void linkCall(void* code, Call call, FunctionPtr function)
     {
-        ARMAssembler::linkCall(code, call.m_jmp, function.value());
+        ARMAssembler::linkCall(code, call.m_label, function.value());
     }
 
     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
     }
 
     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
index 70b2552363f79a321392f83dd0e28d5f6c3b42ed..b72717a6d54fb4d5b581ceb77e5f9c8c0eeb8b2c 100644 (file)
@@ -45,20 +45,18 @@ class MacroAssemblerARMv7 : public AbstractMacroAssembler<ARMv7Assembler> {
     inline ARMRegisters::FPSingleRegisterID fpTempRegisterAsSingle() { return ARMRegisters::asSingle(fpTempRegister); }
 
 public:
     inline ARMRegisters::FPSingleRegisterID fpTempRegisterAsSingle() { return ARMRegisters::asSingle(fpTempRegister); }
 
 public:
+    MacroAssemblerARMv7()
+        : m_makeJumpPatchable(false)
+    {
+    }
+
     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;
     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)
-    {
-    }
     
     
-    void beginUninterruptedSequence() { m_inUninterruptedSequence = true; }
-    void endUninterruptedSequence() { m_inUninterruptedSequence = false; }
     Vector<LinkRecord>& jumpsToLink() { return m_assembler.jumpsToLink(); }
     void* unlinkedCode() { return m_assembler.unlinkedCode(); }
     bool canCompact(JumpType jumpType) { return m_assembler.canCompact(jumpType); }
     Vector<LinkRecord>& jumpsToLink() { return m_assembler.jumpsToLink(); }
     void* unlinkedCode() { return m_assembler.unlinkedCode(); }
     bool canCompact(JumpType jumpType) { return m_assembler.canCompact(jumpType); }
@@ -211,40 +209,80 @@ public:
         store32(dataTempRegister, address.m_ptr);
     }
 
         store32(dataTempRegister, address.m_ptr);
     }
 
-    void and32(RegisterID src, RegisterID dest)
+    void add64(TrustedImm32 imm, AbsoluteAddress address)
+    {
+        move(TrustedImmPtr(address.m_ptr), addressTempRegister);
+
+        m_assembler.ldr(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt12(0));
+        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
+        if (armImm.isValid())
+            m_assembler.add_S(dataTempRegister, dataTempRegister, armImm);
+        else {
+            move(imm, addressTempRegister);
+            m_assembler.add_S(dataTempRegister, dataTempRegister, addressTempRegister);
+            move(TrustedImmPtr(address.m_ptr), addressTempRegister);
+        }
+        m_assembler.str(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt12(0));
+
+        m_assembler.ldr(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt12(4));
+        m_assembler.adc(dataTempRegister, dataTempRegister, ARMThumbImmediate::makeEncodedImm(imm.m_value >> 31));
+        m_assembler.str(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt12(4));
+    }
+
+    void and32(RegisterID op1, RegisterID op2, RegisterID dest)
     {
     {
-        m_assembler.ARM_and(dest, dest, src);
+        m_assembler.ARM_and(dest, op1, op2);
     }
 
     }
 
-    void and32(TrustedImm32 imm, RegisterID dest)
+    void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
-            m_assembler.ARM_and(dest, dest, armImm);
+            m_assembler.ARM_and(dest, src, armImm);
         else {
             move(imm, dataTempRegister);
         else {
             move(imm, dataTempRegister);
-            m_assembler.ARM_and(dest, dest, dataTempRegister);
+            m_assembler.ARM_and(dest, src, dataTempRegister);
         }
     }
 
         }
     }
 
+    void and32(RegisterID src, RegisterID dest)
+    {
+        and32(dest, src, dest);
+    }
+
+    void and32(TrustedImm32 imm, RegisterID dest)
+    {
+        and32(imm, dest, dest);
+    }
+
     void countLeadingZeros32(RegisterID src, RegisterID dest)
     {
         m_assembler.clz(dest, src);
     }
 
     void countLeadingZeros32(RegisterID src, RegisterID dest)
     {
         m_assembler.clz(dest, src);
     }
 
-    void lshift32(RegisterID shift_amount, RegisterID dest)
+    void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
     {
         // Clamp the shift to the range 0..31
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
         ASSERT(armImm.isValid());
     {
         // Clamp the shift to the range 0..31
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
         ASSERT(armImm.isValid());
-        m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
+        m_assembler.ARM_and(dataTempRegister, shiftAmount, armImm);
+
+        m_assembler.lsl(dest, src, dataTempRegister);
+    }
 
 
-        m_assembler.lsl(dest, dest, dataTempRegister);
+    void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.lsl(dest, src, imm.m_value & 0x1f);
+    }
+
+    void lshift32(RegisterID shiftAmount, RegisterID dest)
+    {
+        lshift32(dest, shiftAmount, dest);
     }
 
     void lshift32(TrustedImm32 imm, RegisterID dest)
     {
     }
 
     void lshift32(TrustedImm32 imm, RegisterID dest)
     {
-        m_assembler.lsl(dest, dest, imm.m_value & 0x1f);
+        lshift32(dest, imm, dest);
     }
 
     void mul32(RegisterID src, RegisterID dest)
     }
 
     void mul32(RegisterID src, RegisterID dest)
@@ -263,55 +301,80 @@ public:
         m_assembler.neg(srcDest, srcDest);
     }
 
         m_assembler.neg(srcDest, srcDest);
     }
 
-    void not32(RegisterID srcDest)
-    {
-        m_assembler.mvn(srcDest, srcDest);
-    }
-
     void or32(RegisterID src, RegisterID dest)
     {
         m_assembler.orr(dest, dest, src);
     }
 
     void or32(TrustedImm32 imm, RegisterID dest)
     void or32(RegisterID src, RegisterID dest)
     {
         m_assembler.orr(dest, dest, src);
     }
 
     void or32(TrustedImm32 imm, RegisterID dest)
+    {
+        or32(imm, dest, dest);
+    }
+
+    void or32(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        m_assembler.orr(dest, op1, op2);
+    }
+
+    void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
-            m_assembler.orr(dest, dest, armImm);
+            m_assembler.orr(dest, src, armImm);
         else {
             move(imm, dataTempRegister);
         else {
             move(imm, dataTempRegister);
-            m_assembler.orr(dest, dest, dataTempRegister);
+            m_assembler.orr(dest, src, dataTempRegister);
         }
     }
 
         }
     }
 
-    void rshift32(RegisterID shift_amount, RegisterID dest)
+    void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
     {
         // Clamp the shift to the range 0..31
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
         ASSERT(armImm.isValid());
     {
         // Clamp the shift to the range 0..31
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
         ASSERT(armImm.isValid());
-        m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
+        m_assembler.ARM_and(dataTempRegister, shiftAmount, armImm);
 
 
-        m_assembler.asr(dest, dest, dataTempRegister);
+        m_assembler.asr(dest, src, dataTempRegister);
     }
 
     }
 
-    void rshift32(TrustedImm32 imm, RegisterID dest)
+    void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.asr(dest, src, imm.m_value & 0x1f);
+    }
+
+    void rshift32(RegisterID shiftAmount, RegisterID dest)
     {
     {
-        m_assembler.asr(dest, dest, imm.m_value & 0x1f);
+        rshift32(dest, shiftAmount, dest);
     }
     
     }
     
-    void urshift32(RegisterID shift_amount, RegisterID dest)
+    void rshift32(TrustedImm32 imm, RegisterID dest)
+    {
+        rshift32(dest, imm, dest);
+    }
+
+    void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
     {
         // Clamp the shift to the range 0..31
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
         ASSERT(armImm.isValid());
     {
         // Clamp the shift to the range 0..31
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
         ASSERT(armImm.isValid());
-        m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
+        m_assembler.ARM_and(dataTempRegister, shiftAmount, armImm);
         
         
-        m_assembler.lsr(dest, dest, dataTempRegister);
+        m_assembler.lsr(dest, src, dataTempRegister);
+    }
+    
+    void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.lsr(dest, src, imm.m_value & 0x1f);
+    }
+
+    void urshift32(RegisterID shiftAmount, RegisterID dest)
+    {
+        urshift32(dest, shiftAmount, dest);
     }
     
     void urshift32(TrustedImm32 imm, RegisterID dest)
     {
     }
     
     void urshift32(TrustedImm32 imm, RegisterID dest)
     {
-        m_assembler.lsr(dest, dest, imm.m_value & 0x1f);
+        urshift32(dest, imm, dest);
     }
 
     void sub32(RegisterID src, RegisterID dest)
     }
 
     void sub32(RegisterID src, RegisterID dest)
@@ -370,21 +433,39 @@ public:
         store32(dataTempRegister, address.m_ptr);
     }
 
         store32(dataTempRegister, address.m_ptr);
     }
 
-    void xor32(RegisterID src, RegisterID dest)
+    void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
     {
     {
-        m_assembler.eor(dest, dest, src);
+        m_assembler.eor(dest, op1, op2);
     }
 
     }
 
-    void xor32(TrustedImm32 imm, RegisterID dest)
+    void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
     {
+        if (imm.m_value == -1) {
+            m_assembler.mvn(dest, src);
+            return;
+        }
+
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
-            m_assembler.eor(dest, dest, armImm);
+            m_assembler.eor(dest, src, armImm);
         else {
             move(imm, dataTempRegister);
         else {
             move(imm, dataTempRegister);
-            m_assembler.eor(dest, dest, dataTempRegister);
+            m_assembler.eor(dest, src, dataTempRegister);
         }
     }
         }
     }
+
+    void xor32(RegisterID src, RegisterID dest)
+    {
+        xor32(dest, src, dest);
+    }
+
+    void xor32(TrustedImm32 imm, RegisterID dest)
+    {
+        if (imm.m_value == -1)
+            m_assembler.mvn(dest, dest);
+        else
+            xor32(imm, dest, dest);
+    }
     
 
     // Memory access operations:
     
 
     // Memory access operations:
@@ -422,6 +503,12 @@ private:
             m_assembler.ldrh(dest, address.base, address.u.offset, true, false);
         }
     }
             m_assembler.ldrh(dest, address.base, address.u.offset, true, false);
         }
     }
+    
+    void load16Signed(ArmAddress address, RegisterID dest)
+    {
+        ASSERT(address.type == ArmAddress::HasIndex);
+        m_assembler.ldrsh(dest, address.base, address.u.index, address.u.scale);
+    }
 
     void load8(ArmAddress address, RegisterID dest)
     {
 
     void load8(ArmAddress address, RegisterID dest)
     {
@@ -436,7 +523,14 @@ private:
             m_assembler.ldrb(dest, address.base, address.u.offset, true, false);
         }
     }
             m_assembler.ldrb(dest, address.base, address.u.offset, true, false);
         }
     }
+    
+    void load8Signed(ArmAddress address, RegisterID dest)
+    {
+        ASSERT(address.type == ArmAddress::HasIndex);
+        m_assembler.ldrsb(dest, address.base, address.u.index, address.u.scale);
+    }
 
 
+protected:
     void store32(RegisterID src, ArmAddress address)
     {
         if (address.type == ArmAddress::HasIndex)
     void store32(RegisterID src, ArmAddress address)
     {
         if (address.type == ArmAddress::HasIndex)
@@ -451,6 +545,35 @@ private:
         }
     }
 
         }
     }
 
+private:
+    void store8(RegisterID src, ArmAddress address)
+    {
+        if (address.type == ArmAddress::HasIndex)
+            m_assembler.strb(src, address.base, address.u.index, address.u.scale);
+        else if (address.u.offset >= 0) {
+            ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12(address.u.offset);
+            ASSERT(armImm.isValid());
+            m_assembler.strb(src, address.base, armImm);
+        } else {
+            ASSERT(address.u.offset >= -255);
+            m_assembler.strb(src, address.base, address.u.offset, true, false);
+        }
+    }
+    
+    void store16(RegisterID src, ArmAddress address)
+    {
+        if (address.type == ArmAddress::HasIndex)
+            m_assembler.strh(src, address.base, address.u.index, address.u.scale);
+        else if (address.u.offset >= 0) {
+            ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12(address.u.offset);
+            ASSERT(armImm.isValid());
+            m_assembler.strh(src, address.base, armImm);
+        } else {
+            ASSERT(address.u.offset >= -255);
+            m_assembler.strh(src, address.base, address.u.offset, true, false);
+        }
+    }
+
 public:
     void load32(ImplicitAddress address, RegisterID dest)
     {
 public:
     void load32(ImplicitAddress address, RegisterID dest)
     {
@@ -467,6 +590,11 @@ public:
         load32(setupArmAddress(address), dest);
     }
 
         load32(setupArmAddress(address), dest);
     }
 
+    void load16Unaligned(BaseIndex address, RegisterID dest)
+    {
+        load16(setupArmAddress(address), dest);
+    }
+
     void load32(const void* address, RegisterID dest)
     {
         move(TrustedImmPtr(address), addressTempRegister);
     void load32(const void* address, RegisterID dest)
     {
         move(TrustedImmPtr(address), addressTempRegister);
@@ -478,6 +606,21 @@ public:
         load8(setupArmAddress(address), dest);
     }
 
         load8(setupArmAddress(address), dest);
     }
 
+    void load8Signed(ImplicitAddress, RegisterID)
+    {
+        unreachableForPlatform();
+    }
+
+    void load8(BaseIndex address, RegisterID dest)
+    {
+        load8(setupArmAddress(address), dest);
+    }
+    
+    void load8Signed(BaseIndex address, RegisterID dest)
+    {
+        load8Signed(setupArmAddress(address), dest);
+    }
+
     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     {
         DataLabel32 label = moveWithPatch(TrustedImm32(address.offset), dataTempRegister);
     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     {
         DataLabel32 label = moveWithPatch(TrustedImm32(address.offset), dataTempRegister);
@@ -485,13 +628,26 @@ public:
         return label;
     }
     
         return label;
     }
     
+    // FIXME: we should be able to plant a compact load relative to/from any base/dest register.
     DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
     {
     DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
     {
+        RegisterID base = address.base;
+        
+        if (base >= ARMRegisters::r8) {
+            move(base, addressTempRegister);
+            base = addressTempRegister;
+        }
+
         DataLabelCompact label(this);
         ASSERT(address.offset >= 0);
         ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset);
         ASSERT(ARMThumbImmediate::makeUInt12(address.offset).isUInt7());
         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));
+
+        if (dest >= ARMRegisters::r8) {
+            m_assembler.ldrCompact(addressTempRegister, base, ARMThumbImmediate::makeUInt12(address.offset));
+            move(addressTempRegister, dest);
+        } else
+            m_assembler.ldrCompact(dest, base, ARMThumbImmediate::makeUInt12(address.offset));
         return label;
     }
 
         return label;
     }
 
@@ -500,6 +656,11 @@ public:
         m_assembler.ldrh(dest, makeBaseIndexBase(address), address.index, address.scale);
     }
     
         m_assembler.ldrh(dest, makeBaseIndexBase(address), address.index, address.scale);
     }
     
+    void load16Signed(BaseIndex address, RegisterID dest)
+    {
+        load16Signed(setupArmAddress(address), dest);
+    }
+    
     void load16(ImplicitAddress address, RegisterID dest)
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12(address.offset);
     void load16(ImplicitAddress address, RegisterID dest)
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12(address.offset);
@@ -510,6 +671,11 @@ public:
             m_assembler.ldrh(dest, address.base, dataTempRegister);
         }
     }
             m_assembler.ldrh(dest, address.base, dataTempRegister);
         }
     }
+    
+    void load16Signed(ImplicitAddress, RegisterID)
+    {
+        unreachableForPlatform();
+    }
 
     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
     {
 
     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
     {
@@ -534,6 +700,12 @@ public:
         store32(dataTempRegister, setupArmAddress(address));
     }
 
         store32(dataTempRegister, setupArmAddress(address));
     }
 
+    void store32(TrustedImm32 imm, BaseIndex address)
+    {
+        move(imm, dataTempRegister);
+        store32(dataTempRegister, setupArmAddress(address));
+    }
+
     void store32(RegisterID src, const void* address)
     {
         move(TrustedImmPtr(address), addressTempRegister);
     void store32(RegisterID src, const void* address)
     {
         move(TrustedImmPtr(address), addressTempRegister);
@@ -546,27 +718,42 @@ public:
         store32(dataTempRegister, address);
     }
 
         store32(dataTempRegister, address);
     }
 
+    void store8(RegisterID src, BaseIndex address)
+    {
+        store8(src, setupArmAddress(address));
+    }
+    
+    void store16(RegisterID src, BaseIndex address)
+    {
+        store16(src, setupArmAddress(address));
+    }
 
 
-    // Floating-point operations:
+#if ENABLE(JIT_CONSTANT_BLINDING)
+    static bool shouldBlindForSpecificArch(uint32_t value)
+    {
+        ARMThumbImmediate immediate = ARMThumbImmediate::makeEncodedImm(value);
 
 
-    bool supportsFloatingPoint() const { return true; }
-    // On x86(_64) the MacroAssembler provides an interface to truncate a double to an integer.
-    // If a value is not representable as an integer, and possibly for some values that are,
-    // (on x86 INT_MIN, since this is indistinguishable from results for out-of-range/NaN input)
-    // a branch will  be taken.  It is not clear whether this interface will be well suited to
-    // other platforms.  On ARMv7 the hardware truncation operation produces multiple possible
-    // failure values (saturates to INT_MIN & INT_MAX, NaN reulsts in a value of 0).  This is a
-    // temporary solution while we work out what this interface should be.  Either we need to
-    // decide to make this interface work on all platforms, rework the interface to make it more
-    // generic, or decide that the MacroAssembler cannot practically be used to abstracted these
-    // operations, and make clients go directly to the m_assembler to plant truncation instructions.
-    // In short, FIXME:.
-    bool supportsFloatingPointTruncate() const { return false; }
+        // Couldn't be encoded as an immediate, so assume it's untrusted.
+        if (!immediate.isValid())
+            return true;
+        
+        // If we can encode the immediate, we have less than 16 attacker
+        // controlled bits.
+        if (immediate.isEncodedImm())
+            return false;
 
 
-    bool supportsFloatingPointSqrt() const
-    {
-        return false;
+        // Don't let any more than 12 bits of an instruction word
+        // be controlled by an attacker.
+        return !immediate.isUInt12();
     }
     }
+#endif
+
+    // Floating-point operations:
+
+    static bool supportsFloatingPoint() { return true; }
+    static bool supportsFloatingPointTruncate() { return true; }
+    static bool supportsFloatingPointSqrt() { return true; }
+    static bool supportsFloatingPointAbs() { return true; }
 
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
 
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
@@ -583,6 +770,43 @@ public:
         m_assembler.vldr(dest, base, offset);
     }
 
         m_assembler.vldr(dest, base, offset);
     }
 
+    void loadFloat(ImplicitAddress address, FPRegisterID dest)
+    {
+        RegisterID base = address.base;
+        int32_t offset = address.offset;
+
+        // 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(TrustedImm32(offset), base, addressTempRegister);
+            base = addressTempRegister;
+            offset = 0;
+        }
+        
+        m_assembler.flds(ARMRegisters::asSingle(dest), base, offset);
+    }
+
+    void loadDouble(BaseIndex address, FPRegisterID dest)
+    {
+        move(address.index, addressTempRegister);
+        lshift32(TrustedImm32(address.scale), addressTempRegister);
+        add32(address.base, addressTempRegister);
+        loadDouble(Address(addressTempRegister, address.offset), dest);
+    }
+    
+    void loadFloat(BaseIndex address, FPRegisterID dest)
+    {
+        move(address.index, addressTempRegister);
+        lshift32(TrustedImm32(address.scale), addressTempRegister);
+        add32(address.base, addressTempRegister);
+        loadFloat(Address(addressTempRegister, address.offset), dest);
+    }
+
+    void moveDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        if (src != dest)
+            m_assembler.vmov(dest, src);
+    }
+
     void loadDouble(const void* address, FPRegisterID dest)
     {
         move(TrustedImmPtr(address), addressTempRegister);
     void loadDouble(const void* address, FPRegisterID dest)
     {
         move(TrustedImmPtr(address), addressTempRegister);
@@ -604,9 +828,46 @@ public:
         m_assembler.vstr(src, base, offset);
     }
 
         m_assembler.vstr(src, base, offset);
     }
 
+    void storeFloat(FPRegisterID src, ImplicitAddress address)
+    {
+        RegisterID base = address.base;
+        int32_t offset = address.offset;
+
+        // 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(TrustedImm32(offset), base, addressTempRegister);
+            base = addressTempRegister;
+            offset = 0;
+        }
+        
+        m_assembler.fsts(ARMRegisters::asSingle(src), base, offset);
+    }
+
+    void storeDouble(FPRegisterID src, const void* address)
+    {
+        move(TrustedImmPtr(address), addressTempRegister);
+        storeDouble(src, addressTempRegister);
+    }
+
+    void storeDouble(FPRegisterID src, BaseIndex address)
+    {
+        move(address.index, addressTempRegister);
+        lshift32(TrustedImm32(address.scale), addressTempRegister);
+        add32(address.base, addressTempRegister);
+        storeDouble(src, Address(addressTempRegister, address.offset));
+    }
+    
+    void storeFloat(FPRegisterID src, BaseIndex address)
+    {
+        move(address.index, addressTempRegister);
+        lshift32(TrustedImm32(address.scale), addressTempRegister);
+        add32(address.base, addressTempRegister);
+        storeFloat(src, Address(addressTempRegister, address.offset));
+    }
+    
     void addDouble(FPRegisterID src, FPRegisterID dest)
     {
     void addDouble(FPRegisterID src, FPRegisterID dest)
     {
-        m_assembler.vadd_F64(dest, dest, src);
+        m_assembler.vadd(dest, dest, src);
     }
 
     void addDouble(Address src, FPRegisterID dest)
     }
 
     void addDouble(Address src, FPRegisterID dest)
@@ -615,14 +876,30 @@ public:
         addDouble(fpTempRegister, dest);
     }
 
         addDouble(fpTempRegister, dest);
     }
 
+    void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        m_assembler.vadd(dest, op1, op2);
+    }
+
+    void addDouble(AbsoluteAddress address, FPRegisterID dest)
+    {
+        loadDouble(address.m_ptr, fpTempRegister);
+        m_assembler.vadd(dest, dest, fpTempRegister);
+    }
+
     void divDouble(FPRegisterID src, FPRegisterID dest)
     {
     void divDouble(FPRegisterID src, FPRegisterID dest)
     {
-        m_assembler.vdiv_F64(dest, dest, src);
+        m_assembler.vdiv(dest, dest, src);
+    }
+
+    void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        m_assembler.vdiv(dest, op1, op2);
     }
 
     void subDouble(FPRegisterID src, FPRegisterID dest)
     {
     }
 
     void subDouble(FPRegisterID src, FPRegisterID dest)
     {
-        m_assembler.vsub_F64(dest, dest, src);
+        m_assembler.vsub(dest, dest, src);
     }
 
     void subDouble(Address src, FPRegisterID dest)
     }
 
     void subDouble(Address src, FPRegisterID dest)
@@ -631,9 +908,14 @@ public:
         subDouble(fpTempRegister, dest);
     }
 
         subDouble(fpTempRegister, dest);
     }
 
+    void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        m_assembler.vsub(dest, op1, op2);
+    }
+
     void mulDouble(FPRegisterID src, FPRegisterID dest)
     {
     void mulDouble(FPRegisterID src, FPRegisterID dest)
     {
-        m_assembler.vmul_F64(dest, dest, src);
+        m_assembler.vmul(dest, dest, src);
     }
 
     void mulDouble(Address src, FPRegisterID dest)
     }
 
     void mulDouble(Address src, FPRegisterID dest)
@@ -642,36 +924,61 @@ public:
         mulDouble(fpTempRegister, dest);
     }
 
         mulDouble(fpTempRegister, dest);
     }
 
-    void sqrtDouble(FPRegisterID, FPRegisterID)
+    void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        m_assembler.vmul(dest, op1, op2);
+    }
+
+    void sqrtDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.vsqrt(dest, src);
+    }
+    
+    void absDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.vabs(dest, src);
+    }
+
+    void negateDouble(FPRegisterID src, FPRegisterID dest)
     {
     {
-        ASSERT_NOT_REACHED();
+        m_assembler.vneg(dest, src);
     }
 
     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
     {
     }
 
     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
     {
-        m_assembler.vmov(fpTempRegisterAsSingle(), src);
-        m_assembler.vcvt_F64_S32(dest, fpTempRegisterAsSingle());
+        m_assembler.vmov(fpTempRegister, src, src);
+        m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle());
     }
 
     void convertInt32ToDouble(Address address, FPRegisterID dest)
     {
         // Fixme: load directly into the fpr!
         load32(address, dataTempRegister);
     }
 
     void convertInt32ToDouble(Address address, FPRegisterID dest)
     {
         // Fixme: load directly into the fpr!
         load32(address, dataTempRegister);
-        m_assembler.vmov(fpTempRegisterAsSingle(), dataTempRegister);
-        m_assembler.vcvt_F64_S32(dest, fpTempRegisterAsSingle());
+        m_assembler.vmov(fpTempRegister, dataTempRegister, dataTempRegister);
+        m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle());
     }
 
     void convertInt32ToDouble(AbsoluteAddress address, FPRegisterID dest)
     {
         // Fixme: load directly into the fpr!
         load32(address.m_ptr, dataTempRegister);
     }
 
     void convertInt32ToDouble(AbsoluteAddress address, FPRegisterID dest)
     {
         // Fixme: load directly into the fpr!
         load32(address.m_ptr, dataTempRegister);
-        m_assembler.vmov(fpTempRegisterAsSingle(), dataTempRegister);
-        m_assembler.vcvt_F64_S32(dest, fpTempRegisterAsSingle());
+        m_assembler.vmov(fpTempRegister, dataTempRegister, dataTempRegister);
+        m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle());
+    }
+    
+    void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.vcvtds(dst, ARMRegisters::asSingle(src));
+    }
+    
+    void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.vcvtsd(ARMRegisters::asSingle(dst), src);
     }
 
     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
     {
     }
 
     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
     {
-        m_assembler.vcmp_F64(left, right);
+        m_assembler.vcmp(left, right);
         m_assembler.vmrs();
 
         if (cond == DoubleNotEqual) {
         m_assembler.vmrs();
 
         if (cond == DoubleNotEqual) {
@@ -693,23 +1000,72 @@ public:
         return makeBranch(cond);
     }
 
         return makeBranch(cond);
     }
 
-    Jump branchTruncateDoubleToInt32(FPRegisterID, RegisterID)
+    enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
+    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
     {
     {
-        ASSERT_NOT_REACHED();
-        return jump();
+        // Convert into dest.
+        m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src);
+        m_assembler.vmov(dest, fpTempRegisterAsSingle());
+
+        // Calculate 2x dest.  If the value potentially underflowed, it will have
+        // clamped to 0x80000000, so 2x dest is zero in this case. In the case of
+        // overflow the result will be equal to -2.
+        Jump underflow = branchAdd32(Zero, dest, dest, dataTempRegister);
+        Jump noOverflow = branch32(NotEqual, dataTempRegister, TrustedImm32(-2));
+
+        // For BranchIfTruncateSuccessful, we branch if 'noOverflow' jumps.
+        underflow.link(this);
+        if (branchType == BranchIfTruncateSuccessful)
+            return noOverflow;
+
+        // We'll reach the current point in the code on failure, so plant a
+        // jump here & link the success case.
+        Jump failure = jump();
+        noOverflow.link(this);
+        return failure;
     }
 
     }
 
+    Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
+    {
+        m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src);
+        m_assembler.vmov(dest, fpTempRegisterAsSingle());
+        
+        Jump overflow = branch32(Equal, dest, TrustedImm32(0x7fffffff));
+        Jump success = branch32(GreaterThanOrEqual, dest, TrustedImm32(0));
+        overflow.link(this);
+
+        if (branchType == BranchIfTruncateSuccessful)
+            return success;
+        
+        Jump failure = jump();
+        success.link(this);
+        return failure;
+    }
+
+    // Result is undefined if the value is outside of the integer range.
+    void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
+    {
+        m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src);
+        m_assembler.vmov(dest, fpTempRegisterAsSingle());
+    }
+
+    void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
+    {
+        m_assembler.vcvt_floatingPointToUnsigned(fpTempRegisterAsSingle(), src);
+        m_assembler.vmov(dest, fpTempRegisterAsSingle());
+    }
+    
     // 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)
     {
     // 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)
     {
-        m_assembler.vcvtr_S32_F64(fpTempRegisterAsSingle(), src);
+        m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src);
         m_assembler.vmov(dest, fpTempRegisterAsSingle());
 
         // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
         m_assembler.vmov(dest, fpTempRegisterAsSingle());
 
         // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
-        m_assembler.vcvt_F64_S32(fpTempRegister, fpTempRegisterAsSingle());
+        m_assembler.vcvt_signedToFloatingPoint(fpTempRegister, fpTempRegisterAsSingle());
         failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, fpTempRegister));
 
         // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
         failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, fpTempRegister));
 
         // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
@@ -718,7 +1074,7 @@ public:
 
     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID)
     {
 
     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID)
     {
-        m_assembler.vcmpz_F64(reg);
+        m_assembler.vcmpz(reg);
         m_assembler.vmrs();
         Jump unordered = makeBranch(ARMv7Assembler::ConditionVS);
         Jump result = makeBranch(ARMv7Assembler::ConditionNE);
         m_assembler.vmrs();
         Jump unordered = makeBranch(ARMv7Assembler::ConditionVS);
         Jump result = makeBranch(ARMv7Assembler::ConditionNE);
@@ -728,7 +1084,7 @@ public:
 
     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID)
     {
 
     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID)
     {
-        m_assembler.vcmpz_F64(reg);
+        m_assembler.vcmpz(reg);
         m_assembler.vmrs();
         Jump unordered = makeBranch(ARMv7Assembler::ConditionVS);
         Jump notEqual = makeBranch(ARMv7Assembler::ConditionNE);
         m_assembler.vmrs();
         Jump unordered = makeBranch(ARMv7Assembler::ConditionVS);
         Jump notEqual = makeBranch(ARMv7Assembler::ConditionNE);
@@ -798,7 +1154,8 @@ public:
 
     void move(RegisterID src, RegisterID dest)
     {
 
     void move(RegisterID src, RegisterID dest)
     {
-        m_assembler.mov(dest, src);
+        if (src != dest)
+            m_assembler.mov(dest, src);
     }
 
     void move(TrustedImmPtr imm, RegisterID dest)
     }
 
     void move(TrustedImmPtr imm, RegisterID dest)
@@ -815,14 +1172,18 @@ public:
 
     void signExtend32ToPtr(RegisterID src, RegisterID dest)
     {
 
     void signExtend32ToPtr(RegisterID src, RegisterID dest)
     {
-        if (src != dest)
-            move(src, dest);
+        move(src, dest);
     }
 
     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
     {
     }
 
     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
     {
-        if (src != dest)
-            move(src, dest);
+        move(src, dest);
+    }
+
+    // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
+    static RelationalCondition invert(RelationalCondition cond)
+    {
+        return static_cast<RelationalCondition>(cond ^ 1);
     }
 
     void nop()
     }
 
     void nop()
@@ -944,22 +1305,6 @@ public:
         return branch32(cond, addressTempRegister, right);
     }
 
         return branch32(cond, addressTempRegister, right);
     }
 
-    Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right)
-    {
-        load16(left, dataTempRegister);
-        m_assembler.lsl(addressTempRegister, right, 16);
-        m_assembler.lsl(dataTempRegister, dataTempRegister, 16);
-        return branch32(cond, dataTempRegister, addressTempRegister);
-    }
-
-    Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
-    {
-        // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
-        load16(left, addressTempRegister);
-        m_assembler.lsl(addressTempRegister, addressTempRegister, 16);
-        return branch32(cond, addressTempRegister, TrustedImm32(right.m_value << 16));
-    }
-
     Jump branch8(RelationalCondition cond, RegisterID left, TrustedImm32 right)
     {
         compare32(left, right);
     Jump branch8(RelationalCondition cond, RegisterID left, TrustedImm32 right)
     {
         compare32(left, right);
@@ -968,11 +1313,20 @@ public:
 
     Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
     {
 
     Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
     {
+        ASSERT(!(0xffffff00 & right.m_value));
         // 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 branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
+    {
+        ASSERT(!(0xffffff00 & right.m_value));
+        // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
+        load8(left, addressTempRegister);
+        return branch32(cond, addressTempRegister, right);
+    }
+    
     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
         m_assembler.tst(reg, mask);
     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
         m_assembler.tst(reg, mask);
@@ -999,17 +1353,11 @@ public:
         return branchTest32(cond, addressTempRegister, mask);
     }
 
         return branchTest32(cond, addressTempRegister, mask);
     }
 
-    Jump branchTest8(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
-    {
-        test32(reg, mask);
-        return Jump(makeBranch(cond));
-    }
-
     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/
         load8(address, addressTempRegister);
     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/
         load8(address, addressTempRegister);
-        return branchTest8(cond, addressTempRegister, mask);
+        return branchTest32(cond, addressTempRegister, mask);
     }
 
     void jump(RegisterID target)
     }
 
     void jump(RegisterID target)
@@ -1023,6 +1371,13 @@ public:
         load32(address, dataTempRegister);
         m_assembler.bx(dataTempRegister);
     }
         load32(address, dataTempRegister);
         m_assembler.bx(dataTempRegister);
     }
+    
+    void jump(AbsoluteAddress address)
+    {
+        move(TrustedImmPtr(address.m_ptr), dataTempRegister);
+        load32(Address(dataTempRegister), dataTempRegister);
+        m_assembler.bx(dataTempRegister);
+    }
 
 
     // Arithmetic control flow operations:
 
 
     // Arithmetic control flow operations:
@@ -1035,21 +1390,57 @@ 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(ResultCondition cond, RegisterID src, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
     {
     {
-        m_assembler.add_S(dest, dest, src);
+        m_assembler.add_S(dest, op1, op2);
         return Jump(makeBranch(cond));
     }
 
         return Jump(makeBranch(cond));
     }
 
-    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, RegisterID op1, TrustedImm32 imm, RegisterID dest)
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
-            m_assembler.add_S(dest, dest, armImm);
+            m_assembler.add_S(dest, op1, armImm);
         else {
             move(imm, dataTempRegister);
         else {
             move(imm, dataTempRegister);
-            m_assembler.add_S(dest, dest, dataTempRegister);
+            m_assembler.add_S(dest, op1, dataTempRegister);
+        }
+        return Jump(makeBranch(cond));
+    }
+
+    Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
+    {
+        return branchAdd32(cond, dest, src, dest);
+    }
+
+    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
+    {
+        return branchAdd32(cond, dest, imm, dest);
+    }
+
+    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
+    {
+        // Move the high bits of the address into addressTempRegister,
+        // and load the value into dataTempRegister.
+        move(TrustedImmPtr(dest.m_ptr), addressTempRegister);
+        m_assembler.ldr(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
+
+        // Do the add.
+        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
+        if (armImm.isValid())
+            m_assembler.add_S(dataTempRegister, dataTempRegister, armImm);
+        else {
+            // If the operand does not fit into an immediate then load it temporarily
+            // into addressTempRegister; since we're overwriting addressTempRegister
+            // we'll need to reload it with the high bits of the address afterwards.
+            move(imm, addressTempRegister);
+            m_assembler.add_S(dataTempRegister, dataTempRegister, addressTempRegister);
+            move(TrustedImmPtr(dest.m_ptr), addressTempRegister);
         }
         }
+
+        // Store the result.
+        m_assembler.str(dataTempRegister, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
+
         return Jump(makeBranch(cond));
     }
 
         return Jump(makeBranch(cond));
     }
 
@@ -1076,30 +1467,47 @@ public:
         return branchMul32(cond, dataTempRegister, src, dest);
     }
 
         return branchMul32(cond, dataTempRegister, src, dest);
     }
 
+    Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
+    {
+        ARMThumbImmediate zero = ARMThumbImmediate::makeUInt12(0);
+        m_assembler.sub_S(srcDest, zero, srcDest);
+        return Jump(makeBranch(cond));
+    }
+
     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         m_assembler.orr_S(dest, dest, src);
         return Jump(makeBranch(cond));
     }
 
     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         m_assembler.orr_S(dest, dest, src);
         return Jump(makeBranch(cond));
     }
 
-    Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
+    Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
     {
     {
-        m_assembler.sub_S(dest, dest, src);
+        m_assembler.sub_S(dest, op1, op2);
         return Jump(makeBranch(cond));
     }
 
         return Jump(makeBranch(cond));
     }
 
-    Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
+    Jump branchSub32(ResultCondition cond, RegisterID op1, TrustedImm32 imm, RegisterID dest)
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
-            m_assembler.sub_S(dest, dest, armImm);
+            m_assembler.sub_S(dest, op1, armImm);
         else {
             move(imm, dataTempRegister);
         else {
             move(imm, dataTempRegister);
-            m_assembler.sub_S(dest, dest, dataTempRegister);
+            m_assembler.sub_S(dest, op1, dataTempRegister);
         }
         return Jump(makeBranch(cond));
     }
     
         }
         return Jump(makeBranch(cond));
     }
     
+    Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
+    {
+        return branchSub32(cond, dest, src, dest);
+    }
+
+    Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
+    {
+        return branchSub32(cond, dest, imm, dest);
+    }
+    
     void relativeTableJump(RegisterID index, int scale)
     {
         ASSERT(scale >= 0 && scale <= 31);
     void relativeTableJump(RegisterID index, int scale)
     {
         ASSERT(scale >= 0 && scale <= 31);
@@ -1115,9 +1523,9 @@ public:
 
     // Miscellaneous operations:
 
 
     // Miscellaneous operations:
 
-    void breakpoint()
+    void breakpoint(uint8_t imm = 0)
     {
     {
-        m_assembler.bkpt(0);
+        m_assembler.bkpt(imm);
     }
 
     ALWAYS_INLINE Call nearCall()
     }
 
     ALWAYS_INLINE Call nearCall()
@@ -1162,6 +1570,12 @@ public:
         compare32(cond, dataTempRegister, right, dest);
     }
 
         compare32(cond, dataTempRegister, right, dest);
     }
 
+    void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
+    {
+        load8(left, addressTempRegister);
+        compare32(cond, addressTempRegister, right, dest);
+    }
+
     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
         compare32(left, right);
     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
         compare32(left, right);
@@ -1217,6 +1631,22 @@ public:
         return branch32(cond, addressTempRegister, dataTempRegister);
     }
 
         return branch32(cond, addressTempRegister, dataTempRegister);
     }
 
+    PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
+    {
+        m_makeJumpPatchable = true;
+        Jump result = branchPtrWithPatch(cond, left, dataLabel, initialRightValue);
+        m_makeJumpPatchable = false;
+        return PatchableJump(result);
+    }
+
+    PatchableJump patchableJump()
+    {
+        m_makeJumpPatchable = true;
+        Jump result = jump();
+        m_makeJumpPatchable = false;
+        return PatchableJump(result);
+    }
+
     ALWAYS_INLINE DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
     {
         DataLabelPtr label = moveWithPatch(initialValue, dataTempRegister);
     ALWAYS_INLINE DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
     {
         DataLabelPtr label = moveWithPatch(initialValue, dataTempRegister);
@@ -1245,23 +1675,23 @@ public:
         return m_assembler.executableOffsetFor(location);
     }
 
         return m_assembler.executableOffsetFor(location);
     }
 
-protected:
-    bool inUninterruptedSequence()
+    static FunctionPtr readCallTarget(CodeLocationCall call)
     {
     {
-        return m_inUninterruptedSequence;
+        return FunctionPtr(reinterpret_cast<void(*)()>(ARMv7Assembler::readCallTarget(call.dataLocation())));
     }
 
     }
 
+protected:
     ALWAYS_INLINE Jump jump()
     {
         moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
     ALWAYS_INLINE Jump jump()
     {
         moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
-        return Jump(m_assembler.bx(dataTempRegister), inUninterruptedSequence() ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition);
+        return Jump(m_assembler.bx(dataTempRegister), m_makeJumpPatchable ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition);
     }
 
     ALWAYS_INLINE Jump makeBranch(ARMv7Assembler::Condition cond)
     {
         m_assembler.it(cond, true, true);
         moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
     }
 
     ALWAYS_INLINE Jump makeBranch(ARMv7Assembler::Condition cond)
     {
         m_assembler.it(cond, true, true);
         moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
-        return Jump(m_assembler.bx(dataTempRegister), inUninterruptedSequence() ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond);
+        return Jump(m_assembler.bx(dataTempRegister), m_makeJumpPatchable ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, 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(RelationalCondition cond) { return makeBranch(armV7Condition(cond)); }
     ALWAYS_INLINE Jump makeBranch(ResultCondition cond) { return makeBranch(armV7Condition(cond)); }
@@ -1338,14 +1768,14 @@ protected:
     {
         return static_cast<ARMv7Assembler::Condition>(cond);
     }
     {
         return static_cast<ARMv7Assembler::Condition>(cond);
     }
-
+    
 private:
     friend class LinkBuffer;
     friend class RepatchBuffer;
 
     static void linkCall(void* code, Call call, FunctionPtr function)
     {
 private:
     friend class LinkBuffer;
     friend class RepatchBuffer;
 
     static void linkCall(void* code, Call call, FunctionPtr function)
     {
-        ARMv7Assembler::linkCall(code, call.m_jmp, function.value());
+        ARMv7Assembler::linkCall(code, call.m_label, function.value());
     }
 
     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
     }
 
     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
@@ -1357,8 +1787,8 @@ private:
     {
         ARMv7Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
     }
     {
         ARMv7Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
     }
-    
-    bool m_inUninterruptedSequence;
+
+    bool m_makeJumpPatchable;
 };
 
 } // namespace JSC
 };
 
 } // namespace JSC
index 6d47cb97587fce4e57b93e01c16bcdca29fed503..ac62c422103323bb0d6ebea72a62ff1614703a46 100644 (file)
 #define MacroAssemblerCodeRef_h
 
 #include "ExecutableAllocator.h"
 #define MacroAssemblerCodeRef_h
 
 #include "ExecutableAllocator.h"
-#include "PassRefPtr.h"
-#include "RefPtr.h"
-#include "UnusedParam.h"
-
-#if ENABLE(ASSEMBLER)
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/UnusedParam.h>
 
 // ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
 // instruction address on the platform (for example, check any alignment requirements).
 
 // ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
 // instruction address on the platform (for example, check any alignment requirements).
 #define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes!
 #endif
 
 #define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes!
 #endif
 
+#if CPU(X86) && OS(WINDOWS)
+#define CALLING_CONVENTION_IS_STDCALL 1
+#ifndef CDECL
+#if COMPILER(MSVC)
+#define CDECL __cdecl
+#else
+#define CDECL __attribute__ ((__cdecl))
+#endif // COMPILER(MSVC)
+#endif // CDECL
+#else
+#define CALLING_CONVENTION_IS_STDCALL 0
+#endif
+
+#if CPU(X86)
+#define HAS_FASTCALL_CALLING_CONVENTION 1
+#ifndef FASTCALL
+#if COMPILER(MSVC)
+#define FASTCALL __fastcall
+#else
+#define FASTCALL  __attribute__ ((fastcall))
+#endif // COMPILER(MSVC)
+#endif // FASTCALL
+#else
+#define HAS_FASTCALL_CALLING_CONVENTION 0
+#endif // CPU(X86)
+
 namespace JSC {
 
 // FunctionPtr:
 namespace JSC {
 
 // FunctionPtr:
@@ -100,6 +124,84 @@ public:
         ASSERT_VALID_CODE_POINTER(m_value);
     }
 
         ASSERT_VALID_CODE_POINTER(m_value);
     }
 
+// MSVC doesn't seem to treat functions with different calling conventions as
+// different types; these methods already defined for fastcall, below.
+#if CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS)
+
+    template<typename returnType>
+    FunctionPtr(returnType (CDECL *value)())
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1>
+    FunctionPtr(returnType (CDECL *value)(argType1))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2>
+    FunctionPtr(returnType (CDECL *value)(argType1, argType2))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2, typename argType3>
+    FunctionPtr(returnType (CDECL *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 (CDECL *value)(argType1, argType2, argType3, argType4))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+#endif
+
+#if HAS_FASTCALL_CALLING_CONVENTION
+
+    template<typename returnType>
+    FunctionPtr(returnType (FASTCALL *value)())
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1>
+    FunctionPtr(returnType (FASTCALL *value)(argType1))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2>
+    FunctionPtr(returnType (FASTCALL *value)(argType1, argType2))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2, typename argType3>
+    FunctionPtr(returnType (FASTCALL *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 (FASTCALL *value)(argType1, argType2, argType3, argType4))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+#endif
+
     template<typename FunctionType>
     explicit FunctionPtr(FunctionType* value)
         // Using a C-ctyle cast here to avoid compiler error on RVTC:
     template<typename FunctionType>
     explicit FunctionPtr(FunctionType* value)
         // Using a C-ctyle cast here to avoid compiler error on RVTC:
@@ -169,7 +271,19 @@ public:
     {
         ASSERT_VALID_CODE_POINTER(m_value);
     }
     {
         ASSERT_VALID_CODE_POINTER(m_value);
     }
+    
+    static MacroAssemblerCodePtr createFromExecutableAddress(void* value)
+    {
+        ASSERT_VALID_CODE_POINTER(value);
+        MacroAssemblerCodePtr result;
+        result.m_value = value;
+        return result;
+    }
 
 
+    static MacroAssemblerCodePtr createLLIntCodePtr(void (*function)())
+    {
+        return createFromExecutableAddress(bitwise_cast<void*>(function));
+    }
     explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
         : m_value(ra.value())
     {
     explicit MacroAssemblerCodePtr(ReturnAddressPtr ra)
         : m_value(ra.value())
     {
@@ -199,26 +313,67 @@ private:
 // pointer to the code, and a ref pointer to the pool from within which it
 // was allocated.
 class MacroAssemblerCodeRef {
 // pointer to the code, and a ref pointer to the pool from within which it
 // was allocated.
 class MacroAssemblerCodeRef {
+private:
+    // This is private because it's dangerous enough that we want uses of it
+    // to be easy to find - hence the static create method below.
+    explicit MacroAssemblerCodeRef(MacroAssemblerCodePtr codePtr)
+        : m_codePtr(codePtr)
+    {
+        ASSERT(m_codePtr);
+    }
+
 public:
     MacroAssemblerCodeRef()
 public:
     MacroAssemblerCodeRef()
-        : m_size(0)
     {
     }
 
     {
     }
 
-    MacroAssemblerCodeRef(void* code, PassRefPtr<ExecutablePool> executablePool, size_t size)
-        : m_code(code)
-        , m_executablePool(executablePool)
-        , m_size(size)
+    MacroAssemblerCodeRef(PassRefPtr<ExecutableMemoryHandle> executableMemory)
+        : m_codePtr(executableMemory->start())
+        , m_executableMemory(executableMemory)
     {
     {
+        ASSERT(m_executableMemory->isManaged());
+        ASSERT(m_executableMemory->start());
+        ASSERT(m_codePtr);
     }
     }
+    
+    // Use this only when you know that the codePtr refers to code that is
+    // already being kept alive through some other means. Typically this means
+    // that codePtr is immortal.
+    static MacroAssemblerCodeRef createSelfManagedCodeRef(MacroAssemblerCodePtr codePtr)
+    {
+        return MacroAssemblerCodeRef(codePtr);
+    }
+    
+    // Helper for creating self-managed code refs from LLInt.
+    static MacroAssemblerCodeRef createLLIntCodeRef(void (*function)())
+    {
+        return createSelfManagedCodeRef(MacroAssemblerCodePtr::createFromExecutableAddress(bitwise_cast<void*>(function)));
+    }
+    
+    ExecutableMemoryHandle* executableMemory() const
+    {
+        return m_executableMemory.get();
+    }
+    
+    MacroAssemblerCodePtr code() const
+    {
+        return m_codePtr;
+    }
+    
+    size_t size() const
+    {
+        if (!m_executableMemory)
+            return 0;
+        return m_executableMemory->sizeInBytes();
+    }
+    
+    bool operator!() const { return !m_codePtr; }
 
 
-    MacroAssemblerCodePtr m_code;
-    RefPtr<ExecutablePool> m_executablePool;
-    size_t m_size;
+private:
+    MacroAssemblerCodePtr m_codePtr;
+    RefPtr<ExecutableMemoryHandle> m_executableMemory;
 };
 
 } // namespace JSC
 
 };
 
 } // namespace JSC
 
-#endif // ENABLE(ASSEMBLER)
-
 #endif // MacroAssemblerCodeRef_h
 #endif // MacroAssemblerCodeRef_h
index 9cdfffc8bc7c9c5beeeeaf9a1539589074504e78..0a63c2928734f82025f8829c8da96d105141e49f 100644 (file)
@@ -132,6 +132,11 @@ public:
         }
     }
 
         }
     }
 
+    void add32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        add32(imm, src, dest);
+    }
+
     void add32(TrustedImm32 imm, Address address)
     {
         if (address.offset >= -32768 && address.offset <= 32767
     void add32(TrustedImm32 imm, Address address)
     {
         if (address.offset >= -32768 && address.offset <= 32767
@@ -291,14 +296,14 @@ public:
         m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest);
     }
 
         m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest);
     }
 
-    void not32(RegisterID srcDest)
+    void or32(RegisterID src, RegisterID dest)
     {
     {
-        m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero);
+        m_assembler.orInsn(dest, dest, src);
     }
 
     }
 
-    void or32(RegisterID src, RegisterID dest)
+    void or32(RegisterID op1, RegisterID op2, RegisterID dest)
     {
     {
-        m_assembler.orInsn(dest, dest, src);
+        m_assembler.orInsn(dest, op1, op2);
     }
 
     void or32(TrustedImm32 imm, RegisterID dest)
     }
 
     void or32(TrustedImm32 imm, RegisterID dest)
@@ -330,6 +335,11 @@ public:
         m_assembler.sra(dest, dest, imm.m_value);
     }
 
         m_assembler.sra(dest, dest, imm.m_value);
     }
 
+    void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.sra(dest, src, imm.m_value);
+    }
+
     void urshift32(RegisterID shiftAmount, RegisterID dest)
     {
         m_assembler.srlv(dest, dest, shiftAmount);
     void urshift32(RegisterID shiftAmount, RegisterID dest)
     {
         m_assembler.srlv(dest, dest, shiftAmount);
@@ -363,6 +373,24 @@ public:
         }
     }
 
         }
     }
 
+    void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
+            && !m_fixedWidth) {
+            /*
+              addiu     dest, src, imm
+            */
+            m_assembler.addiu(dest, src, -imm.m_value);
+        } else {
+            /*
+              li        immTemp, imm
+              subu      dest, src, immTemp
+            */
+            move(imm, immTempRegister);
+            m_assembler.subu(dest, src, immTempRegister);
+        }
+    }
+
     void sub32(TrustedImm32 imm, Address address)
     {
         if (address.offset >= -32768 && address.offset <= 32767
     void sub32(TrustedImm32 imm, Address address)
     {
         if (address.offset >= -32768 && address.offset <= 32767
@@ -448,6 +476,11 @@ public:
 
     void xor32(TrustedImm32 imm, RegisterID dest)
     {
 
     void xor32(TrustedImm32 imm, RegisterID dest)
     {
+        if (imm.m_value == -1) {
+            m_assembler.nor(dest, dest, MIPSRegisters::zero);
+            return;
+        }
+
         /*
             li  immTemp, imm
             xor dest, dest, immTemp
         /*
             li  immTemp, imm
             xor dest, dest, immTemp
@@ -460,6 +493,11 @@ public:
     {
         m_assembler.sqrtd(dst, src);
     }
     {
         m_assembler.sqrtd(dst, src);
     }
+    
+    void absDouble(FPRegisterID, FPRegisterID)
+    {
+        ASSERT_NOT_REACHED();
+    }
 
     // Memory access operations:
     //
 
     // Memory access operations:
     //
@@ -486,6 +524,35 @@ public:
         }
     }
 
         }
     }
 
+    void load8(BaseIndex address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+             sll     addrTemp, address.index, address.scale
+             addu    addrTemp, addrTemp, address.base
+             lbu     dest, address.offset(addrTemp)
+             */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lbu(dest, addrTempRegister, address.offset);
+        } else {
+            /*
+             sll     addrTemp, address.index, address.scale
+             addu    addrTemp, addrTemp, address.base
+             lui     immTemp, (address.offset + 0x8000) >> 16
+             addu    addrTemp, addrTemp, immTemp
+             lbu     dest, (address.offset & 0xffff)(at)
+             */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.lbu(dest, addrTempRegister, address.offset);
+        }
+    }
+
     void load32(ImplicitAddress address, RegisterID dest)
     {
         if (address.offset >= -32768 && address.offset <= 32767
     void load32(ImplicitAddress address, RegisterID dest)
     {
         if (address.offset >= -32768 && address.offset <= 32767
@@ -532,6 +599,11 @@ public:
         }
     }
 
         }
     }
 
+    void load16Unaligned(BaseIndex address, RegisterID dest)
+    {
+        load16(address, dest);
+    }
+
     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
     {
         if (address.offset >= -32768 && address.offset <= 32764
     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
     {
         if (address.offset >= -32768 && address.offset <= 32764
@@ -790,7 +862,7 @@ public:
 
     // Floating-point operations:
 
 
     // Floating-point operations:
 
-    bool supportsFloatingPoint() const
+    static bool supportsFloatingPoint()
     {
 #if WTF_MIPS_DOUBLE_FLOAT
         return true;
     {
 #if WTF_MIPS_DOUBLE_FLOAT
         return true;
@@ -799,7 +871,7 @@ public:
 #endif
     }
 
 #endif
     }
 
-    bool supportsFloatingPointTruncate() const
+    static bool supportsFloatingPointTruncate()
     {
 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
         return true;
     {
 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
         return true;
@@ -808,7 +880,7 @@ public:
 #endif
     }
 
 #endif
     }
 
-    bool supportsFloatingPointSqrt() const
+    static bool supportsFloatingPointSqrt()
     {
 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
         return true;
     {
 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
         return true;
@@ -816,6 +888,7 @@ public:
         return false;
 #endif
     }
         return false;
 #endif
     }
+    static bool supportsFloatingPointAbs() { return false; }
 
     // Stack manipulation operations:
     //
 
     // Stack manipulation operations:
     //
@@ -921,6 +994,25 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
+    void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
+    {
+        // Make sure the immediate value is unsigned 8 bits.
+        ASSERT(!(right.m_value & 0xFFFFFF00));
+        load8(left, dataTempRegister);
+        move(right, immTempRegister);
+        compare32(cond, dataTempRegister, immTempRegister, dest);
+    }
+
+    Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
+    {
+        ASSERT(!(right.m_value & 0xFFFFFF00));
+        load8(left, dataTempRegister);
+        // Be careful that the previous load8() uses immTempRegister.
+        // So, we need to put move() after load8().
+        move(right, immTempRegister);
+        return branch32(cond, dataTempRegister, immTempRegister);
+    }
+
     Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
     {
         if (cond == Equal)
     Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
     {
         if (cond == Equal)
@@ -1021,22 +1113,6 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
-    Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right)
-    {
-        load16(left, dataTempRegister);
-        return branch32(cond, dataTempRegister, right);
-    }
-
-    Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
-    {
-        ASSERT(!(right.m_value & 0xFFFF0000));
-        load16(left, dataTempRegister);
-        // Be careful that the previous load16() uses immTempRegister.
-        // So, we need to put move() after load16().
-        move(right, immTempRegister);
-        return branch32(cond, dataTempRegister, immTempRegister);
-    }
-
     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
         ASSERT((cond == Zero) || (cond == NonZero));
     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
         ASSERT((cond == Zero) || (cond == NonZero));
@@ -1159,6 +1235,13 @@ public:
         return branchAdd32(cond, immTempRegister, dest);
     }
 
         return branchAdd32(cond, immTempRegister, dest);
     }
 
+    Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        move(imm, immTempRegister);
+        move(src, dest);
+        return branchAdd32(cond, immTempRegister, dest);
+    }
+
     Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
     Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
@@ -1264,6 +1347,13 @@ public:
         return branchSub32(cond, immTempRegister, dest);
     }
 
         return branchSub32(cond, immTempRegister, dest);
     }
 
+    Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        move(imm, immTempRegister);
+        move(src, dest);
+        return branchSub32(cond, immTempRegister, dest);
+    }
+
     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
@@ -1776,6 +1866,11 @@ public:
         m_assembler.nop();
     }
 
         m_assembler.nop();
     }
 
+    static FunctionPtr readCallTarget(CodeLocationCall call)
+    {
+        return FunctionPtr(reinterpret_cast<void(*)()>(MIPSAssembler::readCallTarget(call.dataLocation())));
+    }
+
 private:
     // If m_fixedWidth is true, we will generate a fixed number of instructions.
     // Otherwise, we can emit any number of instructions.
 private:
     // If m_fixedWidth is true, we will generate a fixed number of instructions.
     // Otherwise, we can emit any number of instructions.
@@ -1786,7 +1881,7 @@ private:
 
     static void linkCall(void* code, Call call, FunctionPtr function)
     {
 
     static void linkCall(void* code, Call call, FunctionPtr function)
     {
-        MIPSAssembler::linkCall(code, call.m_jmp, function.value());
+        MIPSAssembler::linkCall(code, call.m_label, function.value());
     }
 
     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
     }
 
     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
index ee11f55f0d3b90c66f1e6c0e06f22981a7d9ac94..59de3ff48c19c8cb992f255158a4d1a9d8cff350 100644 (file)
@@ -34,7 +34,7 @@ namespace JSC {
 
 void MacroAssemblerSH4::linkCall(void* code, Call call, FunctionPtr function)
 {
 
 void MacroAssemblerSH4::linkCall(void* code, Call call, FunctionPtr function)
 {
-    SH4Assembler::linkCall(code, call.m_jmp, function.value());
+    SH4Assembler::linkCall(code, call.m_label, function.value());
 }
 
 void MacroAssemblerSH4::repatchCall(CodeLocationCall call, CodeLocationLabel destination)
 }
 
 void MacroAssemblerSH4::repatchCall(CodeLocationCall call, CodeLocationLabel destination)
index 8bed14caa4035709f603fbfc386da31223d9798c..c132ad6427e073a1e7c9d47aa9f23df74dbc30f3 100644 (file)
@@ -29,8 +29,8 @@
 
 #if ENABLE(ASSEMBLER) && CPU(SH4)
 
 
 #if ENABLE(ASSEMBLER) && CPU(SH4)
 
-#include "AbstractMacroAssembler.h"
 #include "SH4Assembler.h"
 #include "SH4Assembler.h"
+#include "AbstractMacroAssembler.h"
 #include <wtf/Assertions.h>
 
 namespace JSC {
 #include <wtf/Assertions.h>
 
 namespace JSC {
@@ -45,7 +45,7 @@ public:
     static const RegisterID linkRegister = SH4Registers::pr;
     static const RegisterID scratchReg3 = SH4Registers::r13;
 
     static const RegisterID linkRegister = SH4Registers::pr;
     static const RegisterID scratchReg3 = SH4Registers::r13;
 
-    static const int MaximumCompactPtrAlignedAddressOffset = 0x7FFFFFFF;
+    static const int MaximumCompactPtrAlignedAddressOffset = 60;
 
     enum RelationalCondition {
         Equal = SH4Assembler::EQ,
 
     enum RelationalCondition {
         Equal = SH4Assembler::EQ,
@@ -156,8 +156,27 @@ public:
         releaseScratch(scr);
     }
 
         releaseScratch(scr);
     }
 
+    void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        if (src != dest) {
+            move(imm, dest);
+            and32(src, dest);
+            return;
+        }
+
+        and32(imm, dest);
+    }
+
     void lshift32(RegisterID shiftamount, RegisterID dest)
     {
     void lshift32(RegisterID shiftamount, RegisterID dest)
     {
+        if (shiftamount == SH4Registers::r0)
+            m_assembler.andlImm8r(0x1f, shiftamount);
+        else {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant(0x1f, scr);
+            m_assembler.andlRegReg(scr, shiftamount);
+            releaseScratch(scr);
+        }
         m_assembler.shllRegReg(dest, shiftamount);
     }
 
         m_assembler.shllRegReg(dest, shiftamount);
     }
 
@@ -171,17 +190,28 @@ public:
 
     void lshift32(TrustedImm32 imm, RegisterID dest)
     {
 
     void lshift32(TrustedImm32 imm, RegisterID dest)
     {
+        if (!imm.m_value)
+            return;
+
         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();
         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.loadConstant((imm.m_value & 0x1f) , scr);
         m_assembler.shllRegReg(dest, scr);
         releaseScratch(scr);
     }
 
         m_assembler.shllRegReg(dest, scr);
         releaseScratch(scr);
     }
 
+    void lshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest)
+    {
+        if (src != dest)
+            move(src, dest);
+
+        lshift32(shiftamount, dest);
+    }
+
     void mul32(RegisterID src, RegisterID dest)
     {
         m_assembler.imullRegReg(src, dest);
     void mul32(RegisterID src, RegisterID dest)
     {
         m_assembler.imullRegReg(src, dest);
@@ -198,11 +228,6 @@ public:
         releaseScratch(scr);
     }
 
         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(RegisterID src, RegisterID dest)
     {
         m_assembler.orlRegReg(src, dest);
@@ -221,11 +246,51 @@ public:
         releaseScratch(scr);
     }
 
         releaseScratch(scr);
     }
 
+    void or32(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        if (op1 == op2)
+            move(op1, dest);
+        else if (op1 == dest)
+            or32(op2, dest);
+        else {
+            move(op2, dest);
+            or32(op1, dest);
+        }
+    }
+
+    
+void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        if  (src != dest) {
+            move(imm, dest);
+            or32(src, dest);
+            return;
+        }
+
+        or32(imm, dest);
+    }
+
+    void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        if  (src != dest) {
+            move(imm, dest);
+            xor32(src, dest);
+            return;
+        }
+
+        xor32(imm, dest);
+    }
+
     void rshift32(RegisterID shiftamount, RegisterID dest)
     {
     void rshift32(RegisterID shiftamount, RegisterID dest)
     {
-        compare32(32, shiftamount, Equal);
-        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
-        m_assembler.branch(BT_OPCODE, 1);
+        if (shiftamount == SH4Registers::r0)
+            m_assembler.andlImm8r(0x1f, shiftamount);
+        else {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant(0x1f, scr);
+            m_assembler.andlRegReg(scr, shiftamount);
+            releaseScratch(scr);
+        }
         m_assembler.neg(shiftamount, shiftamount);
         m_assembler.shaRegReg(dest, shiftamount);
     }
         m_assembler.neg(shiftamount, shiftamount);
         m_assembler.shaRegReg(dest, shiftamount);
     }
@@ -236,6 +301,13 @@ public:
             rshift32(imm.m_value & 0x1f, dest);
     }
 
             rshift32(imm.m_value & 0x1f, dest);
     }
 
+    void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        if (src != dest)
+            move(src, dest);
+        rshift32(imm, dest);
+    }
+
     void sub32(RegisterID src, RegisterID dest)
     {
         m_assembler.sublRegReg(src, dest);
     void sub32(RegisterID src, RegisterID dest)
     {
         m_assembler.sublRegReg(src, dest);
@@ -345,6 +417,11 @@ public:
 
     void xor32(TrustedImm32 imm, RegisterID srcDest)
     {
 
     void xor32(TrustedImm32 imm, RegisterID srcDest)
     {
+        if (imm.m_value == -1) {
+            m_assembler.notlReg(srcDest, srcDest);
+            return;
+        }
+
         if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) {
             RegisterID scr = claimScratch();
             m_assembler.loadConstant((imm.m_value), scr);
         if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) {
             RegisterID scr = claimScratch();
             m_assembler.loadConstant((imm.m_value), scr);
@@ -502,6 +579,16 @@ public:
         load8(address.base, address.offset, dest);
     }
 
         load8(address.base, address.offset, dest);
     }
 
+    void load8(BaseIndex address, RegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        move(address.index, scr);
+        lshift32(TrustedImm32(address.scale), scr);
+        add32(address.base, scr);
+        load8(scr, address.offset, dest);
+        releaseScratch(scr);
+    }
+
     void load32(BaseIndex address, RegisterID dest)
     {
         RegisterID scr = claimScratch();
     void load32(BaseIndex address, RegisterID dest)
     {
         RegisterID scr = claimScratch();
@@ -512,9 +599,9 @@ public:
         releaseScratch(scr);
     }
 
         releaseScratch(scr);
     }
 
-    void load32(void* address, RegisterID dest)
+    void load32(const void* address, RegisterID dest)
     {
     {
-        m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), dest);
+        m_assembler.loadConstant(reinterpret_cast<uint32_t>(const_cast<void*>(address)), dest);
         m_assembler.movlMemReg(dest, dest);
     }
 
         m_assembler.movlMemReg(dest, dest);
     }
 
@@ -553,11 +640,13 @@ public:
     {
         if (!offset) {
             m_assembler.movbMemReg(base, dest);
     {
         if (!offset) {
             m_assembler.movbMemReg(base, dest);
+            m_assembler.extub(dest, dest);
             return;
         }
 
         if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) {
             m_assembler.movbMemReg(offset, base, dest);
             return;
         }
 
         if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) {
             m_assembler.movbMemReg(offset, base, dest);
+            m_assembler.extub(dest, dest);
             return;
         }
 
             return;
         }
 
@@ -565,6 +654,7 @@ public:
             m_assembler.loadConstant((offset), dest);
             m_assembler.addlRegReg(base, dest);
             m_assembler.movbMemReg(dest, dest);
             m_assembler.loadConstant((offset), dest);
             m_assembler.addlRegReg(base, dest);
             m_assembler.movbMemReg(dest, dest);
+            m_assembler.extub(dest, dest);
             return;
         }
 
             return;
         }
 
@@ -572,6 +662,7 @@ public:
         m_assembler.loadConstant((offset), scr);
         m_assembler.addlRegReg(base, scr);
         m_assembler.movbMemReg(scr, dest);
         m_assembler.loadConstant((offset), scr);
         m_assembler.addlRegReg(base, scr);
         m_assembler.movbMemReg(scr, dest);
+        m_assembler.extub(dest, dest);
         releaseScratch(scr);
     }
 
         releaseScratch(scr);
     }
 
@@ -590,11 +681,13 @@ public:
     {
         if (!address.offset) {
             m_assembler.movwMemReg(address.base, dest);
     {
         if (!address.offset) {
             m_assembler.movwMemReg(address.base, dest);
+            extuw(dest, dest);
             return;
         }
 
         if ((address.offset > 0) && (address.offset < 64) && (dest == SH4Registers::r0)) {
             m_assembler.movwMemReg(address.offset, address.base, dest);
             return;
         }
 
         if ((address.offset > 0) && (address.offset < 64) && (dest == SH4Registers::r0)) {
             m_assembler.movwMemReg(address.offset, address.base, dest);
+            extuw(dest, dest);
             return;
         }
 
             return;
         }
 
@@ -602,6 +695,7 @@ public:
             m_assembler.loadConstant((address.offset), dest);
             m_assembler.addlRegReg(address.base, dest);
             m_assembler.movwMemReg(dest, dest);
             m_assembler.loadConstant((address.offset), dest);
             m_assembler.addlRegReg(address.base, dest);
             m_assembler.movwMemReg(dest, dest);
+            extuw(dest, dest);
             return;
         }
 
             return;
         }
 
@@ -609,18 +703,44 @@ public:
         m_assembler.loadConstant((address.offset), scr);
         m_assembler.addlRegReg(address.base, scr);
         m_assembler.movwMemReg(scr, dest);
         m_assembler.loadConstant((address.offset), scr);
         m_assembler.addlRegReg(address.base, scr);
         m_assembler.movwMemReg(scr, dest);
+        extuw(dest, dest);
         releaseScratch(scr);
     }
 
         releaseScratch(scr);
     }
 
+    void load16Unaligned(BaseIndex address, RegisterID dest)
+    {
+
+        RegisterID scr = claimScratch();
+        RegisterID scr1 = claimScratch();
+
+        move(address.index, scr);
+        lshift32(TrustedImm32(address.scale), scr);
+
+        if (address.offset)
+            add32(TrustedImm32(address.offset), scr);
+
+        add32(address.base, scr);
+        load8(scr, scr1);
+        add32(TrustedImm32(1), scr);
+        load8(scr, dest);
+        m_assembler.shllImm8r(8, dest);
+        or32(scr1, dest);
+
+        releaseScratch(scr);
+        releaseScratch(scr1);
+    }
+
     void load16(RegisterID src, RegisterID dest)
     {
         m_assembler.movwMemReg(src, dest);
     void load16(RegisterID src, RegisterID dest)
     {
         m_assembler.movwMemReg(src, dest);
+        extuw(dest, dest);
     }
 
     void load16(RegisterID r0, RegisterID src, RegisterID dest)
     {
         ASSERT(r0 == SH4Registers::r0);
         m_assembler.movwR0mr(src, dest);
     }
 
     void load16(RegisterID r0, RegisterID src, RegisterID dest)
     {
         ASSERT(r0 == SH4Registers::r0);
         m_assembler.movwR0mr(src, dest);
+        extuw(dest, dest);
     }
 
     void load16(BaseIndex address, RegisterID dest)
     }
 
     void load16(BaseIndex address, RegisterID dest)
@@ -632,14 +752,13 @@ public:
 
         if (address.offset)
             add32(TrustedImm32(address.offset), scr);
 
         if (address.offset)
             add32(TrustedImm32(address.offset), scr);
-        if (scr == SH4Registers::r0)
-            m_assembler.movwR0mr(address.base, scr);
+        if (address.base == SH4Registers::r0)
+            load16(address.base, scr, dest);
         else {
             add32(address.base, scr);
         else {
             add32(address.base, scr);
-            load16(scr, scr);
+            load16(scr, dest);
         }
 
         }
 
-        extuw(scr, dest);
         releaseScratch(scr);
     }
 
         releaseScratch(scr);
     }
 
@@ -711,7 +830,7 @@ public:
         RegisterID scr1 = claimScratch();
         m_assembler.loadConstant((imm.m_value), scr);
         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr1);
         RegisterID scr1 = claimScratch();
         m_assembler.loadConstant((imm.m_value), scr);
         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr1);
-        m_assembler.movlMemReg(scr, scr1);
+        m_assembler.movlRegMem(scr, scr1);
         releaseScratch(scr);
         releaseScratch(scr1);
     }
         releaseScratch(scr);
         releaseScratch(scr1);
     }
@@ -720,7 +839,7 @@ public:
     {
         RegisterID scr = claimScratch();
         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
     {
         RegisterID scr = claimScratch();
         m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
-        m_assembler.movlMemReg(src, scr);
+        m_assembler.movlRegMem(src, scr);
         releaseScratch(scr);
     }
 
         releaseScratch(scr);
     }
 
@@ -735,17 +854,6 @@ public:
         return label;
     }
     
         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 store32WithAddressOffsetPatch(RegisterID src, Address address)
     {
         RegisterID scr = claimScratch();
@@ -757,11 +865,21 @@ public:
         return label;
     }
 
         return label;
     }
 
+    DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
+    {
+        DataLabelCompact dataLabel(this);
+        ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset);
+        ASSERT(address.offset >= 0);
+        m_assembler.movlMemRegCompact(address.offset >> 2, address.base, dest);
+        return dataLabel;
+    }
+
      // Floating-point operations
 
      // Floating-point operations
 
-    bool supportsFloatingPoint() const { return true; }
-    bool supportsFloatingPointTruncate() const { return true; }
-    bool supportsFloatingPointSqrt() const { return true; }
+    static bool supportsFloatingPoint() { return true; }
+    static bool supportsFloatingPointTruncate() { return true; }
+    static bool supportsFloatingPointSqrt() { return true; }
+    static bool supportsFloatingPointAbs() { return false; }
 
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
 
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
@@ -865,6 +983,12 @@ public:
     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
     {
         RegisterID scr = claimScratch();
     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
     {
         RegisterID scr = claimScratch();
+        RegisterID scr1 = claimScratch();
+        Jump m_jump;
+        JumpList end;
+
+        if (dest != SH4Registers::r0)
+            move(SH4Registers::r0, scr1);
 
         move(address.index, scr);
         lshift32(TrustedImm32(address.scale), scr);
 
         move(address.index, scr);
         lshift32(TrustedImm32(address.scale), scr);
@@ -873,13 +997,44 @@ public:
         if (address.offset)
             add32(TrustedImm32(address.offset), scr);
 
         if (address.offset)
             add32(TrustedImm32(address.offset), scr);
 
-        RegisterID scr1 = claimScratch();
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 68, sizeof(uint32_t));
+        move(scr, SH4Registers::r0);
+        m_assembler.andlImm8r(0x3, SH4Registers::r0);
+        m_assembler.cmpEqImmR0(0x0, SH4Registers::r0);
+        m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear);
+        if (dest != SH4Registers::r0)
+            move(scr1, SH4Registers::r0);
+
+        load32(scr, dest);
+        end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear));
+        m_assembler.nop();
+        m_jump.link(this);
+        m_assembler.andlImm8r(0x1, SH4Registers::r0);
+        m_assembler.cmpEqImmR0(0x0, SH4Registers::r0);
+
+        if (dest != SH4Registers::r0)
+            move(scr1, SH4Registers::r0);
+
+        m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear);
         load16(scr, scr1);
         add32(TrustedImm32(2), scr);
         load16(scr, dest);
         load16(scr, scr1);
         add32(TrustedImm32(2), scr);
         load16(scr, dest);
-        move(TrustedImm32(16), scr);
-        m_assembler.shllRegReg(dest, scr);
+        m_assembler.shllImm8r(16, dest);
         or32(scr1, dest);
         or32(scr1, dest);
+        end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear));
+        m_assembler.nop();
+        m_jump.link(this);
+        load8(scr, scr1);
+        add32(TrustedImm32(1), scr);
+        load16(scr, dest);
+        m_assembler.shllImm8r(8, dest);
+        or32(dest, scr1);
+        add32(TrustedImm32(2), scr);
+        load8(scr, dest);
+        m_assembler.shllImm8r(8, dest);
+        m_assembler.shllImm8r(16, dest);
+        or32(scr1, dest);
+        end.link(this);
 
         releaseScratch(scr);
         releaseScratch(scr1);
 
         releaseScratch(scr);
         releaseScratch(scr1);
@@ -922,19 +1077,22 @@ public:
 
         if (cond == DoubleNotEqual) {
             RegisterID scr = claimScratch();
 
         if (cond == DoubleNotEqual) {
             RegisterID scr = claimScratch();
+            JumpList end;
             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.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);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
-            m_assembler.branch(BT_OPCODE, 4);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcmppeq(right, left);
             releaseScratch(scr);
             m_assembler.dcmppeq(right, left);
             releaseScratch(scr);
-            return branchFalse();
+            Jump m_jump = branchFalse();
+            end.link(this);
+            return m_jump;
         }
 
         if (cond == DoubleGreaterThan) {
         }
 
         if (cond == DoubleGreaterThan) {
@@ -959,113 +1117,135 @@ public:
 
         if (cond == DoubleEqualOrUnordered) {
             RegisterID scr = claimScratch();
 
         if (cond == DoubleEqualOrUnordered) {
             RegisterID scr = claimScratch();
+            JumpList end;
             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.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);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
-            m_assembler.branch(BT_OPCODE, 1);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcmppeq(left, right);
             m_assembler.dcmppeq(left, right);
+            Jump m_jump = Jump(m_assembler.je());
+            end.link(this);
+            m_assembler.extraInstrForBranch(scr);
             releaseScratch(scr);
             releaseScratch(scr);
-            return branchTrue();
+            return m_jump;
         }
 
         if (cond == DoubleGreaterThanOrUnordered) {
             RegisterID scr = claimScratch();
         }
 
         if (cond == DoubleGreaterThanOrUnordered) {
             RegisterID scr = claimScratch();
+            JumpList end;
             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.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);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
-            m_assembler.branch(BT_OPCODE, 1);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcmppgt(right, left);
             m_assembler.dcmppgt(right, left);
+            Jump m_jump = Jump(m_assembler.je());
+            end.link(this);
+            m_assembler.extraInstrForBranch(scr);
             releaseScratch(scr);
             releaseScratch(scr);
-            return branchTrue();
+            return m_jump;
         }
 
         if (cond == DoubleGreaterThanOrEqualOrUnordered) {
             RegisterID scr = claimScratch();
         }
 
         if (cond == DoubleGreaterThanOrEqualOrUnordered) {
             RegisterID scr = claimScratch();
+            JumpList end;
             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.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);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
-            m_assembler.branch(BT_OPCODE, 1);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcmppgt(left, right);
             m_assembler.dcmppgt(left, right);
+            Jump m_jump = Jump(m_assembler.jne());
+            end.link(this);
+            m_assembler.extraInstrForBranch(scr);
             releaseScratch(scr);
             releaseScratch(scr);
-            return branchFalse();
+            return m_jump;
         }
 
         if (cond == DoubleLessThanOrUnordered) {
             RegisterID scr = claimScratch();
         }
 
         if (cond == DoubleLessThanOrUnordered) {
             RegisterID scr = claimScratch();
+            JumpList end;
             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.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);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
-            m_assembler.branch(BT_OPCODE, 1);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcmppgt(left, right);
             m_assembler.dcmppgt(left, right);
+            Jump m_jump = Jump(m_assembler.je());
+            end.link(this);
+            m_assembler.extraInstrForBranch(scr);
             releaseScratch(scr);
             releaseScratch(scr);
-            return branchTrue();
+            return m_jump;
         }
 
         if (cond == DoubleLessThanOrEqualOrUnordered) {
             RegisterID scr = claimScratch();
         }
 
         if (cond == DoubleLessThanOrEqualOrUnordered) {
             RegisterID scr = claimScratch();
+            JumpList end;
             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.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);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
             m_assembler.dcnvds(left);
             m_assembler.stsfpulReg(scr);
             m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
-            m_assembler.branch(BT_OPCODE, 1);
+            end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
             m_assembler.dcmppgt(right, left);
             m_assembler.dcmppgt(right, left);
+            Jump m_jump = Jump(m_assembler.jne());
+            end.link(this);
+            m_assembler.extraInstrForBranch(scr);
             releaseScratch(scr);
             releaseScratch(scr);
-            return branchFalse();
+            return m_jump;
         }
 
         ASSERT(cond == DoubleNotEqualOrUnordered);
         RegisterID scr = claimScratch();
         }
 
         ASSERT(cond == DoubleNotEqualOrUnordered);
         RegisterID scr = claimScratch();
+        JumpList end;
         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.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);
+        end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
         m_assembler.dcnvds(left);
         m_assembler.stsfpulReg(scr);
         m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
         m_assembler.dcnvds(left);
         m_assembler.stsfpulReg(scr);
         m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
-        m_assembler.branch(BT_OPCODE, 1);
+        end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear));
         m_assembler.dcmppeq(right, left);
         m_assembler.dcmppeq(right, left);
+        Jump m_jump = Jump(m_assembler.jne());
+        end.link(this);
+        m_assembler.extraInstrForBranch(scr);
         releaseScratch(scr);
         releaseScratch(scr);
-        return branchFalse();
+        return m_jump;
     }
 
     Jump branchTrue()
     {
         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
         Jump m_jump = Jump(m_assembler.je());
     }
 
     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();
+        m_assembler.extraInstrForBranch(scratchReg3);
         return m_jump;
     }
 
         return m_jump;
     }
 
@@ -1073,9 +1253,7 @@ public:
     {
         m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
         Jump m_jump = Jump(m_assembler.jne());
     {
         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();
+        m_assembler.extraInstrForBranch(scratchReg3);
         return m_jump;
     }
 
         return m_jump;
     }
 
@@ -1100,6 +1278,11 @@ public:
             m_assembler.dmovRegReg(src, dest);
         m_assembler.dsqrt(dest);
     }
             m_assembler.dmovRegReg(src, dest);
         m_assembler.dsqrt(dest);
     }
+    
+    void absDouble(FPRegisterID, FPRegisterID)
+    {
+        ASSERT_NOT_REACHED();
+    }
 
     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
 
     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
@@ -1125,6 +1308,14 @@ public:
         return jmp;
     }
 
         return jmp;
     }
 
+    void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
+    {
+        RegisterID addressTempRegister = claimScratch();
+        load8(left, addressTempRegister);
+        compare32(cond, addressTempRegister, right, dest);
+        releaseScratch(addressTempRegister);
+    }
+
     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     {
         m_assembler.ftrcdrmfpul(src);
     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     {
         m_assembler.ftrcdrmfpul(src);
@@ -1188,14 +1379,16 @@ public:
 
     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
     {
 
     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
     {
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize, sizeof(uint32_t));
         DataLabelPtr dataLabel(this);
         DataLabelPtr dataLabel(this);
-        m_assembler.loadConstantUnReusable(reinterpret_cast<uint32_t>(initialValue.m_value), dest, true);
+        m_assembler.loadConstantUnReusable(reinterpret_cast<uint32_t>(initialValue.m_value), dest);
         return dataLabel;
     }
 
     void move(RegisterID src, RegisterID dest)
     {
         return dataLabel;
     }
 
     void move(RegisterID src, RegisterID dest)
     {
-        m_assembler.movlRegReg(src, dest);
+        if (src != dest)
+            m_assembler.movlRegReg(src, dest);
     }
 
     void move(TrustedImmPtr imm, RegisterID dest)
     }
 
     void move(TrustedImmPtr imm, RegisterID dest)
@@ -1340,25 +1533,9 @@ public:
         return branchTrue();
     }
 
         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)
+    Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
     {
+        ASSERT(!(right.m_value & 0xFFFFFF00));
         RegisterID scr = claimScratch();
 
         move(left.index, scr);
         RegisterID scr = claimScratch();
 
         move(left.index, scr);
@@ -1367,8 +1544,7 @@ public:
         if (left.offset)
             add32(TrustedImm32(left.offset), scr);
         add32(left.base, scr);
         if (left.offset)
             add32(TrustedImm32(left.offset), scr);
         add32(left.base, scr);
-        load16(scr, scr);
-        extuw(scr, scr);
+        load8(scr, scr);
         RegisterID scr1 = claimScratch();
         m_assembler.loadConstant(right.m_value, scr1);
         releaseScratch(scr);
         RegisterID scr1 = claimScratch();
         m_assembler.loadConstant(right.m_value, scr1);
         releaseScratch(scr);
@@ -1498,6 +1674,33 @@ public:
         return branchAdd32(cond, scratchReg3, dest);
     }
 
         return branchAdd32(cond, scratchReg3, dest);
     }
 
+    Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+
+        if (src != dest)
+            move(src, dest);
+
+        if (cond == Overflow) {
+            move(imm, scratchReg3);
+            m_assembler.addvlRegReg(scratchReg3, dest);
+            return branchTrue();
+        }
+
+        add32(imm, dest);
+
+        if (cond == Signed) {
+            m_assembler.cmppz(dest);
+            return branchFalse();
+        }
+
+        compare32(0, dest, Equal);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
     Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
     Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
@@ -1575,6 +1778,21 @@ public:
         return branchSub32(cond, scratchReg3, dest);
     }
 
         return branchSub32(cond, scratchReg3, dest);
     }
 
+    Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        move(imm, scratchReg3);
+        if (src != dest)
+            move(src, dest);
+        return branchSub32(cond, scratchReg3, dest);
+    }
+
+    Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
+    {
+        if (src1 != dest)
+            move(src1, dest);
+        return branchSub32(cond, src2, dest);
+    }
+
     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
@@ -1614,16 +1832,16 @@ public:
         m_assembler.neg(dst, dst);
     }
 
         m_assembler.neg(dst, dst);
     }
 
-    void not32(RegisterID dst)
-    {
-        m_assembler.notlReg(dst, dst);
-    }
-
     void urshift32(RegisterID shiftamount, RegisterID dest)
     {
     void urshift32(RegisterID shiftamount, RegisterID dest)
     {
-        compare32(32, shiftamount, Equal);
-        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
-        m_assembler.branch(BT_OPCODE, 1);
+        if (shiftamount == SH4Registers::r0)
+            m_assembler.andlImm8r(0x1f, shiftamount);
+        else {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant(0x1f, scr);
+            m_assembler.andlRegReg(scr, shiftamount);
+            releaseScratch(scr);
+        }
         m_assembler.neg(shiftamount, shiftamount);
         m_assembler.shllRegReg(dest, shiftamount);
     }
         m_assembler.neg(shiftamount, shiftamount);
         m_assembler.shllRegReg(dest, shiftamount);
     }
@@ -1631,11 +1849,19 @@ public:
     void urshift32(TrustedImm32 imm, RegisterID dest)
     {
         RegisterID scr = claimScratch();
     void urshift32(TrustedImm32 imm, RegisterID dest)
     {
         RegisterID scr = claimScratch();
-        m_assembler.loadConstant(-(imm.m_value), scr);
+        m_assembler.loadConstant(-(imm.m_value & 0x1f), scr);
         m_assembler.shaRegReg(dest, scr);
         releaseScratch(scr);
     }
 
         m_assembler.shaRegReg(dest, scr);
         releaseScratch(scr);
     }
 
+    void urshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest)
+    {
+        if (src != dest)
+           move(src, dest);
+
+        urshift32(shiftamount, dest);
+    }
+
     Call call()
     {
         return Call(m_assembler.call(), Call::Linkable);
     Call call()
     {
         return Call(m_assembler.call(), Call::Linkable);
@@ -1740,6 +1966,11 @@ public:
         m_assembler.nop();
     }
 
         m_assembler.nop();
     }
 
+    static FunctionPtr readCallTarget(CodeLocationCall call)
+    {
+        return FunctionPtr(reinterpret_cast<void(*)()>(SH4Assembler::readCallTarget(call.dataLocation())));
+    }
+
 protected:
     SH4Assembler::Condition SH4Condition(RelationalCondition cond)
     {
 protected:
     SH4Assembler::Condition SH4Condition(RelationalCondition cond)
     {
index a1657e6e01ecc2720c01b4e17eba2d04d274f79e..088fe196b9f84a2c23375de9f8a43f3c2f77f098 100644 (file)
@@ -34,22 +34,22 @@ namespace JSC {
 
 class MacroAssemblerX86 : public MacroAssemblerX86Common {
 public:
 
 class MacroAssemblerX86 : public MacroAssemblerX86Common {
 public:
-    MacroAssemblerX86()
-        : m_isSSE2Present(isSSE2Present())
-    {
-    }
-
     static const Scale ScalePtr = TimesFour;
 
     using MacroAssemblerX86Common::add32;
     using MacroAssemblerX86Common::and32;
     static const Scale ScalePtr = TimesFour;
 
     using MacroAssemblerX86Common::add32;
     using MacroAssemblerX86Common::and32;
+    using MacroAssemblerX86Common::branchAdd32;
+    using MacroAssemblerX86Common::branchSub32;
     using MacroAssemblerX86Common::sub32;
     using MacroAssemblerX86Common::or32;
     using MacroAssemblerX86Common::load32;
     using MacroAssemblerX86Common::store32;
     using MacroAssemblerX86Common::branch32;
     using MacroAssemblerX86Common::call;
     using MacroAssemblerX86Common::sub32;
     using MacroAssemblerX86Common::or32;
     using MacroAssemblerX86Common::load32;
     using MacroAssemblerX86Common::store32;
     using MacroAssemblerX86Common::branch32;
     using MacroAssemblerX86Common::call;
+    using MacroAssemblerX86Common::jump;
+    using MacroAssemblerX86Common::addDouble;
     using MacroAssemblerX86Common::loadDouble;
     using MacroAssemblerX86Common::loadDouble;
+    using MacroAssemblerX86Common::storeDouble;
     using MacroAssemblerX86Common::convertInt32ToDouble;
 
     void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     using MacroAssemblerX86Common::convertInt32ToDouble;
 
     void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
@@ -62,11 +62,12 @@ public:
         m_assembler.addl_im(imm.m_value, address.m_ptr);
     }
     
         m_assembler.addl_im(imm.m_value, address.m_ptr);
     }
     
-    void addWithCarry32(TrustedImm32 imm, AbsoluteAddress address)
+    void add64(TrustedImm32 imm, AbsoluteAddress address)
     {
     {
-        m_assembler.adcl_im(imm.m_value, address.m_ptr);
+        m_assembler.addl_im(imm.m_value, address.m_ptr);
+        m_assembler.adcl_im(imm.m_value >> 31, reinterpret_cast<const char*>(address.m_ptr) + sizeof(int32_t));
     }
     }
-    
+
     void and32(TrustedImm32 imm, AbsoluteAddress address)
     {
         m_assembler.andl_im(imm.m_value, address.m_ptr);
     void and32(TrustedImm32 imm, AbsoluteAddress address)
     {
         m_assembler.andl_im(imm.m_value, address.m_ptr);
@@ -82,15 +83,20 @@ public:
         m_assembler.subl_im(imm.m_value, address.m_ptr);
     }
 
         m_assembler.subl_im(imm.m_value, address.m_ptr);
     }
 
-    void load32(void* address, RegisterID dest)
+    void load32(const void* address, RegisterID dest)
     {
         m_assembler.movl_mr(address, dest);
     }
 
     {
         m_assembler.movl_mr(address, dest);
     }
 
-    void loadDouble(const void* address, FPRegisterID dest)
+    void addDouble(AbsoluteAddress address, FPRegisterID dest)
+    {
+        m_assembler.addsd_mr(address.m_ptr, dest);
+    }
+
+    void storeDouble(FPRegisterID src, const void* address)
     {
         ASSERT(isSSE2Present());
     {
         ASSERT(isSSE2Present());
-        m_assembler.movsd_mr(address, dest);
+        m_assembler.movsd_rm(src, address);
     }
 
     void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
     }
 
     void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
@@ -108,6 +114,18 @@ public:
         m_assembler.movl_rm(src, address);
     }
 
         m_assembler.movl_rm(src, address);
     }
 
+    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
+    {
+        m_assembler.addl_im(imm.m_value, dest.m_ptr);
+        return Jump(m_assembler.jCC(x86Condition(cond)));
+    }
+
+    Jump branchSub32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
+    {
+        m_assembler.subl_im(imm.m_value, dest.m_ptr);
+        return Jump(m_assembler.jCC(x86Condition(cond)));
+    }
+
     Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
     {
         m_assembler.cmpl_rm(right, left.m_ptr);
     Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
     {
         m_assembler.cmpl_rm(right, left.m_ptr);
@@ -125,6 +143,12 @@ public:
         return Call(m_assembler.call(), Call::Linkable);
     }
 
         return Call(m_assembler.call(), Call::Linkable);
     }
 
+    // Address is a memory location containing the address to jump to
+    void jump(AbsoluteAddress address)
+    {
+        m_assembler.jmp_m(address.m_ptr);
+    }
+
     Call tailRecursiveCall()
     {
         return Call::fromTailJump(jump());
     Call tailRecursiveCall()
     {
         return Call::fromTailJump(jump());
@@ -162,20 +186,25 @@ public:
         return DataLabelPtr(this);
     }
 
         return DataLabelPtr(this);
     }
 
-    bool supportsFloatingPoint() const { return m_isSSE2Present; }
+    static bool supportsFloatingPoint() { return isSSE2Present(); }
     // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
     // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
-    bool supportsFloatingPointTruncate() const { return m_isSSE2Present; }
-    bool supportsFloatingPointSqrt() const { return m_isSSE2Present; }
+    static bool supportsFloatingPointTruncate() { return isSSE2Present(); }
+    static bool supportsFloatingPointSqrt() { return isSSE2Present(); }
+    static bool supportsFloatingPointAbs() { return isSSE2Present(); }
+    
+    static FunctionPtr readCallTarget(CodeLocationCall call)
+    {
+        intptr_t offset = reinterpret_cast<int32_t*>(call.dataLocation())[-1];
+        return FunctionPtr(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(call.dataLocation()) + offset));
+    }
 
 private:
 
 private:
-    const bool m_isSSE2Present;
-
     friend class LinkBuffer;
     friend class RepatchBuffer;
 
     static void linkCall(void* code, Call call, FunctionPtr function)
     {
     friend class LinkBuffer;
     friend class RepatchBuffer;
 
     static void linkCall(void* code, Call call, FunctionPtr function)
     {
-        X86Assembler::linkCall(code, call.m_jmp, function.value());
+        X86Assembler::linkCall(code, call.m_label, function.value());
     }
 
     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
     }
 
     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
index 933b36b29327e6920327ddfc5dceb9b2a4aad1ac..e398dcdad29901b8e495262dee06015a55a6ff38 100644 (file)
 namespace JSC {
 
 class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
 namespace JSC {
 
 class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
+protected:
+#if CPU(X86_64)
+    static const X86Registers::RegisterID scratchRegister = X86Registers::r11;
+#endif
+
     static const int DoubleConditionBitInvert = 0x10;
     static const int DoubleConditionBitSpecial = 0x20;
     static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
 
 public:
     typedef X86Assembler::FPRegisterID FPRegisterID;
     static const int DoubleConditionBitInvert = 0x10;
     static const int DoubleConditionBitSpecial = 0x20;
     static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
 
 public:
     typedef X86Assembler::FPRegisterID FPRegisterID;
+    typedef X86Assembler::XMMRegisterID XMMRegisterID;
     
     static const int MaximumCompactPtrAlignedAddressOffset = 127;
 
     
     static const int MaximumCompactPtrAlignedAddressOffset = 127;
 
@@ -85,6 +91,13 @@ public:
 
     static const RegisterID stackPointerRegister = X86Registers::esp;
 
 
     static const RegisterID stackPointerRegister = X86Registers::esp;
 
+#if ENABLE(JIT_CONSTANT_BLINDING)
+    static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
+#if CPU(X86_64)
+    static bool shouldBlindForSpecificArch(uintptr_t value) { return value >= 0x00ffffff; }
+#endif
+#endif
+
     // Integer arithmetic operations:
     //
     // Operations are typically two operand - operation(source, srcDst)
     // Integer arithmetic operations:
     //
     // Operations are typically two operand - operation(source, srcDst)
@@ -116,6 +129,11 @@ public:
     {
         m_assembler.addl_rm(src, dest.offset, dest.base);
     }
     {
         m_assembler.addl_rm(src, dest.offset, dest.base);
     }
+
+    void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        m_assembler.leal_mr(imm.m_value, src, dest);
+    }
     
     void and32(RegisterID src, RegisterID dest)
     {
     
     void and32(RegisterID src, RegisterID dest)
     {
@@ -222,16 +240,6 @@ public:
         m_assembler.negl_m(srcDest.offset, srcDest.base);
     }
 
         m_assembler.negl_m(srcDest.offset, srcDest.base);
     }
 
-    void not32(RegisterID srcDest)
-    {
-        m_assembler.notl_r(srcDest);
-    }
-
-    void not32(Address srcDest)
-    {
-        m_assembler.notl_m(srcDest.offset, srcDest.base);
-    }
-    
     void or32(RegisterID src, RegisterID dest)
     {
         m_assembler.orl_rr(src, dest);
     void or32(RegisterID src, RegisterID dest)
     {
         m_assembler.orl_rr(src, dest);
@@ -374,7 +382,6 @@ public:
         m_assembler.subl_rm(src, dest.offset, dest.base);
     }
 
         m_assembler.subl_rm(src, dest.offset, dest.base);
     }
 
-
     void xor32(RegisterID src, RegisterID dest)
     {
         m_assembler.xorl_rr(src, dest);
     void xor32(RegisterID src, RegisterID dest)
     {
         m_assembler.xorl_rr(src, dest);
@@ -382,11 +389,17 @@ public:
 
     void xor32(TrustedImm32 imm, Address dest)
     {
 
     void xor32(TrustedImm32 imm, Address dest)
     {
-        m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
+        if (imm.m_value == -1)
+            m_assembler.notl_m(dest.offset, dest.base);
+        else
+            m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
     }
 
     void xor32(TrustedImm32 imm, RegisterID dest)
     {
     }
 
     void xor32(TrustedImm32 imm, RegisterID dest)
     {
+        if (imm.m_value == -1)
+        m_assembler.notl_r(dest);
+        else
         m_assembler.xorl_ir(imm.m_value, dest);
     }
 
         m_assembler.xorl_ir(imm.m_value, dest);
     }
 
@@ -423,6 +436,23 @@ public:
         m_assembler.sqrtsd_rr(src, dst);
     }
 
         m_assembler.sqrtsd_rr(src, dst);
     }
 
+    void absDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        ASSERT(src != dst);
+        static const double negativeZeroConstant = -0.0;
+        loadDouble(&negativeZeroConstant, dst);
+        m_assembler.andnpd_rr(src, dst);
+    }
+
+    void negateDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        ASSERT(src != dst);
+        static const double negativeZeroConstant = -0.0;
+        loadDouble(&negativeZeroConstant, dst);
+        m_assembler.xorpd_rr(src, dst);
+    }
+
+
     // 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
@@ -445,6 +475,11 @@ public:
         load32(address, dest);
     }
 
         load32(address, dest);
     }
 
+    void load16Unaligned(BaseIndex address, RegisterID dest)
+    {
+        load16(address, dest);
+    }
+
     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     {
         m_assembler.movl_mr_disp32(address.offset, address.base, dest);
     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     {
         m_assembler.movl_mr_disp32(address.offset, address.base, dest);
@@ -470,6 +505,26 @@ public:
         return DataLabelCompact(this);
     }
 
         return DataLabelCompact(this);
     }
 
+    void load8(BaseIndex address, RegisterID dest)
+    {
+        m_assembler.movzbl_mr(address.offset, address.base, address.index, address.scale, dest);
+    }
+
+    void load8(ImplicitAddress address, RegisterID dest)
+    {
+        m_assembler.movzbl_mr(address.offset, address.base, dest);
+    }
+    
+    void load8Signed(BaseIndex address, RegisterID dest)
+    {
+        m_assembler.movsbl_mr(address.offset, address.base, address.index, address.scale, dest);
+    }
+
+    void load8Signed(ImplicitAddress address, RegisterID dest)
+    {
+        m_assembler.movsbl_mr(address.offset, address.base, dest);
+    }
+    
     void load16(BaseIndex address, RegisterID dest)
     {
         m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
     void load16(BaseIndex address, RegisterID dest)
     {
         m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
@@ -480,6 +535,16 @@ public:
         m_assembler.movzwl_mr(address.offset, address.base, dest);
     }
 
         m_assembler.movzwl_mr(address.offset, address.base, dest);
     }
 
+    void load16Signed(BaseIndex address, RegisterID dest)
+    {
+        m_assembler.movswl_mr(address.offset, address.base, address.index, address.scale, dest);
+    }
+    
+    void load16Signed(Address address, RegisterID dest)
+    {
+        m_assembler.movswl_mr(address.offset, address.base, dest);
+    }
+
     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
     {
         m_assembler.movl_rm_disp32(src, address.offset, address.base);
     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
     {
         m_assembler.movl_rm_disp32(src, address.offset, address.base);
@@ -500,6 +565,77 @@ public:
     {
         m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
     }
     {
         m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
     }
+    
+    void store32(TrustedImm32 imm, BaseIndex address)
+    {
+        m_assembler.movl_i32m(imm.m_value, address.offset, address.base, address.index, address.scale);
+    }
+
+    void store8(TrustedImm32 imm, Address address)
+    {
+        ASSERT(-128 <= imm.m_value && imm.m_value < 128);
+        m_assembler.movb_i8m(imm.m_value, address.offset, address.base);
+    }
+
+    void store8(TrustedImm32 imm, BaseIndex address)
+    {
+        ASSERT(-128 <= imm.m_value && imm.m_value < 128);
+        m_assembler.movb_i8m(imm.m_value, address.offset, address.base, address.index, address.scale);
+    }
+    
+    void store8(RegisterID src, BaseIndex address)
+    {
+#if CPU(X86)
+        // On 32-bit x86 we can only store from the first 4 registers;
+        // esp..edi are mapped to the 'h' registers!
+        if (src >= 4) {
+            // Pick a temporary register.
+            RegisterID temp;
+            if (address.base != X86Registers::eax && address.index != X86Registers::eax)
+                temp = X86Registers::eax;
+            else if (address.base != X86Registers::ebx && address.index != X86Registers::ebx)
+                temp = X86Registers::ebx;
+            else {
+                ASSERT(address.base != X86Registers::ecx && address.index != X86Registers::ecx);
+                temp = X86Registers::ecx;
+            }
+
+            // Swap to the temporary register to perform the store.
+            swap(src, temp);
+            m_assembler.movb_rm(temp, address.offset, address.base, address.index, address.scale);
+            swap(src, temp);
+            return;
+        }
+#endif
+        m_assembler.movb_rm(src, address.offset, address.base, address.index, address.scale);
+    }
+
+    void store16(RegisterID src, BaseIndex address)
+    {
+#if CPU(X86)
+        // On 32-bit x86 we can only store from the first 4 registers;
+        // esp..edi are mapped to the 'h' registers!
+        if (src >= 4) {
+            // Pick a temporary register.
+            RegisterID temp;
+            if (address.base != X86Registers::eax && address.index != X86Registers::eax)
+                temp = X86Registers::eax;
+            else if (address.base != X86Registers::ebx && address.index != X86Registers::ebx)
+                temp = X86Registers::ebx;
+            else {
+                ASSERT(address.base != X86Registers::ecx && address.index != X86Registers::ecx);
+                temp = X86Registers::ecx;
+            }
+            
+            // Swap to the temporary register to perform the store.
+            swap(src, temp);
+            m_assembler.movw_rm(temp, address.offset, address.base, address.index, address.scale);
+            swap(src, temp);
+            return;
+        }
+#endif
+        m_assembler.movw_rm(src, address.offset, address.base, address.index, address.scale);
+    }
 
 
     // Floating-point operation:
 
 
     // Floating-point operation:
@@ -513,17 +649,63 @@ public:
             m_assembler.movsd_rr(src, dest);
     }
 
             m_assembler.movsd_rr(src, dest);
     }
 
+    void loadDouble(const void* address, FPRegisterID dest)
+    {
+#if CPU(X86)
+        ASSERT(isSSE2Present());
+        m_assembler.movsd_mr(address, dest);
+#else
+        move(TrustedImmPtr(address), scratchRegister);
+        loadDouble(scratchRegister, dest);
+#endif
+    }
+
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
         m_assembler.movsd_mr(address.offset, address.base, dest);
     }
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
         m_assembler.movsd_mr(address.offset, address.base, dest);
     }
+    
+    void loadDouble(BaseIndex address, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
+    }
+    void loadFloat(BaseIndex address, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movss_mr(address.offset, address.base, address.index, address.scale, dest);
+    }
 
     void storeDouble(FPRegisterID src, ImplicitAddress address)
     {
         ASSERT(isSSE2Present());
         m_assembler.movsd_rm(src, address.offset, address.base);
     }
 
     void storeDouble(FPRegisterID src, ImplicitAddress address)
     {
         ASSERT(isSSE2Present());
         m_assembler.movsd_rm(src, address.offset, address.base);
     }
+    
+    void storeDouble(FPRegisterID src, BaseIndex address)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movsd_rm(src, address.offset, address.base, address.index, address.scale);
+    }
+    
+    void storeFloat(FPRegisterID src, BaseIndex address)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movss_rm(src, address.offset, address.base, address.index, address.scale);
+    }
+    
+    void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.cvtsd2ss_rr(src, dst);
+    }
+
+    void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.cvtss2sd_rr(src, dst);
+    }
 
     void addDouble(FPRegisterID src, FPRegisterID dest)
     {
 
     void addDouble(FPRegisterID src, FPRegisterID dest)
     {
@@ -664,6 +846,27 @@ public:
         return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000));
     }
 
         return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000));
     }
 
+    Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.cvttsd2si_rr(src, dest);
+        return branch32(branchType ? GreaterThanOrEqual : LessThan, dest, TrustedImm32(0));
+    }
+
+    void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.cvttsd2si_rr(src, dest);
+    }
+    
+#if CPU(X86_64)
+    void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.cvttsd2siq_rr(src, dest);
+    }
+#endif
+    
     // 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
     // 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
@@ -697,6 +900,36 @@ public:
         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
     }
 
         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
     }
 
+    void lshiftPacked(TrustedImm32 imm, XMMRegisterID reg)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.psllq_i8r(imm.m_value, reg);
+    }
+
+    void rshiftPacked(TrustedImm32 imm, XMMRegisterID reg)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.psrlq_i8r(imm.m_value, reg);
+    }
+
+    void orPacked(XMMRegisterID src, XMMRegisterID dst)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.por_rr(src, dst);
+    }
+
+    void moveInt32ToPacked(RegisterID src, XMMRegisterID dst)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movd_rr(src, dst);
+    }
+
+    void movePackedToInt32(XMMRegisterID src, RegisterID dst)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movd_rr(src, dst);
+    }
+
     // 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,
@@ -839,15 +1072,6 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
-    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);
     Jump branch32(RelationalCondition cond, RegisterID left, Address right)
     {
         m_assembler.cmpl_mr(right.offset, right.base, left);
@@ -877,20 +1101,6 @@ public:
         return branch32(cond, left, right);
     }
 
         return branch32(cond, left, right);
     }
 
-    Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right)
-    {
-        m_assembler.cmpw_rm(right, left.offset, left.base, left.index, left.scale);
-        return Jump(m_assembler.jCC(x86Condition(cond)));
-    }
-
-    Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
-    {
-        ASSERT(!(right.m_value & 0xFFFF0000));
-
-        m_assembler.cmpw_im(right.m_value, left.offset, left.base, left.index, left.scale);
-        return Jump(m_assembler.jCC(x86Condition(cond)));
-    }
-
     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
         m_assembler.testl_rr(reg, mask);
     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
         m_assembler.testl_rr(reg, mask);
@@ -902,8 +1112,6 @@ public:
         // 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);
-        else if ((mask.m_value & ~0x7f) == 0)
-            m_assembler.testb_i8r(mask.m_value, reg);
         else
             m_assembler.testl_i32r(mask.m_value, reg);
         return Jump(m_assembler.jCC(x86Condition(cond)));
         else
             m_assembler.testl_i32r(mask.m_value, reg);
         return Jump(m_assembler.jCC(x86Condition(cond)));
@@ -927,17 +1135,6 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
-    Jump branchTest8(ResultCondition cond, RegisterID reg, 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.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.
     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.
@@ -960,6 +1157,14 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
+    Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
+    {
+        ASSERT(!(right.m_value & 0xFFFFFF00));
+
+        m_assembler.cmpb_im(right.m_value, left.offset, left.base, left.index, left.scale);
+        return Jump(m_assembler.jCC(x86Condition(cond)));
+    }
+
     Jump jump()
     {
         return Jump(m_assembler.jmp());
     Jump jump()
     {
         return Jump(m_assembler.jmp());
@@ -1148,11 +1353,16 @@ public:
         m_assembler.ret();
     }
 
         m_assembler.ret();
     }
 
+    void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
+    {
+        m_assembler.cmpb_im(right.m_value, left.offset, left.base);
+        set32(x86Condition(cond), dest);
+    }
+    
     void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
     {
         m_assembler.cmpl_rr(right, left);
     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);
+        set32(x86Condition(cond), dest);
     }
 
     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     }
 
     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
@@ -1161,12 +1371,11 @@ public:
             m_assembler.testl_rr(left, left);
         else
             m_assembler.cmpl_ir(right.m_value, left);
             m_assembler.testl_rr(left, left);
         else
             m_assembler.cmpl_ir(right.m_value, left);
-        m_assembler.setCC_r(x86Condition(cond), dest);
-        m_assembler.movzbl_rr(dest, dest);
+        set32(x86Condition(cond), dest);
     }
 
     // FIXME:
     }
 
     // FIXME:
-    // The mask should be optional... paerhaps the argument order should be
+    // The mask should be optional... perhaps 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().
 
     // dest-src, operations always have a dest? ... possibly not true, considering
     // asm ops like test, or pseudo ops like pop().
 
@@ -1176,8 +1385,7 @@ public:
             m_assembler.cmpb_im(0, address.offset, address.base);
         else
             m_assembler.testb_im(mask.m_value, address.offset, address.base);
             m_assembler.cmpb_im(0, address.offset, address.base);
         else
             m_assembler.testb_im(mask.m_value, address.offset, address.base);
-        m_assembler.setCC_r(x86Condition(cond), dest);
-        m_assembler.movzbl_rr(dest, dest);
+        set32(x86Condition(cond), dest);
     }
 
     void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
     }
 
     void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
@@ -1186,8 +1394,7 @@ public:
             m_assembler.cmpl_im(0, address.offset, address.base);
         else
             m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
             m_assembler.cmpl_im(0, address.offset, address.base);
         else
             m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
-        m_assembler.setCC_r(x86Condition(cond), dest);
-        m_assembler.movzbl_rr(dest, dest);
+        set32(x86Condition(cond), dest);
     }
 
     // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
     }
 
     // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
@@ -1196,25 +1403,6 @@ public:
         return static_cast<RelationalCondition>(cond ^ 1);
     }
 
         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();
     void nop()
     {
         m_assembler.nop();
@@ -1231,6 +1419,23 @@ protected:
         return static_cast<X86Assembler::Condition>(cond);
     }
 
         return static_cast<X86Assembler::Condition>(cond);
     }
 
+    void set32(X86Assembler::Condition cond, RegisterID dest)
+    {
+#if CPU(X86)
+        // On 32-bit x86 we can only set the first 4 registers;
+        // esp..edi are mapped to the 'h' registers!
+        if (dest >= 4) {
+            m_assembler.xchgl_rr(dest, X86Registers::eax);
+            m_assembler.setCC_r(cond, X86Registers::eax);
+            m_assembler.movzbl_rr(X86Registers::eax, X86Registers::eax);
+            m_assembler.xchgl_rr(dest, X86Registers::eax);
+            return;
+        }
+#endif
+        m_assembler.setCC_r(cond, dest);
+        m_assembler.movzbl_rr(dest, dest);
+    }
+
 private:
     // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
     // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
 private:
     // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
     // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
index b95bc2ee75765ea22da91e2e8b4510c475ef4a3e..41479f996ff57e9b58f221bd0d68980ee50dfb6f 100644 (file)
 namespace JSC {
 
 class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
 namespace JSC {
 
 class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
-protected:
-    static const X86Registers::RegisterID scratchRegister = X86Registers::r11;
-
 public:
     static const Scale ScalePtr = TimesEight;
 
     using MacroAssemblerX86Common::add32;
     using MacroAssemblerX86Common::and32;
 public:
     static const Scale ScalePtr = TimesEight;
 
     using MacroAssemblerX86Common::add32;
     using MacroAssemblerX86Common::and32;
+    using MacroAssemblerX86Common::branchAdd32;
     using MacroAssemblerX86Common::or32;
     using MacroAssemblerX86Common::sub32;
     using MacroAssemblerX86Common::load32;
     using MacroAssemblerX86Common::store32;
     using MacroAssemblerX86Common::call;
     using MacroAssemblerX86Common::or32;
     using MacroAssemblerX86Common::sub32;
     using MacroAssemblerX86Common::load32;
     using MacroAssemblerX86Common::store32;
     using MacroAssemblerX86Common::call;
+    using MacroAssemblerX86Common::jump;
     using MacroAssemblerX86Common::addDouble;
     using MacroAssemblerX86Common::loadDouble;
     using MacroAssemblerX86Common::convertInt32ToDouble;
     using MacroAssemblerX86Common::addDouble;
     using MacroAssemblerX86Common::loadDouble;
     using MacroAssemblerX86Common::convertInt32ToDouble;
@@ -76,23 +75,16 @@ public:
         sub32(imm, Address(scratchRegister));
     }
 
         sub32(imm, Address(scratchRegister));
     }
 
-    void load32(void* address, RegisterID dest)
+    void load32(const void* address, RegisterID dest)
     {
         if (dest == X86Registers::eax)
             m_assembler.movl_mEAX(address);
         else {
     {
         if (dest == X86Registers::eax)
             m_assembler.movl_mEAX(address);
         else {
-            move(X86Registers::eax, dest);
-            m_assembler.movl_mEAX(address);
-            swap(X86Registers::eax, dest);
+            move(TrustedImmPtr(address), dest);
+            load32(dest, dest);
         }
     }
 
         }
     }
 
-    void loadDouble(const void* address, FPRegisterID dest)
-    {
-        move(TrustedImmPtr(address), scratchRegister);
-        loadDouble(scratchRegister, dest);
-    }
-
     void addDouble(AbsoluteAddress address, FPRegisterID dest)
     {
         move(TrustedImmPtr(address.m_ptr), scratchRegister);
     void addDouble(AbsoluteAddress address, FPRegisterID dest)
     {
         move(TrustedImmPtr(address.m_ptr), scratchRegister);
@@ -107,10 +99,8 @@ public:
 
     void store32(TrustedImm32 imm, void* address)
     {
 
     void store32(TrustedImm32 imm, void* address)
     {
-        move(X86Registers::eax, scratchRegister);
-        move(imm, X86Registers::eax);
-        m_assembler.movl_EAXm(address);
-        move(scratchRegister, X86Registers::eax);
+        move(TrustedImmPtr(address), scratchRegister);
+        store32(imm, scratchRegister);
     }
 
     Call call()
     }
 
     Call call()
@@ -121,6 +111,13 @@ public:
         return result;
     }
 
         return result;
     }
 
+    // Address is a memory location containing the address to jump to
+    void jump(AbsoluteAddress address)
+    {
+        move(TrustedImmPtr(address.m_ptr), scratchRegister);
+        jump(Address(scratchRegister));
+    }
+
     Call tailRecursiveCall()
     {
         DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister);
     Call tailRecursiveCall()
     {
         DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister);
@@ -170,7 +167,12 @@ public:
         move(TrustedImmPtr(address.m_ptr), scratchRegister);
         addPtr(imm, Address(scratchRegister));
     }
         move(TrustedImmPtr(address.m_ptr), scratchRegister);
         addPtr(imm, Address(scratchRegister));
     }
-    
+
+    void add64(TrustedImm32 imm, AbsoluteAddress address)
+    {
+        addPtr(imm, address);
+    }
+
     void andPtr(RegisterID src, RegisterID dest)
     {
         m_assembler.andq_rr(src, dest);
     void andPtr(RegisterID src, RegisterID dest)
     {
         m_assembler.andq_rr(src, dest);
@@ -214,6 +216,11 @@ public:
         move(src, dest);
         orPtr(imm, dest);
     }
         move(src, dest);
         orPtr(imm, dest);
     }
+    
+    void rotateRightPtr(TrustedImm32 imm, RegisterID srcDst)
+    {
+        m_assembler.rorq_i8r(imm.m_value, srcDst);
+    }
 
     void subPtr(RegisterID src, RegisterID dest)
     {
 
     void subPtr(RegisterID src, RegisterID dest)
     {
@@ -235,13 +242,17 @@ public:
     {
         m_assembler.xorq_rr(src, dest);
     }
     {
         m_assembler.xorq_rr(src, dest);
     }
+    
+    void xorPtr(RegisterID src, Address dest)
+    {
+        m_assembler.xorq_rm(src, dest.offset, dest.base);
+    }
 
     void xorPtr(TrustedImm32 imm, RegisterID srcDest)
     {
         m_assembler.xorq_ir(imm.m_value, srcDest);
     }
 
 
     void xorPtr(TrustedImm32 imm, RegisterID srcDest)
     {
         m_assembler.xorq_ir(imm.m_value, srcDest);
     }
 
-
     void loadPtr(ImplicitAddress address, RegisterID dest)
     {
         m_assembler.movq_mr(address.offset, address.base, dest);
     void loadPtr(ImplicitAddress address, RegisterID dest)
     {
         m_assembler.movq_mr(address.offset, address.base, dest);
@@ -257,9 +268,8 @@ public:
         if (dest == X86Registers::eax)
             m_assembler.movq_mEAX(address);
         else {
         if (dest == X86Registers::eax)
             m_assembler.movq_mEAX(address);
         else {
-            move(X86Registers::eax, dest);
-            m_assembler.movq_mEAX(address);
-            swap(X86Registers::eax, dest);
+            move(TrustedImmPtr(address), dest);
+            loadPtr(dest, dest);
         }
     }
 
         }
     }
 
@@ -290,9 +300,8 @@ public:
         if (src == X86Registers::eax)
             m_assembler.movq_EAXm(address);
         else {
         if (src == X86Registers::eax)
             m_assembler.movq_EAXm(address);
         else {
-            swap(X86Registers::eax, src);
-            m_assembler.movq_EAXm(address);
-            swap(X86Registers::eax, src);
+            move(TrustedImmPtr(address), scratchRegister);
+            storePtr(src, scratchRegister);
         }
     }
 
         }
     }
 
@@ -302,6 +311,12 @@ public:
         storePtr(scratchRegister, address);
     }
 
         storePtr(scratchRegister, address);
     }
 
+    void storePtr(TrustedImmPtr imm, BaseIndex address)
+    {
+        move(imm, scratchRegister);
+        m_assembler.movq_rm(scratchRegister, address.offset, address.base, address.index, address.scale);
+    }
+    
     DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
     {
         m_assembler.movq_rm_disp32(src, address.offset, address.base);
     DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
     {
         m_assembler.movq_rm_disp32(src, address.offset, address.base);
@@ -327,6 +342,20 @@ public:
         m_assembler.setCC_r(x86Condition(cond), dest);
         m_assembler.movzbl_rr(dest, dest);
     }
         m_assembler.setCC_r(x86Condition(cond), dest);
         m_assembler.movzbl_rr(dest, dest);
     }
+    
+    void comparePtr(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
+    {
+        m_assembler.cmpq_rr(right, left);
+        m_assembler.setCC_r(x86Condition(cond), dest);
+        m_assembler.movzbl_rr(dest, dest);
+    }
+    
+    Jump branchAdd32(ResultCondition cond, TrustedImm32 src, AbsoluteAddress dest)
+    {
+        move(TrustedImmPtr(dest.m_ptr), scratchRegister);
+        add32(src, Address(scratchRegister));
+        return Jump(m_assembler.jCC(x86Condition(cond)));
+    }
 
     Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right)
     {
 
     Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right)
     {
@@ -336,6 +365,10 @@ public:
 
     Jump branchPtr(RelationalCondition cond, RegisterID left, TrustedImmPtr right)
     {
 
     Jump branchPtr(RelationalCondition cond, RegisterID left, TrustedImmPtr right)
     {
+        if (((cond == Equal) || (cond == NotEqual)) && !right.m_value) {
+            m_assembler.testq_rr(left, left);
+            return Jump(m_assembler.jCC(x86Condition(cond)));
+        }
         move(right, scratchRegister);
         return branchPtr(cond, left, scratchRegister);
     }
         move(right, scratchRegister);
         return branchPtr(cond, left, scratchRegister);
     }
@@ -369,7 +402,7 @@ public:
         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(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
     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
@@ -382,6 +415,23 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
+    void testPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
+    {
+        if (mask.m_value == -1)
+            m_assembler.testq_rr(reg, reg);
+        else if ((mask.m_value & ~0x7f) == 0)
+            m_assembler.testb_i8r(mask.m_value, reg);
+        else
+            m_assembler.testq_i32r(mask.m_value, reg);
+        set32(x86Condition(cond), dest);
+    }
+
+    void testPtr(ResultCondition cond, RegisterID reg, RegisterID mask, RegisterID dest)
+    {
+        m_assembler.testq_rr(reg, mask);
+        set32(x86Condition(cond), dest);
+    }
+
     Jump branchTestPtr(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
     {
         loadPtr(address.m_ptr, scratchRegister);
     Jump branchTestPtr(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
     {
         loadPtr(address.m_ptr, scratchRegister);
@@ -407,6 +457,12 @@ public:
     }
 
 
     }
 
 
+    Jump branchAddPtr(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
+    {
+        addPtr(imm, dest);
+        return Jump(m_assembler.jCC(x86Condition(cond)));
+    }
+
     Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         addPtr(src, dest);
     Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         addPtr(src, dest);
@@ -419,6 +475,12 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
+    Jump branchSubPtr(ResultCondition cond, RegisterID src1, TrustedImm32 src2, RegisterID dest)
+    {
+        move(src1, dest);
+        return branchSubPtr(cond, src2, dest);
+    }
+
     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
     {
         m_assembler.movq_i64r(initialValue.asIntptr(), dest);
     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
     {
         m_assembler.movq_i64r(initialValue.asIntptr(), dest);
@@ -452,10 +514,18 @@ public:
         return MacroAssemblerX86Common::branchTest8(cond, BaseIndex(scratchRegister, address.base, TimesOne), mask);
     }
 
         return MacroAssemblerX86Common::branchTest8(cond, BaseIndex(scratchRegister, address.base, TimesOne), mask);
     }
 
-    bool supportsFloatingPoint() const { return true; }
+    static bool supportsFloatingPoint() { return true; }
     // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
     // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
-    bool supportsFloatingPointTruncate() const { return true; }
-    bool supportsFloatingPointSqrt() const { return true; }
+    static bool supportsFloatingPointTruncate() { return true; }
+    static bool supportsFloatingPointSqrt() { return true; }
+    static bool supportsFloatingPointAbs() { return true; }
+    
+    static FunctionPtr readCallTarget(CodeLocationCall call)
+    {
+        return FunctionPtr(X86Assembler::readPointer(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11).dataLocation()));
+    }
+
+    static RegisterID scratchRegisterForBlinding() { return scratchRegister; }
 
 private:
     friend class LinkBuffer;
 
 private:
     friend class LinkBuffer;
@@ -464,9 +534,9 @@ 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, call.m_jmp.labelAtOffset(-REPTACH_OFFSET_CALL_R11), function.value());
+            X86Assembler::linkPointer(code, call.m_label.labelAtOffset(-REPTACH_OFFSET_CALL_R11), function.value());
         else
         else
-            X86Assembler::linkCall(code, call.m_jmp, function.value());
+            X86Assembler::linkCall(code, call.m_label, function.value());
     }
 
     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
     }
 
     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
index 6ea6d8df3f6443bbcfa4e3e65dce4775790d08e6..a87294b1bb9f43437743cf61a496646d08824130 100644 (file)
@@ -26,8 +26,9 @@
 #ifndef RepatchBuffer_h
 #define RepatchBuffer_h
 
 #ifndef RepatchBuffer_h
 #define RepatchBuffer_h
 
-#if ENABLE(ASSEMBLER)
+#if ENABLE(JIT)
 
 
+#include "CodeBlock.h"
 #include <MacroAssembler.h>
 #include <wtf/Noncopyable.h>
 
 #include <MacroAssembler.h>
 #include <wtf/Noncopyable.h>
 
index 1d089e5abddb655ecb79637cb9cf7ac94e96d863..59d0422443e4a5d8495853e6ee04669b9a52d878 100644 (file)
 
 #include "AssemblerBuffer.h"
 #include "AssemblerBufferWithConstantPool.h"
 
 #include "AssemblerBuffer.h"
 #include "AssemblerBufferWithConstantPool.h"
+#include "JITCompilationEffort.h"
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdarg.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <wtf/Assertions.h>
 #include <wtf/Assertions.h>
+#include <wtf/DataLog.h>
 #include <wtf/Vector.h>
 
 #ifndef NDEBUG
 #include <wtf/Vector.h>
 
 #ifndef NDEBUG
@@ -151,6 +154,7 @@ enum {
     TST_OPCODE = 0x2008,
     TSTIMM_OPCODE = 0xc800,
     TSTB_OPCODE = 0xcc00,
     TST_OPCODE = 0x2008,
     TSTIMM_OPCODE = 0xc800,
     TSTB_OPCODE = 0xcc00,
+    EXTUB_OPCODE = 0x600c,
     EXTUW_OPCODE = 0x600d,
     XOR_OPCODE = 0x200a,
     XORIMM_OPCODE = 0xca00,
     EXTUW_OPCODE = 0x600d,
     XOR_OPCODE = 0x200a,
     XORIMM_OPCODE = 0xca00,
@@ -322,6 +326,10 @@ public:
         padForAlign32 = 0x00090009,
     };
 
         padForAlign32 = 0x00090009,
     };
 
+    enum JumpType { JumpFar,
+                    JumpNear
+    };
+
     SH4Assembler()
     {
         m_claimscratchReg = 0x0;
     SH4Assembler()
     {
         m_claimscratchReg = 0x0;
@@ -757,6 +765,12 @@ public:
         oneShortOp(opc);
     }
 
         oneShortOp(opc);
     }
 
+    void extub(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(EXTUB_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+    
     void extuw(RegisterID src, RegisterID dst)
     {
         uint16_t opc = getOpcodeGroup1(EXTUW_OPCODE, dst, src);
     void extuw(RegisterID src, RegisterID dst)
     {
         uint16_t opc = getOpcodeGroup1(EXTUW_OPCODE, dst, src);
@@ -1063,6 +1077,11 @@ public:
         oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE, dst, base, offset));
     }
 
         oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE, dst, base, offset));
     }
 
+    void movlMemRegCompact(int offset, RegisterID base, RegisterID dst)
+    {
+        oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE, dst, base, offset));
+    }
+
     void movbMemReg(int offset, RegisterID base, RegisterID dst)
     {
         ASSERT(dst == SH4Registers::r0);
     void movbMemReg(int offset, RegisterID base, RegisterID dst)
     {
         ASSERT(dst == SH4Registers::r0);
@@ -1173,6 +1192,13 @@ public:
         return label;
     }
 
         return label;
     }
 
+    void extraInstrForBranch(RegisterID dst)
+    {
+        loadConstantUnReusable(0x0, dst);
+        nop();
+        nop();
+    }
+
     AssemblerLabel jmp(RegisterID dst)
     {
         jmpReg(dst);
     AssemblerLabel jmp(RegisterID dst)
     {
         jmpReg(dst);
@@ -1200,6 +1226,13 @@ public:
         return label;
     }
 
         return label;
     }
 
+    AssemblerLabel bra()
+    {
+        AssemblerLabel label = m_buffer.label();
+        branch(BRA_OPCODE, 0);
+        return label;
+    }
+
     void ret()
     {
         m_buffer.ensureSpace(maxInstructionSize + 2);
     void ret()
     {
         m_buffer.ensureSpace(maxInstructionSize + 2);
@@ -1232,7 +1265,7 @@ public:
         uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
         *reinterpret_cast<uint32_t*>(address) = 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));
     static uint32_t readPCrelativeAddress(int offset, uint16_t* instructionPtr)
     {
         uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
@@ -1354,7 +1387,7 @@ public:
 
     static void* readPointer(void* code)
     {
 
     static void* readPointer(void* code)
     {
-        return static_cast<void*>(readInt32(code));
+        return reinterpret_cast<void*>(readInt32(code));
     }
 
     static void repatchInt32(void* where, int32_t value)
     }
 
     static void repatchInt32(void* where, int32_t value)
@@ -1365,7 +1398,10 @@ public:
 
     static void repatchCompact(void* where, int32_t value)
     {
 
     static void repatchCompact(void* where, int32_t value)
     {
-        repatchInt32(where, value);
+        ASSERT(value >= 0);
+        ASSERT(value <= 60);
+        *reinterpret_cast<uint16_t*>(where) = ((*reinterpret_cast<uint16_t*>(where) & 0xfff0) | (value >> 2));
+        cacheFlush(reinterpret_cast<uint16_t*>(where), sizeof(uint16_t));
     }
 
     static void relinkCall(void* from, void* to)
     }
 
     static void relinkCall(void* from, void* to)
@@ -1406,7 +1442,7 @@ public:
 
     // Linking & patching
 
 
     // Linking & patching
 
-    void linkJump(AssemblerLabel from, AssemblerLabel to)
+    void linkJump(AssemblerLabel from, AssemblerLabel to, JumpType type = JumpFar)
     {
         ASSERT(to.isSet());
         ASSERT(from.isSet());
     {
         ASSERT(to.isSet());
         ASSERT(from.isSet());
@@ -1415,6 +1451,14 @@ public:
         uint16_t instruction = *instructionPtr;
         int offsetBits;
 
         uint16_t instruction = *instructionPtr;
         int offsetBits;
 
+        if (type == JumpNear) {
+            ASSERT((instruction ==  BT_OPCODE) || (instruction == BF_OPCODE) || (instruction == BRA_OPCODE));
+            int offset = (codeSize() - from.m_offset) - 4;
+            *instructionPtr++ = instruction | (offset >> 1);
+            printInstr(*instructionPtr, from.m_offset + 2);
+            return;
+        }
+
         if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
             /* BT label => BF 2
                nop        LDR reg
         if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
             /* BT label => BF 2
                nop        LDR reg
@@ -1490,9 +1534,27 @@ public:
         return readPCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code));
     }
 
         return readPCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code));
     }
 
-    void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
+    static void* readCallTarget(void* from)
+    {
+        uint16_t* instructionPtr = static_cast<uint16_t*>(from);
+        instructionPtr -= 3;
+        return reinterpret_cast<void*>(readPCrelativeAddress((*instructionPtr & 0xff), instructionPtr));
+    }
+
+    PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort)
     {
     {
-        return m_buffer.executableCopy(globalData, allocator);
+        return m_buffer.executableCopy(globalData, ownerUID, effort);
+    }
+
+    static void cacheFlush(void* code, size_t size)
+    {
+#if !OS(LINUX)
+#error "The cacheFlush support is missing on this platform."
+#elif defined 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
     }
 
     void prefix(uint16_t pre)
     }
 
     void prefix(uint16_t pre)
@@ -1801,6 +1863,9 @@ public:
         case MOVW_READ_R0RM_OPCODE:
             format = "    MOV.W @(R0, R%d), R%d\n";
             break;
         case MOVW_READ_R0RM_OPCODE:
             format = "    MOV.W @(R0, R%d), R%d\n";
             break;
+        case EXTUB_OPCODE:
+            format = "    EXTU.B R%d, R%d\n";
+            break;
         case EXTUW_OPCODE:
             format = "    EXTU.W R%d, R%d\n";
             break;
         case EXTUW_OPCODE:
             format = "    EXTU.W R%d, R%d\n";
             break;
@@ -1999,7 +2064,7 @@ public:
     static void vprintfStdoutInstr(const char* format, va_list args)
     {
         if (getenv("JavaScriptCoreDumpJIT"))
     static void vprintfStdoutInstr(const char* format, va_list args)
     {
         if (getenv("JavaScriptCoreDumpJIT"))
-            vfprintf(stdout, format, args);
+            WTF::dataLogV(format, args);
     }
 
     static void printBlockInstr(uint16_t* first, unsigned int offset, int nbInstr)
     }
 
     static void printBlockInstr(uint16_t* first, unsigned int offset, int nbInstr)
index 41dd50ffcc7cf7cabf700076f45c92e9df446826..ff8d25bcd44c2312c001c848990cb77db8153e03 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64))
 
 #include "AssemblerBuffer.h"
 #if ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64))
 
 #include "AssemblerBuffer.h"
+#include "JITCompilationEffort.h"
 #include <stdint.h>
 #include <wtf/Assertions.h>
 #include <wtf/Vector.h>
 #include <stdint.h>
 #include <wtf/Assertions.h>
 #include <wtf/Vector.h>
@@ -134,6 +135,7 @@ private:
         OP_TEST_EbGb                    = 0x84,
         OP_TEST_EvGv                    = 0x85,
         OP_XCHG_EvGv                    = 0x87,
         OP_TEST_EbGb                    = 0x84,
         OP_TEST_EvGv                    = 0x85,
         OP_XCHG_EvGv                    = 0x87,
+        OP_MOV_EbGb                     = 0x88,
         OP_MOV_EvGv                     = 0x89,
         OP_MOV_GvEv                     = 0x8B,
         OP_LEA                          = 0x8D,
         OP_MOV_EvGv                     = 0x89,
         OP_MOV_GvEv                     = 0x8B,
         OP_LEA                          = 0x8D,
@@ -145,13 +147,16 @@ private:
         OP_MOV_EAXIv                    = 0xB8,
         OP_GROUP2_EvIb                  = 0xC1,
         OP_RET                          = 0xC3,
         OP_MOV_EAXIv                    = 0xB8,
         OP_GROUP2_EvIb                  = 0xC1,
         OP_RET                          = 0xC3,
+        OP_GROUP11_EvIb                 = 0xC6,
         OP_GROUP11_EvIz                 = 0xC7,
         OP_INT3                         = 0xCC,
         OP_GROUP2_Ev1                   = 0xD1,
         OP_GROUP2_EvCL                  = 0xD3,
         OP_GROUP11_EvIz                 = 0xC7,
         OP_INT3                         = 0xCC,
         OP_GROUP2_Ev1                   = 0xD1,
         OP_GROUP2_EvCL                  = 0xD3,
+        OP_ESCAPE_DD                    = 0xDD,
         OP_CALL_rel32                   = 0xE8,
         OP_JMP_rel32                    = 0xE9,
         PRE_SSE_F2                      = 0xF2,
         OP_CALL_rel32                   = 0xE8,
         OP_JMP_rel32                    = 0xE9,
         PRE_SSE_F2                      = 0xF2,
+        PRE_SSE_F3                      = 0xF3,
         OP_HLT                          = 0xF4,
         OP_GROUP3_EbIb                  = 0xF6,
         OP_GROUP3_Ev                    = 0xF7,
         OP_HLT                          = 0xF4,
         OP_GROUP3_EbIb                  = 0xF6,
         OP_GROUP3_Ev                    = 0xF7,
@@ -162,14 +167,19 @@ private:
     typedef enum {
         OP2_MOVSD_VsdWsd    = 0x10,
         OP2_MOVSD_WsdVsd    = 0x11,
     typedef enum {
         OP2_MOVSD_VsdWsd    = 0x10,
         OP2_MOVSD_WsdVsd    = 0x11,
+        OP2_MOVSS_VsdWsd    = 0x10,
+        OP2_MOVSS_WsdVsd    = 0x11,
         OP2_CVTSI2SD_VsdEd  = 0x2A,
         OP2_CVTTSD2SI_GdWsd = 0x2C,
         OP2_UCOMISD_VsdWsd  = 0x2E,
         OP2_ADDSD_VsdWsd    = 0x58,
         OP2_MULSD_VsdWsd    = 0x59,
         OP2_CVTSI2SD_VsdEd  = 0x2A,
         OP2_CVTTSD2SI_GdWsd = 0x2C,
         OP2_UCOMISD_VsdWsd  = 0x2E,
         OP2_ADDSD_VsdWsd    = 0x58,
         OP2_MULSD_VsdWsd    = 0x59,
+        OP2_CVTSD2SS_VsdWsd = 0x5A,
+        OP2_CVTSS2SD_VsdWsd = 0x5A,
         OP2_SUBSD_VsdWsd    = 0x5C,
         OP2_DIVSD_VsdWsd    = 0x5E,
         OP2_SQRTSD_VsdWsd   = 0x51,
         OP2_SUBSD_VsdWsd    = 0x5C,
         OP2_DIVSD_VsdWsd    = 0x5E,
         OP2_SQRTSD_VsdWsd   = 0x51,
+        OP2_ANDNPD_VpdWpd   = 0x55,
         OP2_XORPD_VpdWpd    = 0x57,
         OP2_MOVD_VdEd       = 0x6E,
         OP2_MOVD_EdVd       = 0x7E,
         OP2_XORPD_VpdWpd    = 0x57,
         OP2_MOVD_VdEd       = 0x6E,
         OP2_MOVD_EdVd       = 0x7E,
@@ -177,8 +187,13 @@ private:
         OP_SETCC            = 0x90,
         OP2_IMUL_GvEv       = 0xAF,
         OP2_MOVZX_GvEb      = 0xB6,
         OP_SETCC            = 0x90,
         OP2_IMUL_GvEv       = 0xAF,
         OP2_MOVZX_GvEb      = 0xB6,
+        OP2_MOVSX_GvEb      = 0xBE,
         OP2_MOVZX_GvEw      = 0xB7,
         OP2_MOVZX_GvEw      = 0xB7,
+        OP2_MOVSX_GvEw      = 0xBF,
         OP2_PEXTRW_GdUdIb   = 0xC5,
         OP2_PEXTRW_GdUdIb   = 0xC5,
+        OP2_PSLLQ_UdqIb     = 0x73,
+        OP2_PSRLQ_UdqIb     = 0x73,
+        OP2_POR_VdqWdq      = 0XEB,
     } TwoByteOpcodeID;
 
     TwoByteOpcodeID jccRel32(Condition cond)
     } TwoByteOpcodeID;
 
     TwoByteOpcodeID jccRel32(Condition cond)
@@ -201,7 +216,12 @@ private:
         GROUP1_OP_CMP = 7,
 
         GROUP1A_OP_POP = 0,
         GROUP1_OP_CMP = 7,
 
         GROUP1A_OP_POP = 0,
-
+        
+        GROUP2_OP_ROL = 0,
+        GROUP2_OP_ROR = 1,
+        GROUP2_OP_RCL = 2,
+        GROUP2_OP_RCR = 3,
+        
         GROUP2_OP_SHL = 4,
         GROUP2_OP_SHR = 5,
         GROUP2_OP_SAR = 7,
         GROUP2_OP_SHL = 4,
         GROUP2_OP_SHR = 5,
         GROUP2_OP_SAR = 7,
@@ -216,6 +236,11 @@ private:
         GROUP5_OP_PUSH  = 6,
 
         GROUP11_MOV = 0,
         GROUP5_OP_PUSH  = 6,
 
         GROUP11_MOV = 0,
+
+        GROUP14_OP_PSLLQ = 6,
+        GROUP14_OP_PSRLQ = 2,
+
+        ESCAPE_DD_FSTP_doubleReal = 3,
     } GroupOpcodeID;
     
     class X86InstructionFormatter;
     } GroupOpcodeID;
     
     class X86InstructionFormatter;
@@ -616,6 +641,22 @@ public:
             m_formatter.immediate32(imm);
         }
     }
             m_formatter.immediate32(imm);
         }
     }
+    
+    void xorq_rm(RegisterID src, int offset, RegisterID base)
+    {
+        m_formatter.oneByteOp64(OP_XOR_EvGv, src, base, offset);
+    }
+    
+    void rorq_i8r(int imm, RegisterID dst)
+    {
+        if (imm == 1)
+            m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_ROR, dst);
+        else {
+            m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_ROR, dst);
+            m_formatter.immediate8(imm);
+        }
+    }
+
 #endif
 
     void sarl_i8r(int imm, RegisterID dst)
 #endif
 
     void sarl_i8r(int imm, RegisterID dst)
@@ -841,6 +882,19 @@ public:
     }
 #endif
 
     }
 #endif
 
+    void cmpw_ir(int imm, RegisterID dst)
+    {
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.prefix(PRE_OPERAND_SIZE);
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.prefix(PRE_OPERAND_SIZE);
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
+            m_formatter.immediate16(imm);
+        }
+    }
+
     void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
     {
         m_formatter.prefix(PRE_OPERAND_SIZE);
     void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
     {
         m_formatter.prefix(PRE_OPERAND_SIZE);
@@ -879,7 +933,7 @@ public:
 
     void testb_rr(RegisterID src, RegisterID dst)
     {
 
     void testb_rr(RegisterID src, RegisterID dst)
     {
-        m_formatter.oneByteOp(OP_TEST_EbGb, src, dst);
+        m_formatter.oneByteOp8(OP_TEST_EbGb, src, dst);
     }
 
     void testb_im(int imm, int offset, RegisterID base)
     }
 
     void testb_im(int imm, int offset, RegisterID base)
@@ -969,6 +1023,11 @@ public:
         m_formatter.oneByteOp(OP_CDQ);
     }
 
         m_formatter.oneByteOp(OP_CDQ);
     }
 
+    void fstpl(int offset, RegisterID base)
+    {
+        m_formatter.oneByteOp(OP_ESCAPE_DD, ESCAPE_DD_FSTP_doubleReal, base, offset);
+    }
+
     void xchgl_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst);
     void xchgl_rr(RegisterID src, RegisterID dst)
     {
         m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst);
@@ -1042,6 +1101,37 @@ public:
         m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
         m_formatter.immediate32(imm);
     }
         m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
         m_formatter.immediate32(imm);
     }
+    
+    void movl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
+    {
+        m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset);
+        m_formatter.immediate32(imm);
+    }
+
+    void movb_i8m(int imm, int offset, RegisterID base)
+    {
+        ASSERT(-128 <= imm && imm < 128);
+        m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, base, offset);
+        m_formatter.immediate8(imm);
+    }
+
+    void movb_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale)
+    {
+        ASSERT(-128 <= imm && imm < 128);
+        m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, base, index, scale, offset);
+        m_formatter.immediate8(imm);
+    }
+    
+    void movb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+    {
+        m_formatter.oneByteOp8(OP_MOV_EbGb, src, base, index, scale, offset);
+    }
+    
+    void movw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+    {
+        m_formatter.prefix(PRE_OPERAND_SIZE);
+        m_formatter.oneByteOp8(OP_MOV_EvGv, src, base, index, scale, offset);
+    }
 
     void movl_EAXm(const void* addr)
     {
 
     void movl_EAXm(const void* addr)
     {
@@ -1158,6 +1248,36 @@ public:
         m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, index, scale, offset);
     }
 
         m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, index, scale, offset);
     }
 
+    void movswl_mr(int offset, RegisterID base, RegisterID dst)
+    {
+        m_formatter.twoByteOp(OP2_MOVSX_GvEw, dst, base, offset);
+    }
+
+    void movswl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+    {
+        m_formatter.twoByteOp(OP2_MOVSX_GvEw, dst, base, index, scale, offset);
+    }
+
+    void movzbl_mr(int offset, RegisterID base, RegisterID dst)
+    {
+        m_formatter.twoByteOp(OP2_MOVZX_GvEb, dst, base, offset);
+    }
+    
+    void movzbl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+    {
+        m_formatter.twoByteOp(OP2_MOVZX_GvEb, dst, base, index, scale, offset);
+    }
+
+    void movsbl_mr(int offset, RegisterID base, RegisterID dst)
+    {
+        m_formatter.twoByteOp(OP2_MOVSX_GvEb, dst, base, offset);
+    }
+    
+    void movsbl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+    {
+        m_formatter.twoByteOp(OP2_MOVSX_GvEb, dst, base, index, scale, offset);
+    }
+
     void movzbl_rr(RegisterID src, RegisterID dst)
     {
         // In 64-bit, this may cause an unnecessary REX to be planted (if the dst register
     void movzbl_rr(RegisterID src, RegisterID dst)
     {
         // In 64-bit, this may cause an unnecessary REX to be planted (if the dst register
@@ -1215,6 +1335,13 @@ public:
     {
         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset);
     }
     {
         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset);
     }
+    
+#if !CPU(X86_64)
+    void jmp_m(const void* address)
+    {
+        m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, address);
+    }
+#endif
 
     AssemblerLabel jne()
     {
 
     AssemblerLabel jne()
     {
@@ -1324,6 +1451,14 @@ public:
         m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
         m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
+#if !CPU(X86_64)
+    void addsd_mr(const void* address, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, address);
+    }
+#endif
+
     void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
     void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
@@ -1350,12 +1485,38 @@ public:
         m_formatter.twoByteOp(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
     }
 
         m_formatter.twoByteOp(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
     }
 
+    void cvtsd2ss_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_CVTSD2SS_VsdWsd, dst, (RegisterID)src);
+    }
+
+    void cvtss2sd_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_CVTSS2SD_VsdWsd, dst, (RegisterID)src);
+    }
+    
+#if CPU(X86_64)
+    void cvttsd2siq_rr(XMMRegisterID src, RegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp64(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
+    }
+#endif
+
     void movd_rr(XMMRegisterID src, RegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_66);
         m_formatter.twoByteOp(OP2_MOVD_EdVd, (RegisterID)src, dst);
     }
 
     void movd_rr(XMMRegisterID src, RegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_66);
         m_formatter.twoByteOp(OP2_MOVD_EdVd, (RegisterID)src, dst);
     }
 
+    void movd_rr(RegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.twoByteOp(OP2_MOVD_VdEd, (RegisterID)dst, src);
+    }
+
 #if CPU(X86_64)
     void movq_rr(XMMRegisterID src, RegisterID dst)
     {
 #if CPU(X86_64)
     void movq_rr(XMMRegisterID src, RegisterID dst)
     {
@@ -1381,19 +1542,48 @@ public:
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset);
     }
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset);
     }
-
+    
+    void movsd_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+    {
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, index, scale, offset);
+    }
+    
+    void movss_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, index, scale, offset);
+    }
+    
     void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
     void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
+    void movsd_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, dst, base, index, scale, offset);
+    }
+    
+    void movss_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, dst, base, index, scale, offset);
+    }
+
 #if !CPU(X86_64)
     void movsd_mr(const void* address, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, address);
     }
 #if !CPU(X86_64)
     void movsd_mr(const void* address, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, address);
     }
+    void movsd_rm(XMMRegisterID src, const void* address)
+    {
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, address);
+    }
 #endif
 
     void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
 #endif
 
     void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
@@ -1415,6 +1605,26 @@ public:
         m_formatter.immediate8(whichWord);
     }
 
         m_formatter.immediate8(whichWord);
     }
 
+    void psllq_i8r(int imm, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.twoByteOp8(OP2_PSLLQ_UdqIb, GROUP14_OP_PSLLQ, (RegisterID)dst);
+        m_formatter.immediate8(imm);
+    }
+
+    void psrlq_i8r(int imm, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.twoByteOp8(OP2_PSRLQ_UdqIb, GROUP14_OP_PSRLQ, (RegisterID)dst);
+        m_formatter.immediate8(imm);
+    }
+
+    void por_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.twoByteOp(OP2_POR_VdqWdq, (RegisterID)dst, (RegisterID)src);
+    }
+
     void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
     void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
@@ -1457,6 +1667,12 @@ public:
         m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
     }
 
         m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
     }
 
+    void andnpd_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.twoByteOp(OP2_ANDNPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
+    }
+
     void sqrtsd_rr(XMMRegisterID src, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
     void sqrtsd_rr(XMMRegisterID src, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
@@ -1588,22 +1804,21 @@ public:
         return b.m_offset - a.m_offset;
     }
     
         return b.m_offset - a.m_offset;
     }
     
-    void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
+    PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort)
     {
     {
-        return m_formatter.executableCopy(globalData, allocator);
+        return m_formatter.executableCopy(globalData, ownerUID, effort);
     }
 
     }
 
-    void rewindToLabel(AssemblerLabel rewindTo) { m_formatter.rewindToLabel(rewindTo); }
-
-#ifndef NDEBUG
     unsigned debugOffset() { return m_formatter.debugOffset(); }
     unsigned debugOffset() { return m_formatter.debugOffset(); }
-#endif
 
     void nop()
     {
         m_formatter.oneByteOp(OP_NOP);
     }
 
 
     void nop()
     {
         m_formatter.oneByteOp(OP_NOP);
     }
 
+    // This is a no-op on x86
+    ALWAYS_INLINE static void cacheFlush(void*, size_t) { }
+
 private:
 
     static void setPointer(void* where, void* value)
 private:
 
     static void setPointer(void* where, void* value)
@@ -1868,6 +2083,22 @@ private:
             registerModRM(groupOp, rm);
         }
 
             registerModRM(groupOp, rm);
         }
 
+        void oneByteOp8(OneByteOpcodeID opcode, int reg, RegisterID rm)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIf(byteRegRequiresRex(reg) || byteRegRequiresRex(rm), reg, 0, rm);
+            m_buffer.putByteUnchecked(opcode);
+            registerModRM(reg, rm);
+        }
+
+        void oneByteOp8(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIf(byteRegRequiresRex(reg) || regRequiresRex(index) || regRequiresRex(base), reg, index, base);
+            m_buffer.putByteUnchecked(opcode);
+            memoryModRM(reg, base, index, scale, offset);
+        }
+
         void twoByteOp8(TwoByteOpcodeID opcode, RegisterID reg, RegisterID rm)
         {
             m_buffer.ensureSpace(maxInstructionSize);
         void twoByteOp8(TwoByteOpcodeID opcode, RegisterID reg, RegisterID rm)
         {
             m_buffer.ensureSpace(maxInstructionSize);
@@ -1924,16 +2155,12 @@ private:
         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(JSGlobalData& globalData, ExecutablePool* allocator)
+        PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort)
         {
         {
-            return m_buffer.executableCopy(globalData, allocator);
+            return m_buffer.executableCopy(globalData, ownerUID, effort);
         }
 
         }
 
-        void rewindToLabel(AssemblerLabel rewindTo) { m_buffer.rewindToLabel(rewindTo); }
-
-#ifndef NDEBUG
         unsigned debugOffset() { return m_buffer.debugOffset(); }
         unsigned debugOffset() { return m_buffer.debugOffset(); }
-#endif
 
     private:
 
 
     private:
 
diff --git a/bytecode/BytecodeConventions.h b/bytecode/BytecodeConventions.h
new file mode 100644 (file)
index 0000000..f33b060
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef BytecodeConventions_h
+#define BytecodeConventions_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;
+
+#endif // BytecodeConventions_h
+
diff --git a/bytecode/CallLinkInfo.cpp b/bytecode/CallLinkInfo.cpp
new file mode 100644 (file)
index 0000000..4c108ec
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "CallLinkInfo.h"
+
+#include "DFGOperations.h"
+#include "RepatchBuffer.h"
+
+#if ENABLE(JIT)
+namespace JSC {
+
+void CallLinkInfo::unlink(JSGlobalData& globalData, RepatchBuffer& repatchBuffer)
+{
+    ASSERT(isLinked());
+    
+    if (isDFG) {
+#if ENABLE(DFG_JIT)
+        repatchBuffer.relink(CodeLocationCall(callReturnLocation), callType == Construct ? DFG::operationLinkConstruct : DFG::operationLinkCall);
+#else
+        ASSERT_NOT_REACHED();
+#endif
+    } else
+        repatchBuffer.relink(CodeLocationNearCall(callReturnLocation), callType == Construct ? globalData.jitStubs->ctiVirtualConstructLink() : globalData.jitStubs->ctiVirtualCallLink());
+    hasSeenShouldRepatch = false;
+    callee.clear();
+
+    // It will be on a list if the callee has a code block.
+    if (isOnList())
+        remove();
+}
+
+} // namespace JSC
+#endif // ENABLE(JIT)
+
diff --git a/bytecode/CallLinkInfo.h b/bytecode/CallLinkInfo.h
new file mode 100644 (file)
index 0000000..44d50a9
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CallLinkInfo_h
+#define CallLinkInfo_h
+
+#include "CodeLocation.h"
+#include "JITWriteBarrier.h"
+#include "JSFunction.h"
+#include "Opcode.h"
+#include "WriteBarrier.h"
+#include <wtf/Platform.h>
+#include <wtf/SentinelLinkedList.h>
+
+namespace JSC {
+
+#if ENABLE(JIT)
+
+class RepatchBuffer;
+
+struct CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> {
+    enum CallType { None, Call, CallVarargs, Construct };
+    static CallType callTypeFor(OpcodeID opcodeID)
+    {
+        if (opcodeID == op_call || opcodeID == op_call_eval)
+            return Call;
+        if (opcodeID == op_construct)
+            return Construct;
+        ASSERT(opcodeID == op_call_varargs);
+        return CallVarargs;
+    }
+        
+    CallLinkInfo()
+        : hasSeenShouldRepatch(false)
+        , isDFG(false)
+        , callType(None)
+    {
+    }
+        
+    ~CallLinkInfo()
+    {
+        if (isOnList())
+            remove();
+    }
+
+    CodeLocationLabel callReturnLocation; // it's a near call in the old JIT, or a normal call in DFG
+    CodeLocationDataLabelPtr hotPathBegin;
+    CodeLocationNearCall hotPathOther;
+    JITWriteBarrier<JSFunction> callee;
+    WriteBarrier<JSFunction> lastSeenCallee;
+    bool hasSeenShouldRepatch : 1;
+    bool isDFG : 1;
+    CallType callType : 6;
+    unsigned bytecodeIndex;
+
+    bool isLinked() { return callee; }
+    void unlink(JSGlobalData&, RepatchBuffer&);
+
+    bool seenOnce()
+    {
+        return hasSeenShouldRepatch;
+    }
+
+    void setSeen()
+    {
+        hasSeenShouldRepatch = true;
+    }
+};
+
+inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo)
+{
+    return callLinkInfo->callReturnLocation.executableAddress();
+}
+
+inline unsigned getCallLinkInfoBytecodeIndex(CallLinkInfo* callLinkInfo)
+{
+    return callLinkInfo->bytecodeIndex;
+}
+#endif // ENABLE(JIT)
+
+} // namespace JSC
+
+#endif // CallLinkInfo_h
diff --git a/bytecode/CallLinkStatus.cpp b/bytecode/CallLinkStatus.cpp
new file mode 100644 (file)
index 0000000..7f9e9ee
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "CallLinkStatus.h"
+
+#include "CodeBlock.h"
+#include "LLIntCallLinkInfo.h"
+
+namespace JSC {
+
+CallLinkStatus CallLinkStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex)
+{
+    UNUSED_PARAM(profiledBlock);
+    UNUSED_PARAM(bytecodeIndex);
+#if ENABLE(LLINT)
+    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
+    LLIntCallLinkInfo* callLinkInfo = instruction[4].u.callLinkInfo;
+    
+    return CallLinkStatus(callLinkInfo->lastSeenCallee.get(), false);
+#else
+    return CallLinkStatus(0, false);
+#endif
+}
+
+CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
+{
+    UNUSED_PARAM(profiledBlock);
+    UNUSED_PARAM(bytecodeIndex);
+#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+    if (!profiledBlock->numberOfCallLinkInfos())
+        return computeFromLLInt(profiledBlock, bytecodeIndex);
+    
+    if (profiledBlock->couldTakeSlowCase(bytecodeIndex))
+        return CallLinkStatus(0, true);
+    
+    JSFunction* target = profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get();
+    if (!target)
+        return computeFromLLInt(profiledBlock, bytecodeIndex);
+    
+    return CallLinkStatus(target, false);
+#else
+    return CallLinkStatus(0, false);
+#endif
+}
+
+} // namespace JSC
+
diff --git a/bytecode/CallLinkStatus.h b/bytecode/CallLinkStatus.h
new file mode 100644 (file)
index 0000000..5f72019
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CallLinkStatus_h
+#define CallLinkStatus_h
+
+namespace JSC {
+
+class JSFunction;
+class CodeBlock;
+
+class CallLinkStatus {
+public:
+    CallLinkStatus()
+        : m_callTarget(0)
+        , m_couldTakeSlowPath(false)
+    {
+    }
+    
+    CallLinkStatus(JSFunction* callTarget, bool couldTakeSlowPath)
+        : m_callTarget(callTarget)
+        , m_couldTakeSlowPath(couldTakeSlowPath)
+    {
+    }
+    
+    static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex);
+    
+    bool isSet() const { return !!m_callTarget || m_couldTakeSlowPath; }
+    
+    bool operator!() const { return !isSet(); }
+    
+    bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
+    
+    JSFunction* callTarget() const { return m_callTarget; }
+    
+private:
+    static CallLinkStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex);
+    
+    JSFunction* m_callTarget;
+    bool m_couldTakeSlowPath;
+};
+
+} // namespace JSC
+
+#endif // CallLinkStatus_h
+
diff --git a/bytecode/CallReturnOffsetToBytecodeOffset.h b/bytecode/CallReturnOffsetToBytecodeOffset.h
new file mode 100644 (file)
index 0000000..3a7448e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CallReturnOffsetToBytecodeOffset_h
+#define CallReturnOffsetToBytecodeOffset_h
+
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+#if ENABLE(JIT)
+// This structure is used to map from a call return location
+// (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.
+// FIXME: This should be made inlining aware! Currently it isn't
+// because we never inline code that has exception handlers.
+struct CallReturnOffsetToBytecodeOffset {
+    CallReturnOffsetToBytecodeOffset(unsigned callReturnOffset, unsigned bytecodeOffset)
+        : callReturnOffset(callReturnOffset)
+        , bytecodeOffset(bytecodeOffset)
+    {
+    }
+
+    unsigned callReturnOffset;
+    unsigned bytecodeOffset;
+};
+
+inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeOffset* pc)
+{
+    return pc->callReturnOffset;
+}
+#endif
+
+} // namespace JSC
+
+#endif // CallReturnOffsetToBytecodeOffset_h
+
index fc99e90158dcf6c8345d15e0813fa1bf2a679341..7b828acab736847df615cf626c047bc154c89778 100644 (file)
 #include "CodeBlock.h"
 
 #include "BytecodeGenerator.h"
 #include "CodeBlock.h"
 
 #include "BytecodeGenerator.h"
+#include "DFGCapabilities.h"
+#include "DFGNode.h"
+#include "DFGRepatch.h"
 #include "Debugger.h"
 #include "Interpreter.h"
 #include "JIT.h"
 #include "Debugger.h"
 #include "Interpreter.h"
 #include "JIT.h"
+#include "JITStubs.h"
 #include "JSActivation.h"
 #include "JSFunction.h"
 #include "JSStaticScopeObject.h"
 #include "JSValue.h"
 #include "JSActivation.h"
 #include "JSFunction.h"
 #include "JSStaticScopeObject.h"
 #include "JSValue.h"
+#include "LowLevelInterpreter.h"
 #include "RepatchBuffer.h"
 #include "UStringConcatenate.h"
 #include <stdio.h>
 #include <wtf/StringExtras.h>
 
 #include "RepatchBuffer.h"
 #include "UStringConcatenate.h"
 #include <stdio.h>
 #include <wtf/StringExtras.h>
 
+#if ENABLE(DFG_JIT)
+#include "DFGOperations.h"
+#endif
+
 #define DUMP_CODE_BLOCK_STATISTICS 0
 
 namespace JSC {
 
 #define DUMP_CODE_BLOCK_STATISTICS 0
 
 namespace JSC {
 
-#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
+#if ENABLE(DFG_JIT)
+using namespace DFG;
+#endif
 
 static UString escapeQuotes(const UString& str)
 {
 
 static UString escapeQuotes(const UString& str)
 {
@@ -66,9 +77,9 @@ static UString valueToSourceString(ExecState* exec, JSValue val)
         return "0";
 
     if (val.isString())
         return "0";
 
     if (val.isString())
-        return makeUString("\"", escapeQuotes(val.toString(exec)), "\"");
+        return makeUString("\"", escapeQuotes(val.toString(exec)->value(exec)), "\"");
 
 
-    return val.toString(exec);
+    return val.description();
 }
 
 static CString constantName(ExecState* exec, int k, JSValue value)
 }
 
 static CString constantName(ExecState* exec, int k, JSValue value)
@@ -144,7 +155,7 @@ void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector<Instruction>:
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
 
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
 
-    printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data());
+    dataLog("[%4d] %s\t\t %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data());
 }
 
 void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
 }
 
 void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
@@ -152,14 +163,14 @@ void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
     int r2 = (++it)->u.operand;
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
     int r2 = (++it)->u.operand;
-    printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
+    dataLog("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
 }
 
 void CodeBlock::printConditionalJump(ExecState* exec, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator& it, int location, const char* op) const
 {
     int r0 = (++it)->u.operand;
     int offset = (++it)->u.operand;
 }
 
 void CodeBlock::printConditionalJump(ExecState* exec, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator& it, int location, const char* op) const
 {
     int r0 = (++it)->u.operand;
     int offset = (++it)->u.operand;
-    printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(exec, r0).data(), offset, location + offset);
+    dataLog("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(exec, r0).data(), offset, location + offset);
 }
 
 void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
 }
 
 void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
@@ -167,8 +178,17 @@ void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
     int id0 = (++it)->u.operand;
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
     int id0 = (++it)->u.operand;
-    printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
-    it += 4;
+    dataLog("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
+    it += 5;
+}
+
+void CodeBlock::printCallOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
+{
+    int func = (++it)->u.operand;
+    int argCount = (++it)->u.operand;
+    int registerOffset = (++it)->u.operand;
+    dataLog("[%4d] %s\t %s, %d, %d\n", location, op, registerName(exec, func).data(), argCount, registerOffset);
+    it += 2;
 }
 
 void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
 }
 
 void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
@@ -176,7 +196,7 @@ void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction
     int r0 = (++it)->u.operand;
     int id0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
     int r0 = (++it)->u.operand;
     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());
+    dataLog("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
     it += 5;
 }
 
     it += 5;
 }
 
@@ -192,8 +212,6 @@ static bool isPropertyAccess(OpcodeID opcodeID)
         case op_get_by_id_self:
         case op_get_by_id_proto:
         case op_get_by_id_chain:
         case op_get_by_id_self:
         case op_get_by_id_proto:
         case op_get_by_id_chain:
-        case op_get_by_id_self_list:
-        case op_get_by_id_proto_list:
         case op_put_by_id_transition:
         case op_put_by_id_replace:
         case op_get_by_id:
         case op_put_by_id_transition:
         case op_put_by_id_replace:
         case op_get_by_id:
@@ -208,7 +226,7 @@ static bool isPropertyAccess(OpcodeID opcodeID)
     }
 }
 
     }
 }
 
-static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
+static unsigned instructionOffsetForNth(ExecState* exec, const RefCountedArray<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
 {
     size_t i = 0;
     while (i < instructions.size()) {
 {
     size_t i = 0;
     while (i < instructions.size()) {
@@ -226,50 +244,48 @@ 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).utf8().data());
+    dataLog("  [%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).utf8().data());
+        dataLog("  [%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).utf8().data(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).utf8().data());
+        dataLog("  [%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).utf8().data(), pointerToSourceString(stubInfo.u.getByIdChain.chain).utf8().data());
+        dataLog("  [%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).utf8().data(), stubInfo.u.getByIdSelfList.listSize);
+        dataLog("  [%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).utf8().data(), stubInfo.u.getByIdProtoList.listSize);
+        dataLog("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).utf8().data(), stubInfo.u.getByIdProtoList.listSize);
         return;
         return;
-    case access_put_by_id_transition:
-        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());
+    case access_put_by_id_transition_normal:
+    case access_put_by_id_transition_direct:
+        dataLog("  [%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).utf8().data());
-        return;
-    case access_get_by_id:
-        printf("  [%4d] %s\n", instructionOffset, "get_by_id");
+        dataLog("  [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).utf8().data());
         return;
         return;
-    case access_put_by_id:
-        printf("  [%4d] %s\n", instructionOffset, "put_by_id");
+    case access_unset:
+        dataLog("  [%4d] %s\n", instructionOffset, "unset");
         return;
     case access_get_by_id_generic:
         return;
     case access_get_by_id_generic:
-        printf("  [%4d] %s\n", instructionOffset, "op_get_by_id_generic");
+        dataLog("  [%4d] %s\n", instructionOffset, "op_get_by_id_generic");
         return;
     case access_put_by_id_generic:
         return;
     case access_put_by_id_generic:
-        printf("  [%4d] %s\n", instructionOffset, "op_put_by_id_generic");
+        dataLog("  [%4d] %s\n", instructionOffset, "op_put_by_id_generic");
         return;
     case access_get_array_length:
         return;
     case access_get_array_length:
-        printf("  [%4d] %s\n", instructionOffset, "op_get_array_length");
+        dataLog("  [%4d] %s\n", instructionOffset, "op_get_array_length");
         return;
     case access_get_string_length:
         return;
     case access_get_string_length:
-        printf("  [%4d] %s\n", instructionOffset, "op_get_string_length");
+        dataLog("  [%4d] %s\n", instructionOffset, "op_get_string_length");
         return;
     default:
         ASSERT_NOT_REACHED();
         return;
     default:
         ASSERT_NOT_REACHED();
@@ -279,14 +295,14 @@ static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned i
 
 void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const
 {
 
 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).utf8().data());
+    unsigned instructionOffset = vPC - instructions().begin();
+    dataLog("  [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).utf8().data());
 }
 
 void CodeBlock::printStructures(const Instruction* vPC) const
 {
     Interpreter* interpreter = m_globalData->interpreter;
 }
 
 void CodeBlock::printStructures(const Instruction* vPC) const
 {
     Interpreter* interpreter = m_globalData->interpreter;
-    unsigned instructionOffset = vPC - m_instructions.begin();
+    unsigned instructionOffset = vPC - instructions().begin();
 
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {
         printStructure("get_by_id", vPC, 4);
 
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {
         printStructure("get_by_id", vPC, 4);
@@ -297,15 +313,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).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data());
+        dataLog("  [%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).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data(), pointerToSourceString(vPC[6].u.structureChain).utf8().data());
+        dataLog("  [%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).utf8().data(), pointerToSourceString(vPC[5].u.structureChain).utf8().data());
+        dataLog("  [%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)) {
@@ -331,125 +347,118 @@ void CodeBlock::printStructures(const Instruction* vPC) const
 
 void CodeBlock::dump(ExecState* exec) const
 {
 
 void CodeBlock::dump(ExecState* exec) const
 {
-    if (m_instructions.isEmpty()) {
-        printf("No instructions available.\n");
-        return;
-    }
-
     size_t instructionCount = 0;
 
     size_t instructionCount = 0;
 
-    for (size_t i = 0; i < m_instructions.size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(m_instructions[i].u.opcode)])
+    for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
         ++instructionCount;
 
         ++instructionCount;
 
-    printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
-        static_cast<unsigned long>(instructionCount),
-        static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)),
-        this, m_numParameters, m_numCalleeRegisters);
+    dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s); %d variable(s)\n\n",
+        static_cast<unsigned long>(instructions().size()),
+        static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
+        this, m_numParameters, m_numCalleeRegisters, m_numVars);
 
 
-    Vector<Instruction>::const_iterator begin = m_instructions.begin();
-    Vector<Instruction>::const_iterator end = m_instructions.end();
+    Vector<Instruction>::const_iterator begin = instructions().begin();
+    Vector<Instruction>::const_iterator end = instructions().end();
     for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
         dump(exec, begin, it);
 
     if (!m_identifiers.isEmpty()) {
     for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
         dump(exec, begin, it);
 
     if (!m_identifiers.isEmpty()) {
-        printf("\nIdentifiers:\n");
+        dataLog("\nIdentifiers:\n");
         size_t i = 0;
         do {
         size_t i = 0;
         do {
-            printf("  id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ustring().utf8().data());
+            dataLog("  id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ustring().utf8().data());
             ++i;
         } while (i != m_identifiers.size());
     }
 
     if (!m_constantRegisters.isEmpty()) {
             ++i;
         } while (i != m_identifiers.size());
     }
 
     if (!m_constantRegisters.isEmpty()) {
-        printf("\nConstants:\n");
-        unsigned registerIndex = m_numVars;
+        dataLog("\nConstants:\n");
         size_t i = 0;
         do {
         size_t i = 0;
         do {
-            printf("   k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].get()).utf8().data());
+            dataLog("   k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_constantRegisters[i].get()).utf8().data());
             ++i;
             ++i;
-            ++registerIndex;
         } while (i < m_constantRegisters.size());
     }
 
     if (m_rareData && !m_rareData->m_regexps.isEmpty()) {
         } while (i < m_constantRegisters.size());
     }
 
     if (m_rareData && !m_rareData->m_regexps.isEmpty()) {
-        printf("\nm_regexps:\n");
+        dataLog("\nm_regexps:\n");
         size_t i = 0;
         do {
         size_t i = 0;
         do {
-            printf("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).utf8().data());
+            dataLog("  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());
     }
 
 #if ENABLE(JIT)
     if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty())
             ++i;
         } while (i < m_rareData->m_regexps.size());
     }
 
 #if ENABLE(JIT)
     if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty())
-        printf("\nStructures:\n");
+        dataLog("\nStructures:\n");
 
     if (!m_globalResolveInfos.isEmpty()) {
         size_t i = 0;
         do {
 
     if (!m_globalResolveInfos.isEmpty()) {
         size_t i = 0;
         do {
-             printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isGlobalResolve));
+             printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, instructions(), i + 1, isGlobalResolve));
              ++i;
         } while (i < m_globalResolveInfos.size());
     }
     if (!m_structureStubInfos.isEmpty()) {
         size_t i = 0;
         do {
              ++i;
         } while (i < m_globalResolveInfos.size());
     }
     if (!m_structureStubInfos.isEmpty()) {
         size_t i = 0;
         do {
-            printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isPropertyAccess));
+            printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, instructions(), i + 1, isPropertyAccess));
              ++i;
         } while (i < m_structureStubInfos.size());
     }
 #endif
              ++i;
         } while (i < m_structureStubInfos.size());
     }
 #endif
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
     if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
     if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
-        printf("\nStructures:\n");
+        dataLog("\nStructures:\n");
 
     if (!m_globalResolveInstructions.isEmpty()) {
         size_t i = 0;
         do {
 
     if (!m_globalResolveInstructions.isEmpty()) {
         size_t i = 0;
         do {
-             printStructures(&m_instructions[m_globalResolveInstructions[i]]);
+             printStructures(&instructions()[m_globalResolveInstructions[i]]);
              ++i;
         } while (i < m_globalResolveInstructions.size());
     }
     if (!m_propertyAccessInstructions.isEmpty()) {
         size_t i = 0;
         do {
              ++i;
         } while (i < m_globalResolveInstructions.size());
     }
     if (!m_propertyAccessInstructions.isEmpty()) {
         size_t i = 0;
         do {
-            printStructures(&m_instructions[m_propertyAccessInstructions[i]]);
+            printStructures(&instructions()[m_propertyAccessInstructions[i]]);
              ++i;
         } while (i < m_propertyAccessInstructions.size());
     }
 #endif
 
     if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
              ++i;
         } while (i < m_propertyAccessInstructions.size());
     }
 #endif
 
     if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
-        printf("\nException Handlers:\n");
+        dataLog("\nException Handlers:\n");
         unsigned i = 0;
         do {
         unsigned i = 0;
         do {
-            printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target);
+            dataLog("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target);
             ++i;
         } while (i < m_rareData->m_exceptionHandlers.size());
     }
     
     if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) {
             ++i;
         } while (i < m_rareData->m_exceptionHandlers.size());
     }
     
     if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) {
-        printf("Immediate Switch Jump Tables:\n");
+        dataLog("Immediate Switch Jump Tables:\n");
         unsigned i = 0;
         do {
         unsigned i = 0;
         do {
-            printf("  %1d = {\n", i);
+            dataLog("  %1d = {\n", i);
             int entry = 0;
             Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end();
             for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
                 if (!*iter)
                     continue;
             int entry = 0;
             Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end();
             for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
                 if (!*iter)
                     continue;
-                printf("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter);
+                dataLog("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter);
             }
             }
-            printf("      }\n");
+            dataLog("      }\n");
             ++i;
         } while (i < m_rareData->m_immediateSwitchJumpTables.size());
     }
     
     if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) {
             ++i;
         } while (i < m_rareData->m_immediateSwitchJumpTables.size());
     }
     
     if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) {
-        printf("\nCharacter Switch Jump Tables:\n");
+        dataLog("\nCharacter Switch Jump Tables:\n");
         unsigned i = 0;
         do {
         unsigned i = 0;
         do {
-            printf("  %1d = {\n", i);
+            dataLog("  %1d = {\n", i);
             int entry = 0;
             Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end();
             for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
             int entry = 0;
             Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end();
             for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
@@ -457,27 +466,27 @@ 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).utf8().data(), *iter);
+                dataLog("\t\t\"%s\" => %04d\n", UString(&ch, 1).utf8().data(), *iter);
         }
         }
-            printf("      }\n");
+            dataLog("      }\n");
             ++i;
         } while (i < m_rareData->m_characterSwitchJumpTables.size());
     }
     
     if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {
             ++i;
         } while (i < m_rareData->m_characterSwitchJumpTables.size());
     }
     
     if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {
-        printf("\nString Switch Jump Tables:\n");
+        dataLog("\nString Switch Jump Tables:\n");
         unsigned i = 0;
         do {
         unsigned i = 0;
         do {
-            printf("  %1d = {\n", i);
+            dataLog("  %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)
             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).utf8().data(), iter->second.branchOffset);
-            printf("      }\n");
+                dataLog("\t\t\"%s\" => %04d\n", UString(iter->first).utf8().data(), iter->second.branchOffset);
+            dataLog("      }\n");
             ++i;
         } while (i < m_rareData->m_stringSwitchJumpTables.size());
     }
 
             ++i;
         } while (i < m_rareData->m_stringSwitchJumpTables.size());
     }
 
-    printf("\n");
+    dataLog("\n");
 }
 
 void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const
 }
 
 void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const
@@ -485,74 +494,73 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
     int location = it - begin;
     switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
         case op_enter: {
     int location = it - begin;
     switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
         case op_enter: {
-            printf("[%4d] enter\n", location);
+            dataLog("[%4d] enter\n", location);
             break;
         }
         case op_create_activation: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_create_activation: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] create_activation %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] create_activation %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_create_arguments: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_create_arguments: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] create_arguments\t %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] create_arguments\t %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_init_lazy_reg: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_init_lazy_reg: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] init_lazy_reg\t %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] init_lazy_reg\t %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_get_callee: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_get_callee: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] op_get_callee %s\n", location, registerName(exec, r0).data());
+            dataLog("[%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;
             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());
+            dataLog("[%4d] create_this %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
             break;
         }
         case op_convert_this: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_convert_this: {
             int r0 = (++it)->u.operand;
-            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());
+            dataLog("[%4d] convert_this\t %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_new_object: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_new_object: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] new_object\t %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] new_object\t %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_new_array: {
             int dst = (++it)->u.operand;
             int argv = (++it)->u.operand;
             int argc = (++it)->u.operand;
             break;
         }
         case op_new_array: {
             int dst = (++it)->u.operand;
             int argv = (++it)->u.operand;
             int argc = (++it)->u.operand;
-            printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc);
+            dataLog("[%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;
             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);
+            dataLog("[%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;
             break;
         }
         case op_new_regexp: {
             int r0 = (++it)->u.operand;
             int re0 = (++it)->u.operand;
-            printf("[%4d] new_regexp\t %s, %s\n", location, registerName(exec, r0).data(), regexpName(re0, regexp(re0)).data());
+            dataLog("[%4d] new_regexp\t %s, ", location, registerName(exec, r0).data());
+            if (r0 >=0 && r0 < (int)numberOfRegExps())
+                dataLog("%s\n", regexpName(re0, regexp(re0)).data());
+            else
+                dataLog("bad_regexp(%d)\n", re0);
             break;
         }
         case op_mov: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_mov: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] mov\t\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
+            dataLog("[%4d] mov\t\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
             break;
         }
         case op_not: {
             break;
         }
         case op_not: {
@@ -591,14 +599,22 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printBinaryOp(exec, location, it, "lesseq");
             break;
         }
             printBinaryOp(exec, location, it, "lesseq");
             break;
         }
+        case op_greater: {
+            printBinaryOp(exec, location, it, "greater");
+            break;
+        }
+        case op_greatereq: {
+            printBinaryOp(exec, location, it, "greatereq");
+            break;
+        }
         case op_pre_inc: {
             int r0 = (++it)->u.operand;
         case op_pre_inc: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] pre_inc\t\t %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] pre_inc\t\t %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_pre_dec: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_pre_dec: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] pre_dec\t\t %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] pre_dec\t\t %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_post_inc: {
             break;
         }
         case op_post_inc: {
@@ -668,13 +684,9 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             ++it;
             break;
         }
             ++it;
             break;
         }
-        case op_bitnot: {
-            printUnaryOp(exec, location, it, "bitnot");
-            break;
-        }
         case op_check_has_instance: {
             int base = (++it)->u.operand;
         case op_check_has_instance: {
             int base = (++it)->u.operand;
-            printf("[%4d] check_has_instance\t\t %s\n", location, registerName(exec, base).data());
+            dataLog("[%4d] check_has_instance\t\t %s\n", location, registerName(exec, base).data());
             break;
         }
         case op_instanceof: {
             break;
         }
         case op_instanceof: {
@@ -682,7 +694,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
             int r3 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
             int r3 = (++it)->u.operand;
-            printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data());
+            dataLog("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data());
             break;
         }
         case op_typeof: {
             break;
         }
         case op_typeof: {
@@ -720,21 +732,23 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
         case op_resolve: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
         case op_resolve: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
-            printf("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
+            dataLog("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
+            it++;
             break;
         }
         case op_resolve_skip: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
             break;
         }
         case op_resolve_skip: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
-            printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), skipLevels);
+            dataLog("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), skipLevels);
+            it++;
             break;
         }
         case op_resolve_global: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             break;
         }
         case op_resolve_global: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
-            printf("[%4d] resolve_global\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
-            it += 2;
+            dataLog("[%4d] resolve_global\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
+            it += 3;
             break;
         }
         case op_resolve_global_dynamic: {
             break;
         }
         case op_resolve_global_dynamic: {
@@ -743,53 +757,66 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             JSValue scope = JSValue((++it)->u.jsCell.get());
             ++it;
             int depth = (++it)->u.operand;
             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);
+            dataLog("[%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);
+            ++it;
             break;
         }
         case op_get_scoped_var: {
             int r0 = (++it)->u.operand;
             int index = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
             break;
         }
         case op_get_scoped_var: {
             int r0 = (++it)->u.operand;
             int index = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
-            printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(exec, r0).data(), index, skipLevels);
+            dataLog("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(exec, r0).data(), index, skipLevels);
+            it++;
             break;
         }
         case op_put_scoped_var: {
             int index = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             break;
         }
         case op_put_scoped_var: {
             int index = (++it)->u.operand;
             int skipLevels = (++it)->u.operand;
             int r0 = (++it)->u.operand;
-            printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(exec, r0).data());
+            dataLog("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(exec, r0).data());
             break;
         }
         case op_get_global_var: {
             int r0 = (++it)->u.operand;
             int index = (++it)->u.operand;
             break;
         }
         case op_get_global_var: {
             int r0 = (++it)->u.operand;
             int index = (++it)->u.operand;
-            printf("[%4d] get_global_var\t %s, %d\n", location, registerName(exec, r0).data(), index);
+            dataLog("[%4d] get_global_var\t %s, %d\n", location, registerName(exec, r0).data(), index);
+            it++;
             break;
         }
         case op_put_global_var: {
             int index = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             break;
         }
         case op_put_global_var: {
             int index = (++it)->u.operand;
             int r0 = (++it)->u.operand;
-            printf("[%4d] put_global_var\t %d, %s\n", location, index, registerName(exec, r0).data());
+            dataLog("[%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;
             int isStrict = (++it)->u.operand;
             break;
         }
         case op_resolve_base: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             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());
+            dataLog("[%4d] resolve_base%s\t %s, %s\n", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
+            it++;
             break;
         }
         case op_ensure_property_exists: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             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());
+            dataLog("[%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: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             break;
         }
         case op_resolve_with_base: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
-            printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
+            dataLog("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
+            it++;
+            break;
+        }
+        case op_resolve_with_this: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int id0 = (++it)->u.operand;
+            dataLog("[%4d] resolve_with_this %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
+            it++;
             break;
         }
         case op_get_by_id: {
             break;
         }
         case op_get_by_id: {
@@ -800,18 +827,10 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printGetByIdOp(exec, location, it, "get_by_id_self");
             break;
         }
             printGetByIdOp(exec, location, it, "get_by_id_self");
             break;
         }
-        case op_get_by_id_self_list: {
-            printGetByIdOp(exec, location, it, "get_by_id_self_list");
-            break;
-        }
         case op_get_by_id_proto: {
             printGetByIdOp(exec, location, it, "get_by_id_proto");
             break;
         }
         case op_get_by_id_proto: {
             printGetByIdOp(exec, location, it, "get_by_id_proto");
             break;
         }
-        case op_get_by_id_proto_list: {
-            printGetByIdOp(exec, location, it, "op_get_by_id_proto_list");
-            break;
-        }
         case op_get_by_id_chain: {
             printGetByIdOp(exec, location, it, "get_by_id_chain");
             break;
         case op_get_by_id_chain: {
             printGetByIdOp(exec, location, it, "get_by_id_chain");
             break;
@@ -820,18 +839,10 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printGetByIdOp(exec, location, it, "get_by_id_getter_self");
             break;
         }
             printGetByIdOp(exec, location, it, "get_by_id_getter_self");
             break;
         }
-        case op_get_by_id_getter_self_list: {
-            printGetByIdOp(exec, location, it, "get_by_id_getter_self_list");
-            break;
-        }
         case op_get_by_id_getter_proto: {
             printGetByIdOp(exec, location, it, "get_by_id_getter_proto");
             break;
         }
         case op_get_by_id_getter_proto: {
             printGetByIdOp(exec, location, it, "get_by_id_getter_proto");
             break;
         }
-        case op_get_by_id_getter_proto_list: {
-            printGetByIdOp(exec, location, it, "get_by_id_getter_proto_list");
-            break;
-        }
         case op_get_by_id_getter_chain: {
             printGetByIdOp(exec, location, it, "get_by_id_getter_chain");
             break;
         case op_get_by_id_getter_chain: {
             printGetByIdOp(exec, location, it, "get_by_id_getter_chain");
             break;
@@ -840,18 +851,10 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printGetByIdOp(exec, location, it, "get_by_id_custom_self");
             break;
         }
             printGetByIdOp(exec, location, it, "get_by_id_custom_self");
             break;
         }
-        case op_get_by_id_custom_self_list: {
-            printGetByIdOp(exec, location, it, "get_by_id_custom_self_list");
-            break;
-        }
         case op_get_by_id_custom_proto: {
             printGetByIdOp(exec, location, it, "get_by_id_custom_proto");
             break;
         }
         case op_get_by_id_custom_proto: {
             printGetByIdOp(exec, location, it, "get_by_id_custom_proto");
             break;
         }
-        case op_get_by_id_custom_proto_list: {
-            printGetByIdOp(exec, location, it, "get_by_id_custom_proto_list");
-            break;
-        }
         case op_get_by_id_custom_chain: {
             printGetByIdOp(exec, location, it, "get_by_id_custom_chain");
             break;
         case op_get_by_id_custom_chain: {
             printGetByIdOp(exec, location, it, "get_by_id_custom_chain");
             break;
@@ -885,47 +888,51 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printPutByIdOp(exec, location, it, "put_by_id_transition");
             break;
         }
             printPutByIdOp(exec, location, it, "put_by_id_transition");
             break;
         }
-        case op_put_by_id_generic: {
-            printPutByIdOp(exec, location, it, "put_by_id_generic");
+        case op_put_by_id_transition_direct: {
+            printPutByIdOp(exec, location, it, "put_by_id_transition_direct");
             break;
         }
             break;
         }
-        case op_put_getter: {
-            int r0 = (++it)->u.operand;
-            int id0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
+        case op_put_by_id_transition_normal: {
+            printPutByIdOp(exec, location, it, "put_by_id_transition_normal");
+            break;
+        }
+        case op_put_by_id_generic: {
+            printPutByIdOp(exec, location, it, "put_by_id_generic");
             break;
         }
             break;
         }
-        case op_put_setter: {
+        case op_put_getter_setter: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
+            int r2 = (++it)->u.operand;
+            dataLog("[%4d] put_getter_setter\t %s, %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
             break;
         }
         case op_method_check: {
             break;
         }
         case op_method_check: {
-            printf("[%4d] method_check\n", location);
+            dataLog("[%4d] method_check\n", location);
             break;
         }
         case op_del_by_id: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             break;
         }
         case op_del_by_id: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
-            printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
+            dataLog("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
             break;
         }
         case op_get_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
             break;
         }
         case op_get_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
-            printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
+            dataLog("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
+            it++;
             break;
         }
         case op_get_argument_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
             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());
+            dataLog("[%4d] get_argument_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
+            ++it;
             break;
         }
         case op_get_by_pname: {
             break;
         }
         case op_get_by_pname: {
@@ -935,38 +942,38 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int r3 = (++it)->u.operand;
             int r4 = (++it)->u.operand;
             int r5 = (++it)->u.operand;
             int r3 = (++it)->u.operand;
             int r4 = (++it)->u.operand;
             int r5 = (++it)->u.operand;
-            printf("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), registerName(exec, r4).data(), registerName(exec, r5).data());
+            dataLog("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), registerName(exec, r4).data(), registerName(exec, r5).data());
             break;
         }
         case op_put_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
             break;
         }
         case op_put_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
-            printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
+            dataLog("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
             break;
         }
         case op_del_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
             break;
         }
         case op_del_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int r2 = (++it)->u.operand;
-            printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
+            dataLog("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
             break;
         }
         case op_put_by_index: {
             int r0 = (++it)->u.operand;
             unsigned n0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_put_by_index: {
             int r0 = (++it)->u.operand;
             unsigned n0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data());
+            dataLog("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data());
             break;
         }
         case op_jmp: {
             int offset = (++it)->u.operand;
             break;
         }
         case op_jmp: {
             int offset = (++it)->u.operand;
-            printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, location + offset);
+            dataLog("[%4d] jmp\t\t %d(->%d)\n", location, offset, location + offset);
             break;
         }
         case op_loop: {
             int offset = (++it)->u.operand;
             break;
         }
         case op_loop: {
             int offset = (++it)->u.operand;
-            printf("[%4d] loop\t\t %d(->%d)\n", location, offset, location + offset);
+            dataLog("[%4d] loop\t\t %d(->%d)\n", location, offset, location + offset);
             break;
         }
         case op_jtrue: {
             break;
         }
         case op_jtrue: {
@@ -997,155 +1004,190 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            dataLog("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            break;
+        }
+        case op_jless: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int offset = (++it)->u.operand;
+            dataLog("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            break;
+        }
+        case op_jlesseq: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int offset = (++it)->u.operand;
+            dataLog("[%4d] jlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            break;
+        }
+        case op_jgreater: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int offset = (++it)->u.operand;
+            dataLog("[%4d] jgreater\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            break;
+        }
+        case op_jgreatereq: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int offset = (++it)->u.operand;
+            dataLog("[%4d] jgreatereq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
             break;
         }
         case op_jnless: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             break;
         }
         case op_jnless: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            dataLog("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
             break;
         }
         case op_jnlesseq: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             break;
         }
         case op_jnlesseq: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            dataLog("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
             break;
         }
             break;
         }
-        case op_loop_if_less: {
+        case op_jngreater: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            dataLog("[%4d] jngreater\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
             break;
         }
             break;
         }
-        case op_jless: {
+        case op_jngreatereq: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            dataLog("[%4d] jngreatereq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
             break;
         }
             break;
         }
-        case op_jlesseq: {
+        case op_loop_if_less: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] jlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            dataLog("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
             break;
         }
         case op_loop_if_lesseq: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
             break;
         }
         case op_loop_if_lesseq: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            dataLog("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            break;
+        }
+        case op_loop_if_greater: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int offset = (++it)->u.operand;
+            dataLog("[%4d] loop_if_greater\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            break;
+        }
+        case op_loop_if_greatereq: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int offset = (++it)->u.operand;
+            dataLog("[%4d] loop_if_greatereq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+            break;
+        }
+        case op_loop_hint: {
+            dataLog("[%4d] loop_hint\n", location);
             break;
         }
         case op_switch_imm: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
             break;
         }
         case op_switch_imm: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
-            printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
+            dataLog("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
             break;
         }
         case op_switch_char: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
             break;
         }
         case op_switch_char: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
-            printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
+            dataLog("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
             break;
         }
         case op_switch_string: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
             break;
         }
         case op_switch_string: {
             int tableIndex = (++it)->u.operand;
             int defaultTarget = (++it)->u.operand;
             int scrutineeRegister = (++it)->u.operand;
-            printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
+            dataLog("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
             break;
         }
         case op_new_func: {
             int r0 = (++it)->u.operand;
             int f0 = (++it)->u.operand;
             int shouldCheck = (++it)->u.operand;
             break;
         }
         case op_new_func: {
             int r0 = (++it)->u.operand;
             int f0 = (++it)->u.operand;
             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>");
+            dataLog("[%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: {
             int r0 = (++it)->u.operand;
             int f0 = (++it)->u.operand;
             break;
         }
         case op_new_func_exp: {
             int r0 = (++it)->u.operand;
             int f0 = (++it)->u.operand;
-            printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(exec, r0).data(), f0);
+            dataLog("[%4d] new_func_exp\t %s, f%d\n", location, registerName(exec, r0).data(), f0);
             break;
         }
         case op_call: {
             break;
         }
         case op_call: {
-            int func = (++it)->u.operand;
-            int argCount = (++it)->u.operand;
-            int registerOffset = (++it)->u.operand;
-            printf("[%4d] call\t\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
+            printCallOp(exec, location, it, "call");
             break;
         }
         case op_call_eval: {
             break;
         }
         case op_call_eval: {
-            int func = (++it)->u.operand;
-            int argCount = (++it)->u.operand;
-            int registerOffset = (++it)->u.operand;
-            printf("[%4d] call_eval\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
+            printCallOp(exec, location, it, "call_eval");
             break;
         }
         case op_call_varargs: {
             break;
         }
         case op_call_varargs: {
-            int func = (++it)->u.operand;
-            int argCount = (++it)->u.operand;
-            int registerOffset = (++it)->u.operand;
-            printf("[%4d] call_varargs\t %s, %s, %d\n", location, registerName(exec, func).data(), registerName(exec, argCount).data(), registerOffset);
-            break;
-        }
-        case op_load_varargs: {
-            printUnaryOp(exec, location, it, "load_varargs");
+            int callee = (++it)->u.operand;
+            int thisValue = (++it)->u.operand;
+            int arguments = (++it)->u.operand;
+            int firstFreeRegister = (++it)->u.operand;
+            dataLog("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(exec, callee).data(), registerName(exec, thisValue).data(), registerName(exec, arguments).data(), firstFreeRegister);
             break;
         }
         case op_tear_off_activation: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_tear_off_activation: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] tear_off_activation\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
+            dataLog("[%4d] tear_off_activation\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
             break;
         }
         case op_tear_off_arguments: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_tear_off_arguments: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] tear_off_arguments\t %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] tear_off_arguments %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_ret: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_ret: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] ret\t\t %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] ret\t\t %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_call_put_result: {
             int r0 = (++it)->u.operand;
             break;
         }
         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());
+            dataLog("[%4d] op_call_put_result\t\t %s\n", location, registerName(exec, r0).data());
+            it++;
             break;
         }
         case op_ret_object_or_this: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_ret_object_or_this: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] constructor_ret\t\t %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
+            dataLog("[%4d] constructor_ret\t\t %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
             break;
         }
         case op_construct: {
             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);
+            printCallOp(exec, location, it, "construct");
             break;
         }
         case op_strcat: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int count = (++it)->u.operand;
             break;
         }
         case op_strcat: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             int count = (++it)->u.operand;
-            printf("[%4d] strcat\t\t %s, %s, %d\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count);
+            dataLog("[%4d] strcat\t\t %s, %s, %d\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count);
             break;
         }
         case op_to_primitive: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_to_primitive: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] to_primitive\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
+            dataLog("[%4d] to_primitive\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
             break;
         }
         case op_get_pnames: {
             break;
         }
         case op_get_pnames: {
@@ -1154,7 +1196,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int r2 = it[3].u.operand;
             int r3 = it[4].u.operand;
             int offset = it[5].u.operand;
             int r2 = it[3].u.operand;
             int r3 = it[4].u.operand;
             int offset = it[5].u.operand;
-            printf("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), offset, location + offset);
+            dataLog("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), offset, location + offset);
             it += OPCODE_LENGTH(op_get_pnames) - 1;
             break;
         }
             it += OPCODE_LENGTH(op_get_pnames) - 1;
             break;
         }
@@ -1165,85 +1207,72 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int size = it[4].u.operand;
             int iter = it[5].u.operand;
             int offset = it[6].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);
+            dataLog("[%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;
         }
         case op_push_scope: {
             int r0 = (++it)->u.operand;
             it += OPCODE_LENGTH(op_next_pname) - 1;
             break;
         }
         case op_push_scope: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] push_scope\t %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] push_scope\t %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_pop_scope: {
             break;
         }
         case op_pop_scope: {
-            printf("[%4d] pop_scope\n", location);
+            dataLog("[%4d] pop_scope\n", location);
             break;
         }
         case op_push_new_scope: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             break;
         }
         case op_push_new_scope: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
+            dataLog("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
             break;
         }
         case op_jmp_scopes: {
             int scopeDelta = (++it)->u.operand;
             int offset = (++it)->u.operand;
             break;
         }
         case op_jmp_scopes: {
             int scopeDelta = (++it)->u.operand;
             int offset = (++it)->u.operand;
-            printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, location + offset);
+            dataLog("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, location + offset);
             break;
         }
         case op_catch: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_catch: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] catch\t\t %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] catch\t\t %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_throw: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_throw: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] throw\t\t %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] throw\t\t %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_throw_reference_error: {
             int k0 = (++it)->u.operand;
             break;
         }
         case op_throw_reference_error: {
             int k0 = (++it)->u.operand;
-            printf("[%4d] throw_reference_error\t %s\n", location, constantName(exec, k0, getConstant(k0)).data());
-            break;
-        }
-        case op_jsr: {
-            int retAddrDst = (++it)->u.operand;
-            int offset = (++it)->u.operand;
-            printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(exec, retAddrDst).data(), offset, location + offset);
-            break;
-        }
-        case op_sret: {
-            int retAddrSrc = (++it)->u.operand;
-            printf("[%4d] sret\t\t %s\n", location, registerName(exec, retAddrSrc).data());
+            dataLog("[%4d] throw_reference_error\t %s\n", location, constantName(exec, k0, getConstant(k0)).data());
             break;
         }
         case op_debug: {
             int debugHookID = (++it)->u.operand;
             int firstLine = (++it)->u.operand;
             int lastLine = (++it)->u.operand;
             break;
         }
         case op_debug: {
             int debugHookID = (++it)->u.operand;
             int firstLine = (++it)->u.operand;
             int lastLine = (++it)->u.operand;
-            printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);
+            dataLog("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);
             break;
         }
         case op_profile_will_call: {
             int function = (++it)->u.operand;
             break;
         }
         case op_profile_will_call: {
             int function = (++it)->u.operand;
-            printf("[%4d] profile_will_call %s\n", location, registerName(exec, function).data());
+            dataLog("[%4d] profile_will_call %s\n", location, registerName(exec, function).data());
             break;
         }
         case op_profile_did_call: {
             int function = (++it)->u.operand;
             break;
         }
         case op_profile_did_call: {
             int function = (++it)->u.operand;
-            printf("[%4d] profile_did_call\t %s\n", location, registerName(exec, function).data());
+            dataLog("[%4d] profile_did_call\t %s\n", location, registerName(exec, function).data());
             break;
         }
         case op_end: {
             int r0 = (++it)->u.operand;
             break;
         }
         case op_end: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] end\t\t %s\n", location, registerName(exec, r0).data());
+            dataLog("[%4d] end\t\t %s\n", location, registerName(exec, r0).data());
             break;
         }
     }
 }
 
             break;
         }
     }
 }
 
-#endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
-
 #if DUMP_CODE_BLOCK_STATISTICS
 static HashSet<CodeBlock*> liveCodeBlockSet;
 #endif
 #if DUMP_CODE_BLOCK_STATISTICS
 static HashSet<CodeBlock*> liveCodeBlockSet;
 #endif
@@ -1342,44 +1371,101 @@ void CodeBlock::dumpStatistics()
     totalSize += symbolTableTotalSize;
     totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock));
 
     totalSize += symbolTableTotalSize;
     totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock));
 
-    printf("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size());
-    printf("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock));
-    printf("Size of all CodeBlocks: %zu\n", totalSize);
-    printf("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size());
+    dataLog("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size());
+    dataLog("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock));
+    dataLog("Size of all CodeBlocks: %zu\n", totalSize);
+    dataLog("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size());
 
 
-    printf("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 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());
+    dataLog("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size());
+    dataLog("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size());
+    dataLog("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size());
 
 
-    printf("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size());
+    dataLog("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); 
+    #define PRINT_STATS(name) dataLog("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); dataLog("Size of all " #name ": %zu\n", name##TotalSize); 
         FOR_EACH_MEMBER_VECTOR(PRINT_STATS)
         FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS)
     #undef PRINT_STATS
 
         FOR_EACH_MEMBER_VECTOR(PRINT_STATS)
         FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS)
     #undef PRINT_STATS
 
-    printf("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty);
-    printf("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty);
+    dataLog("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty);
+    dataLog("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty);
 
 
-    printf("Size of all symbolTables: %zu\n", symbolTableTotalSize);
+    dataLog("Size of all symbolTables: %zu\n", symbolTableTotalSize);
 
 #else
 
 #else
-    printf("Dumping CodeBlock statistics is not enabled.\n");
+    dataLog("Dumping CodeBlock statistics is not enabled.\n");
 #endif
 }
 
 #endif
 }
 
-CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject *globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab, bool isConstructor)
+CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab)
+    : m_globalObject(other.m_globalObject)
+    , m_heap(other.m_heap)
+    , m_numCalleeRegisters(other.m_numCalleeRegisters)
+    , m_numVars(other.m_numVars)
+    , m_numCapturedVars(other.m_numCapturedVars)
+    , m_isConstructor(other.m_isConstructor)
+    , m_ownerExecutable(*other.m_globalData, other.m_ownerExecutable.get(), other.m_ownerExecutable.get())
+    , m_globalData(other.m_globalData)
+    , m_instructions(other.m_instructions)
+    , m_thisRegister(other.m_thisRegister)
+    , m_argumentsRegister(other.m_argumentsRegister)
+    , m_activationRegister(other.m_activationRegister)
+    , m_needsFullScopeChain(other.m_needsFullScopeChain)
+    , m_usesEval(other.m_usesEval)
+    , m_isNumericCompareFunction(other.m_isNumericCompareFunction)
+    , m_isStrictMode(other.m_isStrictMode)
+    , m_codeType(other.m_codeType)
+    , m_source(other.m_source)
+    , m_sourceOffset(other.m_sourceOffset)
+#if ENABLE(JIT)
+    , m_globalResolveInfos(other.m_globalResolveInfos)
+#endif
+#if ENABLE(VALUE_PROFILER)
+    , m_executionEntryCount(0)
+#endif
+    , m_jumpTargets(other.m_jumpTargets)
+    , m_loopTargets(other.m_loopTargets)
+    , m_identifiers(other.m_identifiers)
+    , m_constantRegisters(other.m_constantRegisters)
+    , m_functionDecls(other.m_functionDecls)
+    , m_functionExprs(other.m_functionExprs)
+    , m_symbolTable(symTab)
+    , m_speculativeSuccessCounter(0)
+    , m_speculativeFailCounter(0)
+    , m_forcedOSRExitCounter(0)
+    , m_optimizationDelayCounter(0)
+    , m_reoptimizationRetryCounter(0)
+#if ENABLE(JIT)
+    , m_canCompileWithDFGState(CompileWithDFGUnset)
+#endif
+{
+    setNumParameters(other.numParameters());
+    optimizeAfterWarmUp();
+    jitAfterWarmUp();
+    
+    if (other.m_rareData) {
+        createRareDataIfNecessary();
+        
+        m_rareData->m_exceptionHandlers = other.m_rareData->m_exceptionHandlers;
+        m_rareData->m_regexps = other.m_rareData->m_regexps;
+        m_rareData->m_constantBuffers = other.m_rareData->m_constantBuffers;
+        m_rareData->m_immediateSwitchJumpTables = other.m_rareData->m_immediateSwitchJumpTables;
+        m_rareData->m_characterSwitchJumpTables = other.m_rareData->m_characterSwitchJumpTables;
+        m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
+        m_rareData->m_expressionInfo = other.m_rareData->m_expressionInfo;
+        m_rareData->m_lineInfo = other.m_rareData->m_lineInfo;
+    }
+}
+
+CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject *globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab, bool isConstructor, PassOwnPtr<CodeBlock> alternative)
     : m_globalObject(globalObject->globalData(), ownerExecutable, globalObject)
     , m_heap(&m_globalObject->globalData().heap)
     , m_numCalleeRegisters(0)
     , m_numVars(0)
     : m_globalObject(globalObject->globalData(), ownerExecutable, globalObject)
     , m_heap(&m_globalObject->globalData().heap)
     , m_numCalleeRegisters(0)
     , m_numVars(0)
-    , m_numParameters(0)
     , m_isConstructor(isConstructor)
     , m_isConstructor(isConstructor)
+    , m_numParameters(0)
     , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable)
     , m_globalData(0)
     , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable)
     , m_globalData(0)
-#ifndef NDEBUG
-    , m_instructionCount(0)
-#endif
     , m_argumentsRegister(-1)
     , m_needsFullScopeChain(ownerExecutable->needsActivation())
     , m_usesEval(ownerExecutable->usesEval())
     , m_argumentsRegister(-1)
     , m_needsFullScopeChain(ownerExecutable->needsActivation())
     , m_usesEval(ownerExecutable->usesEval())
@@ -1388,9 +1474,20 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlo
     , m_codeType(codeType)
     , m_source(sourceProvider)
     , m_sourceOffset(sourceOffset)
     , m_codeType(codeType)
     , m_source(sourceProvider)
     , m_sourceOffset(sourceOffset)
+#if ENABLE(VALUE_PROFILER)
+    , m_executionEntryCount(0)
+#endif
     , m_symbolTable(symTab)
     , m_symbolTable(symTab)
+    , m_alternative(alternative)
+    , m_speculativeSuccessCounter(0)
+    , m_speculativeFailCounter(0)
+    , m_optimizationDelayCounter(0)
+    , m_reoptimizationRetryCounter(0)
 {
     ASSERT(m_source);
 {
     ASSERT(m_source);
+    
+    optimizeAfterWarmUp();
+    jitAfterWarmUp();
 
 #if DUMP_CODE_BLOCK_STATISTICS
     liveCodeBlockSet.add(this);
 
 #if DUMP_CODE_BLOCK_STATISTICS
     liveCodeBlockSet.add(this);
@@ -1399,7 +1496,34 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlo
 
 CodeBlock::~CodeBlock()
 {
 
 CodeBlock::~CodeBlock()
 {
+#if ENABLE(DFG_JIT)
+    // Remove myself from the set of DFG code blocks. Note that I may not be in this set
+    // (because I'm not a DFG code block), in which case this is a no-op anyway.
+    m_globalData->heap.m_dfgCodeBlocks.m_set.remove(this);
+#endif
+    
+#if ENABLE(VERBOSE_VALUE_PROFILE)
+    dumpValueProfiles();
+#endif
+
+#if ENABLE(LLINT)    
+    while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
+        m_incomingLLIntCalls.begin()->remove();
+#endif // ENABLE(LLINT)
 #if ENABLE(JIT)
 #if ENABLE(JIT)
+    // We may be destroyed before any CodeBlocks that refer to us are destroyed.
+    // Consider that two CodeBlocks become unreachable at the same time. There
+    // is no guarantee about the order in which the CodeBlocks are destroyed.
+    // So, if we don't remove incoming calls, and get destroyed before the
+    // CodeBlock(s) that have calls into us, then the CallLinkInfo vector's
+    // destructor will try to remove nodes from our (no longer valid) linked list.
+    while (m_incomingCalls.begin() != m_incomingCalls.end())
+        m_incomingCalls.begin()->remove();
+    
+    // Note that our outgoing calls will be removed from other CodeBlocks'
+    // m_incomingCalls linked lists through the execution of the ~CallLinkInfo
+    // destructors.
+
     for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
         m_structureStubInfos[i].deref();
 #endif // ENABLE(JIT)
     for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
         m_structureStubInfos[i].deref();
 #endif // ENABLE(JIT)
@@ -1409,6 +1533,24 @@ CodeBlock::~CodeBlock()
 #endif
 }
 
 #endif
 }
 
+void CodeBlock::setNumParameters(int newValue)
+{
+    m_numParameters = newValue;
+
+#if ENABLE(VALUE_PROFILER)
+    m_argumentValueProfiles.resize(newValue);
+#endif
+}
+
+void CodeBlock::addParameter()
+{
+    m_numParameters++;
+
+#if ENABLE(VALUE_PROFILER)
+    m_argumentValueProfiles.append(ValueProfile());
+#endif
+}
+
 void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC) const
 {
     Interpreter* interpreter = m_globalData->interpreter;
 void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC) const
 {
     Interpreter* interpreter = m_globalData->interpreter;
@@ -1429,13 +1571,15 @@ void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC) const
     }
     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)) {
         visitor.append(&vPC[4].u.structure);
     }
     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)) {
         visitor.append(&vPC[4].u.structure);
-        visitor.append(&vPC[5].u.structureChain);
+        if (vPC[5].u.structureChain)
+            visitor.append(&vPC[5].u.structureChain);
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
         visitor.append(&vPC[4].u.structure);
         visitor.append(&vPC[5].u.structure);
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
         visitor.append(&vPC[4].u.structure);
         visitor.append(&vPC[5].u.structure);
-        visitor.append(&vPC[6].u.structureChain);
+        if (vPC[6].u.structureChain)
+            visitor.append(&vPC[6].u.structureChain);
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) && vPC[4].u.structure) {
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) && vPC[4].u.structure) {
@@ -1451,17 +1595,6 @@ void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC) const
             visitor.append(&vPC[3].u.structure);
         return;
     }
             visitor.append(&vPC[3].u.structure);
         return;
     }
-    if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))
-        || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))
-        || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto_list))
-        || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self_list))
-        || (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->visitAggregate(visitor, vPC[5].u.operand);
-        delete polymorphicStructures;
-        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) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length));
 
     // 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) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length));
@@ -1475,6 +1608,308 @@ void EvalCodeCache::visitAggregate(SlotVisitor& visitor)
 }
 
 void CodeBlock::visitAggregate(SlotVisitor& visitor)
 }
 
 void CodeBlock::visitAggregate(SlotVisitor& visitor)
+{
+#if ENABLE(PARALLEL_GC) && ENABLE(DFG_JIT)
+    if (!!m_dfgData) {
+        // I may be asked to scan myself more than once, and it may even happen concurrently.
+        // To this end, use a CAS loop to check if I've been called already. Only one thread
+        // may proceed past this point - whichever one wins the CAS race.
+        unsigned oldValue;
+        do {
+            oldValue = m_dfgData->visitAggregateHasBeenCalled;
+            if (oldValue) {
+                // Looks like someone else won! Return immediately to ensure that we don't
+                // trace the same CodeBlock concurrently. Doing so is hazardous since we will
+                // be mutating the state of ValueProfiles, which contain JSValues, which can
+                // have word-tearing on 32-bit, leading to awesome timing-dependent crashes
+                // that are nearly impossible to track down.
+                
+                // Also note that it must be safe to return early as soon as we see the
+                // value true (well, (unsigned)1), since once a GC thread is in this method
+                // and has won the CAS race (i.e. was responsible for setting the value true)
+                // it will definitely complete the rest of this method before declaring
+                // termination.
+                return;
+            }
+        } while (!WTF::weakCompareAndSwap(&m_dfgData->visitAggregateHasBeenCalled, 0, 1));
+    }
+#endif // ENABLE(PARALLEL_GC) && ENABLE(DFG_JIT)
+    
+    if (!!m_alternative)
+        m_alternative->visitAggregate(visitor);
+
+    // There are three things that may use unconditional finalizers: lazy bytecode freeing,
+    // inline cache clearing, and jettisoning. The probability of us wanting to do at
+    // least one of those things is probably quite close to 1. So we add one no matter what
+    // and when it runs, it figures out whether it has any work to do.
+    visitor.addUnconditionalFinalizer(this);
+    
+    if (shouldImmediatelyAssumeLivenessDuringScan()) {
+        // This code block is live, so scan all references strongly and return.
+        stronglyVisitStrongReferences(visitor);
+        stronglyVisitWeakReferences(visitor);
+        return;
+    }
+    
+#if ENABLE(DFG_JIT)
+    // We get here if we're live in the sense that our owner executable is live,
+    // but we're not yet live for sure in another sense: we may yet decide that this
+    // code block should be jettisoned based on its outgoing weak references being
+    // stale. Set a flag to indicate that we're still assuming that we're dead, and
+    // perform one round of determining if we're live. The GC may determine, based on
+    // either us marking additional objects, or by other objects being marked for
+    // other reasons, that this iteration should run again; it will notify us of this
+    // decision by calling harvestWeakReferences().
+    
+    m_dfgData->livenessHasBeenProved = false;
+    m_dfgData->allTransitionsHaveBeenMarked = false;
+    
+    performTracingFixpointIteration(visitor);
+
+    // GC doesn't have enough information yet for us to decide whether to keep our DFG
+    // data, so we need to register a handler to run again at the end of GC, when more
+    // information is available.
+    if (!(m_dfgData->livenessHasBeenProved && m_dfgData->allTransitionsHaveBeenMarked))
+        visitor.addWeakReferenceHarvester(this);
+    
+#else // ENABLE(DFG_JIT)
+    ASSERT_NOT_REACHED();
+#endif // ENABLE(DFG_JIT)
+}
+
+void CodeBlock::performTracingFixpointIteration(SlotVisitor& visitor)
+{
+    UNUSED_PARAM(visitor);
+    
+#if ENABLE(DFG_JIT)
+    // Evaluate our weak reference transitions, if there are still some to evaluate.
+    if (!m_dfgData->allTransitionsHaveBeenMarked) {
+        bool allAreMarkedSoFar = true;
+        for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) {
+            if ((!m_dfgData->transitions[i].m_codeOrigin
+                 || Heap::isMarked(m_dfgData->transitions[i].m_codeOrigin.get()))
+                && Heap::isMarked(m_dfgData->transitions[i].m_from.get())) {
+                // If the following three things are live, then the target of the
+                // transition is also live:
+                // - This code block. We know it's live already because otherwise
+                //   we wouldn't be scanning ourselves.
+                // - The code origin of the transition. Transitions may arise from
+                //   code that was inlined. They are not relevant if the user's
+                //   object that is required for the inlinee to run is no longer
+                //   live.
+                // - The source of the transition. The transition checks if some
+                //   heap location holds the source, and if so, stores the target.
+                //   Hence the source must be live for the transition to be live.
+                visitor.append(&m_dfgData->transitions[i].m_to);
+            } else
+                allAreMarkedSoFar = false;
+        }
+        
+        if (allAreMarkedSoFar)
+            m_dfgData->allTransitionsHaveBeenMarked = true;
+    }
+    
+    // Check if we have any remaining work to do.
+    if (m_dfgData->livenessHasBeenProved)
+        return;
+    
+    // Now check all of our weak references. If all of them are live, then we
+    // have proved liveness and so we scan our strong references. If at end of
+    // GC we still have not proved liveness, then this code block is toast.
+    bool allAreLiveSoFar = true;
+    for (unsigned i = 0; i < m_dfgData->weakReferences.size(); ++i) {
+        if (!Heap::isMarked(m_dfgData->weakReferences[i].get())) {
+            allAreLiveSoFar = false;
+            break;
+        }
+    }
+    
+    // If some weak references are dead, then this fixpoint iteration was
+    // unsuccessful.
+    if (!allAreLiveSoFar)
+        return;
+    
+    // All weak references are live. Record this information so we don't
+    // come back here again, and scan the strong references.
+    m_dfgData->livenessHasBeenProved = true;
+    stronglyVisitStrongReferences(visitor);
+#endif // ENABLE(DFG_JIT)
+}
+
+void CodeBlock::visitWeakReferences(SlotVisitor& visitor)
+{
+    performTracingFixpointIteration(visitor);
+}
+
+void CodeBlock::finalizeUnconditionally()
+{
+#if ENABLE(JIT)
+#if ENABLE(JIT_VERBOSE_OSR)
+    static const bool verboseUnlinking = true;
+#else
+    static const bool verboseUnlinking = false;
+#endif
+#endif // ENABLE(JIT)
+    
+#if ENABLE(LLINT)
+    Interpreter* interpreter = m_globalData->interpreter;
+    // interpreter->classicEnabled() returns true if the old C++ interpreter is enabled. If that's enabled
+    // then we're not using LLInt.
+    if (!interpreter->classicEnabled() && !!numberOfInstructions()) {
+        for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {
+            Instruction* curInstruction = &instructions()[m_propertyAccessInstructions[i]];
+            switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
+            case op_get_by_id:
+            case op_put_by_id:
+                if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get()))
+                    break;
+                if (verboseUnlinking)
+                    dataLog("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get());
+                curInstruction[4].u.structure.clear();
+                curInstruction[5].u.operand = 0;
+                break;
+            case op_put_by_id_transition_direct:
+            case op_put_by_id_transition_normal:
+                if (Heap::isMarked(curInstruction[4].u.structure.get())
+                    && Heap::isMarked(curInstruction[6].u.structure.get())
+                    && Heap::isMarked(curInstruction[7].u.structureChain.get()))
+                    break;
+                if (verboseUnlinking) {
+                    dataLog("Clearing LLInt put transition with structures %p -> %p, chain %p.\n",
+                            curInstruction[4].u.structure.get(),
+                            curInstruction[6].u.structure.get(),
+                            curInstruction[7].u.structureChain.get());
+                }
+                curInstruction[4].u.structure.clear();
+                curInstruction[6].u.structure.clear();
+                curInstruction[7].u.structureChain.clear();
+                curInstruction[0].u.opcode = interpreter->getOpcode(op_put_by_id);
+                break;
+            default:
+                ASSERT_NOT_REACHED();
+            }
+        }
+        for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i) {
+            Instruction* curInstruction = &instructions()[m_globalResolveInstructions[i]];
+            ASSERT(interpreter->getOpcodeID(curInstruction[0].u.opcode) == op_resolve_global
+                   || interpreter->getOpcodeID(curInstruction[0].u.opcode) == op_resolve_global_dynamic);
+            if (!curInstruction[3].u.structure || Heap::isMarked(curInstruction[3].u.structure.get()))
+                continue;
+            if (verboseUnlinking)
+                dataLog("Clearing LLInt global resolve cache with structure %p.\n", curInstruction[3].u.structure.get());
+            curInstruction[3].u.structure.clear();
+            curInstruction[4].u.operand = 0;
+        }
+        for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
+            if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
+                if (verboseUnlinking)
+                    dataLog("Clearing LLInt call from %p.\n", this);
+                m_llintCallLinkInfos[i].unlink();
+            }
+            if (!!m_llintCallLinkInfos[i].lastSeenCallee && !Heap::isMarked(m_llintCallLinkInfos[i].lastSeenCallee.get()))
+                m_llintCallLinkInfos[i].lastSeenCallee.clear();
+        }
+    }
+#endif // ENABLE(LLINT)
+
+#if ENABLE(DFG_JIT)
+    // Check if we're not live. If we are, then jettison.
+    if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_dfgData->livenessHasBeenProved)) {
+        if (verboseUnlinking)
+            dataLog("Code block %p has dead weak references, jettisoning during GC.\n", this);
+
+        // Make sure that the baseline JIT knows that it should re-warm-up before
+        // optimizing.
+        alternative()->optimizeAfterWarmUp();
+        
+        jettison();
+        return;
+    }
+#endif // ENABLE(DFG_JIT)
+    
+#if ENABLE(JIT)
+    // Handle inline caches.
+    if (!!getJITCode()) {
+        RepatchBuffer repatchBuffer(this);
+        for (unsigned i = 0; i < numberOfCallLinkInfos(); ++i) {
+            if (callLinkInfo(i).isLinked() && !Heap::isMarked(callLinkInfo(i).callee.get())) {
+                if (verboseUnlinking)
+                    dataLog("Clearing call from %p to %p.\n", this, callLinkInfo(i).callee.get());
+                callLinkInfo(i).unlink(*m_globalData, repatchBuffer);
+            }
+            if (!!callLinkInfo(i).lastSeenCallee
+                && !Heap::isMarked(callLinkInfo(i).lastSeenCallee.get()))
+                callLinkInfo(i).lastSeenCallee.clear();
+        }
+        for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) {
+            if (m_globalResolveInfos[i].structure && !Heap::isMarked(m_globalResolveInfos[i].structure.get())) {
+                if (verboseUnlinking)
+                    dataLog("Clearing resolve info in %p.\n", this);
+                m_globalResolveInfos[i].structure.clear();
+            }
+        }
+
+        for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) {
+            StructureStubInfo& stubInfo = m_structureStubInfos[i];
+            
+            AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
+            
+            if (stubInfo.visitWeakReferences())
+                continue;
+            
+            if (verboseUnlinking)
+                dataLog("Clearing structure cache (kind %d) in %p.\n", stubInfo.accessType, this);
+            
+            if (isGetByIdAccess(accessType)) {
+                if (getJITCode().jitType() == JITCode::DFGJIT)
+                    DFG::dfgResetGetByID(repatchBuffer, stubInfo);
+                else
+                    JIT::resetPatchGetById(repatchBuffer, &stubInfo);
+            } else {
+                ASSERT(isPutByIdAccess(accessType));
+                if (getJITCode().jitType() == JITCode::DFGJIT)
+                    DFG::dfgResetPutByID(repatchBuffer, stubInfo);
+                else 
+                    JIT::resetPatchPutById(repatchBuffer, &stubInfo);
+            }
+            
+            stubInfo.reset();
+        }
+
+        for (size_t size = m_methodCallLinkInfos.size(), i = 0; i < size; ++i) {
+            if (!m_methodCallLinkInfos[i].cachedStructure)
+                continue;
+            
+            ASSERT(m_methodCallLinkInfos[i].seenOnce());
+            ASSERT(!!m_methodCallLinkInfos[i].cachedPrototypeStructure);
+
+            if (!Heap::isMarked(m_methodCallLinkInfos[i].cachedStructure.get())
+                || !Heap::isMarked(m_methodCallLinkInfos[i].cachedPrototypeStructure.get())
+                || !Heap::isMarked(m_methodCallLinkInfos[i].cachedFunction.get())
+                || !Heap::isMarked(m_methodCallLinkInfos[i].cachedPrototype.get())) {
+                if (verboseUnlinking)
+                    dataLog("Clearing method call in %p.\n", this);
+                m_methodCallLinkInfos[i].reset(repatchBuffer, getJITType());
+
+                StructureStubInfo& stubInfo = getStubInfo(m_methodCallLinkInfos[i].bytecodeIndex);
+
+                AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
+
+                if (accessType != access_unset) {
+                    ASSERT(isGetByIdAccess(accessType));
+                    if (getJITCode().jitType() == JITCode::DFGJIT)
+                        DFG::dfgResetGetByID(repatchBuffer, stubInfo);
+                    else
+                        JIT::resetPatchGetById(repatchBuffer, &stubInfo);
+                    stubInfo.reset();
+                }
+            }
+        }
+    }
+#endif
+}
+
+void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
 {
     visitor.append(&m_globalObject);
     visitor.append(&m_ownerExecutable);
 {
     visitor.append(&m_globalObject);
     visitor.append(&m_ownerExecutable);
@@ -1490,44 +1925,60 @@ void CodeBlock::visitAggregate(SlotVisitor& visitor)
         visitor.append(&m_functionExprs[i]);
     for (size_t i = 0; i < m_functionDecls.size(); ++i)
         visitor.append(&m_functionDecls[i]);
         visitor.append(&m_functionExprs[i]);
     for (size_t i = 0; i < m_functionDecls.size(); ++i)
         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);
+#if ENABLE(CLASSIC_INTERPRETER)
+    if (m_globalData->interpreter->classicEnabled() && !!numberOfInstructions()) {
+        for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
+            visitStructures(visitor, &instructions()[m_propertyAccessInstructions[i]]);
+        for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
+            visitStructures(visitor, &instructions()[m_globalResolveInstructions[i]]);
     }
     }
+#endif
 
 
-    for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
-        m_structureStubInfos[i].visitAggregate(visitor);
-
-    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);
+#if ENABLE(DFG_JIT)
+    if (hasCodeOrigins()) {
+        // Make sure that executables that we have inlined don't die.
+        // FIXME: If they would have otherwise died, we should probably trigger recompilation.
+        for (size_t i = 0; i < inlineCallFrames().size(); ++i) {
+            InlineCallFrame& inlineCallFrame = inlineCallFrames()[i];
+            visitor.append(&inlineCallFrame.executable);
+            visitor.append(&inlineCallFrame.callee);
         }
     }
         }
     }
+    
+    m_lazyOperandValueProfiles.computeUpdatedPredictions();
+#endif
+
+#if ENABLE(VALUE_PROFILER)
+    for (unsigned profileIndex = 0; profileIndex < numberOfArgumentValueProfiles(); ++profileIndex)
+        valueProfileForArgument(profileIndex)->computeUpdatedPrediction();
+    for (unsigned profileIndex = 0; profileIndex < numberOfValueProfiles(); ++profileIndex)
+        valueProfile(profileIndex)->computeUpdatedPrediction();
 #endif
 }
 
 #endif
 }
 
+void CodeBlock::stronglyVisitWeakReferences(SlotVisitor& visitor)
+{
+    UNUSED_PARAM(visitor);
+
+#if ENABLE(DFG_JIT)
+    if (!m_dfgData)
+        return;
+
+    for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) {
+        if (!!m_dfgData->transitions[i].m_codeOrigin)
+            visitor.append(&m_dfgData->transitions[i].m_codeOrigin); // Almost certainly not necessary, since the code origin should also be a weak reference. Better to be safe, though.
+        visitor.append(&m_dfgData->transitions[i].m_from);
+        visitor.append(&m_dfgData->transitions[i].m_to);
+    }
+    
+    for (unsigned i = 0; i < m_dfgData->weakReferences.size(); ++i)
+        visitor.append(&m_dfgData->weakReferences[i]);
+#endif    
+}
+
 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
 {
 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
 {
-    ASSERT(bytecodeOffset < m_instructionCount);
+    ASSERT(bytecodeOffset < instructions().size());
 
     if (!m_rareData)
         return 0;
 
     if (!m_rareData)
         return 0;
@@ -1545,7 +1996,7 @@ HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
 
 int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
 {
 
 int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
 {
-    ASSERT(bytecodeOffset < m_instructionCount);
+    ASSERT(bytecodeOffset < instructions().size());
 
     if (!m_rareData)
         return m_ownerExecutable->source().firstLine();
 
     if (!m_rareData)
         return m_ownerExecutable->source().firstLine();
@@ -1569,7 +2020,7 @@ int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
 
 void CodeBlock::expressionRangeForBytecodeOffset(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 < instructions().size());
 
     if (!m_rareData) {
         startOffset = 0;
 
     if (!m_rareData) {
         startOffset = 0;
@@ -1604,7 +2055,7 @@ void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& d
     return;
 }
 
     return;
 }
 
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
 bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
 {
     if (m_globalResolveInstructions.isEmpty())
 bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
 {
     if (m_globalResolveInstructions.isEmpty())
@@ -1649,9 +2100,7 @@ bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
 
 void CodeBlock::shrinkToFit()
 {
 
 void CodeBlock::shrinkToFit()
 {
-    m_instructions.shrinkToFit();
-
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
     m_propertyAccessInstructions.shrinkToFit();
     m_globalResolveInstructions.shrinkToFit();
 #endif
     m_propertyAccessInstructions.shrinkToFit();
     m_globalResolveInstructions.shrinkToFit();
 #endif
@@ -1682,14 +2131,32 @@ void CodeBlock::createActivation(CallFrame* callFrame)
     ASSERT(codeType() == FunctionCode);
     ASSERT(needsFullScopeChain());
     ASSERT(!callFrame->uncheckedR(activationRegister()).jsValue());
     ASSERT(codeType() == FunctionCode);
     ASSERT(needsFullScopeChain());
     ASSERT(!callFrame->uncheckedR(activationRegister()).jsValue());
-    JSActivation* activation = new (callFrame) JSActivation(callFrame, static_cast<FunctionExecutable*>(ownerExecutable()));
+    JSActivation* activation = JSActivation::create(callFrame->globalData(), callFrame, static_cast<FunctionExecutable*>(ownerExecutable()));
     callFrame->uncheckedR(activationRegister()) = JSValue(activation);
     callFrame->setScopeChain(callFrame->scopeChain()->push(activation));
 }
     callFrame->uncheckedR(activationRegister()) = JSValue(activation);
     callFrame->setScopeChain(callFrame->scopeChain()->push(activation));
 }
-    
+
+unsigned CodeBlock::addOrFindConstant(JSValue v)
+{
+    unsigned numberOfConstants = numberOfConstantRegisters();
+    for (unsigned i = 0; i < numberOfConstants; ++i) {
+        if (getConstant(FirstConstantRegisterIndex + i) == v)
+            return i;
+    }
+    return addConstant(v);
+}
+
 #if ENABLE(JIT)
 void CodeBlock::unlinkCalls()
 {
 #if ENABLE(JIT)
 void CodeBlock::unlinkCalls()
 {
+    if (!!m_alternative)
+        m_alternative->unlinkCalls();
+#if ENABLE(LLINT)
+    for (size_t i = 0; i < m_llintCallLinkInfos.size(); ++i) {
+        if (m_llintCallLinkInfos[i].isLinked())
+            m_llintCallLinkInfos[i].unlink();
+    }
+#endif
     if (!(m_callLinkInfos.size() || m_methodCallLinkInfos.size()))
         return;
     if (!m_globalData->canUseJIT())
     if (!(m_callLinkInfos.size() || m_methodCallLinkInfos.size()))
         return;
     if (!m_globalData->canUseJIT())
@@ -1698,17 +2165,359 @@ void CodeBlock::unlinkCalls()
     for (size_t i = 0; i < m_callLinkInfos.size(); i++) {
         if (!m_callLinkInfos[i].isLinked())
             continue;
     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();
+        m_callLinkInfos[i].unlink(*m_globalData, repatchBuffer);
     }
 }
     }
 }
+
+void CodeBlock::unlinkIncomingCalls()
+{
+#if ENABLE(LLINT)
+    while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
+        m_incomingLLIntCalls.begin()->unlink();
+#endif
+    if (m_incomingCalls.isEmpty())
+        return;
+    RepatchBuffer repatchBuffer(this);
+    while (m_incomingCalls.begin() != m_incomingCalls.end())
+        m_incomingCalls.begin()->unlink(*m_globalData, repatchBuffer);
+}
+
+unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddress)
+{
+#if ENABLE(LLINT)
+    if (returnAddress.value() >= bitwise_cast<void*>(&llint_begin)
+        && returnAddress.value() <= bitwise_cast<void*>(&llint_end)) {
+        ASSERT(exec->codeBlock());
+        ASSERT(exec->codeBlock() == this);
+        ASSERT(JITCode::isBaselineCode(getJITType()));
+        Instruction* instruction = exec->currentVPC();
+        ASSERT(instruction);
+        
+        // The LLInt stores the PC after the call instruction rather than the PC of
+        // the call instruction. This requires some correcting. We rely on the fact
+        // that the preceding instruction must be one of the call instructions, so
+        // either it's a call_varargs or it's a call, construct, or eval.
+        ASSERT(OPCODE_LENGTH(op_call_varargs) <= OPCODE_LENGTH(op_call));
+        ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
+        ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
+        if (instruction[-OPCODE_LENGTH(op_call_varargs)].u.pointer == bitwise_cast<void*>(llint_op_call_varargs)) {
+            // We know that the preceding instruction must be op_call_varargs because there is no way that
+            // the pointer to the call_varargs could be an operand to the call.
+            instruction -= OPCODE_LENGTH(op_call_varargs);
+            ASSERT(instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_call)
+                   && instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_construct)
+                   && instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_call_eval));
+        } else {
+            // Must be that the last instruction was some op_call.
+            ASSERT(instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_call)
+                   || instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_construct)
+                   || instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_call_eval));
+            instruction -= OPCODE_LENGTH(op_call);
+        }
+        
+        return bytecodeOffset(instruction);
+    }
+#else
+    UNUSED_PARAM(exec);
+#endif
+    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;
+}
 #endif
 
 void CodeBlock::clearEvalCache()
 {
 #endif
 
 void CodeBlock::clearEvalCache()
 {
+    if (!!m_alternative)
+        m_alternative->clearEvalCache();
     if (!m_rareData)
         return;
     m_rareData->m_evalCodeCache.clear();
 }
 
     if (!m_rareData)
         return;
     m_rareData->m_evalCodeCache.clear();
 }
 
+template<typename T>
+inline void replaceExistingEntries(Vector<T>& target, Vector<T>& source)
+{
+    ASSERT(target.size() <= source.size());
+    for (size_t i = 0; i < target.size(); ++i)
+        target[i] = source[i];
+}
+
+void CodeBlock::copyPostParseDataFrom(CodeBlock* alternative)
+{
+    if (!alternative)
+        return;
+    
+    replaceExistingEntries(m_constantRegisters, alternative->m_constantRegisters);
+    replaceExistingEntries(m_functionDecls, alternative->m_functionDecls);
+    replaceExistingEntries(m_functionExprs, alternative->m_functionExprs);
+    if (!!m_rareData && !!alternative->m_rareData)
+        replaceExistingEntries(m_rareData->m_constantBuffers, alternative->m_rareData->m_constantBuffers);
+}
+
+void CodeBlock::copyPostParseDataFromAlternative()
+{
+    copyPostParseDataFrom(m_alternative.get());
+}
+
+#if ENABLE(JIT)
+CodeBlock* ProgramCodeBlock::replacement()
+{
+    return &static_cast<ProgramExecutable*>(ownerExecutable())->generatedBytecode();
+}
+
+CodeBlock* EvalCodeBlock::replacement()
+{
+    return &static_cast<EvalExecutable*>(ownerExecutable())->generatedBytecode();
+}
+
+CodeBlock* FunctionCodeBlock::replacement()
+{
+    return &static_cast<FunctionExecutable*>(ownerExecutable())->generatedBytecodeFor(m_isConstructor ? CodeForConstruct : CodeForCall);
+}
+
+JSObject* ProgramCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+    if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
+        return 0;
+    JSObject* error = static_cast<ProgramExecutable*>(ownerExecutable())->compileOptimized(exec, scopeChainNode);
+    return error;
+}
+
+JSObject* EvalCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+    if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
+        return 0;
+    JSObject* error = static_cast<EvalExecutable*>(ownerExecutable())->compileOptimized(exec, scopeChainNode);
+    return error;
+}
+
+JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+    if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
+        return 0;
+    JSObject* error = static_cast<FunctionExecutable*>(ownerExecutable())->compileOptimizedFor(exec, scopeChainNode, m_isConstructor ? CodeForConstruct : CodeForCall);
+    return error;
+}
+
+bool ProgramCodeBlock::canCompileWithDFGInternal()
+{
+    return DFG::canCompileProgram(this);
+}
+
+bool EvalCodeBlock::canCompileWithDFGInternal()
+{
+    return DFG::canCompileEval(this);
+}
+
+bool FunctionCodeBlock::canCompileWithDFGInternal()
+{
+    if (m_isConstructor)
+        return DFG::canCompileFunctionForConstruct(this);
+    return DFG::canCompileFunctionForCall(this);
+}
+
+void ProgramCodeBlock::jettison()
+{
+    ASSERT(JITCode::isOptimizingJIT(getJITType()));
+    ASSERT(this == replacement());
+    static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData());
+}
+
+void EvalCodeBlock::jettison()
+{
+    ASSERT(JITCode::isOptimizingJIT(getJITType()));
+    ASSERT(this == replacement());
+    static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData());
+}
+
+void FunctionCodeBlock::jettison()
+{
+    ASSERT(JITCode::isOptimizingJIT(getJITType()));
+    ASSERT(this == replacement());
+    static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*globalData(), m_isConstructor ? CodeForConstruct : CodeForCall);
+}
+
+bool ProgramCodeBlock::jitCompileImpl(JSGlobalData& globalData)
+{
+    ASSERT(getJITType() == JITCode::InterpreterThunk);
+    ASSERT(this == replacement());
+    return static_cast<ProgramExecutable*>(ownerExecutable())->jitCompile(globalData);
+}
+
+bool EvalCodeBlock::jitCompileImpl(JSGlobalData& globalData)
+{
+    ASSERT(getJITType() == JITCode::InterpreterThunk);
+    ASSERT(this == replacement());
+    return static_cast<EvalExecutable*>(ownerExecutable())->jitCompile(globalData);
+}
+
+bool FunctionCodeBlock::jitCompileImpl(JSGlobalData& globalData)
+{
+    ASSERT(getJITType() == JITCode::InterpreterThunk);
+    ASSERT(this == replacement());
+    return static_cast<FunctionExecutable*>(ownerExecutable())->jitCompileFor(globalData, m_isConstructor ? CodeForConstruct : CodeForCall);
+}
+#endif
+
+#if ENABLE(VALUE_PROFILER)
+bool CodeBlock::shouldOptimizeNow()
+{
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("Considering optimizing %p...\n", this);
+#endif
+
+#if ENABLE(VERBOSE_VALUE_PROFILE)
+    dumpValueProfiles();
+#endif
+
+    if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay)
+        return true;
+    
+    unsigned numberOfLiveNonArgumentValueProfiles = 0;
+    unsigned numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
+    for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
+        ValueProfile* profile = getFromAllValueProfiles(i);
+        unsigned numSamples = profile->totalNumberOfSamples();
+        if (numSamples > ValueProfile::numberOfBuckets)
+            numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
+        numberOfSamplesInProfiles += numSamples;
+        if (profile->m_bytecodeOffset < 0) {
+            profile->computeUpdatedPrediction();
+            continue;
+        }
+        if (profile->numberOfSamples() || profile->m_prediction != PredictNone)
+            numberOfLiveNonArgumentValueProfiles++;
+        profile->computeUpdatedPrediction();
+    }
+
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("Profile hotness: %lf, %lf\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(), (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles());
+#endif
+
+    if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate)
+        && (!totalNumberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / totalNumberOfValueProfiles() >= Options::desiredProfileFullnessRate)
+        && static_cast<unsigned>(m_optimizationDelayCounter) + 1 >= Options::minimumOptimizationDelay)
+        return true;
+    
+    ASSERT(m_optimizationDelayCounter < std::numeric_limits<uint8_t>::max());
+    m_optimizationDelayCounter++;
+    optimizeAfterWarmUp();
+    return false;
+}
+#endif
+
+#if ENABLE(DFG_JIT)
+void CodeBlock::tallyFrequentExitSites()
+{
+    ASSERT(getJITType() == JITCode::DFGJIT);
+    ASSERT(alternative()->getJITType() == JITCode::BaselineJIT);
+    ASSERT(!!m_dfgData);
+    
+    CodeBlock* profiledBlock = alternative();
+    
+    for (unsigned i = 0; i < m_dfgData->osrExit.size(); ++i) {
+        DFG::OSRExit& exit = m_dfgData->osrExit[i];
+        
+        if (!exit.considerAddingAsFrequentExitSite(this, profiledBlock))
+            continue;
+        
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("OSR exit #%u (bc#%u, @%u, %s) for code block %p occurred frequently; counting as frequent exit site.\n", i, exit.m_codeOrigin.bytecodeIndex, exit.m_nodeIndex, DFG::exitKindToString(exit.m_kind), this);
+#endif
+    }
+}
+#endif // ENABLE(DFG_JIT)
+
+#if ENABLE(VERBOSE_VALUE_PROFILE)
+void CodeBlock::dumpValueProfiles()
+{
+    dataLog("ValueProfile for %p:\n", this);
+    for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
+        ValueProfile* profile = getFromAllValueProfiles(i);
+        if (profile->m_bytecodeOffset < 0) {
+            ASSERT(profile->m_bytecodeOffset == -1);
+            dataLog("   arg = %u: ", i);
+        } else
+            dataLog("   bc = %d: ", profile->m_bytecodeOffset);
+        if (!profile->numberOfSamples() && profile->m_prediction == PredictNone) {
+            dataLog("<empty>\n");
+            continue;
+        }
+        profile->dump(WTF::dataFile());
+        dataLog("\n");
+    }
+    dataLog("RareCaseProfile for %p:\n", this);
+    for (unsigned i = 0; i < numberOfRareCaseProfiles(); ++i) {
+        RareCaseProfile* profile = rareCaseProfile(i);
+        dataLog("   bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
+    }
+    dataLog("SpecialFastCaseProfile for %p:\n", this);
+    for (unsigned i = 0; i < numberOfSpecialFastCaseProfiles(); ++i) {
+        RareCaseProfile* profile = specialFastCaseProfile(i);
+        dataLog("   bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
+    }
+}
+#endif
+
+size_t CodeBlock::predictedMachineCodeSize()
+{
+    // This will be called from CodeBlock::CodeBlock before either m_globalData or the
+    // instructions have been initialized. It's OK to return 0 because what will really
+    // matter is the recomputation of this value when the slow path is triggered.
+    if (!m_globalData)
+        return 0;
+    
+    if (!m_globalData->machineCodeBytesPerBytecodeWordForBaselineJIT)
+        return 0; // It's as good of a prediction as we'll get.
+    
+    // Be conservative: return a size that will be an overestimation 84% of the time.
+    double multiplier = m_globalData->machineCodeBytesPerBytecodeWordForBaselineJIT.mean() +
+        m_globalData->machineCodeBytesPerBytecodeWordForBaselineJIT.standardDeviation();
+    
+    // Be paranoid: silently reject bogus multipiers. Silently doing the "wrong" thing
+    // here is OK, since this whole method is just a heuristic.
+    if (multiplier < 0 || multiplier > 1000)
+        return 0;
+    
+    double doubleResult = multiplier * m_instructions.size();
+    
+    // Be even more paranoid: silently reject values that won't fit into a size_t. If
+    // the function is so huge that we can't even fit it into virtual memory then we
+    // should probably have some other guards in place to prevent us from even getting
+    // to this point.
+    if (doubleResult > std::numeric_limits<size_t>::max())
+        return 0;
+    
+    return static_cast<size_t>(doubleResult);
+}
+
+bool CodeBlock::usesOpcode(OpcodeID opcodeID)
+{
+    Interpreter* interpreter = globalData()->interpreter;
+    Instruction* instructionsBegin = instructions().begin();
+    unsigned instructionCount = instructions().size();
+    
+    for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount; ) {
+        switch (interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode)) {
+#define DEFINE_OP(curOpcode, length)        \
+        case curOpcode:                     \
+            if (curOpcode == opcodeID)      \
+                return true;                \
+            bytecodeOffset += length;       \
+            break;
+            FOR_EACH_OPCODE_ID(DEFINE_OP)
+#undef DEFINE_OP
+        default:
+            ASSERT_NOT_REACHED();
+            break;
+        }
+    }
+    
+    return false;
+}
+
 } // namespace JSC
 } // namespace JSC
index 7aa356ecf159a38e240dbd63b1a2b9b3daa0623e..778376f94c62f92eb06a8b523bb301e2ecec9e60 100644 (file)
 #ifndef CodeBlock_h
 #define CodeBlock_h
 
 #ifndef CodeBlock_h
 #define CodeBlock_h
 
+#include "BytecodeConventions.h"
+#include "CallLinkInfo.h"
+#include "CallReturnOffsetToBytecodeOffset.h"
+#include "CodeOrigin.h"
+#include "CodeType.h"
+#include "CompactJITCodeMap.h"
+#include "DFGCodeBlocks.h"
+#include "DFGExitProfile.h"
+#include "DFGOSREntry.h"
+#include "DFGOSRExit.h"
 #include "EvalCodeCache.h"
 #include "EvalCodeCache.h"
+#include "ExecutionCounter.h"
+#include "ExpressionRangeInfo.h"
+#include "GlobalResolveInfo.h"
+#include "HandlerInfo.h"
+#include "MethodCallLinkInfo.h"
+#include "Options.h"
 #include "Instruction.h"
 #include "JITCode.h"
 #include "JITWriteBarrier.h"
 #include "JSGlobalObject.h"
 #include "JumpTable.h"
 #include "Instruction.h"
 #include "JITCode.h"
 #include "JITWriteBarrier.h"
 #include "JSGlobalObject.h"
 #include "JumpTable.h"
+#include "LLIntCallLinkInfo.h"
+#include "LazyOperandValueProfile.h"
+#include "LineInfo.h"
 #include "Nodes.h"
 #include "RegExpObject.h"
 #include "Nodes.h"
 #include "RegExpObject.h"
+#include "StructureStubInfo.h"
 #include "UString.h"
 #include "UString.h"
+#include "UnconditionalFinalizer.h"
+#include "ValueProfile.h"
+#include <wtf/RefCountedArray.h>
 #include <wtf/FastAllocBase.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/RefPtr.h>
 #include <wtf/FastAllocBase.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/RefPtr.h>
+#include <wtf/SegmentedVector.h>
 #include <wtf/Vector.h>
 #include <wtf/Vector.h>
-
-#if ENABLE(JIT)
 #include "StructureStubInfo.h"
 #include "StructureStubInfo.h"
-#endif
-
-// 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;
 
 namespace JSC {
 
 
 namespace JSC {
 
-    enum HasSeenShouldRepatch {
-        hasSeenShouldRepatch
-    };
-
+    class DFGCodeBlocks;
     class ExecState;
     class ExecState;
-
-    enum CodeType { GlobalCode, EvalCode, FunctionCode };
+    class LLIntOffsetsExtractor;
 
     inline int unmodifiedArgumentsRegister(int argumentsRegister) { return argumentsRegister - 1; }
 
     static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
 
 
     inline int unmodifiedArgumentsRegister(int argumentsRegister) { return argumentsRegister - 1; }
 
     static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
 
-    struct HandlerInfo {
-        uint32_t start;
-        uint32_t end;
-        uint32_t target;
-        uint32_t scopeDepth;
-#if ENABLE(JIT)
-        CodeLocationLabel nativeCode;
-#endif
-    };
-
-    struct ExpressionRangeInfo {
-        enum {
-            MaxOffset = (1 << 7) - 1, 
-            MaxDivot = (1 << 25) - 1
-        };
-        uint32_t instructionOffset : 25;
-        uint32_t divotPoint : 25;
-        uint32_t startOffset : 7;
-        uint32_t endOffset : 7;
-    };
-
-    struct LineInfo {
-        uint32_t instructionOffset;
-        int32_t lineNumber;
-    };
-
-#if ENABLE(JIT)
-    struct CallLinkInfo {
-        CallLinkInfo()
-            : hasSeenShouldRepatch(false)
-            , isCall(false)
-        {
-        }
-
-        CodeLocationNearCall callReturnLocation;
-        CodeLocationDataLabelPtr hotPathBegin;
-        CodeLocationNearCall hotPathOther;
-        JITWriteBarrier<JSFunction> callee;
-        bool hasSeenShouldRepatch : 1;
-        bool isCall : 1;
-
-        bool isLinked() { return callee; }
-        void unlink()
-        {
-            hasSeenShouldRepatch = false;
-            callee.clear();
-        }
-
-        bool seenOnce()
-        {
-            return hasSeenShouldRepatch;
-        }
-
-        void setSeen()
-        {
-            hasSeenShouldRepatch = true;
-        }
-    };
-
-    struct MethodCallLinkInfo {
-        MethodCallLinkInfo()
-        {
-        }
-
-        bool seenOnce()
-        {
-            ASSERT(!cachedStructure);
-            return cachedPrototypeStructure.isFlagged();
-        }
-
-        void setSeen()
-        {
-            ASSERT(!cachedStructure && !cachedPrototypeStructure);
-            // We use the values of cachedStructure & cachedPrototypeStructure to indicate the
-            // current state.
-            //     - In the initial state, both are null.
-            //     - 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.setFlagOnBarrier();
-        }
-
-        CodeLocationCall callReturnLocation;
-        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)
-            : offset(0)
-            , bytecodeOffset(bytecodeOffset)
-        {
-        }
-
-        WriteBarrier<Structure> structure;
-        unsigned offset;
-        unsigned bytecodeOffset;
-    };
-
-    // This structure is used to map from a call return location
-    // (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 CallReturnOffsetToBytecodeOffset {
-        CallReturnOffsetToBytecodeOffset(unsigned callReturnOffset, unsigned bytecodeOffset)
-            : callReturnOffset(callReturnOffset)
-            , bytecodeOffset(bytecodeOffset)
-        {
-        }
-
-        unsigned callReturnOffset;
-        unsigned bytecodeOffset;
-    };
-
-    // valueAtPosition helpers for the binarySearch algorithm.
-
-    inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
-    {
-        return structureStubInfo->callReturnLocation.executableAddress();
-    }
-
-    inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo)
-    {
-        return callLinkInfo->callReturnLocation.executableAddress();
-    }
-
-    inline void* getMethodCallLinkInfoReturnLocation(MethodCallLinkInfo* methodCallLinkInfo)
-    {
-        return methodCallLinkInfo->callReturnLocation.executableAddress();
-    }
-
-    inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeOffset* pc)
-    {
-        return pc->callReturnOffset;
-    }
-#endif
-
-    class CodeBlock {
+    class CodeBlock : public UnconditionalFinalizer, public WeakReferenceHarvester {
         WTF_MAKE_FAST_ALLOCATED;
         friend class JIT;
         WTF_MAKE_FAST_ALLOCATED;
         friend class JIT;
+        friend class LLIntOffsetsExtractor;
+    public:
+        enum CopyParsedBlockTag { CopyParsedBlock };
     protected:
     protected:
-        CodeBlock(ScriptExecutable* ownerExecutable, CodeType, JSGlobalObject*, PassRefPtr<SourceProvider>, unsigned sourceOffset, SymbolTable* symbolTable, bool isConstructor);
+        CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable*);
+        
+        CodeBlock(ScriptExecutable* ownerExecutable, CodeType, JSGlobalObject*, PassRefPtr<SourceProvider>, unsigned sourceOffset, SymbolTable*, bool isConstructor, PassOwnPtr<CodeBlock> alternative);
 
         WriteBarrier<JSGlobalObject> m_globalObject;
         Heap* m_heap;
 
     public:
 
         WriteBarrier<JSGlobalObject> m_globalObject;
         Heap* m_heap;
 
     public:
-        virtual ~CodeBlock();
+        JS_EXPORT_PRIVATE virtual ~CodeBlock();
+        
+        int numParameters() const { return m_numParameters; }
+        void setNumParameters(int newValue);
+        void addParameter();
+        
+        int* addressOfNumParameters() { return &m_numParameters; }
+        static ptrdiff_t offsetOfNumParameters() { return OBJECT_OFFSETOF(CodeBlock, m_numParameters); }
 
 
+        CodeBlock* alternative() { return m_alternative.get(); }
+        PassOwnPtr<CodeBlock> releaseAlternative() { return m_alternative.release(); }
+        void setAlternative(PassOwnPtr<CodeBlock> alternative) { m_alternative = alternative; }
+        
+        CodeSpecializationKind specializationKind()
+        {
+            if (m_isConstructor)
+                return CodeForConstruct;
+            return CodeForCall;
+        }
+        
+#if ENABLE(JIT)
+        CodeBlock* baselineVersion()
+        {
+            CodeBlock* result = replacement();
+            if (!result)
+                return 0; // This can happen if we're in the process of creating the baseline version.
+            while (result->alternative())
+                result = result->alternative();
+            ASSERT(result);
+            ASSERT(JITCode::isBaselineCode(result->getJITType()));
+            return result;
+        }
+#endif
+        
         void visitAggregate(SlotVisitor&);
 
         static void dumpStatistics();
 
         void visitAggregate(SlotVisitor&);
 
         static void dumpStatistics();
 
-#if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
         void dump(ExecState*) const;
         void printStructures(const Instruction*) const;
         void printStructure(const char* name, const Instruction*, int operand) const;
         void dump(ExecState*) const;
         void printStructures(const Instruction*) const;
         void printStructure(const char* name, const Instruction*, int operand) const;
-#endif
 
         bool isStrictMode() const { return m_isStrictMode; }
 
 
         bool isStrictMode() const { return m_isStrictMode; }
 
@@ -260,55 +165,264 @@ namespace JSC {
             return *(binarySearch<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress.value()));
         }
 
             return *(binarySearch<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress.value()));
         }
 
+        StructureStubInfo& getStubInfo(unsigned bytecodeIndex)
+        {
+            return *(binarySearch<StructureStubInfo, unsigned, getStructureStubInfoBytecodeIndex>(m_structureStubInfos.begin(), m_structureStubInfos.size(), bytecodeIndex));
+        }
+
         CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress)
         {
             return *(binarySearch<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress.value()));
         }
         CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress)
         {
             return *(binarySearch<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress.value()));
         }
+        
+        CallLinkInfo& getCallLinkInfo(unsigned bytecodeIndex)
+        {
+            return *(binarySearch<CallLinkInfo, unsigned, getCallLinkInfoBytecodeIndex>(m_callLinkInfos.begin(), m_callLinkInfos.size(), bytecodeIndex));
+        }
 
         MethodCallLinkInfo& getMethodCallLinkInfo(ReturnAddressPtr returnAddress)
         {
             return *(binarySearch<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value()));
         }
 
 
         MethodCallLinkInfo& getMethodCallLinkInfo(ReturnAddressPtr returnAddress)
         {
             return *(binarySearch<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value()));
         }
 
-        unsigned bytecodeOffset(ReturnAddressPtr returnAddress)
+        MethodCallLinkInfo& getMethodCallLinkInfo(unsigned bytecodeIndex)
+        {
+            return *(binarySearch<MethodCallLinkInfo, unsigned, getMethodCallLinkInfoBytecodeIndex>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), bytecodeIndex));
+        }
+
+        unsigned bytecodeOffset(ExecState*, ReturnAddressPtr);
+
+        unsigned bytecodeOffsetForCallAtIndex(unsigned index)
         {
             if (!m_rareData)
                 return 1;
             Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector;
             if (!callIndices.size())
                 return 1;
         {
             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;
+            ASSERT(index < m_rareData->m_callReturnIndexVector.size());
+            return m_rareData->m_callReturnIndexVector[index].bytecodeOffset;
         }
 
         void unlinkCalls();
         }
 
         void unlinkCalls();
+        
+        bool hasIncomingCalls() { return m_incomingCalls.begin() != m_incomingCalls.end(); }
+        
+        void linkIncomingCall(CallLinkInfo* incoming)
+        {
+            m_incomingCalls.push(incoming);
+        }
+#if ENABLE(LLINT)
+        void linkIncomingCall(LLIntCallLinkInfo* incoming)
+        {
+            m_incomingLLIntCalls.push(incoming);
+        }
+#endif // ENABLE(LLINT)
+        
+        void unlinkIncomingCalls();
+#endif // ENABLE(JIT)
+
+#if ENABLE(DFG_JIT) || ENABLE(LLINT)
+        void setJITCodeMap(PassOwnPtr<CompactJITCodeMap> jitCodeMap)
+        {
+            m_jitCodeMap = jitCodeMap;
+        }
+        CompactJITCodeMap* jitCodeMap()
+        {
+            return m_jitCodeMap.get();
+        }
+#endif
+        
+#if ENABLE(DFG_JIT)
+        void createDFGDataIfNecessary()
+        {
+            if (!!m_dfgData)
+                return;
+            
+            m_dfgData = adoptPtr(new DFGData);
+        }
+        
+        DFG::OSREntryData* appendDFGOSREntryData(unsigned bytecodeIndex, unsigned machineCodeOffset)
+        {
+            createDFGDataIfNecessary();
+            DFG::OSREntryData entry;
+            entry.m_bytecodeIndex = bytecodeIndex;
+            entry.m_machineCodeOffset = machineCodeOffset;
+            m_dfgData->osrEntry.append(entry);
+            return &m_dfgData->osrEntry.last();
+        }
+        unsigned numberOfDFGOSREntries() const
+        {
+            if (!m_dfgData)
+                return 0;
+            return m_dfgData->osrEntry.size();
+        }
+        DFG::OSREntryData* dfgOSREntryData(unsigned i) { return &m_dfgData->osrEntry[i]; }
+        DFG::OSREntryData* dfgOSREntryDataForBytecodeIndex(unsigned bytecodeIndex)
+        {
+            return binarySearch<DFG::OSREntryData, unsigned, DFG::getOSREntryDataBytecodeIndex>(m_dfgData->osrEntry.begin(), m_dfgData->osrEntry.size(), bytecodeIndex);
+        }
+        
+        void appendOSRExit(const DFG::OSRExit& osrExit)
+        {
+            createDFGDataIfNecessary();
+            m_dfgData->osrExit.append(osrExit);
+        }
+        
+        DFG::OSRExit& lastOSRExit()
+        {
+            return m_dfgData->osrExit.last();
+        }
+        
+        void appendSpeculationRecovery(const DFG::SpeculationRecovery& recovery)
+        {
+            createDFGDataIfNecessary();
+            m_dfgData->speculationRecovery.append(recovery);
+        }
+        
+        unsigned numberOfOSRExits()
+        {
+            if (!m_dfgData)
+                return 0;
+            return m_dfgData->osrExit.size();
+        }
+        
+        unsigned numberOfSpeculationRecoveries()
+        {
+            if (!m_dfgData)
+                return 0;
+            return m_dfgData->speculationRecovery.size();
+        }
+        
+        DFG::OSRExit& osrExit(unsigned index)
+        {
+            return m_dfgData->osrExit[index];
+        }
+        
+        DFG::SpeculationRecovery& speculationRecovery(unsigned index)
+        {
+            return m_dfgData->speculationRecovery[index];
+        }
+        
+        void appendWeakReference(JSCell* target)
+        {
+            createDFGDataIfNecessary();
+            m_dfgData->weakReferences.append(WriteBarrier<JSCell>(*globalData(), ownerExecutable(), target));
+        }
+        
+        void shrinkWeakReferencesToFit()
+        {
+            if (!m_dfgData)
+                return;
+            m_dfgData->weakReferences.shrinkToFit();
+        }
+        
+        void appendWeakReferenceTransition(JSCell* codeOrigin, JSCell* from, JSCell* to)
+        {
+            createDFGDataIfNecessary();
+            m_dfgData->transitions.append(
+                WeakReferenceTransition(*globalData(), ownerExecutable(), codeOrigin, from, to));
+        }
+        
+        void shrinkWeakReferenceTransitionsToFit()
+        {
+            if (!m_dfgData)
+                return;
+            m_dfgData->transitions.shrinkToFit();
+        }
 #endif
 
 #endif
 
-#if ENABLE(INTERPRETER)
         unsigned bytecodeOffset(Instruction* returnAddress)
         {
         unsigned bytecodeOffset(Instruction* returnAddress)
         {
+            ASSERT(returnAddress >= instructions().begin() && returnAddress < instructions().end());
             return static_cast<Instruction*>(returnAddress) - instructions().begin();
         }
             return static_cast<Instruction*>(returnAddress) - instructions().begin();
         }
-#endif
 
         void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
         bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
 
 
         void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
         bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
 
-        Vector<Instruction>& instructions() { return m_instructions; }
-        void discardBytecode() { m_instructions.clear(); }
+        unsigned numberOfInstructions() const { return m_instructions.size(); }
+        RefCountedArray<Instruction>& instructions() { return m_instructions; }
+        const RefCountedArray<Instruction>& instructions() const { return m_instructions; }
+        
+        size_t predictedMachineCodeSize();
+        
+        bool usesOpcode(OpcodeID);
 
 
-#ifndef NDEBUG
-        unsigned instructionCount() { return m_instructionCount; }
-        void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; }
-#endif
+        unsigned instructionCount() { return m_instructions.size(); }
 
 #if ENABLE(JIT)
 
 #if ENABLE(JIT)
-        JITCode& getJITCode() { return m_isConstructor ? ownerExecutable()->generatedJITCodeForConstruct() : ownerExecutable()->generatedJITCodeForCall(); }
-        ExecutablePool* executablePool() { return getJITCode().getExecutablePool(); }
+        void setJITCode(const JITCode& code, MacroAssemblerCodePtr codeWithArityCheck)
+        {
+            m_jitCode = code;
+            m_jitCodeWithArityCheck = codeWithArityCheck;
+#if ENABLE(DFG_JIT)
+            if (m_jitCode.jitType() == JITCode::DFGJIT) {
+                createDFGDataIfNecessary();
+                m_globalData->heap.m_dfgCodeBlocks.m_set.add(this);
+            }
+#endif
+        }
+        JITCode& getJITCode() { return m_jitCode; }
+        MacroAssemblerCodePtr getJITCodeWithArityCheck() { return m_jitCodeWithArityCheck; }
+        JITCode::JITType getJITType() { return m_jitCode.jitType(); }
+        ExecutableMemoryHandle* executableMemory() { return getJITCode().getExecutableMemory(); }
+        virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0;
+        virtual void jettison() = 0;
+        enum JITCompilationResult { AlreadyCompiled, CouldNotCompile, CompiledSuccessfully };
+        JITCompilationResult jitCompile(JSGlobalData& globalData)
+        {
+            if (getJITType() != JITCode::InterpreterThunk) {
+                ASSERT(getJITType() == JITCode::BaselineJIT);
+                return AlreadyCompiled;
+            }
+#if ENABLE(JIT)
+            if (jitCompileImpl(globalData))
+                return CompiledSuccessfully;
+            return CouldNotCompile;
+#else
+            UNUSED_PARAM(globalData);
+            return CouldNotCompile;
+#endif
+        }
+        virtual CodeBlock* replacement() = 0;
+
+        enum CompileWithDFGState {
+            CompileWithDFGFalse,
+            CompileWithDFGTrue,
+            CompileWithDFGUnset
+        };
+
+        virtual bool canCompileWithDFGInternal() = 0;
+        bool canCompileWithDFG()
+        {
+            bool result = canCompileWithDFGInternal();
+            m_canCompileWithDFGState = result ? CompileWithDFGTrue : CompileWithDFGFalse;
+            return result;
+        }
+        CompileWithDFGState canCompileWithDFGState() { return m_canCompileWithDFGState; }
+
+        bool hasOptimizedReplacement()
+        {
+            ASSERT(JITCode::isBaselineCode(getJITType()));
+            bool result = replacement()->getJITType() > getJITType();
+#if !ASSERT_DISABLED
+            if (result)
+                ASSERT(replacement()->getJITType() == JITCode::DFGJIT);
+            else {
+                ASSERT(JITCode::isBaselineCode(replacement()->getJITType()));
+                ASSERT(replacement() == this);
+            }
+#endif
+            return result;
+        }
+#else
+        JITCode::JITType getJITType() { return JITCode::BaselineJIT; }
 #endif
 
         ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
 
         void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
 #endif
 
         ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
 
         void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
+        JSGlobalData* globalData() { return m_globalData; }
 
         void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
         int thisRegister() const { return m_thisRegister; }
 
         void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
         int thisRegister() const { return m_thisRegister; }
@@ -354,43 +468,168 @@ namespace JSC {
 
         void clearEvalCache();
 
 
         void clearEvalCache();
 
-#if ENABLE(INTERPRETER)
         void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
         {
         void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
         {
-            if (!m_globalData->canUseJIT())
-                m_propertyAccessInstructions.append(propertyAccessInstruction);
+            m_propertyAccessInstructions.append(propertyAccessInstruction);
         }
         void addGlobalResolveInstruction(unsigned globalResolveInstruction)
         {
         }
         void addGlobalResolveInstruction(unsigned globalResolveInstruction)
         {
-            if (!m_globalData->canUseJIT())
-                m_globalResolveInstructions.append(globalResolveInstruction);
+            m_globalResolveInstructions.append(globalResolveInstruction);
         }
         bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset);
         }
         bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset);
+#if ENABLE(LLINT)
+        LLIntCallLinkInfo* addLLIntCallLinkInfo()
+        {
+            m_llintCallLinkInfos.append(LLIntCallLinkInfo());
+            return &m_llintCallLinkInfos.last();
+        }
 #endif
 #if ENABLE(JIT)
 #endif
 #if ENABLE(JIT)
+        void setNumberOfStructureStubInfos(size_t size) { m_structureStubInfos.grow(size); }
         size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); }
         size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); }
-        void addStructureStubInfo(const StructureStubInfo& stubInfo)
-        {
-            if (m_globalData->canUseJIT())
-                m_structureStubInfos.append(stubInfo);
-        }
         StructureStubInfo& structureStubInfo(int index) { return m_structureStubInfos[index]; }
 
         void addGlobalResolveInfo(unsigned globalResolveInstruction)
         {
         StructureStubInfo& structureStubInfo(int index) { return m_structureStubInfos[index]; }
 
         void addGlobalResolveInfo(unsigned globalResolveInstruction)
         {
-            if (m_globalData->canUseJIT())
-                m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction));
+            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);
 
+        void setNumberOfCallLinkInfos(size_t size) { m_callLinkInfos.grow(size); }
         size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }
         size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }
-        void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); }
         CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
 
         void addMethodCallLinkInfos(unsigned n) { ASSERT(m_globalData->canUseJIT()); m_methodCallLinkInfos.grow(n); }
         MethodCallLinkInfo& methodCallLinkInfo(int index) { return m_methodCallLinkInfos[index]; }
         CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
 
         void addMethodCallLinkInfos(unsigned n) { ASSERT(m_globalData->canUseJIT()); m_methodCallLinkInfos.grow(n); }
         MethodCallLinkInfo& methodCallLinkInfo(int index) { return m_methodCallLinkInfos[index]; }
+        size_t numberOfMethodCallLinkInfos() { return m_methodCallLinkInfos.size(); }
+#endif
+        
+#if ENABLE(VALUE_PROFILER)
+        unsigned numberOfArgumentValueProfiles()
+        {
+            ASSERT(m_numParameters >= 0);
+            ASSERT(m_argumentValueProfiles.size() == static_cast<unsigned>(m_numParameters));
+            return m_argumentValueProfiles.size();
+        }
+        ValueProfile* valueProfileForArgument(unsigned argumentIndex)
+        {
+            ValueProfile* result = &m_argumentValueProfiles[argumentIndex];
+            ASSERT(result->m_bytecodeOffset == -1);
+            return result;
+        }
+        
+        ValueProfile* addValueProfile(int bytecodeOffset)
+        {
+            ASSERT(bytecodeOffset != -1);
+            ASSERT(m_valueProfiles.isEmpty() || m_valueProfiles.last().m_bytecodeOffset < bytecodeOffset);
+            m_valueProfiles.append(ValueProfile(bytecodeOffset));
+            return &m_valueProfiles.last();
+        }
+        unsigned numberOfValueProfiles() { return m_valueProfiles.size(); }
+        ValueProfile* valueProfile(int index)
+        {
+            ValueProfile* result = &m_valueProfiles[index];
+            ASSERT(result->m_bytecodeOffset != -1);
+            return result;
+        }
+        ValueProfile* valueProfileForBytecodeOffset(int bytecodeOffset)
+        {
+            ValueProfile* result = WTF::genericBinarySearch<ValueProfile, int, getValueProfileBytecodeOffset>(m_valueProfiles, m_valueProfiles.size(), bytecodeOffset);
+            ASSERT(result->m_bytecodeOffset != -1);
+            ASSERT(instructions()[bytecodeOffset + opcodeLength(
+                       m_globalData->interpreter->getOpcodeID(
+                           instructions()[
+                               bytecodeOffset].u.opcode)) - 1].u.profile == result);
+            return result;
+        }
+        PredictedType valueProfilePredictionForBytecodeOffset(int bytecodeOffset)
+        {
+            return valueProfileForBytecodeOffset(bytecodeOffset)->computeUpdatedPrediction();
+        }
+        
+        unsigned totalNumberOfValueProfiles()
+        {
+            return numberOfArgumentValueProfiles() + numberOfValueProfiles();
+        }
+        ValueProfile* getFromAllValueProfiles(unsigned index)
+        {
+            if (index < numberOfArgumentValueProfiles())
+                return valueProfileForArgument(index);
+            return valueProfile(index - numberOfArgumentValueProfiles());
+        }
+        
+        RareCaseProfile* addRareCaseProfile(int bytecodeOffset)
+        {
+            m_rareCaseProfiles.append(RareCaseProfile(bytecodeOffset));
+            return &m_rareCaseProfiles.last();
+        }
+        unsigned numberOfRareCaseProfiles() { return m_rareCaseProfiles.size(); }
+        RareCaseProfile* rareCaseProfile(int index) { return &m_rareCaseProfiles[index]; }
+        RareCaseProfile* rareCaseProfileForBytecodeOffset(int bytecodeOffset)
+        {
+            return WTF::genericBinarySearch<RareCaseProfile, int, getRareCaseProfileBytecodeOffset>(m_rareCaseProfiles, m_rareCaseProfiles.size(), bytecodeOffset);
+        }
+        
+        bool likelyToTakeSlowCase(int bytecodeOffset)
+        {
+            if (!numberOfRareCaseProfiles())
+                return false;
+            unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+            return value >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold;
+        }
+        
+        bool couldTakeSlowCase(int bytecodeOffset)
+        {
+            if (!numberOfRareCaseProfiles())
+                return false;
+            unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+            return value >= Options::couldTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::couldTakeSlowCaseThreshold;
+        }
+        
+        RareCaseProfile* addSpecialFastCaseProfile(int bytecodeOffset)
+        {
+            m_specialFastCaseProfiles.append(RareCaseProfile(bytecodeOffset));
+            return &m_specialFastCaseProfiles.last();
+        }
+        unsigned numberOfSpecialFastCaseProfiles() { return m_specialFastCaseProfiles.size(); }
+        RareCaseProfile* specialFastCaseProfile(int index) { return &m_specialFastCaseProfiles[index]; }
+        RareCaseProfile* specialFastCaseProfileForBytecodeOffset(int bytecodeOffset)
+        {
+            return WTF::genericBinarySearch<RareCaseProfile, int, getRareCaseProfileBytecodeOffset>(m_specialFastCaseProfiles, m_specialFastCaseProfiles.size(), bytecodeOffset);
+        }
+        
+        bool likelyToTakeSpecialFastCase(int bytecodeOffset)
+        {
+            if (!numberOfRareCaseProfiles())
+                return false;
+            unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+            return specialFastCaseCount >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(specialFastCaseCount) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold;
+        }
+        
+        bool likelyToTakeDeepestSlowCase(int bytecodeOffset)
+        {
+            if (!numberOfRareCaseProfiles())
+                return false;
+            unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+            unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+            unsigned value = slowCaseCount - specialFastCaseCount;
+            return value >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold;
+        }
+        
+        bool likelyToTakeAnySlowCase(int bytecodeOffset)
+        {
+            if (!numberOfRareCaseProfiles())
+                return false;
+            unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+            unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
+            unsigned value = slowCaseCount + specialFastCaseCount;
+            return value >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold;
+        }
+        
+        unsigned executionEntryCount() const { return m_executionEntryCount; }
 #endif
 #endif
+
         unsigned globalResolveInfoCount() const
         {
 #if ENABLE(JIT)    
         unsigned globalResolveInfoCount() const
         {
 #if ENABLE(JIT)    
@@ -440,6 +679,57 @@ namespace JSC {
         }
 #endif
 
         }
 #endif
 
+#if ENABLE(DFG_JIT)
+        SegmentedVector<InlineCallFrame, 4>& inlineCallFrames()
+        {
+            createRareDataIfNecessary();
+            return m_rareData->m_inlineCallFrames;
+        }
+        
+        Vector<CodeOriginAtCallReturnOffset>& codeOrigins()
+        {
+            createRareDataIfNecessary();
+            return m_rareData->m_codeOrigins;
+        }
+        
+        // Having code origins implies that there has been some inlining.
+        bool hasCodeOrigins()
+        {
+            return m_rareData && !!m_rareData->m_codeOrigins.size();
+        }
+        
+        bool codeOriginForReturn(ReturnAddressPtr returnAddress, CodeOrigin& codeOrigin)
+        {
+            if (!hasCodeOrigins())
+                return false;
+            unsigned offset = getJITCode().offsetOf(returnAddress.value());
+            CodeOriginAtCallReturnOffset* entry = binarySearch<CodeOriginAtCallReturnOffset, unsigned, getCallReturnOffsetForCodeOrigin>(codeOrigins().begin(), codeOrigins().size(), offset, WTF::KeyMustNotBePresentInArray);
+            if (entry->callReturnOffset != offset)
+                return false;
+            codeOrigin = entry->codeOrigin;
+            return true;
+        }
+        
+        CodeOrigin codeOrigin(unsigned index)
+        {
+            ASSERT(m_rareData);
+            return m_rareData->m_codeOrigins[index].codeOrigin;
+        }
+        
+        bool addFrequentExitSite(const DFG::FrequentExitSite& site)
+        {
+            ASSERT(JITCode::isBaselineCode(getJITType()));
+            return m_exitProfile.add(site);
+        }
+
+        DFG::ExitProfile& exitProfile() { return m_exitProfile; }
+        
+        CompressedLazyOperandValueProfileHolder& lazyOperandValueProfiles()
+        {
+            return m_lazyOperandValueProfiles;
+        }
+#endif
+
         // Constant Pool
 
         size_t numberOfIdentifiers() const { return m_identifiers.size(); }
         // Constant Pool
 
         size_t numberOfIdentifiers() const { return m_identifiers.size(); }
@@ -447,11 +737,14 @@ 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 addConstant(JSValue v)
+        unsigned addConstant(JSValue v)
         {
         {
+            unsigned result = m_constantRegisters.size();
             m_constantRegisters.append(WriteBarrier<Unknown>());
             m_constantRegisters.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), v);
             m_constantRegisters.append(WriteBarrier<Unknown>());
             m_constantRegisters.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), v);
+            return result;
         }
         }
+        unsigned addOrFindConstant(JSValue);
         WriteBarrier<Unknown>& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
         ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
         ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
         WriteBarrier<Unknown>& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
         ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
         ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
@@ -481,6 +774,12 @@ namespace JSC {
             m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_globalData, ownerExecutable(), r));
             return size;
         }
             m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_globalData, ownerExecutable(), r));
             return size;
         }
+        unsigned numberOfRegExps() const
+        {
+            if (!m_rareData)
+                return 0;
+            return m_rareData->m_regexps.size();
+        }
         RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
 
         unsigned addConstantBuffer(unsigned length)
         RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
 
         unsigned addConstantBuffer(unsigned length)
@@ -498,6 +797,14 @@ namespace JSC {
         }
 
         JSGlobalObject* globalObject() { return m_globalObject.get(); }
         }
 
         JSGlobalObject* globalObject() { return m_globalObject.get(); }
+        
+        JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin)
+        {
+            if (!codeOrigin.inlineCallFrame)
+                return globalObject();
+            // FIXME: if we ever inline based on executable not function, this code will need to change.
+            return codeOrigin.inlineCallFrame->callee->scope()->globalObject.get();
+        }
 
         // Jump Tables
 
 
         // Jump Tables
 
@@ -520,17 +827,263 @@ namespace JSC {
         EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }
 
         void shrinkToFit();
         EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }
 
         void shrinkToFit();
+        
+        void copyPostParseDataFrom(CodeBlock* alternative);
+        void copyPostParseDataFromAlternative();
+        
+        // Functions for controlling when JITting kicks in, in a mixed mode
+        // execution world.
+        
+        bool checkIfJITThresholdReached()
+        {
+            return m_llintExecuteCounter.checkIfThresholdCrossedAndSet(this);
+        }
+        
+        void dontJITAnytimeSoon()
+        {
+            m_llintExecuteCounter.deferIndefinitely();
+        }
+        
+        void jitAfterWarmUp()
+        {
+            m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITAfterWarmUp, this);
+        }
+        
+        void jitSoon()
+        {
+            m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITSoon, this);
+        }
+        
+        int32_t llintExecuteCounter() const
+        {
+            return m_llintExecuteCounter.m_counter;
+        }
+        
+        // Functions for controlling when tiered compilation kicks in. This
+        // controls both when the optimizing compiler is invoked and when OSR
+        // entry happens. Two triggers exist: the loop trigger and the return
+        // trigger. In either case, when an addition to m_jitExecuteCounter
+        // causes it to become non-negative, the optimizing compiler is
+        // invoked. This includes a fast check to see if this CodeBlock has
+        // already been optimized (i.e. replacement() returns a CodeBlock
+        // that was optimized with a higher tier JIT than this one). In the
+        // case of the loop trigger, if the optimized compilation succeeds
+        // (or has already succeeded in the past) then OSR is attempted to
+        // redirect program flow into the optimized code.
+        
+        // These functions are called from within the optimization triggers,
+        // and are used as a single point at which we define the heuristics
+        // for how much warm-up is mandated before the next optimization
+        // trigger files. All CodeBlocks start out with optimizeAfterWarmUp(),
+        // as this is called from the CodeBlock constructor.
+        
+        // When we observe a lot of speculation failures, we trigger a
+        // reoptimization. But each time, we increase the optimization trigger
+        // to avoid thrashing.
+        unsigned reoptimizationRetryCounter() const
+        {
+            ASSERT(m_reoptimizationRetryCounter <= Options::reoptimizationRetryCounterMax);
+            return m_reoptimizationRetryCounter;
+        }
+        
+        void countReoptimization()
+        {
+            m_reoptimizationRetryCounter++;
+            if (m_reoptimizationRetryCounter > Options::reoptimizationRetryCounterMax)
+                m_reoptimizationRetryCounter = Options::reoptimizationRetryCounterMax;
+        }
+        
+        int32_t counterValueForOptimizeAfterWarmUp()
+        {
+            return Options::thresholdForOptimizeAfterWarmUp << reoptimizationRetryCounter();
+        }
+        
+        int32_t counterValueForOptimizeAfterLongWarmUp()
+        {
+            return Options::thresholdForOptimizeAfterLongWarmUp << reoptimizationRetryCounter();
+        }
+        
+        int32_t* addressOfJITExecuteCounter()
+        {
+            return &m_jitExecuteCounter.m_counter;
+        }
+        
+        static ptrdiff_t offsetOfJITExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(ExecutionCounter, m_counter); }
+        static ptrdiff_t offsetOfJITExecutionActiveThreshold() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(ExecutionCounter, m_activeThreshold); }
+        static ptrdiff_t offsetOfJITExecutionTotalCount() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(ExecutionCounter, m_totalCount); }
 
 
+        int32_t jitExecuteCounter() const { return m_jitExecuteCounter.m_counter; }
+        
+        unsigned optimizationDelayCounter() const { return m_optimizationDelayCounter; }
+        
+        // Check if the optimization threshold has been reached, and if not,
+        // adjust the heuristics accordingly. Returns true if the threshold has
+        // been reached.
+        bool checkIfOptimizationThresholdReached()
+        {
+            return m_jitExecuteCounter.checkIfThresholdCrossedAndSet(this);
+        }
+        
+        // Call this to force the next optimization trigger to fire. This is
+        // rarely wise, since optimization triggers are typically more
+        // expensive than executing baseline code.
+        void optimizeNextInvocation()
+        {
+            m_jitExecuteCounter.setNewThreshold(0, this);
+        }
+        
+        // Call this to prevent optimization from happening again. Note that
+        // optimization will still happen after roughly 2^29 invocations,
+        // so this is really meant to delay that as much as possible. This
+        // is called if optimization failed, and we expect it to fail in
+        // the future as well.
+        void dontOptimizeAnytimeSoon()
+        {
+            m_jitExecuteCounter.deferIndefinitely();
+        }
+        
+        // Call this to reinitialize the counter to its starting state,
+        // forcing a warm-up to happen before the next optimization trigger
+        // fires. This is called in the CodeBlock constructor. It also
+        // makes sense to call this if an OSR exit occurred. Note that
+        // OSR exit code is code generated, so the value of the execute
+        // counter that this corresponds to is also available directly.
+        void optimizeAfterWarmUp()
+        {
+            m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeAfterWarmUp(), this);
+        }
+        
+        // Call this to force an optimization trigger to fire only after
+        // a lot of warm-up.
+        void optimizeAfterLongWarmUp()
+        {
+            m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeAfterLongWarmUp(), this);
+        }
+        
+        // Call this to cause an optimization trigger to fire soon, but
+        // not necessarily the next one. This makes sense if optimization
+        // succeeds. Successfuly optimization means that all calls are
+        // relinked to the optimized code, so this only affects call
+        // frames that are still executing this CodeBlock. The value here
+        // is tuned to strike a balance between the cost of OSR entry
+        // (which is too high to warrant making every loop back edge to
+        // trigger OSR immediately) and the cost of executing baseline
+        // code (which is high enough that we don't necessarily want to
+        // have a full warm-up). The intuition for calling this instead of
+        // optimizeNextInvocation() is for the case of recursive functions
+        // with loops. Consider that there may be N call frames of some
+        // recursive function, for a reasonably large value of N. The top
+        // one triggers optimization, and then returns, and then all of
+        // the others return. We don't want optimization to be triggered on
+        // each return, as that would be superfluous. It only makes sense
+        // to trigger optimization if one of those functions becomes hot
+        // in the baseline code.
+        void optimizeSoon()
+        {
+            m_jitExecuteCounter.setNewThreshold(Options::thresholdForOptimizeSoon << reoptimizationRetryCounter(), this);
+        }
+        
+        // The speculative JIT tracks its success rate, so that we can
+        // decide when to reoptimize. It's interesting to note that these
+        // counters may overflow without any protection. The success
+        // counter will overflow before the fail one does, becuase the
+        // fail one is used as a trigger to reoptimize. So the worst case
+        // is that the success counter overflows and we reoptimize without
+        // needing to. But this is harmless. If a method really did
+        // execute 2^32 times then compiling it again probably won't hurt
+        // anyone.
+        
+        void countSpeculationSuccess()
+        {
+            m_speculativeSuccessCounter++;
+        }
+        
+        void countSpeculationFailure()
+        {
+            m_speculativeFailCounter++;
+        }
+        
+        uint32_t speculativeSuccessCounter() const { return m_speculativeSuccessCounter; }
+        uint32_t speculativeFailCounter() const { return m_speculativeFailCounter; }
+        uint32_t forcedOSRExitCounter() const { return m_forcedOSRExitCounter; }
+        
+        uint32_t* addressOfSpeculativeSuccessCounter() { return &m_speculativeSuccessCounter; }
+        uint32_t* addressOfSpeculativeFailCounter() { return &m_speculativeFailCounter; }
+        uint32_t* addressOfForcedOSRExitCounter() { return &m_forcedOSRExitCounter; }
+        
+        static ptrdiff_t offsetOfSpeculativeSuccessCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeSuccessCounter); }
+        static ptrdiff_t offsetOfSpeculativeFailCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeFailCounter); }
+        static ptrdiff_t offsetOfForcedOSRExitCounter() { return OBJECT_OFFSETOF(CodeBlock, m_forcedOSRExitCounter); }
+
+#if ENABLE(JIT)
+        // The number of failures that triggers the use of the ratio.
+        unsigned largeFailCountThreshold() { return Options::largeFailCountThresholdBase << baselineVersion()->reoptimizationRetryCounter(); }
+        unsigned largeFailCountThresholdForLoop() { return Options::largeFailCountThresholdBaseForLoop << baselineVersion()->reoptimizationRetryCounter(); }
+
+        bool shouldReoptimizeNow()
+        {
+            return (Options::desiredSpeculativeSuccessFailRatio *
+                        speculativeFailCounter() >= speculativeSuccessCounter()
+                    && speculativeFailCounter() >= largeFailCountThreshold())
+                || forcedOSRExitCounter() >=
+                       Options::forcedOSRExitCountForReoptimization;
+        }
+
+        bool shouldReoptimizeFromLoopNow()
+        {
+            return (Options::desiredSpeculativeSuccessFailRatio *
+                        speculativeFailCounter() >= speculativeSuccessCounter()
+                    && speculativeFailCounter() >= largeFailCountThresholdForLoop())
+                || forcedOSRExitCounter() >=
+                       Options::forcedOSRExitCountForReoptimization;
+        }
+#endif
+
+#if ENABLE(VALUE_PROFILER)
+        bool shouldOptimizeNow();
+#else
+        bool shouldOptimizeNow() { return false; }
+#endif
+        
+#if ENABLE(JIT)
+        void reoptimize()
+        {
+            ASSERT(replacement() != this);
+            ASSERT(replacement()->alternative() == this);
+            replacement()->tallyFrequentExitSites();
+            replacement()->jettison();
+            countReoptimization();
+            optimizeAfterWarmUp();
+        }
+#endif
+
+#if ENABLE(VERBOSE_VALUE_PROFILE)
+        void dumpValueProfiles();
+#endif
+        
         // FIXME: Make these remaining members private.
 
         int m_numCalleeRegisters;
         int m_numVars;
         int m_numCapturedVars;
         // FIXME: Make these remaining members private.
 
         int m_numCalleeRegisters;
         int m_numVars;
         int m_numCapturedVars;
-        int m_numParameters;
         bool m_isConstructor;
 
         bool m_isConstructor;
 
+    protected:
+#if ENABLE(JIT)
+        virtual bool jitCompileImpl(JSGlobalData&) = 0;
+#endif
+        virtual void visitWeakReferences(SlotVisitor&);
+        virtual void finalizeUnconditionally();
+        
     private:
     private:
-#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
+        friend class DFGCodeBlocks;
+        
+#if ENABLE(DFG_JIT)
+        void tallyFrequentExitSites();
+#else
+        void tallyFrequentExitSites() { }
+#endif
+        
         void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
 
         CString registerName(ExecState*, int r) const;
         void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
 
         CString registerName(ExecState*, int r) const;
@@ -538,23 +1091,49 @@ namespace JSC {
         void printBinaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
         void printConditionalJump(ExecState*, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator&, int location, const char* op) const;
         void printGetByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
         void printBinaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
         void printConditionalJump(ExecState*, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator&, int location, const char* op) const;
         void printGetByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
+        void printCallOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
         void printPutByIdOp(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 visitStructures(SlotVisitor&, Instruction* vPC) const;
         void visitStructures(SlotVisitor&, Instruction* vPC) const;
+        
+#if ENABLE(DFG_JIT)
+        bool shouldImmediatelyAssumeLivenessDuringScan()
+        {
+            // Null m_dfgData means that this is a baseline JIT CodeBlock. Baseline JIT
+            // CodeBlocks don't need to be jettisoned when their weak references go
+            // stale. So if a basline JIT CodeBlock gets scanned, we can assume that
+            // this means that it's live.
+            if (!m_dfgData)
+                return true;
+            
+            // For simplicity, we don't attempt to jettison code blocks during GC if
+            // they are executing. Instead we strongly mark their weak references to
+            // allow them to continue to execute soundly.
+            if (m_dfgData->mayBeExecuting)
+                return true;
+
+            return false;
+        }
+#else
+        bool shouldImmediatelyAssumeLivenessDuringScan() { return true; }
+#endif
+        
+        void performTracingFixpointIteration(SlotVisitor&);
+        
+        void stronglyVisitStrongReferences(SlotVisitor&);
+        void stronglyVisitWeakReferences(SlotVisitor&);
 
         void createRareDataIfNecessary()
         {
             if (!m_rareData)
                 m_rareData = adoptPtr(new RareData);
         }
 
         void createRareDataIfNecessary()
         {
             if (!m_rareData)
                 m_rareData = adoptPtr(new RareData);
         }
+        
+        int m_numParameters;
 
         WriteBarrier<ScriptExecutable> m_ownerExecutable;
         JSGlobalData* m_globalData;
 
 
         WriteBarrier<ScriptExecutable> m_ownerExecutable;
         JSGlobalData* m_globalData;
 
-        Vector<Instruction> m_instructions;
-#ifndef NDEBUG
-        unsigned m_instructionCount;
-#endif
+        RefCountedArray<Instruction> m_instructions;
 
         int m_thisRegister;
         int m_argumentsRegister;
 
         int m_thisRegister;
         int m_argumentsRegister;
@@ -570,18 +1149,77 @@ namespace JSC {
         RefPtr<SourceProvider> m_source;
         unsigned m_sourceOffset;
 
         RefPtr<SourceProvider> m_source;
         unsigned m_sourceOffset;
 
-#if ENABLE(INTERPRETER)
         Vector<unsigned> m_propertyAccessInstructions;
         Vector<unsigned> m_globalResolveInstructions;
         Vector<unsigned> m_propertyAccessInstructions;
         Vector<unsigned> m_globalResolveInstructions;
+#if ENABLE(LLINT)
+        SegmentedVector<LLIntCallLinkInfo, 8> m_llintCallLinkInfos;
+        SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo> > m_incomingLLIntCalls;
 #endif
 #if ENABLE(JIT)
         Vector<StructureStubInfo> m_structureStubInfos;
         Vector<GlobalResolveInfo> m_globalResolveInfos;
         Vector<CallLinkInfo> m_callLinkInfos;
         Vector<MethodCallLinkInfo> m_methodCallLinkInfos;
 #endif
 #if ENABLE(JIT)
         Vector<StructureStubInfo> m_structureStubInfos;
         Vector<GlobalResolveInfo> m_globalResolveInfos;
         Vector<CallLinkInfo> m_callLinkInfos;
         Vector<MethodCallLinkInfo> m_methodCallLinkInfos;
+        JITCode m_jitCode;
+        MacroAssemblerCodePtr m_jitCodeWithArityCheck;
+        SentinelLinkedList<CallLinkInfo, BasicRawSentinelNode<CallLinkInfo> > m_incomingCalls;
+#endif
+#if ENABLE(DFG_JIT) || ENABLE(LLINT)
+        OwnPtr<CompactJITCodeMap> m_jitCodeMap;
+#endif
+#if ENABLE(DFG_JIT)
+        struct WeakReferenceTransition {
+            WeakReferenceTransition() { }
+            
+            WeakReferenceTransition(JSGlobalData& globalData, JSCell* owner, JSCell* codeOrigin, JSCell* from, JSCell* to)
+                : m_from(globalData, owner, from)
+                , m_to(globalData, owner, to)
+            {
+                if (!!codeOrigin)
+                    m_codeOrigin.set(globalData, owner, codeOrigin);
+            }
+
+            WriteBarrier<JSCell> m_codeOrigin;
+            WriteBarrier<JSCell> m_from;
+            WriteBarrier<JSCell> m_to;
+        };
+        
+        struct DFGData {
+            DFGData()
+                : mayBeExecuting(false)
+                , isJettisoned(false)
+            {
+            }
+            
+            Vector<DFG::OSREntryData> osrEntry;
+            SegmentedVector<DFG::OSRExit, 8> osrExit;
+            Vector<DFG::SpeculationRecovery> speculationRecovery;
+            Vector<WeakReferenceTransition> transitions;
+            Vector<WriteBarrier<JSCell> > weakReferences;
+            bool mayBeExecuting;
+            bool isJettisoned;
+            bool livenessHasBeenProved; // Initialized and used on every GC.
+            bool allTransitionsHaveBeenMarked; // Initialized and used on every GC.
+            unsigned visitAggregateHasBeenCalled; // Unsigned to make it work seamlessly with the broadest set of CAS implementations.
+        };
+        
+        OwnPtr<DFGData> m_dfgData;
+        
+        // This is relevant to non-DFG code blocks that serve as the profiled code block
+        // for DFG code blocks.
+        DFG::ExitProfile m_exitProfile;
+        CompressedLazyOperandValueProfileHolder m_lazyOperandValueProfiles;
+#endif
+#if ENABLE(VALUE_PROFILER)
+        Vector<ValueProfile> m_argumentValueProfiles;
+        SegmentedVector<ValueProfile, 8> m_valueProfiles;
+        SegmentedVector<RareCaseProfile, 8> m_rareCaseProfiles;
+        SegmentedVector<RareCaseProfile, 8> m_specialFastCaseProfiles;
+        unsigned m_executionEntryCount;
 #endif
 
         Vector<unsigned> m_jumpTargets;
 #endif
 
         Vector<unsigned> m_jumpTargets;
+        Vector<unsigned> m_loopTargets;
 
         // Constant Pool
         Vector<Identifier> m_identifiers;
 
         // Constant Pool
         Vector<Identifier> m_identifiers;
@@ -592,6 +1230,18 @@ namespace JSC {
 
         SymbolTable* m_symbolTable;
 
 
         SymbolTable* m_symbolTable;
 
+        OwnPtr<CodeBlock> m_alternative;
+        
+        ExecutionCounter m_llintExecuteCounter;
+        
+        ExecutionCounter m_jitExecuteCounter;
+        int32_t m_totalJITExecutions;
+        uint32_t m_speculativeSuccessCounter;
+        uint32_t m_speculativeFailCounter;
+        uint32_t m_forcedOSRExitCounter;
+        uint16_t m_optimizationDelayCounter;
+        uint16_t m_reoptimizationRetryCounter;
+        
         struct RareData {
            WTF_MAKE_FAST_ALLOCATED;
         public:
         struct RareData {
            WTF_MAKE_FAST_ALLOCATED;
         public:
@@ -616,21 +1266,34 @@ namespace JSC {
             Vector<LineInfo> m_lineInfo;
 #if ENABLE(JIT)
             Vector<CallReturnOffsetToBytecodeOffset> m_callReturnIndexVector;
             Vector<LineInfo> m_lineInfo;
 #if ENABLE(JIT)
             Vector<CallReturnOffsetToBytecodeOffset> m_callReturnIndexVector;
+#endif
+#if ENABLE(DFG_JIT)
+            SegmentedVector<InlineCallFrame, 4> m_inlineCallFrames;
+            Vector<CodeOriginAtCallReturnOffset> m_codeOrigins;
 #endif
         };
 #if COMPILER(MSVC)
         friend void WTF::deleteOwnedPtr<RareData>(RareData*);
 #endif
         OwnPtr<RareData> m_rareData;
 #endif
         };
 #if COMPILER(MSVC)
         friend void WTF::deleteOwnedPtr<RareData>(RareData*);
 #endif
         OwnPtr<RareData> m_rareData;
+#if ENABLE(JIT)
+        CompileWithDFGState m_canCompileWithDFGState;
+#endif
     };
 
     // Program code is not marked by any function, so we make the global object
     // responsible for marking it.
 
     class GlobalCodeBlock : public CodeBlock {
     };
 
     // Program code is not marked by any function, so we make the global object
     // responsible for marking it.
 
     class GlobalCodeBlock : public CodeBlock {
-    public:
-        GlobalCodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
-            : CodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, sourceOffset, &m_unsharedSymbolTable, false)
+    protected:
+        GlobalCodeBlock(CopyParsedBlockTag, GlobalCodeBlock& other)
+            : CodeBlock(CopyParsedBlock, other, &m_unsharedSymbolTable)
+            , m_unsharedSymbolTable(other.m_unsharedSymbolTable)
+        {
+        }
+        
+        GlobalCodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, PassOwnPtr<CodeBlock> alternative)
+            : CodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, sourceOffset, &m_unsharedSymbolTable, false, alternative)
         {
         }
 
         {
         }
 
@@ -640,16 +1303,37 @@ namespace JSC {
 
     class ProgramCodeBlock : public GlobalCodeBlock {
     public:
 
     class ProgramCodeBlock : public GlobalCodeBlock {
     public:
-        ProgramCodeBlock(ProgramExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
-            : GlobalCodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, 0)
+        ProgramCodeBlock(CopyParsedBlockTag, ProgramCodeBlock& other)
+            : GlobalCodeBlock(CopyParsedBlock, other)
         {
         }
         {
         }
+
+        ProgramCodeBlock(ProgramExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, PassOwnPtr<CodeBlock> alternative)
+            : GlobalCodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, 0, alternative)
+        {
+        }
+        
+#if ENABLE(JIT)
+    protected:
+        virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
+        virtual void jettison();
+        virtual bool jitCompileImpl(JSGlobalData&);
+        virtual CodeBlock* replacement();
+        virtual bool canCompileWithDFGInternal();
+#endif
     };
 
     class EvalCodeBlock : public GlobalCodeBlock {
     public:
     };
 
     class EvalCodeBlock : public GlobalCodeBlock {
     public:
-        EvalCodeBlock(EvalExecutable* ownerExecutable, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth)
-            : GlobalCodeBlock(ownerExecutable, EvalCode, globalObject, sourceProvider, 0)
+        EvalCodeBlock(CopyParsedBlockTag, EvalCodeBlock& other)
+            : GlobalCodeBlock(CopyParsedBlock, other)
+            , m_baseScopeDepth(other.m_baseScopeDepth)
+            , m_variables(other.m_variables)
+        {
+        }
+        
+        EvalCodeBlock(EvalExecutable* ownerExecutable, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth, PassOwnPtr<CodeBlock> alternative)
+            : GlobalCodeBlock(ownerExecutable, EvalCode, globalObject, sourceProvider, 0, alternative)
             , m_baseScopeDepth(baseScopeDepth)
         {
         }
             , m_baseScopeDepth(baseScopeDepth)
         {
         }
@@ -663,6 +1347,15 @@ namespace JSC {
             ASSERT(m_variables.isEmpty());
             m_variables.swap(variables);
         }
             ASSERT(m_variables.isEmpty());
             m_variables.swap(variables);
         }
+        
+#if ENABLE(JIT)
+    protected:
+        virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
+        virtual void jettison();
+        virtual bool jitCompileImpl(JSGlobalData&);
+        virtual CodeBlock* replacement();
+        virtual bool canCompileWithDFGInternal();
+#endif
 
     private:
         int m_baseScopeDepth;
 
     private:
         int m_baseScopeDepth;
@@ -671,20 +1364,54 @@ namespace JSC {
 
     class FunctionCodeBlock : public CodeBlock {
     public:
 
     class FunctionCodeBlock : public CodeBlock {
     public:
+        FunctionCodeBlock(CopyParsedBlockTag, FunctionCodeBlock& other)
+            : CodeBlock(CopyParsedBlock, other, other.sharedSymbolTable())
+        {
+            // The fact that we have to do this is yucky, but is necessary because of the
+            // class hierarchy issues described in the comment block for the main
+            // constructor, below.
+            sharedSymbolTable()->ref();
+        }
+
         // Rather than using the usual RefCounted::create idiom for SharedSymbolTable we just use new
         // 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.
         // Rather than using the usual RefCounted::create idiom for SharedSymbolTable we just use new
         // 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, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, bool isConstructor)
-            : CodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, sourceOffset, SharedSymbolTable::create().leakRef(), isConstructor)
+        FunctionCodeBlock(FunctionExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, bool isConstructor, PassOwnPtr<CodeBlock> alternative = nullptr)
+            : CodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, sourceOffset, SharedSymbolTable::create().leakRef(), isConstructor, alternative)
         {
         }
         ~FunctionCodeBlock()
         {
             sharedSymbolTable()->deref();
         }
         {
         }
         ~FunctionCodeBlock()
         {
             sharedSymbolTable()->deref();
         }
+        
+#if ENABLE(JIT)
+    protected:
+        virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
+        virtual void jettison();
+        virtual bool jitCompileImpl(JSGlobalData&);
+        virtual CodeBlock* replacement();
+        virtual bool canCompileWithDFGInternal();
+#endif
     };
 
     };
 
+    inline CodeBlock* baselineCodeBlockForInlineCallFrame(InlineCallFrame* inlineCallFrame)
+    {
+        ASSERT(inlineCallFrame);
+        ExecutableBase* executable = inlineCallFrame->executable.get();
+        ASSERT(executable->structure()->classInfo() == &FunctionExecutable::s_info);
+        return static_cast<FunctionExecutable*>(executable)->baselineCodeBlockFor(inlineCallFrame->isCall ? CodeForCall : CodeForConstruct);
+    }
+    
+    inline CodeBlock* baselineCodeBlockForOriginAndBaselineCodeBlock(const CodeOrigin& codeOrigin, CodeBlock* baselineCodeBlock)
+    {
+        if (codeOrigin.inlineCallFrame)
+            return baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame);
+        return baselineCodeBlock;
+    }
+    
+
     inline Register& ExecState::r(int index)
     {
         CodeBlock* codeBlock = this->codeBlock();
     inline Register& ExecState::r(int index)
     {
         CodeBlock* codeBlock = this->codeBlock();
@@ -698,6 +1425,35 @@ namespace JSC {
         ASSERT(index < FirstConstantRegisterIndex);
         return this[index];
     }
         ASSERT(index < FirstConstantRegisterIndex);
         return this[index];
     }
+
+#if ENABLE(DFG_JIT)
+    inline bool ExecState::isInlineCallFrame()
+    {
+        if (LIKELY(!codeBlock() || codeBlock()->getJITType() != JITCode::DFGJIT))
+            return false;
+        return isInlineCallFrameSlow();
+    }
+#endif
+
+#if ENABLE(DFG_JIT)
+    inline void DFGCodeBlocks::mark(void* candidateCodeBlock)
+    {
+        // We have to check for 0 and -1 because those are used by the HashMap as markers.
+        uintptr_t value = reinterpret_cast<uintptr_t>(candidateCodeBlock);
+        
+        // This checks for both of those nasty cases in one go.
+        // 0 + 1 = 1
+        // -1 + 1 = 0
+        if (value + 1 <= 1)
+            return;
+        
+        HashSet<CodeBlock*>::iterator iter = m_set.find(static_cast<CodeBlock*>(candidateCodeBlock));
+        if (iter == m_set.end())
+            return;
+        
+        (*iter)->m_dfgData->mayBeExecuting = true;
+    }
+#endif
     
 } // namespace JSC
 
     
 } // namespace JSC
 
diff --git a/bytecode/CodeOrigin.h b/bytecode/CodeOrigin.h
new file mode 100644 (file)
index 0000000..eda1764
--- /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 CodeOrigin_h
+#define CodeOrigin_h
+
+#include "ValueRecovery.h"
+#include "WriteBarrier.h"
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+struct InlineCallFrame;
+class ExecutableBase;
+class JSFunction;
+
+struct CodeOrigin {
+    // Bytecode offset that you'd use to re-execute this instruction.
+    unsigned bytecodeIndex : 29;
+    // Bytecode offset corresponding to the opcode that gives the result (needed to handle
+    // op_call/op_call_put_result and op_method_check/op_get_by_id).
+    unsigned valueProfileOffset : 3;
+    
+    InlineCallFrame* inlineCallFrame;
+    
+    CodeOrigin()
+        : bytecodeIndex(std::numeric_limits<uint32_t>::max())
+        , valueProfileOffset(0)
+        , inlineCallFrame(0)
+    {
+    }
+    
+    explicit CodeOrigin(unsigned bytecodeIndex, InlineCallFrame* inlineCallFrame = 0, unsigned valueProfileOffset = 0)
+        : bytecodeIndex(bytecodeIndex)
+        , valueProfileOffset(valueProfileOffset)
+        , inlineCallFrame(inlineCallFrame)
+    {
+        ASSERT(bytecodeIndex < (1u << 29));
+        ASSERT(valueProfileOffset < (1u << 3));
+    }
+    
+    bool isSet() const { return bytecodeIndex != std::numeric_limits<uint32_t>::max(); }
+    
+    unsigned bytecodeIndexForValueProfile() const
+    {
+        return bytecodeIndex + valueProfileOffset;
+    }
+    
+    // The inline depth is the depth of the inline stack, so 1 = not inlined,
+    // 2 = inlined one deep, etc.
+    unsigned inlineDepth() const;
+    
+    // If the code origin corresponds to inlined code, gives you the heap object that
+    // would have owned the code if it had not been inlined. Otherwise returns 0.
+    ExecutableBase* codeOriginOwner() const;
+    
+    static unsigned inlineDepthForCallFrame(InlineCallFrame*);
+    
+    bool operator==(const CodeOrigin& other) const;
+    
+    bool operator!=(const CodeOrigin& other) const { return !(*this == other); }
+    
+    // Get the inline stack. This is slow, and is intended for debugging only.
+    Vector<CodeOrigin> inlineStack() const;
+};
+
+struct InlineCallFrame {
+    Vector<ValueRecovery> arguments;
+    WriteBarrier<ExecutableBase> executable;
+    WriteBarrier<JSFunction> callee;
+    CodeOrigin caller;
+    unsigned stackOffset : 31;
+    bool isCall : 1;
+};
+
+struct CodeOriginAtCallReturnOffset {
+    CodeOrigin codeOrigin;
+    unsigned callReturnOffset;
+};
+
+inline unsigned CodeOrigin::inlineDepthForCallFrame(InlineCallFrame* inlineCallFrame)
+{
+    unsigned result = 1;
+    for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame)
+        result++;
+    return result;
+}
+
+inline unsigned CodeOrigin::inlineDepth() const
+{
+    return inlineDepthForCallFrame(inlineCallFrame);
+}
+    
+inline bool CodeOrigin::operator==(const CodeOrigin& other) const
+{
+    return bytecodeIndex == other.bytecodeIndex
+        && inlineCallFrame == other.inlineCallFrame;
+}
+    
+// Get the inline stack. This is slow, and is intended for debugging only.
+inline Vector<CodeOrigin> CodeOrigin::inlineStack() const
+{
+    Vector<CodeOrigin> result(inlineDepth());
+    result.last() = *this;
+    unsigned index = result.size() - 2;
+    for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame)
+        result[index--] = current->caller;
+    return result;
+}
+
+inline unsigned getCallReturnOffsetForCodeOrigin(CodeOriginAtCallReturnOffset* data)
+{
+    return data->callReturnOffset;
+}
+
+inline ExecutableBase* CodeOrigin::codeOriginOwner() const
+{
+    if (!inlineCallFrame)
+        return 0;
+    return inlineCallFrame->executable.get();
+}
+
+} // namespace JSC
+
+#endif // CodeOrigin_h
+
diff --git a/bytecode/CodeType.h b/bytecode/CodeType.h
new file mode 100644 (file)
index 0000000..d33677a
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CodeType_h
+#define CodeType_h
+
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+enum CodeType { GlobalCode, EvalCode, FunctionCode };
+
+inline const char* codeTypeToString(CodeType codeType)
+{
+    switch (codeType) {
+    case GlobalCode:
+        return "GlobalCode";
+    case EvalCode:
+        return "EvalCode";
+    case FunctionCode:
+        return "FunctionCode";
+    default:
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+}
+
+} // namespace JSC
+
+#endif // CodeType_h
+
diff --git a/bytecode/DFGExitProfile.cpp b/bytecode/DFGExitProfile.cpp
new file mode 100644 (file)
index 0000000..69fdc37
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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 "DFGExitProfile.h"
+
+#include <wtf/PassOwnPtr.h>
+
+namespace JSC { namespace DFG {
+
+ExitProfile::ExitProfile() { }
+ExitProfile::~ExitProfile() { }
+
+bool ExitProfile::add(const FrequentExitSite& site)
+{
+    // If we've never seen any frequent exits then create the list and put this site
+    // into it.
+    if (!m_frequentExitSites) {
+        m_frequentExitSites = adoptPtr(new Vector<FrequentExitSite>());
+        m_frequentExitSites->append(site);
+        return true;
+    }
+    
+    // Don't add it if it's already there. This is O(n), but that's OK, because we
+    // know that the total number of places where code exits tends to not be large,
+    // and this code is only used when recompilation is triggered.
+    for (unsigned i = 0; i < m_frequentExitSites->size(); ++i) {
+        if (m_frequentExitSites->at(i) == site)
+            return false;
+    }
+    
+    m_frequentExitSites->append(site);
+    return true;
+}
+
+QueryableExitProfile::QueryableExitProfile(const ExitProfile& profile)
+{
+    if (!profile.m_frequentExitSites)
+        return;
+    
+    for (unsigned i = 0; i < profile.m_frequentExitSites->size(); ++i)
+        m_frequentExitSites.add(profile.m_frequentExitSites->at(i));
+}
+
+QueryableExitProfile::~QueryableExitProfile() { }
+
+} } // namespace JSC::DFG
diff --git a/bytecode/DFGExitProfile.h b/bytecode/DFGExitProfile.h
new file mode 100644 (file)
index 0000000..31db084
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * 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 DFGExitProfile_h
+#define DFGExitProfile_h
+
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace JSC { namespace DFG {
+
+enum ExitKind {
+    ExitKindUnset,
+    BadType, // We exited because a type prediction was wrong.
+    BadCache, // We exited because an inline cache was wrong.
+    Overflow, // We exited because of overflow.
+    NegativeZero, // We exited because we encountered negative zero.
+    InadequateCoverage, // We exited because we ended up in code that didn't have profiling coverage.
+    Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME.
+};
+
+inline const char* exitKindToString(ExitKind kind)
+{
+    switch (kind) {
+    case ExitKindUnset:
+        return "Unset";
+    case BadType:
+        return "BadType";
+    case BadCache:
+        return "BadCache";
+    case Overflow:
+        return "Overflow";
+    case NegativeZero:
+        return "NegativeZero";
+    case InadequateCoverage:
+        return "InadequateCoverage";
+    default:
+        return "Unknown";
+    }
+}
+
+inline bool exitKindIsCountable(ExitKind kind)
+{
+    switch (kind) {
+    case ExitKindUnset:
+        ASSERT_NOT_REACHED();
+    case BadType:
+    case Uncountable:
+        return false;
+    default:
+        return true;
+    }
+}
+
+class FrequentExitSite {
+public:
+    FrequentExitSite()
+        : m_bytecodeOffset(0) // 0 = empty value
+        , m_kind(ExitKindUnset)
+    {
+    }
+    
+    FrequentExitSite(WTF::HashTableDeletedValueType)
+        : m_bytecodeOffset(1) // 1 = deleted value
+        , m_kind(ExitKindUnset)
+    {
+    }
+    
+    explicit FrequentExitSite(unsigned bytecodeOffset, ExitKind kind)
+        : m_bytecodeOffset(bytecodeOffset)
+        , m_kind(kind)
+    {
+        ASSERT(exitKindIsCountable(kind));
+    }
+    
+    bool operator!() const
+    {
+        return m_kind == ExitKindUnset;
+    }
+    
+    bool operator==(const FrequentExitSite& other) const
+    {
+        return m_bytecodeOffset == other.m_bytecodeOffset
+            && m_kind == other.m_kind;
+    }
+    
+    unsigned hash() const
+    {
+        return WTF::intHash(m_bytecodeOffset) + m_kind;
+    }
+    
+    unsigned bytecodeOffset() const { return m_bytecodeOffset; }
+    ExitKind kind() const { return m_kind; }
+
+    bool isHashTableDeletedValue() const
+    {
+        return m_kind == ExitKindUnset && m_bytecodeOffset;
+    }
+
+private:
+    unsigned m_bytecodeOffset;
+    ExitKind m_kind;
+};
+
+struct FrequentExitSiteHash {
+    static unsigned hash(const FrequentExitSite& key) { return key.hash(); }
+    static bool equal(const FrequentExitSite& a, const FrequentExitSite& b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::DFG::FrequentExitSite> {
+    typedef JSC::DFG::FrequentExitSiteHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::DFG::FrequentExitSite> : SimpleClassHashTraits<JSC::DFG::FrequentExitSite> { };
+
+} // namespace WTF
+
+namespace JSC { namespace DFG {
+
+class QueryableExitProfile;
+
+class ExitProfile {
+public:
+    ExitProfile();
+    ~ExitProfile();
+    
+    // Add a new frequent exit site. Return true if this is a new one, or false
+    // if we already knew about it. This is an O(n) operation, because it errs
+    // on the side of keeping the data structure compact. Also, this will only
+    // be called a fixed number of times per recompilation. Recompilation is
+    // rare to begin with, and implies doing O(n) operations on the CodeBlock
+    // anyway.
+    bool add(const FrequentExitSite&);
+    
+private:
+    friend class QueryableExitProfile;
+    
+    OwnPtr<Vector<FrequentExitSite> > m_frequentExitSites;
+};
+
+class QueryableExitProfile {
+public:
+    explicit QueryableExitProfile(const ExitProfile&);
+    ~QueryableExitProfile();
+    
+    bool hasExitSite(const FrequentExitSite& site) const
+    {
+        return m_frequentExitSites.find(site) != m_frequentExitSites.end();
+    }
+    
+    bool hasExitSite(unsigned bytecodeIndex, ExitKind kind) const
+    {
+        return hasExitSite(FrequentExitSite(bytecodeIndex, kind));
+    }
+private:
+    HashSet<FrequentExitSite> m_frequentExitSites;
+};
+
+} } // namespace JSC::DFG
+
+#endif // DFGExitProfile_h
diff --git a/bytecode/DataFormat.h b/bytecode/DataFormat.h
new file mode 100644 (file)
index 0000000..4f01548
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * 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 DataFormat_h
+#define DataFormat_h
+
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+// === 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,
+    DataFormatBoolean = 3,
+    DataFormatCell = 4,
+    DataFormatStorage = 5,
+    DataFormatJS = 8,
+    DataFormatJSInteger = DataFormatJS | DataFormatInteger,
+    DataFormatJSDouble = DataFormatJS | DataFormatDouble,
+    DataFormatJSCell = DataFormatJS | DataFormatCell,
+    DataFormatJSBoolean = DataFormatJS | DataFormatBoolean
+};
+
+inline const char* dataFormatToString(DataFormat dataFormat)
+{
+    switch (dataFormat) {
+    case DataFormatNone:
+        return "None";
+    case DataFormatInteger:
+        return "Integer";
+    case DataFormatDouble:
+        return "Double";
+    case DataFormatCell:
+        return "Cell";
+    case DataFormatBoolean:
+        return "Boolean";
+    case DataFormatStorage:
+        return "Storage";
+    case DataFormatJS:
+        return "JS";
+    case DataFormatJSInteger:
+        return "JSInteger";
+    case DataFormatJSDouble:
+        return "JSDouble";
+    case DataFormatJSCell:
+        return "JSCell";
+    case DataFormatJSBoolean:
+        return "JSBoolean";
+    default:
+        return "Unknown";
+    }
+}
+
+#if USE(JSVALUE64)
+inline bool needDataFormatConversion(DataFormat from, DataFormat to)
+{
+    ASSERT(from != DataFormatNone);
+    ASSERT(to != DataFormatNone);
+    switch (from) {
+    case DataFormatInteger:
+    case DataFormatDouble:
+        return to != from;
+    case DataFormatCell:
+    case DataFormatJS:
+    case DataFormatJSInteger:
+    case DataFormatJSDouble:
+    case DataFormatJSCell:
+    case DataFormatJSBoolean:
+        switch (to) {
+        case DataFormatInteger:
+        case DataFormatDouble:
+            return true;
+        case DataFormatCell:
+        case DataFormatJS:
+        case DataFormatJSInteger:
+        case DataFormatJSDouble:
+        case DataFormatJSCell:
+        case DataFormatJSBoolean:
+            return false;
+        default:
+            // This captures DataFormatBoolean, which is currently unused.
+            ASSERT_NOT_REACHED();
+        }
+    case DataFormatStorage:
+        ASSERT(to == DataFormatStorage);
+        return false;
+    default:
+        // This captures DataFormatBoolean, which is currently unused.
+        ASSERT_NOT_REACHED();
+    }
+    return true;
+}
+
+#elif USE(JSVALUE32_64)
+inline bool needDataFormatConversion(DataFormat from, DataFormat to)
+{
+    ASSERT(from != DataFormatNone);
+    ASSERT(to != DataFormatNone);
+    switch (from) {
+    case DataFormatInteger:
+    case DataFormatCell:
+    case DataFormatBoolean:
+        return ((to & DataFormatJS) || to == DataFormatDouble);
+    case DataFormatDouble:
+    case DataFormatJSDouble:
+        return (to != DataFormatDouble && to != DataFormatJSDouble);
+    case DataFormatJS:
+    case DataFormatJSInteger:
+    case DataFormatJSCell:
+    case DataFormatJSBoolean:
+        return (!(to & DataFormatJS) || to == DataFormatJSDouble);
+    case DataFormatStorage:
+        ASSERT(to == DataFormatStorage);
+        return false;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    return true;
+}
+#endif
+
+inline bool isJSFormat(DataFormat format, DataFormat expectedFormat)
+{
+    ASSERT(expectedFormat & DataFormatJS);
+    return (format | DataFormatJS) == expectedFormat;
+}
+
+inline bool isJSInteger(DataFormat format)
+{
+    return isJSFormat(format, DataFormatJSInteger);
+}
+
+inline bool isJSDouble(DataFormat format)
+{
+    return isJSFormat(format, DataFormatJSDouble);
+}
+
+inline bool isJSCell(DataFormat format)
+{
+    return isJSFormat(format, DataFormatJSCell);
+}
+
+inline bool isJSBoolean(DataFormat format)
+{
+    return isJSFormat(format, DataFormatJSBoolean);
+}
+
+}
+
+#endif // DataFormat_h
index 1e181b9d7c359e9ef21d014c61fbea00670d1700..fba1d32f5ff03886493884186fbe330427d157d4 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class MarkStack;
-    typedef MarkStack SlotVisitor;
+    class SlotVisitor;
 
     class EvalCodeCache {
     public:
 
     class EvalCodeCache {
     public:
-        EvalExecutable* get(ExecState* exec, ScriptExecutable* owner, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
+        EvalExecutable* tryGet(bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain)
         {
         {
-            EvalExecutable* evalExecutable = 0;
-
             if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
             if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
-                evalExecutable = m_cacheMap.get(evalSource.impl()).get();
-
-            if (!evalExecutable) {
-                evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext);
-                exceptionValue = evalExecutable->compile(exec, scopeChain);
-                if (exceptionValue)
-                    return 0;
+                return m_cacheMap.get(evalSource.impl()).get();
+            return 0;
+        }
+        
+        EvalExecutable* getSlow(ExecState* exec, ScriptExecutable* owner, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
+        {
+            EvalExecutable* evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext);
+            exceptionValue = evalExecutable->compile(exec, scopeChain);
+            if (exceptionValue)
+                return 0;
+            
+            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;
+        }
+        
+        EvalExecutable* get(ExecState* exec, ScriptExecutable* owner, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
+        {
+            EvalExecutable* evalExecutable = tryGet(inStrictContext, evalSource, scopeChain);
 
 
-                if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
-                    m_cacheMap.set(evalSource.impl(), WriteBarrier<EvalExecutable>(exec->globalData(), owner, evalExecutable));
-            }
+            if (!evalExecutable)
+                evalExecutable = getSlow(exec, owner, inStrictContext, evalSource, scopeChain, exceptionValue);
 
             return evalExecutable;
         }
 
             return evalExecutable;
         }
diff --git a/bytecode/ExecutionCounter.cpp b/bytecode/ExecutionCounter.cpp
new file mode 100644 (file)
index 0000000..ea33500
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "ExecutionCounter.h"
+
+#include "CodeBlock.h"
+#include "ExecutableAllocator.h"
+
+namespace JSC {
+
+ExecutionCounter::ExecutionCounter()
+{
+    reset();
+}
+
+bool ExecutionCounter::checkIfThresholdCrossedAndSet(CodeBlock* codeBlock)
+{
+    if (hasCrossedThreshold(codeBlock))
+        return true;
+    
+    if (setThreshold(codeBlock))
+        return true;
+    
+    return false;
+}
+
+void ExecutionCounter::setNewThreshold(int32_t threshold, CodeBlock* codeBlock)
+{
+    reset();
+    m_activeThreshold = threshold;
+    setThreshold(codeBlock);
+}
+
+void ExecutionCounter::deferIndefinitely()
+{
+    m_totalCount = 0;
+    m_activeThreshold = std::numeric_limits<int32_t>::max();
+    m_counter = std::numeric_limits<int32_t>::min();
+}
+
+double ExecutionCounter::applyMemoryUsageHeuristics(int32_t value, CodeBlock* codeBlock)
+{
+#if ENABLE(JIT)
+    double multiplier =
+        ExecutableAllocator::memoryPressureMultiplier(
+            codeBlock->predictedMachineCodeSize());
+#else
+    // This code path will probably not be taken, but if it is, we fake it.
+    double multiplier = 1.0;
+    UNUSED_PARAM(codeBlock);
+#endif
+    ASSERT(multiplier >= 1.0);
+    return multiplier * value;
+}
+
+int32_t ExecutionCounter::applyMemoryUsageHeuristicsAndConvertToInt(
+    int32_t value, CodeBlock* codeBlock)
+{
+    double doubleResult = applyMemoryUsageHeuristics(value, codeBlock);
+    
+    ASSERT(doubleResult >= 0);
+    
+    if (doubleResult > std::numeric_limits<int32_t>::max())
+        return std::numeric_limits<int32_t>::max();
+    
+    return static_cast<int32_t>(doubleResult);
+}
+
+bool ExecutionCounter::hasCrossedThreshold(CodeBlock* codeBlock) const
+{
+    // This checks if the current count rounded up to the threshold we were targeting.
+    // For example, if we are using half of available executable memory and have
+    // m_activeThreshold = 1000, applyMemoryUsageHeuristics(m_activeThreshold) will be
+    // 2000, but we will pretend as if the threshold was crossed if we reach 2000 -
+    // 1000 / 2, or 1500. The reasoning here is that we want to avoid thrashing. If
+    // this method returns false, then the JIT's threshold for when it will again call
+    // into the slow path (which will call this method a second time) will be set
+    // according to the difference between the current count and the target count
+    // according to *current* memory usage. But by the time we call into this again, we
+    // may have JIT'ed more code, and so the target count will increase slightly. This
+    // may lead to a repeating pattern where the target count is slightly incremented,
+    // the JIT immediately matches that increase, calls into the slow path again, and
+    // again the target count is slightly incremented. Instead of having this vicious
+    // cycle, we declare victory a bit early if the difference between the current
+    // total and our target according to memory heuristics is small. Our definition of
+    // small is arbitrarily picked to be half of the original threshold (i.e.
+    // m_activeThreshold).
+    
+    double modifiedThreshold = applyMemoryUsageHeuristics(m_activeThreshold, codeBlock);
+    
+    return static_cast<double>(m_totalCount) + m_counter >=
+         modifiedThreshold - static_cast<double>(m_activeThreshold) / 2;
+}
+
+bool ExecutionCounter::setThreshold(CodeBlock* codeBlock)
+{
+    if (m_activeThreshold == std::numeric_limits<int32_t>::max()) {
+        deferIndefinitely();
+        return false;
+    }
+        
+    ASSERT(!hasCrossedThreshold(codeBlock));
+        
+    // Compute the true total count.
+    double trueTotalCount = static_cast<double>(m_totalCount) + m_counter;
+        
+    // Correct the threshold for current memory usage.
+    double threshold = applyMemoryUsageHeuristics(m_activeThreshold, codeBlock);
+        
+    // Threshold must be non-negative and not NaN.
+    ASSERT(threshold >= 0);
+        
+    // Adjust the threshold according to the number of executions we have already
+    // seen. This shouldn't go negative, but it might, because of round-off errors.
+    threshold -= trueTotalCount;
+        
+    if (threshold <= 0) {
+        m_counter = 0;
+        m_totalCount = trueTotalCount;
+        return true;
+    }
+
+    if (threshold > std::numeric_limits<int32_t>::max())
+        threshold = std::numeric_limits<int32_t>::max();
+        
+    m_counter = static_cast<int32_t>(-threshold);
+        
+    m_totalCount = trueTotalCount + threshold;
+        
+    return false;
+}
+
+void ExecutionCounter::reset()
+{
+    m_counter = 0;
+    m_totalCount = 0;
+    m_activeThreshold = 0;
+}
+
+} // namespace JSC
+
diff --git a/bytecode/ExecutionCounter.h b/bytecode/ExecutionCounter.h
new file mode 100644 (file)
index 0000000..d2ffbb6
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef ExecutionCounter_h
+#define ExecutionCounter_h
+
+#include <wtf/SimpleStats.h>
+
+namespace JSC {
+
+class CodeBlock;
+
+class ExecutionCounter {
+public:
+    ExecutionCounter();
+    bool checkIfThresholdCrossedAndSet(CodeBlock*);
+    void setNewThreshold(int32_t threshold, CodeBlock*);
+    void deferIndefinitely();
+    static double applyMemoryUsageHeuristics(int32_t value, CodeBlock*);
+    static int32_t applyMemoryUsageHeuristicsAndConvertToInt(int32_t value, CodeBlock*);
+
+    static int32_t formattedTotalCount(float value)
+    {
+        union {
+            int32_t i;
+            float f;
+        } u;
+        u.f = value;
+        return u.i;
+    }
+    
+private:
+    bool hasCrossedThreshold(CodeBlock*) const;
+    bool setThreshold(CodeBlock*);
+    void reset();
+
+public:
+
+    // NB. These are intentionally public because it will be modified from machine code.
+    
+    // This counter is incremented by the JIT or LLInt. It starts out negative and is
+    // counted up until it becomes non-negative. At the start of a counting period,
+    // the threshold we wish to reach is m_totalCount + m_counter, in the sense that
+    // we will add X to m_totalCount and subtract X from m_counter.
+    int32_t m_counter;
+
+    // Counts the total number of executions we have seen plus the ones we've set a
+    // threshold for in m_counter. Because m_counter's threshold is negative, the
+    // total number of actual executions can always be computed as m_totalCount +
+    // m_counter.
+    float m_totalCount;
+
+    // This is the threshold we were originally targetting, without any correction for
+    // the memory usage heuristics.
+    int32_t m_activeThreshold;
+};
+
+} // namespace JSC
+
+#endif // ExecutionCounter_h
+
diff --git a/bytecode/ExpressionRangeInfo.h b/bytecode/ExpressionRangeInfo.h
new file mode 100644 (file)
index 0000000..f4949a6
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef ExpressionRangeInfo_h
+#define ExpressionRangeInfo_h
+
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+struct ExpressionRangeInfo {
+    enum {
+        MaxOffset = (1 << 7) - 1, 
+        MaxDivot = (1 << 25) - 1
+    };
+    uint32_t instructionOffset : 25;
+    uint32_t divotPoint : 25;
+    uint32_t startOffset : 7;
+    uint32_t endOffset : 7;
+};
+
+} // namespace JSC
+
+#endif // ExpressionRangeInfo_h
+
diff --git a/bytecode/GetByIdStatus.cpp b/bytecode/GetByIdStatus.cpp
new file mode 100644 (file)
index 0000000..11aead3
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "GetByIdStatus.h"
+
+#include "CodeBlock.h"
+#include "LowLevelInterpreter.h"
+
+namespace JSC {
+
+GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
+{
+    UNUSED_PARAM(profiledBlock);
+    UNUSED_PARAM(bytecodeIndex);
+    UNUSED_PARAM(ident);
+#if ENABLE(LLINT)
+    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
+    
+    if (instruction[0].u.opcode == llint_op_method_check)
+        instruction++;
+
+    Structure* structure = instruction[4].u.structure.get();
+    if (!structure)
+        return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+    
+    size_t offset = structure->get(*profiledBlock->globalData(), ident);
+    if (offset == notFound)
+        return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+    
+    return GetByIdStatus(SimpleDirect, StructureSet(structure), offset, false);
+#else
+    return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+#endif
+}
+
+GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
+{
+    UNUSED_PARAM(profiledBlock);
+    UNUSED_PARAM(bytecodeIndex);
+    UNUSED_PARAM(ident);
+#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+    if (!profiledBlock->numberOfStructureStubInfos())
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+    
+    // First check if it makes either calls, in which case we want to be super careful, or
+    // if it's not set at all, in which case we punt.
+    StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
+    if (!stubInfo.seen)
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+    
+    PolymorphicAccessStructureList* list;
+    int listSize;
+    switch (stubInfo.accessType) {
+    case access_get_by_id_self_list:
+        list = stubInfo.u.getByIdSelfList.structureList;
+        listSize = stubInfo.u.getByIdSelfList.listSize;
+        break;
+    case access_get_by_id_proto_list:
+        list = stubInfo.u.getByIdProtoList.structureList;
+        listSize = stubInfo.u.getByIdProtoList.listSize;
+        break;
+    default:
+        list = 0;
+        listSize = 0;
+        break;
+    }
+    for (int i = 0; i < listSize; ++i) {
+        if (!list->list[i].isDirect)
+            return GetByIdStatus(MakesCalls, StructureSet(), notFound, true);
+    }
+    
+    // Next check if it takes slow case, in which case we want to be kind of careful.
+    if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
+        return GetByIdStatus(TakesSlowPath, StructureSet(), notFound, true);
+    
+    // Finally figure out if we can derive an access strategy.
+    GetByIdStatus result;
+    result.m_wasSeenInJIT = true;
+    switch (stubInfo.accessType) {
+    case access_unset:
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+        
+    case access_get_by_id_self: {
+        Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
+        result.m_offset = structure->get(*profiledBlock->globalData(), ident);
+        
+        if (result.m_offset != notFound)
+            result.m_structureSet.add(structure);
+        
+        if (result.m_offset != notFound)
+            ASSERT(result.m_structureSet.size());
+        break;
+    }
+        
+    case access_get_by_id_self_list: {
+        PolymorphicAccessStructureList* list = stubInfo.u.getByIdProtoList.structureList;
+        unsigned size = stubInfo.u.getByIdProtoList.listSize;
+        for (unsigned i = 0; i < size; ++i) {
+            ASSERT(list->list[i].isDirect);
+            
+            Structure* structure = list->list[i].base.get();
+            if (result.m_structureSet.contains(structure))
+                continue;
+            
+            size_t myOffset = structure->get(*profiledBlock->globalData(), ident);
+            
+            if (myOffset == notFound) {
+                result.m_offset = notFound;
+                break;
+            }
+                    
+            if (!i)
+                result.m_offset = myOffset;
+            else if (result.m_offset != myOffset) {
+                result.m_offset = notFound;
+                break;
+            }
+                    
+            result.m_structureSet.add(structure);
+        }
+                    
+        if (result.m_offset != notFound)
+            ASSERT(result.m_structureSet.size());
+        break;
+    }
+        
+    default:
+        ASSERT(result.m_offset == notFound);
+        break;
+    }
+    
+    if (result.m_offset == notFound) {
+        result.m_state = TakesSlowPath;
+        result.m_structureSet.clear();
+    } else
+        result.m_state = SimpleDirect;
+    
+    return result;
+#else // ENABLE(JIT)
+    return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
+#endif // ENABLE(JIT)
+}
+
+} // namespace JSC
+
diff --git a/bytecode/GetByIdStatus.h b/bytecode/GetByIdStatus.h
new file mode 100644 (file)
index 0000000..39476c0
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef GetByIdStatus_h
+#define GetByIdStatus_h
+
+#include "StructureSet.h"
+#include <wtf/NotFound.h>
+
+namespace JSC {
+
+class CodeBlock;
+class Identifier;
+
+class GetByIdStatus {
+public:
+    enum State {
+        NoInformation,  // It's uncached so we have no information.
+        SimpleDirect,   // It's cached for a direct access to a known object property.
+        TakesSlowPath,  // It's known to often take slow path.
+        MakesCalls      // It's known to take paths that make calls.
+    };
+
+    GetByIdStatus()
+        : m_state(NoInformation)
+        , m_offset(notFound)
+    {
+    }
+    
+    GetByIdStatus(State state, const StructureSet& structureSet, size_t offset, bool wasSeenInJIT)
+        : m_state(state)
+        , m_structureSet(structureSet)
+        , m_offset(offset)
+        , m_wasSeenInJIT(wasSeenInJIT)
+    {
+        ASSERT((state == SimpleDirect) == (offset != notFound));
+    }
+    
+    static GetByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&);
+    
+    State state() const { return m_state; }
+    
+    bool isSet() const { return m_state != NoInformation; }
+    bool operator!() const { return !isSet(); }
+    bool isSimpleDirect() const { return m_state == SimpleDirect; }
+    bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
+    bool makesCalls() const { return m_state == MakesCalls; }
+    
+    const StructureSet& structureSet() const { return m_structureSet; }
+    size_t offset() const { return m_offset; }
+    
+    bool wasSeenInJIT() const { return m_wasSeenInJIT; }
+    
+private:
+    static GetByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, Identifier&);
+    
+    State m_state;
+    StructureSet m_structureSet;
+    size_t m_offset;
+    bool m_wasSeenInJIT;
+};
+
+} // namespace JSC
+
+#endif // PropertyAccessStatus_h
+
diff --git a/bytecode/GlobalResolveInfo.h b/bytecode/GlobalResolveInfo.h
new file mode 100644 (file)
index 0000000..5576cfa
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef GlobalResolveInfo_h
+#define GlobalResolveInfo_h
+
+#include "WriteBarrier.h"
+
+namespace JSC {
+
+struct GlobalResolveInfo {
+    GlobalResolveInfo(unsigned bytecodeOffset)
+        : offset(0)
+        , bytecodeOffset(bytecodeOffset)
+    {
+    }
+    
+    WriteBarrier<Structure> structure;
+    unsigned offset;
+    unsigned bytecodeOffset;
+};
+
+} // namespace JSC
+
+#endif // GlobalResolveInfo_h
+
diff --git a/bytecode/HandlerInfo.h b/bytecode/HandlerInfo.h
new file mode 100644 (file)
index 0000000..8396c96
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef HandlerInfo_h
+#define HandlerInfo_h
+
+#include "CodeLocation.h"
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+struct HandlerInfo {
+    uint32_t start;
+    uint32_t end;
+    uint32_t target;
+    uint32_t scopeDepth;
+#if ENABLE(JIT)
+    CodeLocationLabel nativeCode;
+#endif
+};
+
+} // namespace JSC
+
+#endif // HandlerInfo_h
+
index b3bb5b711fe6a8a51ee9a4bbff2c46385964c170..c4989d2db51eb04eb362c6185248b409bc85fbe6 100644 (file)
@@ -44,15 +44,15 @@ namespace JSC {
     // If the JIT is not in use we don't actually need the variable (that said, if the JIT is not in use we don't
     // curently actually use PolymorphicAccessStructureLists, which we should).  Anyway, this seems like the best
     // solution for now - will need to something smarter if/when we actually want mixed-mode operation.
     // If the JIT is not in use we don't actually need the variable (that said, if the JIT is not in use we don't
     // curently actually use PolymorphicAccessStructureLists, which we should).  Anyway, this seems like the best
     // solution for now - will need to something smarter if/when we actually want mixed-mode operation.
-#if ENABLE(JIT)
-    typedef CodeLocationLabel PolymorphicAccessStructureListStubRoutineType;
-#else
-    typedef void* PolymorphicAccessStructureListStubRoutineType;
-#endif
 
     class JSCell;
     class Structure;
     class StructureChain;
 
     class JSCell;
     class Structure;
     class StructureChain;
+    struct LLIntCallLinkInfo;
+    struct ValueProfile;
+
+#if ENABLE(JIT)
+    typedef MacroAssemblerCodeRef PolymorphicAccessStructureListStubRoutineType;
 
     // 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 {
 
     // 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 {
@@ -60,6 +60,7 @@ namespace JSC {
     public:
         struct PolymorphicStubInfo {
             bool isChain;
     public:
         struct PolymorphicStubInfo {
             bool isChain;
+            bool isDirect;
             PolymorphicAccessStructureListStubRoutineType stubRoutine;
             WriteBarrier<Structure> base;
             union {
             PolymorphicAccessStructureListStubRoutineType stubRoutine;
             WriteBarrier<Structure> base;
             union {
@@ -72,47 +73,54 @@ namespace JSC {
                 u.proto.clear();
             }
 
                 u.proto.clear();
             }
 
-            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base)
+            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, bool isDirect)
             {
                 stubRoutine = _stubRoutine;
                 base.set(globalData, owner, _base);
                 u.proto.clear();
                 isChain = false;
             {
                 stubRoutine = _stubRoutine;
                 base.set(globalData, owner, _base);
                 u.proto.clear();
                 isChain = false;
+                this->isDirect = isDirect;
             }
             
             }
             
-            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto)
+            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto, bool isDirect)
             {
                 stubRoutine = _stubRoutine;
                 base.set(globalData, owner, _base);
                 u.proto.set(globalData, owner, _proto);
                 isChain = false;
             {
                 stubRoutine = _stubRoutine;
                 base.set(globalData, owner, _base);
                 u.proto.set(globalData, owner, _proto);
                 isChain = false;
+                this->isDirect = isDirect;
             }
             
             }
             
-            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain)
+            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain, bool isDirect)
             {
                 stubRoutine = _stubRoutine;
                 base.set(globalData, owner, _base);
                 u.chain.set(globalData, owner, _chain);
                 isChain = true;
             {
                 stubRoutine = _stubRoutine;
                 base.set(globalData, owner, _base);
                 u.chain.set(globalData, owner, _chain);
                 isChain = true;
+                this->isDirect = isDirect;
             }
         } list[POLYMORPHIC_LIST_CACHE_SIZE];
         
             }
         } list[POLYMORPHIC_LIST_CACHE_SIZE];
         
-        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase)
+        PolymorphicAccessStructureList()
         {
         {
-            list[0].set(globalData, owner, stubRoutine, firstBase);
+        }
+        
+        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, bool isDirect)
+        {
+            list[0].set(globalData, owner, stubRoutine, firstBase, isDirect);
         }
 
         }
 
-        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto)
+        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto, bool isDirect)
         {
         {
-            list[0].set(globalData, owner, stubRoutine, firstBase, firstProto);
+            list[0].set(globalData, owner, stubRoutine, firstBase, firstProto, isDirect);
         }
 
         }
 
-        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain)
+        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain, bool isDirect)
         {
         {
-            list[0].set(globalData, owner, stubRoutine, firstBase, firstChain);
+            list[0].set(globalData, owner, stubRoutine, firstBase, firstChain, isDirect);
         }
 
         }
 
-        void visitAggregate(SlotVisitor& visitor, int count)
+        bool visitWeak(int count)
         {
             for (int i = 0; i < count; ++i) {
                 PolymorphicStubInfo& info = list[i];
         {
             for (int i = 0; i < count; ++i) {
                 PolymorphicStubInfo& info = list[i];
@@ -122,19 +130,31 @@ namespace JSC {
                     continue;
                 }
                 
                     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);
+                if (!Heap::isMarked(info.base.get()))
+                    return false;
+                if (info.u.proto && !info.isChain
+                    && !Heap::isMarked(info.u.proto.get()))
+                    return false;
+                if (info.u.chain && info.isChain
+                    && !Heap::isMarked(info.u.chain.get()))
+                    return false;
             }
             }
+            
+            return true;
         }
     };
 
         }
     };
 
+#endif
+
     struct Instruction {
     struct Instruction {
+        Instruction()
+        {
+            u.jsCell.clear();
+        }
+        
         Instruction(Opcode opcode)
         {
         Instruction(Opcode opcode)
         {
-#if !ENABLE(COMPUTED_GOTO_INTERPRETER)
+#if !ENABLE(COMPUTED_GOTO_CLASSIC_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.clear();
             // 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.clear();
@@ -165,8 +185,12 @@ namespace JSC {
             u.jsCell.clear();
             u.jsCell.set(globalData, owner, jsCell);
         }
             u.jsCell.clear();
             u.jsCell.set(globalData, owner, jsCell);
         }
-        Instruction(PolymorphicAccessStructureList* polymorphicStructures) { u.polymorphicStructures = polymorphicStructures; }
+
         Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; }
         Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; }
+        
+        Instruction(LLIntCallLinkInfo* callLinkInfo) { u.callLinkInfo = callLinkInfo; }
+        
+        Instruction(ValueProfile* profile) { u.profile = profile; }
 
         union {
             Opcode opcode;
 
         union {
             Opcode opcode;
@@ -174,8 +198,10 @@ namespace JSC {
             WriteBarrierBase<Structure> structure;
             WriteBarrierBase<StructureChain> structureChain;
             WriteBarrierBase<JSCell> jsCell;
             WriteBarrierBase<Structure> structure;
             WriteBarrierBase<StructureChain> structureChain;
             WriteBarrierBase<JSCell> jsCell;
-            PolymorphicAccessStructureList* polymorphicStructures;
             PropertySlot::GetValueFunc getterFunc;
             PropertySlot::GetValueFunc getterFunc;
+            LLIntCallLinkInfo* callLinkInfo;
+            ValueProfile* profile;
+            void* pointer;
         } u;
         
     private:
         } u;
         
     private:
diff --git a/bytecode/LLIntCallLinkInfo.h b/bytecode/LLIntCallLinkInfo.h
new file mode 100644 (file)
index 0000000..bfb9510
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef LLIntCallLinkInfo_h
+#define LLIntCallLinkInfo_h
+
+#include "JSFunction.h"
+#include "MacroAssemblerCodeRef.h"
+#include <wtf/SentinelLinkedList.h>
+
+namespace JSC {
+
+struct Instruction;
+
+struct LLIntCallLinkInfo : public BasicRawSentinelNode<LLIntCallLinkInfo> {
+    LLIntCallLinkInfo()
+    {
+    }
+    
+    ~LLIntCallLinkInfo()
+    {
+        if (isOnList())
+            remove();
+    }
+    
+    bool isLinked() { return callee; }
+    
+    void unlink()
+    {
+        callee.clear();
+        machineCodeTarget = MacroAssemblerCodePtr();
+        if (isOnList())
+            remove();
+    }
+    
+    WriteBarrier<JSFunction> callee;
+    WriteBarrier<JSFunction> lastSeenCallee;
+    MacroAssemblerCodePtr machineCodeTarget;
+};
+
+} // namespace JSC
+
+#endif // LLIntCallLinkInfo_h
+
diff --git a/bytecode/LazyOperandValueProfile.cpp b/bytecode/LazyOperandValueProfile.cpp
new file mode 100644 (file)
index 0000000..f199b69
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "LazyOperandValueProfile.h"
+
+#if ENABLE(VALUE_PROFILER)
+
+namespace JSC {
+
+CompressedLazyOperandValueProfileHolder::CompressedLazyOperandValueProfileHolder() { }
+CompressedLazyOperandValueProfileHolder::~CompressedLazyOperandValueProfileHolder() { }
+
+void CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions()
+{
+    if (!m_data)
+        return;
+    
+    for (unsigned i = 0; i < m_data->size(); ++i)
+        m_data->at(i).computeUpdatedPrediction();
+}
+
+LazyOperandValueProfile* CompressedLazyOperandValueProfileHolder::add(
+    const LazyOperandValueProfileKey& key)
+{
+    if (!m_data)
+        m_data = adoptPtr(new LazyOperandValueProfile::List());
+    else {
+        for (unsigned i = 0; i < m_data->size(); ++i) {
+            if (m_data->at(i).key() == key)
+                return &m_data->at(i);
+        }
+    }
+    
+    m_data->append(LazyOperandValueProfile(key));
+    return &m_data->last();
+}
+
+LazyOperandValueProfileParser::LazyOperandValueProfileParser(
+    CompressedLazyOperandValueProfileHolder& holder)
+    : m_holder(holder)
+{
+    if (!m_holder.m_data)
+        return;
+    
+    LazyOperandValueProfile::List& data = *m_holder.m_data;
+    for (unsigned i = 0; i < data.size(); ++i)
+        m_map.add(data[i].key(), &data[i]);
+}
+
+LazyOperandValueProfileParser::~LazyOperandValueProfileParser() { }
+
+LazyOperandValueProfile* LazyOperandValueProfileParser::getIfPresent(
+    const LazyOperandValueProfileKey& key) const
+{
+    HashMap<LazyOperandValueProfileKey, LazyOperandValueProfile*>::const_iterator iter =
+        m_map.find(key);
+    
+    if (iter == m_map.end())
+        return 0;
+    
+    return iter->second;
+}
+
+PredictedType LazyOperandValueProfileParser::prediction(
+    const LazyOperandValueProfileKey& key) const
+{
+    LazyOperandValueProfile* profile = getIfPresent(key);
+    if (!profile)
+        return PredictNone;
+    
+    return profile->computeUpdatedPrediction();
+}
+
+} // namespace JSC
+
+#endif // ENABLE(VALUE_PROFILER)
+
diff --git a/bytecode/LazyOperandValueProfile.h b/bytecode/LazyOperandValueProfile.h
new file mode 100644 (file)
index 0000000..d0260f9
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef LazyOperandValueProfile_h
+#define LazyOperandValueProfile_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(VALUE_PROFILER)
+
+#include "ValueProfile.h"
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/SegmentedVector.h>
+
+namespace JSC {
+
+class ScriptExecutable;
+
+class LazyOperandValueProfileKey {
+public:
+    LazyOperandValueProfileKey()
+        : m_bytecodeOffset(0) // 0 = empty value
+        , m_operand(-1) // not a valid operand index in our current scheme
+    {
+    }
+    
+    LazyOperandValueProfileKey(WTF::HashTableDeletedValueType)
+        : m_bytecodeOffset(1) // 1 = deleted value
+        , m_operand(-1) // not a valid operand index in our current scheme
+    {
+    }
+    
+    LazyOperandValueProfileKey(unsigned bytecodeOffset, int operand)
+        : m_bytecodeOffset(bytecodeOffset)
+        , m_operand(operand)
+    {
+        ASSERT(operand != -1);
+    }
+    
+    bool operator!() const
+    {
+        return m_operand == -1;
+    }
+    
+    bool operator==(const LazyOperandValueProfileKey& other) const
+    {
+        return m_bytecodeOffset == other.m_bytecodeOffset
+            && m_operand == other.m_operand;
+    }
+    
+    unsigned hash() const
+    {
+        return WTF::intHash(m_bytecodeOffset) + m_operand;
+    }
+    
+    unsigned bytecodeOffset() const
+    {
+        ASSERT(!!*this);
+        return m_bytecodeOffset;
+    }
+    int operand() const
+    {
+        ASSERT(!!*this);
+        return m_operand;
+    }
+    
+    bool isHashTableDeletedValue() const
+    {
+        return m_operand == -1 && m_bytecodeOffset;
+    }
+private: 
+    unsigned m_bytecodeOffset;
+    int m_operand;
+};
+
+struct LazyOperandValueProfileKeyHash {
+    static unsigned hash(const LazyOperandValueProfileKey& key) { return key.hash(); }
+    static bool equal(
+        const LazyOperandValueProfileKey& a,
+        const LazyOperandValueProfileKey& b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::LazyOperandValueProfileKey> {
+    typedef JSC::LazyOperandValueProfileKeyHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::LazyOperandValueProfileKey> : public GenericHashTraits<JSC::LazyOperandValueProfileKey> {
+    static void constructDeletedValue(JSC::LazyOperandValueProfileKey& slot) { new (NotNull, &slot) JSC::LazyOperandValueProfileKey(HashTableDeletedValue); }
+    static bool isDeletedValue(const JSC::LazyOperandValueProfileKey& value) { return value.isHashTableDeletedValue(); }
+};
+
+} // namespace WTF
+
+namespace JSC {
+
+struct LazyOperandValueProfile : public MinimalValueProfile {
+    LazyOperandValueProfile()
+        : MinimalValueProfile()
+        , m_operand(-1)
+    {
+    }
+    
+    explicit LazyOperandValueProfile(const LazyOperandValueProfileKey& key)
+        : MinimalValueProfile(key.bytecodeOffset())
+        , m_operand(key.operand())
+    {
+    }
+    
+    LazyOperandValueProfileKey key() const
+    {
+        return LazyOperandValueProfileKey(m_bytecodeOffset, m_operand);
+    }
+    
+    int m_operand;
+    
+    typedef SegmentedVector<LazyOperandValueProfile, 8> List;
+};
+
+class LazyOperandValueProfileParser;
+
+class CompressedLazyOperandValueProfileHolder {
+    WTF_MAKE_NONCOPYABLE(CompressedLazyOperandValueProfileHolder);
+public:
+    CompressedLazyOperandValueProfileHolder();
+    ~CompressedLazyOperandValueProfileHolder();
+    
+    void computeUpdatedPredictions();
+    
+    LazyOperandValueProfile* add(const LazyOperandValueProfileKey& key);
+    
+private:
+    friend class LazyOperandValueProfileParser;
+    OwnPtr<LazyOperandValueProfile::List> m_data;
+};
+
+class LazyOperandValueProfileParser {
+    WTF_MAKE_NONCOPYABLE(LazyOperandValueProfileParser);
+public:
+    explicit LazyOperandValueProfileParser(
+        CompressedLazyOperandValueProfileHolder& holder);
+    ~LazyOperandValueProfileParser();
+    
+    LazyOperandValueProfile* getIfPresent(
+        const LazyOperandValueProfileKey& key) const;
+    
+    PredictedType prediction(const LazyOperandValueProfileKey& key) const;
+private:
+    CompressedLazyOperandValueProfileHolder& m_holder;
+    HashMap<LazyOperandValueProfileKey, LazyOperandValueProfile*> m_map;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(VALUE_PROFILER)
+
+#endif // LazyOperandValueProfile_h
+
+
diff --git a/bytecode/LineInfo.h b/bytecode/LineInfo.h
new file mode 100644 (file)
index 0000000..e9e7013
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef LineInfo_h
+#define LineInfo_h
+
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+struct LineInfo {
+    uint32_t instructionOffset;
+    int32_t lineNumber;
+};
+
+} // namespace JSC
+
+#endif // LineInfo_h
+
diff --git a/bytecode/MethodCallLinkInfo.cpp b/bytecode/MethodCallLinkInfo.cpp
new file mode 100644 (file)
index 0000000..1fcf585
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "MethodCallLinkInfo.h"
+
+#if ENABLE(JIT)
+
+#include "JITStubs.h"
+#include "RepatchBuffer.h"
+
+namespace JSC {
+
+void MethodCallLinkInfo::reset(RepatchBuffer& repatchBuffer, JITCode::JITType jitType)
+{
+    cachedStructure.clearToMaxUnsigned();
+    cachedPrototype.clear();
+    cachedPrototypeStructure.clearToMaxUnsigned();
+    cachedFunction.clear();
+    
+    ASSERT_UNUSED(jitType, jitType == JITCode::BaselineJIT);
+    
+    repatchBuffer.relink(callReturnLocation, cti_op_get_by_id_method_check);
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
diff --git a/bytecode/MethodCallLinkInfo.h b/bytecode/MethodCallLinkInfo.h
new file mode 100644 (file)
index 0000000..2243bc2
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef MethodCallLinkInfo_h
+#define MethodCallLinkInfo_h
+
+#include "CodeLocation.h"
+#include "JITCode.h"
+#include "JITWriteBarrier.h"
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+#if ENABLE(JIT)
+
+class RepatchBuffer;
+
+struct MethodCallLinkInfo {
+    MethodCallLinkInfo()
+        : seen(false)
+    {
+    }
+
+    bool seenOnce()
+    {
+        return seen;
+    }
+
+    void setSeen()
+    {
+        seen = true;
+    }
+        
+    void reset(RepatchBuffer&, JITCode::JITType);
+
+    unsigned bytecodeIndex;
+    CodeLocationCall callReturnLocation;
+    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<JSObject> cachedFunction;
+    JITWriteBarrier<JSObject> cachedPrototype;
+    bool seen;
+};
+
+inline void* getMethodCallLinkInfoReturnLocation(MethodCallLinkInfo* methodCallLinkInfo)
+{
+    return methodCallLinkInfo->callReturnLocation.executableAddress();
+}
+
+inline unsigned getMethodCallLinkInfoBytecodeIndex(MethodCallLinkInfo* methodCallLinkInfo)
+{
+    return methodCallLinkInfo->bytecodeIndex;
+}
+
+#endif // ENABLE(JIT)
+
+} // namespace JSC
+
+#endif // MethodCallLinkInfo_h
diff --git a/bytecode/MethodCallLinkStatus.cpp b/bytecode/MethodCallLinkStatus.cpp
new file mode 100644 (file)
index 0000000..795b41b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "MethodCallLinkStatus.h"
+
+#include "CodeBlock.h"
+
+namespace JSC {
+
+MethodCallLinkStatus MethodCallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
+{
+    UNUSED_PARAM(profiledBlock);
+    UNUSED_PARAM(bytecodeIndex);
+#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+    // NOTE: This does not have an LLInt fall-back because LLInt does not do any method
+    // call link caching.
+    if (!profiledBlock->numberOfMethodCallLinkInfos())
+        return MethodCallLinkStatus();
+    
+    MethodCallLinkInfo& methodCall = profiledBlock->getMethodCallLinkInfo(bytecodeIndex);
+    
+    if (!methodCall.seen || !methodCall.cachedStructure)
+        return MethodCallLinkStatus();
+    
+    if (methodCall.cachedPrototype.get() == profiledBlock->globalObject()->methodCallDummy()) {
+        return MethodCallLinkStatus(
+            methodCall.cachedStructure.get(),
+            0,
+            methodCall.cachedFunction.get(),
+            0);
+    }
+    
+    return MethodCallLinkStatus(
+        methodCall.cachedStructure.get(),
+        methodCall.cachedPrototypeStructure.get(),
+        methodCall.cachedFunction.get(),
+        methodCall.cachedPrototype.get());
+#else // ENABLE(JIT)
+    return MethodCallLinkStatus();
+#endif // ENABLE(JIT)
+}
+
+} // namespace JSC
diff --git a/bytecode/MethodCallLinkStatus.h b/bytecode/MethodCallLinkStatus.h
new file mode 100644 (file)
index 0000000..c3d11a1
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef MethodCallLinkStatus_h
+#define MethodCallLinkStatus_h
+
+namespace JSC {
+
+class CodeBlock;
+class JSObject;
+class Structure;
+
+class MethodCallLinkStatus {
+public:
+    MethodCallLinkStatus()
+        : m_structure(0)
+        , m_prototypeStructure(0)
+        , m_function(0)
+        , m_prototype(0)
+    {
+    }
+    
+    MethodCallLinkStatus(
+        Structure* structure,
+        Structure* prototypeStructure,
+        JSObject* function,
+        JSObject* prototype)
+        : m_structure(structure)
+        , m_prototypeStructure(prototypeStructure)
+        , m_function(function)
+        , m_prototype(prototype)
+    {
+        if (!m_function) {
+            ASSERT(!m_structure);
+            ASSERT(!m_prototypeStructure);
+            ASSERT(!m_prototype);
+        } else
+            ASSERT(m_structure);
+        
+        ASSERT(!m_prototype == !m_prototypeStructure);
+    }
+    
+    static MethodCallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex);
+
+    bool isSet() const { return !!m_function; }
+    bool operator!() const { return !m_function; }
+    
+    bool needsPrototypeCheck() const { return !!m_prototype; }
+    
+    Structure* structure() { return m_structure; }
+    Structure* prototypeStructure() { return m_prototypeStructure; }
+    JSObject* function() const { return m_function; }
+    JSObject* prototype() const { return m_prototype; }
+    
+private:
+    Structure* m_structure;
+    Structure* m_prototypeStructure;
+    JSObject* m_function;
+    JSObject* m_prototype;
+};
+
+} // namespace JSC
+
+#endif // MethodCallLinkStatus_h
+
diff --git a/bytecode/MethodOfGettingAValueProfile.cpp b/bytecode/MethodOfGettingAValueProfile.cpp
new file mode 100644 (file)
index 0000000..857ed9c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "MethodOfGettingAValueProfile.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeBlock.h"
+
+namespace JSC {
+
+MethodOfGettingAValueProfile MethodOfGettingAValueProfile::fromLazyOperand(
+    CodeBlock* codeBlock, const LazyOperandValueProfileKey& key)
+{
+    MethodOfGettingAValueProfile result;
+    result.m_kind = LazyOperand;
+    result.u.lazyOperand.codeBlock = codeBlock;
+    result.u.lazyOperand.bytecodeOffset = key.bytecodeOffset();
+    result.u.lazyOperand.operand = key.operand();
+    return result;
+}
+
+EncodedJSValue* MethodOfGettingAValueProfile::getSpecFailBucket(unsigned index) const
+{
+    switch (m_kind) {
+    case None:
+        return 0;
+        
+    case Ready:
+        return u.profile->specFailBucket(index);
+        
+    case LazyOperand:
+        return u.lazyOperand.codeBlock->lazyOperandValueProfiles().add(
+            LazyOperandValueProfileKey(
+                u.lazyOperand.bytecodeOffset, u.lazyOperand.operand))->specFailBucket(index);
+        
+    default:
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+}
+
+} // namespace JSC
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/bytecode/MethodOfGettingAValueProfile.h b/bytecode/MethodOfGettingAValueProfile.h
new file mode 100644 (file)
index 0000000..0f5c2be
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef MethodOfGettingAValueProfile_h
+#define MethodOfGettingAValueProfile_h
+
+#include <wtf/Platform.h>
+
+// This is guarded by ENABLE_DFG_JIT only because it uses some value profiles
+// that are currently only used if the DFG is enabled (i.e. they are not
+// available in the profile-only configuration). Hopefully someday all of
+// these #if's will disappear...
+#if ENABLE(DFG_JIT)
+
+#include "JSValue.h"
+
+namespace JSC {
+
+class CodeBlock;
+class LazyOperandValueProfileKey;
+struct ValueProfile;
+
+class MethodOfGettingAValueProfile {
+public:
+    MethodOfGettingAValueProfile()
+        : m_kind(None)
+    {
+    }
+    
+    explicit MethodOfGettingAValueProfile(ValueProfile* profile)
+    {
+        if (profile) {
+            m_kind = Ready;
+            u.profile = profile;
+        } else
+            m_kind = None;
+    }
+    
+    static MethodOfGettingAValueProfile fromLazyOperand(
+        CodeBlock*, const LazyOperandValueProfileKey&);
+    
+    bool operator!() const { return m_kind == None; }
+    
+    // This logically has a pointer to a "There exists X such that
+    // ValueProfileBase<X>". But since C++ does not have existential
+    // templates, I cannot return it. So instead, for any methods that
+    // users of this class would like to call, we'll just have to provide
+    // a method here that does it through an indirection. Or we could
+    // possibly just make ValueProfile less template-based. But last I
+    // tried that, it felt more yucky than this class.
+    
+    EncodedJSValue* getSpecFailBucket(unsigned index) const;
+    
+private:
+    enum Kind {
+        None,
+        Ready,
+        LazyOperand
+    };
+    
+    Kind m_kind;
+    union {
+        ValueProfile* profile;
+        struct {
+            CodeBlock* codeBlock;
+            unsigned bytecodeOffset;
+            int operand;
+        } lazyOperand;
+    } u;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // MethodOfGettingAValueProfile_h
+
index 0bb714bca2d14ed884574fb73c9cac8947faca4f..a27714026dc8c14209c535b83ccf450b6b272edd 100644 (file)
@@ -39,16 +39,12 @@ using namespace std;
 
 namespace JSC {
 
 
 namespace JSC {
 
-#if ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS)
-
 const char* const opcodeNames[] = {
 #define OPCODE_NAME_ENTRY(opcode, size) #opcode,
     FOR_EACH_OPCODE_ID(OPCODE_NAME_ENTRY)
 #undef OPCODE_NAME_ENTRY
 };
 
 const char* const opcodeNames[] = {
 #define OPCODE_NAME_ENTRY(opcode, size) #opcode,
     FOR_EACH_OPCODE_ID(OPCODE_NAME_ENTRY)
 #undef OPCODE_NAME_ENTRY
 };
 
-#endif
-
 #if ENABLE(OPCODE_STATS)
 
 long long OpcodeStats::opcodeCounts[numOpcodeIDs];
 #if ENABLE(OPCODE_STATS)
 
 long long OpcodeStats::opcodeCounts[numOpcodeIDs];
@@ -118,19 +114,19 @@ OpcodeStats::~OpcodeStats()
             *(currentPairIndex++) = make_pair(i, j);
     qsort(sortedPairIndices, numOpcodeIDs * numOpcodeIDs, sizeof(pair<int, int>), compareOpcodePairIndices);
     
             *(currentPairIndex++) = make_pair(i, j);
     qsort(sortedPairIndices, numOpcodeIDs * numOpcodeIDs, sizeof(pair<int, int>), compareOpcodePairIndices);
     
-    printf("\nExecuted opcode statistics\n"); 
+    dataLog("\nExecuted opcode statistics\n"); 
     
     
-    printf("Total instructions executed: %lld\n\n", totalInstructions);
+    dataLog("Total instructions executed: %lld\n\n", totalInstructions);
 
 
-    printf("All opcodes by frequency:\n\n");
+    dataLog("All opcodes by frequency:\n\n");
 
     for (int i = 0; i < numOpcodeIDs; ++i) {
         int index = sortedIndices[i];
 
     for (int i = 0; i < numOpcodeIDs; ++i) {
         int index = sortedIndices[i];
-        printf("%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 28), opcodeCounts[index], ((double) opcodeCounts[index]) / ((double) totalInstructions) * 100.0);    
+        dataLog("%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 28), opcodeCounts[index], ((double) opcodeCounts[index]) / ((double) totalInstructions) * 100.0);    
     }
     
     }
     
-    printf("\n");
-    printf("2-opcode sequences by frequency: %lld\n\n", totalInstructions);
+    dataLog("\n");
+    dataLog("2-opcode sequences by frequency: %lld\n\n", totalInstructions);
     
     for (int i = 0; i < numOpcodeIDs * numOpcodeIDs; ++i) {
         pair<int, int> indexPair = sortedPairIndices[i];
     
     for (int i = 0; i < numOpcodeIDs * numOpcodeIDs; ++i) {
         pair<int, int> indexPair = sortedPairIndices[i];
@@ -139,11 +135,11 @@ OpcodeStats::~OpcodeStats()
         if (!count)
             break;
         
         if (!count)
             break;
         
-        printf("%s%s %s:%s %lld %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 28), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 28), count, ((double) count) / ((double) totalInstructionPairs) * 100.0);
+        dataLog("%s%s %s:%s %lld %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 28), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 28), count, ((double) count) / ((double) totalInstructionPairs) * 100.0);
     }
     
     }
     
-    printf("\n");
-    printf("Most common opcodes and sequences:\n");
+    dataLog("\n");
+    dataLog("Most common opcodes and sequences:\n");
 
     for (int i = 0; i < numOpcodeIDs; ++i) {
         int index = sortedIndices[i];
 
     for (int i = 0; i < numOpcodeIDs; ++i) {
         int index = sortedIndices[i];
@@ -151,7 +147,7 @@ OpcodeStats::~OpcodeStats()
         double opcodeProportion = ((double) opcodeCount) / ((double) totalInstructions);
         if (opcodeProportion < 0.0001)
             break;
         double opcodeProportion = ((double) opcodeCount) / ((double) totalInstructions);
         if (opcodeProportion < 0.0001)
             break;
-        printf("\n%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 28), opcodeCount, opcodeProportion * 100.0);
+        dataLog("\n%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 28), opcodeCount, opcodeProportion * 100.0);
 
         for (int j = 0; j < numOpcodeIDs * numOpcodeIDs; ++j) {
             pair<int, int> indexPair = sortedPairIndices[j];
 
         for (int j = 0; j < numOpcodeIDs * numOpcodeIDs; ++j) {
             pair<int, int> indexPair = sortedPairIndices[j];
@@ -164,11 +160,11 @@ OpcodeStats::~OpcodeStats()
             if (indexPair.first != index && indexPair.second != index)
                 continue;
 
             if (indexPair.first != index && indexPair.second != index)
                 continue;
 
-            printf("    %s%s %s:%s %lld - %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 28), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 28), pairCount, pairProportion * 100.0);
+            dataLog("    %s%s %s:%s %lld - %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 28), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 28), pairCount, pairProportion * 100.0);
         }
         
     }
         }
         
     }
-    printf("\n");
+    dataLog("\n");
 }
 
 void OpcodeStats::recordInstruction(int opcode)
 }
 
 void OpcodeStats::recordInstruction(int opcode)
index 18902eb2690a3ee406d683b68045129d6895a9f6..a564de2da1dea51d61caf9f138714960f5271bc5 100644 (file)
@@ -45,7 +45,6 @@ namespace JSC {
         macro(op_create_this, 3) \
         macro(op_get_callee, 2) \
         macro(op_convert_this, 2) \
         macro(op_create_this, 3) \
         macro(op_get_callee, 2) \
         macro(op_convert_this, 2) \
-        macro(op_convert_this_strict, 2) \
         \
         macro(op_new_object, 2) \
         macro(op_new_array, 4) \
         \
         macro(op_new_object, 2) \
         macro(op_new_array, 4) \
@@ -62,6 +61,8 @@ namespace JSC {
         macro(op_nstricteq, 4) \
         macro(op_less, 4) \
         macro(op_lesseq, 4) \
         macro(op_nstricteq, 4) \
         macro(op_less, 4) \
         macro(op_lesseq, 4) \
+        macro(op_greater, 4) \
+        macro(op_greatereq, 4) \
         \
         macro(op_pre_inc, 2) \
         macro(op_pre_dec, 2) \
         \
         macro(op_pre_inc, 2) \
         macro(op_pre_dec, 2) \
@@ -81,7 +82,6 @@ namespace JSC {
         macro(op_bitand, 5) \
         macro(op_bitxor, 5) \
         macro(op_bitor, 5) \
         macro(op_bitand, 5) \
         macro(op_bitxor, 5) \
         macro(op_bitor, 5) \
-        macro(op_bitnot, 3) \
         \
         macro(op_check_has_instance, 2) \
         macro(op_instanceof, 5) \
         \
         macro(op_check_has_instance, 2) \
         macro(op_instanceof, 5) \
@@ -94,50 +94,46 @@ namespace JSC {
         macro(op_is_function, 3) \
         macro(op_in, 4) \
         \
         macro(op_is_function, 3) \
         macro(op_in, 4) \
         \
-        macro(op_resolve, 3) \
-        macro(op_resolve_skip, 4) \
-        macro(op_resolve_global, 5) \
-        macro(op_resolve_global_dynamic, 6) \
-        macro(op_get_scoped_var, 4) \
+        macro(op_resolve, 4) /* has value profiling */  \
+        macro(op_resolve_skip, 5) /* has value profiling */ \
+        macro(op_resolve_global, 6) /* has value profiling */ \
+        macro(op_resolve_global_dynamic, 7) /* has value profiling */ \
+        macro(op_get_scoped_var, 5) /* has value profiling */ \
         macro(op_put_scoped_var, 4) \
         macro(op_put_scoped_var, 4) \
-        macro(op_get_global_var, 3) \
+        macro(op_get_global_var, 4) /* has value profiling */ \
         macro(op_put_global_var, 3) \
         macro(op_put_global_var, 3) \
-        macro(op_resolve_base, 4) \
+        macro(op_resolve_base, 5) /* has value profiling */ \
         macro(op_ensure_property_exists, 3) \
         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_get_by_id_self_list, 8) \
-        macro(op_get_by_id_proto, 8) \
-        macro(op_get_by_id_proto_list, 8) \
-        macro(op_get_by_id_chain, 8) \
-        macro(op_get_by_id_getter_self, 8) \
-        macro(op_get_by_id_getter_self_list, 8) \
-        macro(op_get_by_id_getter_proto, 8) \
-        macro(op_get_by_id_getter_proto_list, 8) \
-        macro(op_get_by_id_getter_chain, 8) \
-        macro(op_get_by_id_custom_self, 8) \
-        macro(op_get_by_id_custom_self_list, 8) \
-        macro(op_get_by_id_custom_proto, 8) \
-        macro(op_get_by_id_custom_proto_list, 8) \
-        macro(op_get_by_id_custom_chain, 8) \
-        macro(op_get_by_id_generic, 8) \
-        macro(op_get_array_length, 8) \
-        macro(op_get_string_length, 8) \
+        macro(op_resolve_with_base, 5) /* has value profiling */ \
+        macro(op_resolve_with_this, 5) /* has value profiling */ \
+        macro(op_get_by_id, 9) /* has value profiling */ \
+        macro(op_get_by_id_self, 9) /* has value profiling */ \
+        macro(op_get_by_id_proto, 9) /* has value profiling */ \
+        macro(op_get_by_id_chain, 9) /* has value profiling */ \
+        macro(op_get_by_id_getter_self, 9) /* has value profiling */ \
+        macro(op_get_by_id_getter_proto, 9) /* has value profiling */ \
+        macro(op_get_by_id_getter_chain, 9) /* has value profiling */ \
+        macro(op_get_by_id_custom_self, 9) /* has value profiling */ \
+        macro(op_get_by_id_custom_proto, 9) /* has value profiling */ \
+        macro(op_get_by_id_custom_chain, 9) /* has value profiling */ \
+        macro(op_get_by_id_generic, 9) /* has value profiling */ \
+        macro(op_get_array_length, 9) /* has value profiling */ \
+        macro(op_get_string_length, 9) /* has value profiling */ \
         macro(op_get_arguments_length, 4) \
         macro(op_put_by_id, 9) \
         macro(op_put_by_id_transition, 9) \
         macro(op_get_arguments_length, 4) \
         macro(op_put_by_id, 9) \
         macro(op_put_by_id_transition, 9) \
+        macro(op_put_by_id_transition_direct, 9) \
+        macro(op_put_by_id_transition_normal, 9) \
         macro(op_put_by_id_replace, 9) \
         macro(op_put_by_id_generic, 9) \
         macro(op_del_by_id, 4) \
         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_val, 5) /* has value profiling */ \
+        macro(op_get_argument_by_val, 5) /* must be the same size as op_get_by_val */ \
         macro(op_get_by_pname, 7) \
         macro(op_put_by_val, 4) \
         macro(op_del_by_val, 4) \
         macro(op_put_by_index, 4) \
         macro(op_get_by_pname, 7) \
         macro(op_put_by_val, 4) \
         macro(op_del_by_val, 4) \
         macro(op_put_by_index, 4) \
-        macro(op_put_getter, 4) \
-        macro(op_put_setter, 4) \
+        macro(op_put_getter_setter, 5) \
         \
         macro(op_jmp, 2) \
         macro(op_jtrue, 3) \
         \
         macro(op_jmp, 2) \
         macro(op_jtrue, 3) \
@@ -145,34 +141,40 @@ namespace JSC {
         macro(op_jeq_null, 3) \
         macro(op_jneq_null, 3) \
         macro(op_jneq_ptr, 4) \
         macro(op_jeq_null, 3) \
         macro(op_jneq_null, 3) \
         macro(op_jneq_ptr, 4) \
-        macro(op_jnless, 4) \
-        macro(op_jnlesseq, 4) \
         macro(op_jless, 4) \
         macro(op_jlesseq, 4) \
         macro(op_jless, 4) \
         macro(op_jlesseq, 4) \
+        macro(op_jgreater, 4) \
+        macro(op_jgreatereq, 4) \
+        macro(op_jnless, 4) \
+        macro(op_jnlesseq, 4) \
+        macro(op_jngreater, 4) \
+        macro(op_jngreatereq, 4) \
         macro(op_jmp_scopes, 3) \
         macro(op_loop, 2) \
         macro(op_loop_if_true, 3) \
         macro(op_loop_if_false, 3) \
         macro(op_loop_if_less, 4) \
         macro(op_loop_if_lesseq, 4) \
         macro(op_jmp_scopes, 3) \
         macro(op_loop, 2) \
         macro(op_loop_if_true, 3) \
         macro(op_loop_if_false, 3) \
         macro(op_loop_if_less, 4) \
         macro(op_loop_if_lesseq, 4) \
+        macro(op_loop_if_greater, 4) \
+        macro(op_loop_if_greatereq, 4) \
+        macro(op_loop_hint, 1) \
         macro(op_switch_imm, 4) \
         macro(op_switch_char, 4) \
         macro(op_switch_string, 4) \
         \
         macro(op_new_func, 4) \
         macro(op_new_func_exp, 3) \
         macro(op_switch_imm, 4) \
         macro(op_switch_char, 4) \
         macro(op_switch_string, 4) \
         \
         macro(op_new_func, 4) \
         macro(op_new_func_exp, 3) \
-        macro(op_call, 4) \
-        macro(op_call_eval, 4) \
-        macro(op_call_varargs, 4) \
-        macro(op_load_varargs, 4) \
+        macro(op_call, 6) \
+        macro(op_call_eval, 6) \
+        macro(op_call_varargs, 5) \
         macro(op_tear_off_activation, 3) \
         macro(op_tear_off_arguments, 2) \
         macro(op_ret, 2) \
         macro(op_tear_off_activation, 3) \
         macro(op_tear_off_arguments, 2) \
         macro(op_ret, 2) \
-        macro(op_call_put_result, 2) \
+        macro(op_call_put_result, 3) /* has value profiling */ \
         macro(op_ret_object_or_this, 3) \
         macro(op_method_check, 1) \
         \
         macro(op_ret_object_or_this, 3) \
         macro(op_method_check, 1) \
         \
-        macro(op_construct, 4) \
+        macro(op_construct, 6) \
         macro(op_strcat, 4) \
         macro(op_to_primitive, 3) \
         \
         macro(op_strcat, 4) \
         macro(op_to_primitive, 3) \
         \
@@ -187,9 +189,6 @@ namespace JSC {
         macro(op_throw, 2) \
         macro(op_throw_reference_error, 2) \
         \
         macro(op_throw, 2) \
         macro(op_throw_reference_error, 2) \
         \
-        macro(op_jsr, 3) \
-        macro(op_sret, 2) \
-        \
         macro(op_debug, 4) \
         macro(op_profile_will_call, 2) \
         macro(op_profile_did_call, 2) \
         macro(op_debug, 4) \
         macro(op_profile_will_call, 2) \
         macro(op_profile_did_call, 2) \
@@ -200,6 +199,7 @@ namespace JSC {
         typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID;
     #undef OPCODE_ID_ENUM
 
         typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID;
     #undef OPCODE_ID_ENUM
 
+    const int maxOpcodeLength = 9;
     const int numOpcodeIDs = op_end + 1;
 
     #define OPCODE_ID_LENGTHS(id, length) const int id##_length = length;
     const int numOpcodeIDs = op_end + 1;
 
     #define OPCODE_ID_LENGTHS(id, length) const int id##_length = length;
@@ -216,7 +216,7 @@ namespace JSC {
         FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
     #undef VERIFY_OPCODE_ID
 
         FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
     #undef VERIFY_OPCODE_ID
 
-#if ENABLE(COMPUTED_GOTO_INTERPRETER)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
 #if COMPILER(RVCT) || COMPILER(INTEL)
     typedef void* Opcode;
 #else
 #if COMPILER(RVCT) || COMPILER(INTEL)
     typedef void* Opcode;
 #else
@@ -226,8 +226,6 @@ namespace JSC {
     typedef OpcodeID Opcode;
 #endif
 
     typedef OpcodeID Opcode;
 #endif
 
-#if ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS)
-
 #define PADDING_STRING "                                "
 #define PADDING_STRING_LENGTH static_cast<unsigned>(strlen(PADDING_STRING))
 
 #define PADDING_STRING "                                "
 #define PADDING_STRING_LENGTH static_cast<unsigned>(strlen(PADDING_STRING))
 
@@ -243,8 +241,6 @@ namespace JSC {
 #undef PADDING_STRING_LENGTH
 #undef PADDING_STRING
 
 #undef PADDING_STRING_LENGTH
 #undef PADDING_STRING
 
-#endif
-
 #if ENABLE(OPCODE_STATS)
 
     struct OpcodeStats {
 #if ENABLE(OPCODE_STATS)
 
     struct OpcodeStats {
diff --git a/bytecode/Operands.h b/bytecode/Operands.h
new file mode 100644 (file)
index 0000000..a05159f
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef Operands_h
+#define Operands_h
+
+#include "CallFrame.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+// argument 0 is 'this'.
+inline bool operandIsArgument(int operand) { return operand < 0; }
+inline int operandToArgument(int operand) { return -operand + CallFrame::thisArgumentOffset(); }
+inline int argumentToOperand(int argument) { return -argument + CallFrame::thisArgumentOffset(); }
+
+template<typename T> struct OperandValueTraits;
+
+template<typename T>
+struct OperandValueTraits {
+    static T defaultValue() { return T(); }
+    static void dump(const T& value, FILE* out) { value.dump(out); }
+};
+
+template<typename T, typename Traits = OperandValueTraits<T> >
+class Operands {
+public:
+    Operands() { }
+    
+    explicit Operands(size_t numArguments, size_t numLocals)
+    {
+        m_arguments.fill(Traits::defaultValue(), numArguments);
+        m_locals.fill(Traits::defaultValue(), numLocals);
+    }
+    
+    size_t numberOfArguments() const { return m_arguments.size(); }
+    size_t numberOfLocals() const { return m_locals.size(); }
+    
+    T& argument(size_t idx) { return m_arguments[idx]; }
+    const T& argument(size_t idx) const { return m_arguments[idx]; }
+    
+    T& local(size_t idx) { return m_locals[idx]; }
+    const T& local(size_t idx) const { return m_locals[idx]; }
+    
+    void ensureLocals(size_t size)
+    {
+        if (size <= m_locals.size())
+            return;
+
+        size_t oldSize = m_locals.size();
+        m_locals.resize(size);
+        for (size_t i = oldSize; i < m_locals.size(); ++i)
+            m_locals[i] = Traits::defaultValue();
+    }
+    
+    void setLocal(size_t idx, const T& value)
+    {
+        ensureLocals(idx + 1);
+        
+        m_locals[idx] = value;
+    }
+    
+    T getLocal(size_t idx)
+    {
+        if (idx >= m_locals.size())
+            return Traits::defaultValue();
+        return m_locals[idx];
+    }
+    
+    void setArgumentFirstTime(size_t idx, const T& value)
+    {
+        ASSERT(m_arguments[idx] == Traits::defaultValue());
+        argument(idx) = value;
+    }
+    
+    void setLocalFirstTime(size_t idx, const T& value)
+    {
+        ASSERT(idx >= m_locals.size() || m_locals[idx] == Traits::defaultValue());
+        setLocal(idx, value);
+    }
+    
+    T& operand(int operand)
+    {
+        if (operandIsArgument(operand)) {
+            int argument = operandToArgument(operand);
+            return m_arguments[argument];
+        }
+        
+        return m_locals[operand];
+    }
+    
+    const T& operand(int operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); }
+    
+    void setOperand(int operand, const T& value)
+    {
+        if (operandIsArgument(operand)) {
+            int argument = operandToArgument(operand);
+            m_arguments[argument] = value;
+            return;
+        }
+        
+        setLocal(operand, value);
+    }
+    
+    void clear()
+    {
+        for (size_t i = 0; i < m_arguments.size(); ++i)
+            m_arguments[i] = Traits::defaultValue();
+        for (size_t i = 0; i < m_locals.size(); ++i)
+            m_locals[i] = Traits::defaultValue();
+    }
+    
+private:
+    Vector<T, 8> m_arguments;
+    Vector<T, 16> m_locals;
+};
+
+template<typename T, typename Traits>
+void dumpOperands(Operands<T, Traits>& operands, FILE* out)
+{
+    for (size_t argument = 0; argument < operands.numberOfArguments(); ++argument) {
+        if (argument)
+            fprintf(out, " ");
+        Traits::dump(operands.argument(argument), out);
+    }
+    fprintf(out, " : ");
+    for (size_t local = 0; local < operands.numberOfLocals(); ++local) {
+        if (local)
+            fprintf(out, " ");
+        Traits::dump(operands.local(local), out);
+    }
+}
+
+} // namespace JSC
+
+#endif // Operands_h
+
diff --git a/bytecode/PolymorphicPutByIdList.cpp b/bytecode/PolymorphicPutByIdList.cpp
new file mode 100644 (file)
index 0000000..170615b
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "PolymorphicPutByIdList.h"
+
+#if ENABLE(JIT)
+
+#include "StructureStubInfo.h"
+
+namespace JSC {
+
+PutByIdAccess PutByIdAccess::fromStructureStubInfo(
+    StructureStubInfo& stubInfo,
+    MacroAssemblerCodePtr initialSlowPath)
+{
+    PutByIdAccess result;
+    
+    switch (stubInfo.accessType) {
+    case access_put_by_id_replace:
+        result.m_type = Replace;
+        result.m_oldStructure.copyFrom(stubInfo.u.putByIdReplace.baseObjectStructure);
+        result.m_stubRoutine = MacroAssemblerCodeRef::createSelfManagedCodeRef(initialSlowPath);
+        break;
+        
+    case access_put_by_id_transition_direct:
+    case access_put_by_id_transition_normal:
+        result.m_type = Transition;
+        result.m_oldStructure.copyFrom(stubInfo.u.putByIdTransition.previousStructure);
+        result.m_newStructure.copyFrom(stubInfo.u.putByIdTransition.structure);
+        result.m_chain.copyFrom(stubInfo.u.putByIdTransition.chain);
+        result.m_stubRoutine = stubInfo.stubRoutine;
+        break;
+        
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    
+    return result;
+}
+
+bool PutByIdAccess::visitWeak() const
+{
+    switch (m_type) {
+    case Replace:
+        if (!Heap::isMarked(m_oldStructure.get()))
+            return false;
+        break;
+    case Transition:
+        if (!Heap::isMarked(m_oldStructure.get()))
+            return false;
+        if (!Heap::isMarked(m_newStructure.get()))
+            return false;
+        if (!Heap::isMarked(m_chain.get()))
+            return false;
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+    return true;
+}
+
+PolymorphicPutByIdList::PolymorphicPutByIdList(
+    PutKind putKind,
+    StructureStubInfo& stubInfo,
+    MacroAssemblerCodePtr initialSlowPath)
+    : m_kind(putKind)
+{
+    m_list.append(PutByIdAccess::fromStructureStubInfo(stubInfo, initialSlowPath));
+}
+
+PolymorphicPutByIdList* PolymorphicPutByIdList::from(
+    PutKind putKind,
+    StructureStubInfo& stubInfo,
+    MacroAssemblerCodePtr initialSlowPath)
+{
+    if (stubInfo.accessType == access_put_by_id_list)
+        return stubInfo.u.putByIdList.list;
+    
+    ASSERT(stubInfo.accessType == access_put_by_id_replace
+           || stubInfo.accessType == access_put_by_id_transition_normal
+           || stubInfo.accessType == access_put_by_id_transition_direct);
+    
+    PolymorphicPutByIdList* result =
+        new PolymorphicPutByIdList(putKind, stubInfo, initialSlowPath);
+    
+    stubInfo.initPutByIdList(result);
+    
+    return result;
+}
+
+PolymorphicPutByIdList::~PolymorphicPutByIdList() { }
+
+bool PolymorphicPutByIdList::isFull() const
+{
+    ASSERT(size() <= POLYMORPHIC_LIST_CACHE_SIZE);
+    return size() == POLYMORPHIC_LIST_CACHE_SIZE;
+}
+
+bool PolymorphicPutByIdList::isAlmostFull() const
+{
+    ASSERT(size() <= POLYMORPHIC_LIST_CACHE_SIZE);
+    return size() >= POLYMORPHIC_LIST_CACHE_SIZE - 1;
+}
+
+void PolymorphicPutByIdList::addAccess(const PutByIdAccess& putByIdAccess)
+{
+    ASSERT(!isFull());
+    // Make sure that the resizing optimizes for space, not time.
+    m_list.resize(m_list.size() + 1);
+    m_list.last() = putByIdAccess;
+}
+
+bool PolymorphicPutByIdList::visitWeak() const
+{
+    for (unsigned i = 0; i < size(); ++i) {
+        if (!at(i).visitWeak())
+            return false;
+    }
+    return true;
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
diff --git a/bytecode/PolymorphicPutByIdList.h b/bytecode/PolymorphicPutByIdList.h
new file mode 100644 (file)
index 0000000..60b632d
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef PolymorphicPutByIdList_h
+#define PolymorphicPutByIdList_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#include "CodeOrigin.h"
+#include "MacroAssembler.h"
+#include "Opcode.h"
+#include "PutKind.h"
+#include "Structure.h"
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+struct StructureStubInfo;
+
+class PutByIdAccess {
+public:
+    enum AccessType {
+        Invalid,
+        Transition,
+        Replace
+    };
+    
+    PutByIdAccess()
+        : m_type(Invalid)
+    {
+    }
+    
+    static PutByIdAccess transition(
+        JSGlobalData& globalData,
+        JSCell* owner,
+        Structure* oldStructure,
+        Structure* newStructure,
+        StructureChain* chain,
+        MacroAssemblerCodeRef stubRoutine)
+    {
+        PutByIdAccess result;
+        result.m_type = Transition;
+        result.m_oldStructure.set(globalData, owner, oldStructure);
+        result.m_newStructure.set(globalData, owner, newStructure);
+        result.m_chain.set(globalData, owner, chain);
+        result.m_stubRoutine = stubRoutine;
+        return result;
+    }
+    
+    static PutByIdAccess replace(
+        JSGlobalData& globalData,
+        JSCell* owner,
+        Structure* structure,
+        MacroAssemblerCodeRef stubRoutine)
+    {
+        PutByIdAccess result;
+        result.m_type = Replace;
+        result.m_oldStructure.set(globalData, owner, structure);
+        result.m_stubRoutine = stubRoutine;
+        return result;
+    }
+    
+    static PutByIdAccess fromStructureStubInfo(
+        StructureStubInfo&,
+        MacroAssemblerCodePtr initialSlowPath);
+    
+    bool isSet() const { return m_type != Invalid; }
+    bool operator!() const { return !isSet(); }
+    
+    AccessType type() const { return m_type; }
+    
+    bool isTransition() const { return m_type == Transition; }
+    bool isReplace() const { return m_type == Replace; }
+    
+    Structure* oldStructure() const
+    {
+        // Using this instead of isSet() to make this assertion robust against the possibility
+        // of additional access types being added.
+        ASSERT(isTransition() || isReplace());
+        
+        return m_oldStructure.get();
+    }
+    
+    Structure* structure() const
+    {
+        ASSERT(isReplace());
+        return m_oldStructure.get();
+    }
+    
+    Structure* newStructure() const
+    {
+        ASSERT(isTransition());
+        return m_newStructure.get();
+    }
+    
+    StructureChain* chain() const
+    {
+        ASSERT(isTransition());
+        return m_chain.get();
+    }
+    
+    MacroAssemblerCodeRef stubRoutine() const
+    {
+        ASSERT(isTransition() || isReplace());
+        return m_stubRoutine;
+    }
+    
+    bool visitWeak() const;
+    
+private:
+    AccessType m_type;
+    WriteBarrier<Structure> m_oldStructure;
+    WriteBarrier<Structure> m_newStructure;
+    WriteBarrier<StructureChain> m_chain;
+    MacroAssemblerCodeRef m_stubRoutine;
+};
+
+class PolymorphicPutByIdList {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    // Initialize from a stub info; this will place one element in the list and it will
+    // be created by converting the stub info's put by id access information into our
+    // PutByIdAccess.
+    PolymorphicPutByIdList(
+        PutKind,
+        StructureStubInfo&,
+        MacroAssemblerCodePtr initialSlowPath);
+
+    // Either creates a new polymorphic put list, or returns the one that is already
+    // in place.
+    static PolymorphicPutByIdList* from(
+        PutKind,
+        StructureStubInfo&,
+        MacroAssemblerCodePtr initialSlowPath);
+    
+    ~PolymorphicPutByIdList();
+    
+    MacroAssemblerCodePtr currentSlowPathTarget() const
+    {
+        return m_list.last().stubRoutine().code();
+    }
+    
+    void addAccess(const PutByIdAccess&);
+    
+    bool isEmpty() const { return m_list.isEmpty(); }
+    unsigned size() const { return m_list.size(); }
+    bool isFull() const;
+    bool isAlmostFull() const; // True if adding an element would make isFull() true.
+    const PutByIdAccess& at(unsigned i) const { return m_list[i]; }
+    const PutByIdAccess& operator[](unsigned i) const { return m_list[i]; }
+    
+    PutKind kind() const { return m_kind; }
+    
+    bool visitWeak() const;
+    
+private:
+    Vector<PutByIdAccess, 2> m_list;
+    PutKind m_kind;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // PolymorphicPutByIdList_h
+
diff --git a/bytecode/PredictedType.cpp b/bytecode/PredictedType.cpp
new file mode 100644 (file)
index 0000000..e8a7177
--- /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.
+ * 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 "PredictedType.h"
+
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "ValueProfile.h"
+#include <wtf/BoundsCheckedPointer.h>
+
+namespace JSC {
+
+const char* predictionToString(PredictedType value)
+{
+    if (value == PredictNone)
+        return "None";
+    
+    static const int size = 256;
+    static char description[size];
+    BoundsCheckedPointer<char> ptr(description, size);
+    
+    bool isTop = true;
+    
+    if (value & PredictCellOther)
+        ptr.strcat("Othercell");
+    else
+        isTop = false;
+    
+    if (value & PredictObjectOther)
+        ptr.strcat("Otherobj");
+    else
+        isTop = false;
+    
+    if (value & PredictFinalObject)
+        ptr.strcat("Final");
+    else
+        isTop = false;
+
+    if (value & PredictArray)
+        ptr.strcat("Array");
+    else
+        isTop = false;
+    
+    if (value & PredictInt8Array)
+        ptr.strcat("Int8array");
+    else
+        isTop = false;
+    
+    if (value & PredictInt16Array)
+        ptr.strcat("Int16array");
+    else
+        isTop = false;
+    
+    if (value & PredictInt32Array)
+        ptr.strcat("Int32array");
+    else
+        isTop = false;
+    
+    if (value & PredictUint8Array)
+        ptr.strcat("Uint8array");
+    else
+        isTop = false;
+
+    if (value & PredictUint8ClampedArray)
+        ptr.strcat("Uint8clampedarray");
+    else
+        isTop = false;
+    
+    if (value & PredictUint16Array)
+        ptr.strcat("Uint16array");
+    else
+        isTop = false;
+    
+    if (value & PredictUint32Array)
+        ptr.strcat("Uint32array");
+    else
+        isTop = false;
+    
+    if (value & PredictFloat32Array)
+        ptr.strcat("Float32array");
+    else
+        isTop = false;
+    
+    if (value & PredictFloat64Array)
+        ptr.strcat("Float64array");
+    else
+        isTop = false;
+    
+    if (value & PredictFunction)
+        ptr.strcat("Function");
+    else
+        isTop = false;
+    
+    if (value & PredictString)
+        ptr.strcat("String");
+    else
+        isTop = false;
+    
+    if (value & PredictInt32)
+        ptr.strcat("Int");
+    else
+        isTop = false;
+    
+    if (value & PredictDoubleReal)
+        ptr.strcat("Doublereal");
+    else
+        isTop = false;
+    
+    if (value & PredictDoubleNaN)
+        ptr.strcat("Doublenan");
+    else
+        isTop = false;
+    
+    if (value & PredictBoolean)
+        ptr.strcat("Bool");
+    else
+        isTop = false;
+    
+    if (value & PredictOther)
+        ptr.strcat("Other");
+    else
+        isTop = false;
+    
+    if (isTop) {
+        ptr = description;
+        ptr.strcat("Top");
+    }
+    
+    if (value & PredictEmpty)
+        ptr.strcat("Empty");
+    
+    *ptr++ = 0;
+    
+    return description;
+}
+
+const char* predictionToAbbreviatedString(PredictedType prediction)
+{
+    if (isFinalObjectPrediction(prediction))
+        return "<Final>";
+    if (isArrayPrediction(prediction))
+        return "<Array>";
+    if (isStringPrediction(prediction))
+        return "<String>";
+    if (isFunctionPrediction(prediction))
+        return "<Function>";
+    if (isInt8ArrayPrediction(prediction))
+        return "<Int8array>";
+    if (isInt16ArrayPrediction(prediction))
+        return "<Int16array>";
+    if (isInt32ArrayPrediction(prediction))
+        return "<Int32array>";
+    if (isUint8ArrayPrediction(prediction))
+        return "<Uint8array>";
+    if (isUint16ArrayPrediction(prediction))
+        return "<Uint16array>";
+    if (isUint32ArrayPrediction(prediction))
+        return "<Uint32array>";
+    if (isFloat32ArrayPrediction(prediction))
+        return "<Float32array>";
+    if (isFloat64ArrayPrediction(prediction))
+        return "<Float64array>";
+    if (isObjectPrediction(prediction))
+        return "<Object>";
+    if (isCellPrediction(prediction))
+        return "<Cell>";
+    if (isInt32Prediction(prediction))
+        return "<Int32>";
+    if (isDoublePrediction(prediction))
+        return "<Double>";
+    if (isNumberPrediction(prediction))
+        return "<Number>";
+    if (isBooleanPrediction(prediction))
+        return "<Boolean>";
+    if (isOtherPrediction(prediction))
+        return "<Other>";
+    return "";
+}
+
+PredictedType predictionFromClassInfo(const ClassInfo* classInfo)
+{
+    if (classInfo == &JSFinalObject::s_info)
+        return PredictFinalObject;
+    
+    if (classInfo == &JSArray::s_info)
+        return PredictArray;
+    
+    if (classInfo == &JSString::s_info)
+        return PredictString;
+    
+    if (classInfo->isSubClassOf(&JSFunction::s_info))
+        return PredictFunction;
+
+    
+    if (classInfo->typedArrayStorageType != TypedArrayNone) {
+        switch (classInfo->typedArrayStorageType) {
+        case TypedArrayInt8:
+            return PredictInt8Array;
+        case TypedArrayInt16:
+            return PredictInt16Array;
+        case TypedArrayInt32:
+            return PredictInt32Array;
+        case TypedArrayUint8:
+            return PredictUint8Array;
+        case TypedArrayUint8Clamped:
+            return PredictUint8ClampedArray;
+        case TypedArrayUint16:
+            return PredictUint16Array;
+        case TypedArrayUint32:
+            return PredictUint32Array;
+        case TypedArrayFloat32:
+            return PredictFloat32Array;
+        case TypedArrayFloat64:
+            return PredictFloat64Array;
+        default:
+            break;
+        }
+    }
+    
+    if (classInfo->isSubClassOf(&JSObject::s_info))
+        return PredictObjectOther;
+    
+    return PredictCellOther;
+}
+
+PredictedType predictionFromStructure(Structure* structure)
+{
+    return predictionFromClassInfo(structure->classInfo());
+}
+
+PredictedType predictionFromCell(JSCell* cell)
+{
+    return predictionFromStructure(cell->structure());
+}
+
+PredictedType predictionFromValue(JSValue value)
+{
+    if (value.isEmpty())
+        return PredictEmpty;
+    if (value.isInt32())
+        return PredictInt32;
+    if (value.isDouble()) {
+        double number = value.asNumber();
+        if (number == number)
+            return PredictDoubleReal;
+        return PredictDoubleNaN;
+    }
+    if (value.isCell())
+        return predictionFromCell(value.asCell());
+    if (value.isBoolean())
+        return PredictBoolean;
+    ASSERT(value.isUndefinedOrNull());
+    return PredictOther;
+}
+
+} // namespace JSC
+
diff --git a/bytecode/PredictedType.h b/bytecode/PredictedType.h
new file mode 100644 (file)
index 0000000..54b3081
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * 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 PredictedType_h
+#define PredictedType_h
+
+#include "JSValue.h"
+
+namespace JSC {
+
+class Structure;
+
+typedef uint32_t PredictedType;
+static const PredictedType PredictNone              = 0x00000000; // We don't know anything yet.
+static const PredictedType PredictFinalObject       = 0x00000001; // It's definitely a JSFinalObject.
+static const PredictedType PredictArray             = 0x00000002; // It's definitely a JSArray.
+static const PredictedType PredictFunction          = 0x00000008; // It's definitely a JSFunction or one of its subclasses.
+static const PredictedType PredictInt8Array         = 0x00000010; // It's definitely an Int8Array or one of its subclasses.
+static const PredictedType PredictInt16Array        = 0x00000020; // It's definitely an Int16Array or one of its subclasses.
+static const PredictedType PredictInt32Array        = 0x00000040; // It's definitely an Int32Array or one of its subclasses.
+static const PredictedType PredictUint8Array        = 0x00000080; // It's definitely an Uint8Array or one of its subclasses.
+static const PredictedType PredictUint8ClampedArray = 0x00000100; // It's definitely an Uint8ClampedArray or one of its subclasses.
+static const PredictedType PredictUint16Array       = 0x00000200; // It's definitely an Uint16Array or one of its subclasses.
+static const PredictedType PredictUint32Array       = 0x00000400; // It's definitely an Uint32Array or one of its subclasses.
+static const PredictedType PredictFloat32Array      = 0x00000800; // It's definitely an Uint16Array or one of its subclasses.
+static const PredictedType PredictFloat64Array      = 0x00001000; // It's definitely an Uint16Array or one of its subclasses.
+static const PredictedType PredictObjectOther       = 0x00002000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
+static const PredictedType PredictObjectMask        = 0x00003fff; // Bitmask used for testing for any kind of object prediction.
+static const PredictedType PredictString            = 0x00004000; // It's definitely a JSString.
+static const PredictedType PredictCellOther         = 0x00008000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString.
+static const PredictedType PredictCell              = 0x0000ffff; // It's definitely a JSCell.
+static const PredictedType PredictInt32             = 0x00010000; // It's definitely an Int32.
+static const PredictedType PredictDoubleReal        = 0x00020000; // It's definitely a non-NaN double.
+static const PredictedType PredictDoubleNaN         = 0x00040000; // It's definitely a NaN.
+static const PredictedType PredictDouble            = 0x00060000; // It's either a non-NaN or a NaN double.
+static const PredictedType PredictNumber            = 0x00070000; // It's either an Int32 or a Double.
+static const PredictedType PredictBoolean           = 0x00080000; // It's definitely a Boolean.
+static const PredictedType PredictOther             = 0x08000000; // It's definitely none of the above.
+static const PredictedType PredictTop               = 0x0fffffff; // It can be any of the above.
+static const PredictedType PredictEmpty             = 0x10000000; // It's definitely an empty value marker.
+static const PredictedType PredictEmptyOrTop        = 0x1fffffff; // It can be any of the above.
+static const PredictedType FixedIndexedStorageMask = PredictInt8Array | PredictInt16Array | PredictInt32Array | PredictUint8Array | PredictUint8ClampedArray | PredictUint16Array | PredictUint32Array | PredictFloat32Array | PredictFloat64Array;
+
+typedef bool (*PredictionChecker)(PredictedType);
+
+inline bool isCellPrediction(PredictedType value)
+{
+    return !!(value & PredictCell) && !(value & ~PredictCell);
+}
+
+inline bool isObjectPrediction(PredictedType value)
+{
+    return !!(value & PredictObjectMask) && !(value & ~PredictObjectMask);
+}
+
+inline bool isFinalObjectPrediction(PredictedType value)
+{
+    return value == PredictFinalObject;
+}
+
+inline bool isFinalObjectOrOtherPrediction(PredictedType value)
+{
+    return !!(value & (PredictFinalObject | PredictOther)) && !(value & ~(PredictFinalObject | PredictOther));
+}
+
+inline bool isFixedIndexedStorageObjectPrediction(PredictedType value)
+{
+    return !!value && (value & FixedIndexedStorageMask) == value;
+}
+
+inline bool isStringPrediction(PredictedType value)
+{
+    return value == PredictString;
+}
+
+inline bool isArrayPrediction(PredictedType value)
+{
+    return value == PredictArray;
+}
+
+inline bool isFunctionPrediction(PredictedType value)
+{
+    return value == PredictFunction;
+}
+
+inline bool isInt8ArrayPrediction(PredictedType value)
+{
+    return value == PredictInt8Array;
+}
+
+inline bool isInt16ArrayPrediction(PredictedType value)
+{
+    return value == PredictInt16Array;
+}
+
+inline bool isInt32ArrayPrediction(PredictedType value)
+{
+    return value == PredictInt32Array;
+}
+
+inline bool isUint8ArrayPrediction(PredictedType value)
+{
+    return value == PredictUint8Array;
+}
+
+inline bool isUint8ClampedArrayPrediction(PredictedType value)
+{
+    return value == PredictUint8ClampedArray;
+}
+
+inline bool isUint16ArrayPrediction(PredictedType value)
+{
+    return value == PredictUint16Array;
+}
+
+inline bool isUint32ArrayPrediction(PredictedType value)
+{
+    return value == PredictUint32Array;
+}
+
+inline bool isFloat32ArrayPrediction(PredictedType value)
+{
+    return value == PredictFloat32Array;
+}
+
+inline bool isFloat64ArrayPrediction(PredictedType value)
+{
+    return value == PredictFloat64Array;
+}
+
+inline bool isActionableIntMutableArrayPrediction(PredictedType value)
+{
+    return isInt8ArrayPrediction(value)
+        || isInt16ArrayPrediction(value)
+        || isInt32ArrayPrediction(value)
+        || isUint8ArrayPrediction(value)
+        || isUint8ClampedArrayPrediction(value)
+        || isUint16ArrayPrediction(value)
+        || isUint32ArrayPrediction(value);
+}
+
+inline bool isActionableFloatMutableArrayPrediction(PredictedType value)
+{
+    return isFloat32ArrayPrediction(value)
+        || isFloat64ArrayPrediction(value);
+}
+
+inline bool isActionableTypedMutableArrayPrediction(PredictedType value)
+{
+    return isActionableIntMutableArrayPrediction(value)
+        || isActionableFloatMutableArrayPrediction(value);
+}
+
+inline bool isActionableMutableArrayPrediction(PredictedType value)
+{
+    return isArrayPrediction(value)
+        || isActionableTypedMutableArrayPrediction(value);
+}
+
+inline bool isActionableArrayPrediction(PredictedType value)
+{
+    return isStringPrediction(value)
+        || isActionableMutableArrayPrediction(value);
+}
+
+inline bool isArrayOrOtherPrediction(PredictedType value)
+{
+    return !!(value & (PredictArray | PredictOther)) && !(value & ~(PredictArray | PredictOther));
+}
+
+inline bool isInt32Prediction(PredictedType value)
+{
+    return value == PredictInt32;
+}
+
+inline bool isDoubleRealPrediction(PredictedType value)
+{
+    return value == PredictDoubleReal;
+}
+
+inline bool isDoublePrediction(PredictedType value)
+{
+    return !!value && (value & PredictDouble) == value;
+}
+
+inline bool isNumberPrediction(PredictedType value)
+{
+    return !!(value & PredictNumber) && !(value & ~PredictNumber);
+}
+
+inline bool isBooleanPrediction(PredictedType value)
+{
+    return value == PredictBoolean;
+}
+
+inline bool isOtherPrediction(PredictedType value)
+{
+    return value == PredictOther;
+}
+
+inline bool isEmptyPrediction(PredictedType value)
+{
+    return value == PredictEmpty;
+}
+
+const char* predictionToString(PredictedType value);
+const char* predictionToAbbreviatedString(PredictedType value);
+
+// Merge two predictions. Note that currently this just does left | right. It may
+// seem tempting to do so directly, but you would be doing so at your own peril,
+// since the merging protocol PredictedType may change at any time (and has already
+// changed several times in its history).
+inline PredictedType mergePredictions(PredictedType left, PredictedType right)
+{
+    return left | right;
+}
+
+template<typename T>
+inline bool mergePrediction(T& left, PredictedType right)
+{
+    PredictedType newPrediction = static_cast<T>(mergePredictions(static_cast<PredictedType>(left), right));
+    bool result = newPrediction != static_cast<PredictedType>(left);
+    left = newPrediction;
+    return result;
+}
+
+PredictedType predictionFromClassInfo(const ClassInfo*);
+PredictedType predictionFromStructure(Structure*);
+PredictedType predictionFromCell(JSCell*);
+PredictedType predictionFromValue(JSValue);
+
+} // namespace JSC
+
+#endif // PredictedType_h
diff --git a/bytecode/PutByIdStatus.cpp b/bytecode/PutByIdStatus.cpp
new file mode 100644 (file)
index 0000000..209d4cd
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "PutByIdStatus.h"
+
+#include "CodeBlock.h"
+#include "LowLevelInterpreter.h"
+#include "Structure.h"
+#include "StructureChain.h"
+
+namespace JSC {
+
+PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
+{
+    UNUSED_PARAM(profiledBlock);
+    UNUSED_PARAM(bytecodeIndex);
+    UNUSED_PARAM(ident);
+#if ENABLE(LLINT)
+    Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
+
+    Structure* structure = instruction[4].u.structure.get();
+    if (!structure)
+        return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+    
+    if (instruction[0].u.opcode == llint_op_put_by_id) {
+        size_t offset = structure->get(*profiledBlock->globalData(), ident);
+        if (offset == notFound)
+            return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+        
+        return PutByIdStatus(SimpleReplace, structure, 0, 0, offset);
+    }
+    
+    ASSERT(instruction[0].u.opcode == llint_op_put_by_id_transition_direct
+           || instruction[0].u.opcode == llint_op_put_by_id_transition_normal);
+    
+    Structure* newStructure = instruction[6].u.structure.get();
+    StructureChain* chain = instruction[7].u.structureChain.get();
+    ASSERT(newStructure);
+    ASSERT(chain);
+    
+    size_t offset = newStructure->get(*profiledBlock->globalData(), ident);
+    if (offset == notFound)
+        return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+    
+    return PutByIdStatus(SimpleTransition, structure, newStructure, chain, offset);
+#else
+    return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+#endif
+}
+
+PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
+{
+    UNUSED_PARAM(profiledBlock);
+    UNUSED_PARAM(bytecodeIndex);
+    UNUSED_PARAM(ident);
+#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
+    if (!profiledBlock->numberOfStructureStubInfos())
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+    
+    if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
+        return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+    
+    StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
+    if (!stubInfo.seen)
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+    
+    switch (stubInfo.accessType) {
+    case access_unset:
+        return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
+        
+    case access_put_by_id_replace: {
+        size_t offset = stubInfo.u.putByIdReplace.baseObjectStructure->get(
+            *profiledBlock->globalData(), ident);
+        if (offset != notFound) {
+            return PutByIdStatus(
+                SimpleReplace,
+                stubInfo.u.putByIdReplace.baseObjectStructure.get(),
+                0, 0,
+                offset);
+        }
+        return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+    }
+        
+    case access_put_by_id_transition_normal:
+    case access_put_by_id_transition_direct: {
+        size_t offset = stubInfo.u.putByIdTransition.structure->get(
+            *profiledBlock->globalData(), ident);
+        if (offset != notFound) {
+            return PutByIdStatus(
+                SimpleTransition,
+                stubInfo.u.putByIdTransition.previousStructure.get(),
+                stubInfo.u.putByIdTransition.structure.get(),
+                stubInfo.u.putByIdTransition.chain.get(),
+                offset);
+        }
+        return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+    }
+        
+    default:
+        return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+    }
+#else // ENABLE(JIT)
+    return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+#endif // ENABLE(JIT)
+}
+
+} // namespace JSC
+
diff --git a/bytecode/PutByIdStatus.h b/bytecode/PutByIdStatus.h
new file mode 100644 (file)
index 0000000..a6d95a4
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef PutByIdStatus_h
+#define PutByIdStatus_h
+
+#include <wtf/NotFound.h>
+
+namespace JSC {
+
+class CodeBlock;
+class Identifier;
+class Structure;
+class StructureChain;
+
+class PutByIdStatus {
+public:
+    enum State {
+        // It's uncached so we have no information.
+        NoInformation,
+        // It's cached as a direct store into an object property for cases where the object
+        // already has the property.
+        SimpleReplace,
+        // It's cached as a transition from one structure that lacks the property to one that
+        // includes the property, and a direct store to this new property.
+        SimpleTransition,
+        // It's known to often take slow path.
+        TakesSlowPath
+    };
+    
+    PutByIdStatus()
+        : m_state(NoInformation)
+        , m_oldStructure(0)
+        , m_newStructure(0)
+        , m_structureChain(0)
+        , m_offset(notFound)
+    {
+    }
+    
+    PutByIdStatus(
+        State state,
+        Structure* oldStructure,
+        Structure* newStructure,
+        StructureChain* structureChain,
+        size_t offset)
+        : m_state(state)
+        , m_oldStructure(oldStructure)
+        , m_newStructure(newStructure)
+        , m_structureChain(structureChain)
+        , m_offset(offset)
+    {
+        ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == !m_oldStructure);
+        ASSERT((m_state != SimpleTransition) == !m_newStructure);
+        ASSERT((m_state != SimpleTransition) == !m_structureChain);
+        ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == (m_offset == notFound));
+    }
+    
+    static PutByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&);
+    
+    State state() const { return m_state; }
+    
+    bool isSet() const { return m_state != NoInformation; }
+    bool operator!() const { return m_state == NoInformation; }
+    bool isSimpleReplace() const { return m_state == SimpleReplace; }
+    bool isSimpleTransition() const { return m_state == SimpleTransition; }
+    bool takesSlowPath() const { return m_state == TakesSlowPath; }
+    
+    Structure* oldStructure() const { return m_oldStructure; }
+    Structure* newStructure() const { return m_newStructure; }
+    StructureChain* structureChain() const { return m_structureChain; }
+    size_t offset() const { return m_offset; }
+    
+private:
+    static PutByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, Identifier&);
+    
+    State m_state;
+    Structure* m_oldStructure;
+    Structure* m_newStructure;
+    StructureChain* m_structureChain;
+    size_t m_offset;
+};
+
+} // namespace JSC
+
+#endif // PutByIdStatus_h
+
diff --git a/bytecode/PutKind.h b/bytecode/PutKind.h
new file mode 100644 (file)
index 0000000..7a1dd64
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef PutKind_h
+#define PutKind_h
+
+namespace JSC {
+
+enum PutKind { Direct, NotDirect };
+
+} // namespace JSC
+
+#endif // PutKind_h
+
index f47e6982517c3f7df7f2b3208a9404874cbb4209..f07dc79fb78258d861d4f48517f1b55b2963953d 100644 (file)
@@ -67,14 +67,14 @@ void SamplingFlags::stop()
         total += s_flagCounts[i];
 
     if (total) {
         total += s_flagCounts[i];
 
     if (total) {
-        printf("\nSamplingFlags: sample counts with flags set: (%lld total)\n", total);
+        dataLog("\nSamplingFlags: sample counts with flags set: (%lld total)\n", total);
         for (unsigned i = 0; i <= 32; ++i) {
             if (s_flagCounts[i])
         for (unsigned i = 0; i <= 32; ++i) {
             if (s_flagCounts[i])
-                printf("  [ %02d ] : %lld\t\t(%03.2f%%)\n", i, s_flagCounts[i], (100.0 * s_flagCounts[i]) / total);
+                dataLog("  [ %02d ] : %lld\t\t(%03.2f%%)\n", i, s_flagCounts[i], (100.0 * s_flagCounts[i]) / total);
         }
         }
-        printf("\n");
+        dataLog("\n");
     } else
     } else
-    printf("\nSamplingFlags: no samples.\n\n");
+    dataLog("\nSamplingFlags: no samples.\n\n");
 }
 uint64_t SamplingFlags::s_flagCounts[33];
 
 }
 uint64_t SamplingFlags::s_flagCounts[33];
 
@@ -83,6 +83,93 @@ void SamplingFlags::start() {}
 void SamplingFlags::stop() {}
 #endif
 
 void SamplingFlags::stop() {}
 #endif
 
+#if ENABLE(SAMPLING_REGIONS)
+volatile uintptr_t SamplingRegion::s_currentOrReserved;
+Spectrum<const char*>* SamplingRegion::s_spectrum;
+unsigned long SamplingRegion::s_noneOfTheAbove;
+unsigned SamplingRegion::s_numberOfSamplesSinceDump;
+
+SamplingRegion::Locker::Locker()
+{
+    uintptr_t previous;
+    while (true) {
+        previous = s_currentOrReserved;
+        if (previous & 1) {
+#if OS(UNIX)
+            sched_yield();
+#endif
+            continue;
+        }
+        if (WTF::weakCompareAndSwapUIntPtr(&s_currentOrReserved, previous, previous | 1))
+            break;
+    }
+}
+
+SamplingRegion::Locker::~Locker()
+{
+    // We don't need the CAS, but we do it out of an
+    // abundance of caution (and because it gives us a memory fence, which is
+    // never bad).
+    uintptr_t previous;
+    do {
+        previous = s_currentOrReserved;
+    } while (!WTF::weakCompareAndSwapUIntPtr(&s_currentOrReserved, previous, previous & ~1));
+}
+
+void SamplingRegion::sample()
+{
+    // Make sure we lock s_current.
+    Locker locker;
+    
+    // Create a spectrum if we don't have one already.
+    if (!s_spectrum)
+        s_spectrum = new Spectrum<const char*>();
+    
+    ASSERT(s_currentOrReserved & 1);
+    
+    // Walk the region stack, and record each region we see.
+    SamplingRegion* region = bitwise_cast<SamplingRegion*>(s_currentOrReserved & ~1);
+    if (region) {
+        for (; region; region = region->m_previous)
+            s_spectrum->add(region->m_name);
+    } else
+        s_noneOfTheAbove++;
+    
+    if (s_numberOfSamplesSinceDump++ == SamplingThread::s_hertz) {
+        s_numberOfSamplesSinceDump = 0;
+        dumpInternal();
+    }
+}
+
+void SamplingRegion::dump()
+{
+    Locker locker;
+    
+    dumpInternal();
+}
+
+void SamplingRegion::dumpInternal()
+{
+    if (!s_spectrum) {
+        dataLog("\nSamplingRegion: was never sampled.\n\n");
+        return;
+    }
+    
+    Vector<Spectrum<const char*>::KeyAndCount> list = s_spectrum->buildList();
+    
+    unsigned long total = s_noneOfTheAbove;
+    for (unsigned i = list.size(); i--;)
+        total += list[i].count;
+    
+    dataLog("\nSamplingRegion: sample counts for regions: (%lu samples)\n", total);
+
+    for (unsigned i = list.size(); i--;)
+        dataLog("    %3.2lf%%  %s\n", (100.0 * list[i].count) / total, list[i].key);
+}
+#else // ENABLE(SAMPLING_REGIONS)
+void SamplingRegion::dump() { }
+#endif // ENABLE(SAMPLING_REGIONS)
+
 /*
   Start with flag 16 set.
   By doing this the monitoring of lower valued flags will be masked out
 /*
   Start with flag 16 set.
   By doing this the monitoring of lower valued flags will be masked out
@@ -123,7 +210,7 @@ bool SamplingThread::s_running = false;
 unsigned SamplingThread::s_hertz = 10000;
 ThreadIdentifier SamplingThread::s_samplingThread;
 
 unsigned SamplingThread::s_hertz = 10000;
 ThreadIdentifier SamplingThread::s_samplingThread;
 
-void* SamplingThread::threadStartFunc(void*)
+void SamplingThread::threadStartFunc(void*)
 {
     while (s_running) {
         sleepForMicroseconds(hertz2us(s_hertz));
 {
     while (s_running) {
         sleepForMicroseconds(hertz2us(s_hertz));
@@ -131,12 +218,13 @@ void* SamplingThread::threadStartFunc(void*)
 #if ENABLE(SAMPLING_FLAGS)
         SamplingFlags::sample();
 #endif
 #if ENABLE(SAMPLING_FLAGS)
         SamplingFlags::sample();
 #endif
+#if ENABLE(SAMPLING_REGIONS)
+        SamplingRegion::sample();
+#endif
 #if ENABLE(OPCODE_SAMPLING)
         SamplingTool::sample();
 #endif
     }
 #if ENABLE(OPCODE_SAMPLING)
         SamplingTool::sample();
 #endif
     }
-
-    return 0;
 }
 
 
 }
 
 
@@ -153,7 +241,7 @@ void SamplingThread::stop()
 {
     ASSERT(s_running);
     s_running = false;
 {
     ASSERT(s_running);
     s_running = false;
-    waitForThreadCompletion(s_samplingThread, 0);
+    waitForThreadCompletion(s_samplingThread);
 }
 
 
 }
 
 
@@ -209,12 +297,13 @@ void SamplingTool::sample()
     s_samplingTool->doRun();
 }
 
     s_samplingTool->doRun();
 }
 
-void SamplingTool::notifyOfScope(ScriptExecutable* script)
+void SamplingTool::notifyOfScope(JSGlobalData& globalData, ScriptExecutable* script)
 {
 #if ENABLE(CODEBLOCK_SAMPLING)
     MutexLocker locker(m_scriptSampleMapMutex);
 {
 #if ENABLE(CODEBLOCK_SAMPLING)
     MutexLocker locker(m_scriptSampleMapMutex);
-    m_scopeSampleMap->set(script, new ScriptSampleRecord(script));
+    m_scopeSampleMap->set(script, adoptPtr(new ScriptSampleRecord(globalData, script)));
 #else
 #else
+    UNUSED_PARAM(globalData);
     UNUSED_PARAM(script);
 #endif
 }
     UNUSED_PARAM(script);
 #endif
 }
@@ -282,10 +371,10 @@ void SamplingTool::dump(ExecState* exec)
 
     // (2) Print Opcode sampling results.
 
 
     // (2) Print Opcode sampling results.
 
-    printf("\nBytecode samples [*]\n");
-    printf("                             sample   %% of       %% of     |   cti     cti %%\n");
-    printf("opcode                       count     VM        total    |  count   of self\n");
-    printf("-------------------------------------------------------   |  ----------------\n");
+    dataLog("\nBytecode samples [*]\n");
+    dataLog("                             sample   %% of       %% of     |   cti     cti %%\n");
+    dataLog("opcode                       count     VM        total    |  count   of self\n");
+    dataLog("-------------------------------------------------------   |  ----------------\n");
 
     for (int i = 0; i < numOpcodeIDs; ++i) {
         long long count = opcodeSampleInfo[i].count;
 
     for (int i = 0; i < numOpcodeIDs; ++i) {
         long long count = opcodeSampleInfo[i].count;
@@ -300,18 +389,18 @@ void SamplingTool::dump(ExecState* exec)
         double percentOfTotal = (static_cast<double>(count) * 100) / m_sampleCount;
         long long countInCTIFunctions = opcodeSampleInfo[i].countInCTIFunctions;
         double percentInCTIFunctions = (static_cast<double>(countInCTIFunctions) * 100) / count;
         double percentOfTotal = (static_cast<double>(count) * 100) / m_sampleCount;
         long long countInCTIFunctions = opcodeSampleInfo[i].countInCTIFunctions;
         double percentInCTIFunctions = (static_cast<double>(countInCTIFunctions) * 100) / count;
-        fprintf(stdout, "%s:%s%-6lld %.3f%%\t%.3f%%\t  |   %-6lld %.3f%%\n", opcodeName, opcodePadding, count, percentOfVM, percentOfTotal, countInCTIFunctions, percentInCTIFunctions);
+        debugDebugPrintf("%s:%s%-6lld %.3f%%\t%.3f%%\t  |   %-6lld %.3f%%\n", opcodeName, opcodePadding, count, percentOfVM, percentOfTotal, countInCTIFunctions, percentInCTIFunctions);
     }
     
     }
     
-    printf("\n[*] Samples inside host code are not charged to any Bytecode.\n\n");
-    printf("\tSamples inside VM:\t\t%lld / %lld (%.3f%%)\n", m_opcodeSampleCount, m_sampleCount, (static_cast<double>(m_opcodeSampleCount) * 100) / m_sampleCount);
-    printf("\tSamples inside host code:\t%lld / %lld (%.3f%%)\n\n", m_sampleCount - m_opcodeSampleCount, m_sampleCount, (static_cast<double>(m_sampleCount - m_opcodeSampleCount) * 100) / m_sampleCount);
-    printf("\tsample count:\tsamples inside this opcode\n");
-    printf("\t%% of VM:\tsample count / all opcode samples\n");
-    printf("\t%% of total:\tsample count / all samples\n");
-    printf("\t--------------\n");
-    printf("\tcti count:\tsamples inside a CTI function called by this opcode\n");
-    printf("\tcti %% of self:\tcti count / sample count\n");
+    dataLog("\n[*] Samples inside host code are not charged to any Bytecode.\n\n");
+    dataLog("\tSamples inside VM:\t\t%lld / %lld (%.3f%%)\n", m_opcodeSampleCount, m_sampleCount, (static_cast<double>(m_opcodeSampleCount) * 100) / m_sampleCount);
+    dataLog("\tSamples inside host code:\t%lld / %lld (%.3f%%)\n\n", m_sampleCount - m_opcodeSampleCount, m_sampleCount, (static_cast<double>(m_sampleCount - m_opcodeSampleCount) * 100) / m_sampleCount);
+    dataLog("\tsample count:\tsamples inside this opcode\n");
+    dataLog("\t%% of VM:\tsample count / all opcode samples\n");
+    dataLog("\t%% of total:\tsample count / all samples\n");
+    dataLog("\t--------------\n");
+    dataLog("\tcti count:\tsamples inside a CTI function called by this opcode\n");
+    dataLog("\tcti %% of self:\tcti count / sample count\n");
     
 #if ENABLE(CODEBLOCK_SAMPLING)
 
     
 #if ENABLE(CODEBLOCK_SAMPLING)
 
@@ -321,13 +410,13 @@ void SamplingTool::dump(ExecState* exec)
     Vector<ScriptSampleRecord*> codeBlockSamples(scopeCount);
     ScriptSampleRecordMap::iterator iter = m_scopeSampleMap->begin();
     for (int i = 0; i < scopeCount; ++i, ++iter)
     Vector<ScriptSampleRecord*> codeBlockSamples(scopeCount);
     ScriptSampleRecordMap::iterator iter = m_scopeSampleMap->begin();
     for (int i = 0; i < scopeCount; ++i, ++iter)
-        codeBlockSamples[i] = iter->second;
+        codeBlockSamples[i] = iter->second.get();
 
     qsort(codeBlockSamples.begin(), scopeCount, sizeof(ScriptSampleRecord*), compareScriptSampleRecords);
 
     // (4) Print data from 'codeBlockSamples' array.
 
 
     qsort(codeBlockSamples.begin(), scopeCount, sizeof(ScriptSampleRecord*), compareScriptSampleRecords);
 
     // (4) Print data from 'codeBlockSamples' array.
 
-    printf("\nCodeBlock samples\n\n"); 
+    dataLog("\nCodeBlock samples\n\n"); 
 
     for (int i = 0; i < scopeCount; ++i) {
         ScriptSampleRecord* record = codeBlockSamples[i];
 
     for (int i = 0; i < scopeCount; ++i) {
         ScriptSampleRecord* record = codeBlockSamples[i];
@@ -337,21 +426,21 @@ 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().utf8().data(), codeBlock->lineNumberForBytecodeOffset(0), record->m_sampleCount, m_sampleCount, blockPercent);
+            dataLog("#%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);
 
-                printf("    Opcode and line number samples [*]\n\n");
+                dataLog("    Opcode and line number samples [*]\n\n");
                 for (unsigned op = 0; op < record->m_size; ++op) {
                     int count = record->m_samples[op];
                     if (count) {
                 for (unsigned op = 0; op < record->m_size; ++op) {
                     int count = record->m_samples[op];
                     if (count) {
-                        printf("    [% 4d] has sample count: % 4d\n", op, count);
+                        dataLog("    [% 4d] has sample count: % 4d\n", op, count);
                         unsigned line = codeBlock->lineNumberForBytecodeOffset(op);
                         lineCounts.set(line, (lineCounts.contains(line) ? lineCounts.get(line) : 0) + count);
                     }
                 }
                         unsigned line = codeBlock->lineNumberForBytecodeOffset(op);
                         lineCounts.set(line, (lineCounts.contains(line) ? lineCounts.get(line) : 0) + count);
                     }
                 }
-                printf("\n");
+                dataLog("\n");
 
                 int linesCount = lineCounts.size();
                 Vector<LineCountInfo> lineCountInfo(linesCount);
 
                 int linesCount = lineCounts.size();
                 Vector<LineCountInfo> lineCountInfo(linesCount);
@@ -364,12 +453,12 @@ void SamplingTool::dump(ExecState* exec)
                 qsort(lineCountInfo.begin(), linesCount, sizeof(LineCountInfo), compareLineCountInfoSampling);
 
                 for (lineno = 0; lineno < linesCount; ++lineno) {
                 qsort(lineCountInfo.begin(), linesCount, sizeof(LineCountInfo), compareLineCountInfoSampling);
 
                 for (lineno = 0; lineno < linesCount; ++lineno) {
-                    printf("    Line #%d has sample count %d.\n", lineCountInfo[lineno].line, lineCountInfo[lineno].count);
+                    dataLog("    Line #%d has sample count %d.\n", lineCountInfo[lineno].line, lineCountInfo[lineno].count);
                 }
                 }
-                printf("\n");
-                printf("    [*] Samples inside host code are charged to the calling Bytecode.\n");
-                printf("        Samples on a call / return boundary are not charged to a specific opcode or line.\n\n");
-                printf("            Samples on a call / return boundary: %d / %d (%.3f%%)\n\n", record->m_sampleCount - record->m_opcodeSampleCount, record->m_sampleCount, (static_cast<double>(record->m_sampleCount - record->m_opcodeSampleCount) * 100) / record->m_sampleCount);
+                dataLog("\n");
+                dataLog("    [*] Samples inside host code are charged to the calling Bytecode.\n");
+                dataLog("        Samples on a call / return boundary are not charged to a specific opcode or line.\n\n");
+                dataLog("            Samples on a call / return boundary: %d / %d (%.3f%%)\n\n", record->m_sampleCount - record->m_opcodeSampleCount, record->m_sampleCount, (static_cast<double>(record->m_sampleCount - record->m_opcodeSampleCount) * 100) / record->m_sampleCount);
             }
         }
     }
             }
         }
     }
@@ -386,21 +475,4 @@ void SamplingTool::dump(ExecState*)
 
 #endif
 
 
 #endif
 
-void AbstractSamplingCounter::dump()
-{
-#if ENABLE(SAMPLING_COUNTERS)
-    if (s_abstractSamplingCounterChain != &s_abstractSamplingCounterChainEnd) {
-        printf("\nSampling Counter Values:\n");
-        for (AbstractSamplingCounter* currCounter = s_abstractSamplingCounterChain; (currCounter != &s_abstractSamplingCounterChainEnd); currCounter = currCounter->m_next)
-            printf("\t%s\t: %lld\n", currCounter->m_name, currCounter->m_counter);
-        printf("\n\n");
-    }
-    s_completed = true;
-#endif
-}
-
-AbstractSamplingCounter AbstractSamplingCounter::s_abstractSamplingCounterChainEnd;
-AbstractSamplingCounter* AbstractSamplingCounter::s_abstractSamplingCounterChain = &s_abstractSamplingCounterChainEnd;
-bool AbstractSamplingCounter::s_completed = false;
-
 } // namespace JSC
 } // namespace JSC
index 1d77b31d76e7af32b4a4f102257f66e0b95e1a61..52a6e35ad1e5cdc87c44275b28255a8dc95e34e2 100644 (file)
 #include "Strong.h"
 #include "Nodes.h"
 #include "Opcode.h"
 #include "Strong.h"
 #include "Nodes.h"
 #include "Opcode.h"
+#include "SamplingCounter.h"
 #include <wtf/Assertions.h>
 #include <wtf/Assertions.h>
+#include <wtf/Atomics.h>
 #include <wtf/HashMap.h>
 #include <wtf/HashMap.h>
+#include <wtf/MainThread.h>
 #include <wtf/Threading.h>
 
 namespace JSC {
 #include <wtf/Threading.h>
 
 namespace JSC {
@@ -42,8 +45,8 @@ namespace JSC {
 
     class SamplingFlags {
     public:
 
     class SamplingFlags {
     public:
-        static void start();
-        static void stop();
+        JS_EXPORT_PRIVATE static void start();
+        JS_EXPORT_PRIVATE static void stop();
 
 #if ENABLE(SAMPLING_FLAGS)
         static void setFlag(unsigned flag)
 
 #if ENABLE(SAMPLING_FLAGS)
         static void setFlag(unsigned flag)
@@ -86,12 +89,95 @@ namespace JSC {
 
 #endif
     private:
 
 #endif
     private:
-        static uint32_t s_flags;
+        JS_EXPORTDATA static uint32_t s_flags;
 #if ENABLE(SAMPLING_FLAGS)
         static uint64_t s_flagCounts[33];
 #endif
     };
 
 #if ENABLE(SAMPLING_FLAGS)
         static uint64_t s_flagCounts[33];
 #endif
     };
 
+#if ENABLE(SAMPLING_REGIONS)
+    class SamplingRegion {
+    public:
+        // Create a scoped sampling region using a C string constant name that describes
+        // what you are doing. This must be a string constant that persists for the
+        // lifetime of the process and is immutable.
+        SamplingRegion(const char* name)
+        {
+            if (!isMainThread()) {
+                m_name = 0;
+                return;
+            }
+            
+            m_name = name;
+            exchangeCurrent(this, &m_previous);
+            ASSERT(!m_previous || m_previous > this);
+        }
+        
+        ~SamplingRegion()
+        {
+            if (!m_name)
+                return;
+            
+            ASSERT(bitwise_cast<SamplingRegion*>(s_currentOrReserved & ~1) == this);
+            exchangeCurrent(m_previous);
+        }
+        
+        static void sample();
+        
+        JS_EXPORT_PRIVATE static void dump();
+        
+    private:
+        const char* m_name;
+        SamplingRegion* m_previous;
+
+        static void exchangeCurrent(SamplingRegion* current, SamplingRegion** previousPtr = 0)
+        {
+            uintptr_t previous;
+            while (true) {
+                previous = s_currentOrReserved;
+                
+                // If it's reserved (i.e. sampling thread is reading it), loop around.
+                if (previous & 1) {
+#if OS(UNIX)
+                    sched_yield();
+#endif
+                    continue;
+                }
+                
+                // If we're going to CAS, then make sure previous is set.
+                if (previousPtr)
+                    *previousPtr = bitwise_cast<SamplingRegion*>(previous);
+                
+                if (WTF::weakCompareAndSwapUIntPtr(&s_currentOrReserved, previous, bitwise_cast<uintptr_t>(current)))
+                    break;
+            }
+        }
+        
+        static void dumpInternal();
+
+        class Locker {
+        public:
+            Locker();
+            ~Locker();
+        };
+
+        static volatile uintptr_t s_currentOrReserved;
+        
+        // rely on identity hashing of string constants
+        static Spectrum<const char*>* s_spectrum;
+        
+        static unsigned long s_noneOfTheAbove;
+        
+        static unsigned s_numberOfSamplesSinceDump;
+    };
+#else // ENABLE(SAMPLING_REGIONS)
+    class SamplingRegion {
+    public:
+        SamplingRegion(const char*) { }
+        JS_EXPORT_PRIVATE void dump();
+    };
+#endif // ENABLE(SAMPLING_REGIONS)
+
     class CodeBlock;
     class ExecState;
     class Interpreter;
     class CodeBlock;
     class ExecState;
     class Interpreter;
@@ -125,7 +211,7 @@ namespace JSC {
         unsigned m_size;
     };
 
         unsigned m_size;
     };
 
-    typedef WTF::HashMap<ScriptExecutable*, ScriptSampleRecord*> ScriptSampleRecordMap;
+    typedef HashMap<ScriptExecutable*, OwnPtr<ScriptSampleRecord> > ScriptSampleRecordMap;
 
     class SamplingThread {
     public:
 
     class SamplingThread {
     public:
@@ -134,10 +220,10 @@ namespace JSC {
         static unsigned s_hertz;
         static ThreadIdentifier s_samplingThread;
 
         static unsigned s_hertz;
         static ThreadIdentifier s_samplingThread;
 
-        static void start(unsigned hertz=10000);
-        static void stop();
+        JS_EXPORT_PRIVATE static void start(unsigned hertz=10000);
+        JS_EXPORT_PRIVATE static void stop();
 
 
-        static void* threadStartFunc(void*);
+        static void threadStartFunc(void*);
     };
 
     class SamplingTool {
     };
 
     class SamplingTool {
@@ -201,24 +287,17 @@ namespace JSC {
             , m_sampleCount(0)
             , m_opcodeSampleCount(0)
 #if ENABLE(CODEBLOCK_SAMPLING)
             , m_sampleCount(0)
             , m_opcodeSampleCount(0)
 #if ENABLE(CODEBLOCK_SAMPLING)
-            , m_scopeSampleMap(new ScriptSampleRecordMap())
+            , m_scopeSampleMap(adoptPtr(new ScriptSampleRecordMap))
 #endif
         {
             memset(m_opcodeSamples, 0, sizeof(m_opcodeSamples));
             memset(m_opcodeSamplesInCTIFunctions, 0, sizeof(m_opcodeSamplesInCTIFunctions));
         }
 
 #endif
         {
             memset(m_opcodeSamples, 0, sizeof(m_opcodeSamples));
             memset(m_opcodeSamplesInCTIFunctions, 0, sizeof(m_opcodeSamplesInCTIFunctions));
         }
 
-        ~SamplingTool()
-        {
-#if ENABLE(CODEBLOCK_SAMPLING)
-            deleteAllValues(*m_scopeSampleMap);
-#endif
-        }
-
-        void setup();
+        JS_EXPORT_PRIVATE void setup();
         void dump(ExecState*);
 
         void dump(ExecState*);
 
-        void notifyOfScope(ScriptExecutable* scope);
+        void notifyOfScope(JSGlobalData&, ScriptExecutable* scope);
 
         void sample(CodeBlock* codeBlock, Instruction* vPC)
         {
 
         void sample(CodeBlock* codeBlock, Instruction* vPC)
         {
@@ -279,143 +358,6 @@ namespace JSC {
 #endif
     };
 
 #endif
     };
 
-    // 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 DeletableSamplingCounter;
-    public:
-        void count(uint32_t count = 1)
-        {
-            m_counter += count;
-        }
-
-        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)
-        {
-            m_counter = 0;
-            m_name = name;
-
-            // Set m_next to point to the head of the chain, and inform whatever is
-            // currently at the head that this node will now hold the pointer to it.
-            m_next = s_abstractSamplingCounterChain;
-            s_abstractSamplingCounterChain->m_referer = &m_next;
-            // Add this node to the head of the list.
-            s_abstractSamplingCounterChain = this;
-            m_referer = &s_abstractSamplingCounterChain;
-        }
-
-        int64_t m_counter;
-        const char* m_name;
-        AbstractSamplingCounter* m_next;
-        // This is a pointer to the pointer to this node in the chain; used to
-        // allow fast linked list deletion.
-        AbstractSamplingCounter** m_referer;
-        // Null object used to detect end of static chain.
-        static AbstractSamplingCounter s_abstractSamplingCounterChainEnd;
-        static AbstractSamplingCounter* s_abstractSamplingCounterChain;
-        static bool s_completed;
-    };
-
-#if ENABLE(SAMPLING_COUNTERS)
-    // SamplingCounter:
-    //
-    // This class is suitable and (hopefully!) convenient for cases where a counter is
-    // required within the scope of a single function.  It can be instantiated as a
-    // static variable since it contains a constructor but not a destructor (static
-    // variables in WebKit cannot have destructors).
-    //
-    // For example:
-    //
-    // void someFunction()
-    // {
-    //     static SamplingCounter countMe("This is my counter.  There are many like it, but this one is mine.");
-    //     countMe.count();
-    //     // ...
-    // }
-    //
-    class SamplingCounter : public AbstractSamplingCounter {
-    public:
-        SamplingCounter(const char* name) { init(name); }
-    };
-
-    // GlobalSamplingCounter:
-    //
-    // This class is suitable for use where a counter is to be declared globally,
-    // since it contains neither a constructor nor destructor.  Instead, ensure
-    // that 'name()' is called to provide the counter with a name (and also to
-    // allow it to be printed out on exit).
-    //
-    // GlobalSamplingCounter globalCounter;
-    //
-    // void firstFunction()
-    // {
-    //     // Put this within a function that is definitely called!
-    //     // (Or alternatively alongside all calls to 'count()').
-    //     globalCounter.name("I Name You Destroyer.");
-    //     globalCounter.count();
-    //     // ...
-    // }
-    //
-    // void secondFunction()
-    // {
-    //     globalCounter.count();
-    //     // ...
-    // }
-    //
-    class GlobalSamplingCounter : public AbstractSamplingCounter {
-    public:
-        void name(const char* name)
-        {
-            // Global objects should be mapped in zero filled memory, so this should
-            // be a safe (albeit not necessarily threadsafe) check for 'first call'.
-            if (!m_next)
-                init(name);
-        }
-    };
-
-    // DeletableSamplingCounter:
-    //
-    // The above classes (SamplingCounter, GlobalSamplingCounter), are intended for
-    // use within a global or static scope, and as such cannot have a destructor.
-    // This means there is no convenient way for them to remove themselves from the
-    // static list of counters, and should an instance of either class be freed
-    // before 'dump()' has walked over the list it will potentially walk over an
-    // invalid pointer.
-    //
-    // This class is intended for use where the counter may possibly be deleted before
-    // the program exits.  Should this occur, the counter will print it's value to
-    // stderr, and remove itself from the static list.  Example:
-    //
-    // DeletableSamplingCounter* counter = new DeletableSamplingCounter("The Counter With No Name");
-    // counter->count();
-    // delete counter;
-    //
-    class DeletableSamplingCounter : public AbstractSamplingCounter {
-    public:
-        DeletableSamplingCounter(const char* name) { init(name); }
-
-        ~DeletableSamplingCounter()
-        {
-            if (!s_completed)
-                fprintf(stderr, "DeletableSamplingCounter \"%s\" deleted early (with count %lld)\n", m_name, m_counter);
-            // Our m_referer pointer should know where the pointer to this node is,
-            // and m_next should know that this node is the previous node in the list.
-            ASSERT(*m_referer == this);
-            ASSERT(m_next->m_referer == &m_next);
-            // Remove this node from the list, and inform m_next that we have done so.
-            m_next->m_referer = m_referer;
-            *m_referer = m_next;
-        }
-    };
-#endif
-
 } // namespace JSC
 
 #endif // SamplingTool_h
 } // namespace JSC
 
 #endif // SamplingTool_h
diff --git a/bytecode/StructureSet.h b/bytecode/StructureSet.h
new file mode 100644 (file)
index 0000000..bfc30fc
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * 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 StructureSet_h
+#define StructureSet_h
+
+#include "PredictedType.h"
+#include "Structure.h"
+#include <stdio.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+namespace DFG {
+class StructureAbstractValue;
+}
+
+class StructureSet {
+public:
+    StructureSet() { }
+    
+    StructureSet(Structure* structure)
+    {
+        m_structures.append(structure);
+    }
+    
+    void clear()
+    {
+        m_structures.clear();
+    }
+    
+    void add(Structure* structure)
+    {
+        ASSERT(!contains(structure));
+        m_structures.append(structure);
+    }
+    
+    bool addAll(const StructureSet& other)
+    {
+        bool changed = false;
+        for (size_t i = 0; i < other.size(); ++i) {
+            if (contains(other[i]))
+                continue;
+            add(other[i]);
+            changed = true;
+        }
+        return changed;
+    }
+    
+    void remove(Structure* structure)
+    {
+        for (size_t i = 0; i < m_structures.size(); ++i) {
+            if (m_structures[i] != structure)
+                continue;
+            
+            m_structures[i] = m_structures.last();
+            m_structures.removeLast();
+            return;
+        }
+    }
+    
+    bool contains(Structure* structure) const
+    {
+        for (size_t i = 0; i < m_structures.size(); ++i) {
+            if (m_structures[i] == structure)
+                return true;
+        }
+        return false;
+    }
+    
+    bool isSubsetOf(const StructureSet& other) const
+    {
+        for (size_t i = 0; i < m_structures.size(); ++i) {
+            if (!other.contains(m_structures[i]))
+                return false;
+        }
+        return true;
+    }
+    
+    bool isSupersetOf(const StructureSet& other) const
+    {
+        return other.isSubsetOf(*this);
+    }
+    
+    size_t size() const { return m_structures.size(); }
+    
+    bool allAreUsingInlinePropertyStorage() const
+    {
+        for (size_t i = 0; i < m_structures.size(); ++i) {
+            if (!m_structures[i]->isUsingInlineStorage())
+                return false;
+        }
+        return true;
+    }
+    
+    Structure* at(size_t i) const { return m_structures.at(i); }
+    
+    Structure* operator[](size_t i) const { return at(i); }
+    
+    Structure* last() const { return m_structures.last(); }
+
+    PredictedType predictionFromStructures() const
+    {
+        PredictedType result = PredictNone;
+        
+        for (size_t i = 0; i < m_structures.size(); ++i)
+            mergePrediction(result, predictionFromStructure(m_structures[i]));
+        
+        return result;
+    }
+    
+    bool operator==(const StructureSet& other) const
+    {
+        if (m_structures.size() != other.m_structures.size())
+            return false;
+        
+        for (size_t i = 0; i < m_structures.size(); ++i) {
+            if (!other.contains(m_structures[i]))
+                return false;
+        }
+        
+        return true;
+    }
+    
+    void dump(FILE* out)
+    {
+        fprintf(out, "[");
+        for (size_t i = 0; i < m_structures.size(); ++i) {
+            if (i)
+                fprintf(out, ", ");
+            fprintf(out, "%p", m_structures[i]);
+        }
+        fprintf(out, "]");
+    }
+    
+private:
+    friend class DFG::StructureAbstractValue;
+    
+    Vector<Structure*, 2> m_structures;
+};
+
+} // namespace JSC
+
+#endif // StructureSet_h
index 9dd41a6e32f7bda7831d47f1170b01cc98225c23..f66860a455be5a5f35a03a9b79ac6b5b61485a78 100644 (file)
@@ -27,6 +27,7 @@
 #include "StructureStubInfo.h"
 
 #include "JSObject.h"
 #include "StructureStubInfo.h"
 
 #include "JSObject.h"
+#include "PolymorphicPutByIdList.h"
 #include "ScopeChain.h"
 
 namespace JSC {
 #include "ScopeChain.h"
 
 namespace JSC {
@@ -45,13 +46,16 @@ void StructureStubInfo::deref()
         delete polymorphicStructures;
         return;
     }
         delete polymorphicStructures;
         return;
     }
+    case access_put_by_id_list:
+        delete u.putByIdList.list;
+        return;
     case access_get_by_id_self:
     case access_get_by_id_proto:
     case access_get_by_id_chain:
     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_transition_normal:
+    case access_put_by_id_transition_direct:
     case access_put_by_id_replace:
     case access_put_by_id_replace:
-    case access_get_by_id:
-    case access_put_by_id:
+    case access_unset:
     case access_get_by_id_generic:
     case access_put_by_id_generic:
     case access_get_array_length:
     case access_get_by_id_generic:
     case access_put_by_id_generic:
     case access_get_array_length:
@@ -63,49 +67,56 @@ void StructureStubInfo::deref()
     }
 }
 
     }
 }
 
-void StructureStubInfo::visitAggregate(SlotVisitor& visitor)
+bool StructureStubInfo::visitWeakReferences()
 {
     switch (accessType) {
     case access_get_by_id_self:
 {
     switch (accessType) {
     case access_get_by_id_self:
-        visitor.append(&u.getByIdSelf.baseObjectStructure);
-        return;
+        if (!Heap::isMarked(u.getByIdSelf.baseObjectStructure.get()))
+            return false;
+        break;
     case access_get_by_id_proto:
     case access_get_by_id_proto:
-        visitor.append(&u.getByIdProto.baseObjectStructure);
-        visitor.append(&u.getByIdProto.prototypeStructure);
-        return;
+        if (!Heap::isMarked(u.getByIdProto.baseObjectStructure.get())
+            || !Heap::isMarked(u.getByIdProto.prototypeStructure.get()))
+            return false;
+        break;
     case access_get_by_id_chain:
     case access_get_by_id_chain:
-        visitor.append(&u.getByIdChain.baseObjectStructure);
-        visitor.append(&u.getByIdChain.chain);
-        return;
+        if (!Heap::isMarked(u.getByIdChain.baseObjectStructure.get())
+            || !Heap::isMarked(u.getByIdChain.chain.get()))
+            return false;
+        break;
     case access_get_by_id_self_list: {
         PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList;
     case access_get_by_id_self_list: {
         PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList;
-        polymorphicStructures->visitAggregate(visitor, u.getByIdSelfList.listSize);
-        return;
+        if (!polymorphicStructures->visitWeak(u.getByIdSelfList.listSize))
+            return false;
+        break;
     }
     case access_get_by_id_proto_list: {
         PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList;
     }
     case access_get_by_id_proto_list: {
         PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList;
-        polymorphicStructures->visitAggregate(visitor, u.getByIdProtoList.listSize);
-        return;
+        if (!polymorphicStructures->visitWeak(u.getByIdProtoList.listSize))
+            return false;
+        break;
     }
     }
-    case access_put_by_id_transition:
-        visitor.append(&u.putByIdTransition.previousStructure);
-        visitor.append(&u.putByIdTransition.structure);
-        visitor.append(&u.putByIdTransition.chain);
-        return;
+    case access_put_by_id_transition_normal:
+    case access_put_by_id_transition_direct:
+        if (!Heap::isMarked(u.putByIdTransition.previousStructure.get())
+            || !Heap::isMarked(u.putByIdTransition.structure.get())
+            || !Heap::isMarked(u.putByIdTransition.chain.get()))
+            return false;
+        break;
     case access_put_by_id_replace:
     case access_put_by_id_replace:
-        visitor.append(&u.putByIdReplace.baseObjectStructure);
-        return;
-    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 need to mark anything
-        return;
+        if (!Heap::isMarked(u.putByIdReplace.baseObjectStructure.get()))
+            return false;
+        break;
+    case access_put_by_id_list:
+        if (!u.putByIdList.list->visitWeak())
+            return false;
+        break;
     default:
     default:
-        ASSERT_NOT_REACHED();
+        // The rest of the instructions don't require references, so there is no need to
+        // do anything.
+        break;
     }
     }
+    return true;
 }
 #endif
 
 }
 #endif
 
index 7f11edd769691518876cd10f5f2855e8423f68cd..03c64bf3975f099ab3aec059f7fe58594661097a 100644 (file)
 #ifndef StructureStubInfo_h
 #define StructureStubInfo_h
 
 #ifndef StructureStubInfo_h
 #define StructureStubInfo_h
 
+#include <wtf/Platform.h>
+
 #if ENABLE(JIT)
 
 #if ENABLE(JIT)
 
+#include "CodeOrigin.h"
 #include "Instruction.h"
 #include "MacroAssembler.h"
 #include "Opcode.h"
 #include "Instruction.h"
 #include "MacroAssembler.h"
 #include "Opcode.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
+    class PolymorphicPutByIdList;
+
     enum AccessType {
         access_get_by_id_self,
         access_get_by_id_proto,
         access_get_by_id_chain,
         access_get_by_id_self_list,
         access_get_by_id_proto_list,
     enum AccessType {
         access_get_by_id_self,
         access_get_by_id_proto,
         access_get_by_id_chain,
         access_get_by_id_self_list,
         access_get_by_id_proto_list,
-        access_put_by_id_transition,
+        access_put_by_id_transition_normal,
+        access_put_by_id_transition_direct,
         access_put_by_id_replace,
         access_put_by_id_replace,
-        access_get_by_id,
-        access_put_by_id,
+        access_put_by_id_list,
+        access_unset,
         access_get_by_id_generic,
         access_put_by_id_generic,
         access_get_array_length,
         access_get_string_length,
     };
 
         access_get_by_id_generic,
         access_put_by_id_generic,
         access_get_array_length,
         access_get_string_length,
     };
 
+    inline bool isGetByIdAccess(AccessType accessType)
+    {
+        switch (accessType) {
+        case access_get_by_id_self:
+        case access_get_by_id_proto:
+        case access_get_by_id_chain:
+        case access_get_by_id_self_list:
+        case access_get_by_id_proto_list:
+        case access_get_by_id_generic:
+        case access_get_array_length:
+        case access_get_string_length:
+            return true;
+        default:
+            return false;
+        }
+    }
+    
+    inline bool isPutByIdAccess(AccessType accessType)
+    {
+        switch (accessType) {
+        case access_put_by_id_transition_normal:
+        case access_put_by_id_transition_direct:
+        case access_put_by_id_replace:
+        case access_put_by_id_list:
+        case access_put_by_id_generic:
+            return true;
+        default:
+            return false;
+        }
+    }
+
     struct StructureStubInfo {
     struct StructureStubInfo {
-        StructureStubInfo(AccessType accessType)
-            : accessType(accessType)
+        StructureStubInfo()
+            : accessType(access_unset)
             , seen(false)
         {
         }
             , seen(false)
         {
         }
@@ -85,8 +122,8 @@ namespace JSC {
         {
             accessType = access_get_by_id_self_list;
 
         {
             accessType = access_get_by_id_self_list;
 
-            u.getByIdProtoList.structureList = structureList;
-            u.getByIdProtoList.listSize = listSize;
+            u.getByIdSelfList.structureList = structureList;
+            u.getByIdSelfList.listSize = listSize;
         }
 
         void initGetByIdProtoList(PolymorphicAccessStructureList* structureList, int listSize)
         }
 
         void initGetByIdProtoList(PolymorphicAccessStructureList* structureList, int listSize)
@@ -99,9 +136,12 @@ namespace JSC {
 
         // PutById*
 
 
         // PutById*
 
-        void initPutByIdTransition(JSGlobalData& globalData, JSCell* owner, Structure* previousStructure, Structure* structure, StructureChain* chain)
+        void initPutByIdTransition(JSGlobalData& globalData, JSCell* owner, Structure* previousStructure, Structure* structure, StructureChain* chain, bool isDirect)
         {
         {
-            accessType = access_put_by_id_transition;
+            if (isDirect)
+                accessType = access_put_by_id_transition_direct;
+            else
+                accessType = access_put_by_id_transition_normal;
 
             u.putByIdTransition.previousStructure.set(globalData, owner, previousStructure);
             u.putByIdTransition.structure.set(globalData, owner, structure);
 
             u.putByIdTransition.previousStructure.set(globalData, owner, previousStructure);
             u.putByIdTransition.structure.set(globalData, owner, structure);
@@ -114,10 +154,24 @@ namespace JSC {
     
             u.putByIdReplace.baseObjectStructure.set(globalData, owner, baseObjectStructure);
         }
     
             u.putByIdReplace.baseObjectStructure.set(globalData, owner, baseObjectStructure);
         }
+        
+        void initPutByIdList(PolymorphicPutByIdList* list)
+        {
+            accessType = access_put_by_id_list;
+            u.putByIdList.list = list;
+        }
+        
+        void reset()
+        {
+            deref();
+            accessType = access_unset;
+            stubRoutine = MacroAssemblerCodeRef();
+        }
 
         void deref();
 
         void deref();
-        void visitAggregate(SlotVisitor&);
 
 
+        bool visitWeakReferences();
+        
         bool seenOnce()
         {
             return seen;
         bool seenOnce()
         {
             return seen;
@@ -127,11 +181,70 @@ namespace JSC {
         {
             seen = true;
         }
         {
             seen = true;
         }
+        
+        unsigned bytecodeIndex;
+
+        int8_t accessType;
+        int8_t seen;
 
 
-        int accessType : 31;
-        int seen : 1;
+#if ENABLE(DFG_JIT)
+        CodeOrigin codeOrigin;
+#endif // ENABLE(DFG_JIT)
 
         union {
 
         union {
+            struct {
+                int8_t registersFlushed;
+                int8_t baseGPR;
+#if USE(JSVALUE32_64)
+                int8_t valueTagGPR;
+#endif
+                int8_t valueGPR;
+                int8_t scratchGPR;
+                int16_t deltaCallToDone;
+                int16_t deltaCallToStructCheck;
+                int16_t deltaCallToSlowCase;
+                int16_t deltaCheckImmToCall;
+#if USE(JSVALUE64)
+                int16_t deltaCallToLoadOrStore;
+#else
+                int16_t deltaCallToTagLoadOrStore;
+                int16_t deltaCallToPayloadLoadOrStore;
+#endif
+            } dfg;
+            struct {
+                union {
+                    struct {
+                        int16_t structureToCompare;
+                        int16_t structureCheck;
+#if USE(JSVALUE64)
+                        int16_t displacementLabel;
+#else
+                        int16_t displacementLabel1;
+                        int16_t displacementLabel2;
+#endif
+                        int16_t putResult;
+                        int16_t coldPathBegin;
+                    } get;
+                    struct {
+                        int16_t structureToCompare;
+#if USE(JSVALUE64)
+                        int16_t displacementLabel;
+#else
+                        int16_t displacementLabel1;
+                        int16_t displacementLabel2;
+#endif
+                    } put;
+                } u;
+                int16_t methodCheckProtoObj;
+                int16_t methodCheckProtoStructureToCompare;
+                int16_t methodCheckPutFunction;
+            } baseline;
+        } patch;
+
+        union {
+            struct {
+                // It would be unwise to put anything here, as it will surely be overwritten.
+            } unset;
             struct {
                 WriteBarrierBase<Structure> baseObjectStructure;
             } getByIdSelf;
             struct {
                 WriteBarrierBase<Structure> baseObjectStructure;
             } getByIdSelf;
@@ -159,15 +272,28 @@ namespace JSC {
             struct {
                 WriteBarrierBase<Structure> baseObjectStructure;
             } putByIdReplace;
             struct {
                 WriteBarrierBase<Structure> baseObjectStructure;
             } putByIdReplace;
+            struct {
+                PolymorphicPutByIdList* list;
+            } putByIdList;
         } u;
 
         } u;
 
-        CodeLocationLabel stubRoutine;
+        MacroAssemblerCodeRef stubRoutine;
         CodeLocationCall callReturnLocation;
         CodeLocationLabel hotPathBegin;
     };
 
         CodeLocationCall callReturnLocation;
         CodeLocationLabel hotPathBegin;
     };
 
+    inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
+    {
+        return structureStubInfo->callReturnLocation.executableAddress();
+    }
+
+    inline unsigned getStructureStubInfoBytecodeIndex(StructureStubInfo* structureStubInfo)
+    {
+        return structureStubInfo->bytecodeIndex;
+    }
+
 } // namespace JSC
 
 } // namespace JSC
 
-#endif
+#endif // ENABLE(JIT)
 
 #endif // StructureStubInfo_h
 
 #endif // StructureStubInfo_h
diff --git a/bytecode/ValueProfile.h b/bytecode/ValueProfile.h
new file mode 100644 (file)
index 0000000..73e363a
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 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 ValueProfile_h
+#define ValueProfile_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(VALUE_PROFILER)
+
+#include "JSArray.h"
+#include "PredictedType.h"
+#include "Structure.h"
+#include "WriteBarrier.h"
+
+namespace JSC {
+
+template<unsigned numberOfBucketsArgument>
+struct ValueProfileBase {
+    static const unsigned numberOfBuckets = numberOfBucketsArgument;
+    static const unsigned numberOfSpecFailBuckets = 1;
+    static const unsigned bucketIndexMask = numberOfBuckets - 1;
+    static const unsigned totalNumberOfBuckets = numberOfBuckets + numberOfSpecFailBuckets;
+    
+    ValueProfileBase()
+        : m_bytecodeOffset(-1)
+        , m_prediction(PredictNone)
+        , m_numberOfSamplesInPrediction(0)
+    {
+        for (unsigned i = 0; i < totalNumberOfBuckets; ++i)
+            m_buckets[i] = JSValue::encode(JSValue());
+    }
+    
+    ValueProfileBase(int bytecodeOffset)
+        : m_bytecodeOffset(bytecodeOffset)
+        , m_prediction(PredictNone)
+        , m_numberOfSamplesInPrediction(0)
+    {
+        for (unsigned i = 0; i < totalNumberOfBuckets; ++i)
+            m_buckets[i] = JSValue::encode(JSValue());
+    }
+    
+    EncodedJSValue* specFailBucket(unsigned i)
+    {
+        ASSERT(numberOfBuckets + i < totalNumberOfBuckets);
+        return m_buckets + numberOfBuckets + i;
+    }
+    
+    const ClassInfo* classInfo(unsigned bucket) const
+    {
+        JSValue value = JSValue::decode(m_buckets[bucket]);
+        if (!!value) {
+            if (!value.isCell())
+                return 0;
+            return value.asCell()->structure()->classInfo();
+        }
+        return 0;
+    }
+    
+    unsigned numberOfSamples() const
+    {
+        unsigned result = 0;
+        for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
+            if (!!JSValue::decode(m_buckets[i]))
+                result++;
+        }
+        return result;
+    }
+    
+    unsigned totalNumberOfSamples() const
+    {
+        return numberOfSamples() + m_numberOfSamplesInPrediction;
+    }
+    
+    bool isLive() const
+    {
+        for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
+            if (!!JSValue::decode(m_buckets[i]))
+                return true;
+        }
+        return false;
+    }
+    
+    void dump(FILE* out)
+    {
+        fprintf(out,
+                "samples = %u, prediction = %s",
+                totalNumberOfSamples(),
+                predictionToString(m_prediction));
+        bool first = true;
+        for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
+            JSValue value = JSValue::decode(m_buckets[i]);
+            if (!!value) {
+                if (first) {
+                    fprintf(out, ": ");
+                    first = false;
+                } else
+                    fprintf(out, ", ");
+                fprintf(out, "%s", value.description());
+            }
+        }
+    }
+    
+    // Updates the prediction and returns the new one.
+    PredictedType computeUpdatedPrediction()
+    {
+        for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
+            JSValue value = JSValue::decode(m_buckets[i]);
+            if (!value)
+                continue;
+            
+            m_numberOfSamplesInPrediction++;
+            mergePrediction(m_prediction, predictionFromValue(value));
+            
+            m_buckets[i] = JSValue::encode(JSValue());
+        }
+        
+        return m_prediction;
+    }
+    
+    int m_bytecodeOffset; // -1 for prologue
+    
+    PredictedType m_prediction;
+    unsigned m_numberOfSamplesInPrediction;
+    
+    EncodedJSValue m_buckets[totalNumberOfBuckets];
+};
+
+struct MinimalValueProfile : public ValueProfileBase<0> {
+    MinimalValueProfile(): ValueProfileBase<0>() { }
+    MinimalValueProfile(int bytecodeOffset): ValueProfileBase<0>(bytecodeOffset) { }
+};
+
+template<unsigned logNumberOfBucketsArgument>
+struct ValueProfileWithLogNumberOfBuckets : public ValueProfileBase<1 << logNumberOfBucketsArgument> {
+    static const unsigned logNumberOfBuckets = logNumberOfBucketsArgument;
+    
+    ValueProfileWithLogNumberOfBuckets()
+        : ValueProfileBase<1 << logNumberOfBucketsArgument>()
+    {
+    }
+    ValueProfileWithLogNumberOfBuckets(int bytecodeOffset)
+        : ValueProfileBase<1 << logNumberOfBucketsArgument>(bytecodeOffset)
+    {
+    }
+};
+
+struct ValueProfile : public ValueProfileWithLogNumberOfBuckets<0> {
+    ValueProfile(): ValueProfileWithLogNumberOfBuckets<0>() { }
+    ValueProfile(int bytecodeOffset): ValueProfileWithLogNumberOfBuckets<0>(bytecodeOffset) { }
+};
+
+template<typename T>
+inline int getValueProfileBytecodeOffset(T* valueProfile)
+{
+    return valueProfile->m_bytecodeOffset;
+}
+
+// This is a mini value profile to catch pathologies. It is a counter that gets
+// incremented when we take the slow path on any instruction.
+struct RareCaseProfile {
+    RareCaseProfile(int bytecodeOffset)
+        : m_bytecodeOffset(bytecodeOffset)
+        , m_counter(0)
+    {
+    }
+    
+    int m_bytecodeOffset;
+    uint32_t m_counter;
+};
+
+inline int getRareCaseProfileBytecodeOffset(RareCaseProfile* rareCaseProfile)
+{
+    return rareCaseProfile->m_bytecodeOffset;
+}
+
+} // namespace JSC
+
+#endif // ENABLE(VALUE_PROFILER)
+
+#endif // ValueProfile_h
+
diff --git a/bytecode/ValueRecovery.h b/bytecode/ValueRecovery.h
new file mode 100644 (file)
index 0000000..007c6d3
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * 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 ValueRecovery_h
+#define ValueRecovery_h
+
+#include "DataFormat.h"
+#include "JSValue.h"
+#include "MacroAssembler.h"
+#include "VirtualRegister.h"
+#include <stdio.h>
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+// Describes how to recover a given bytecode virtual register at a given
+// code point.
+enum ValueRecoveryTechnique {
+    // It's already in the register file at the right location.
+    AlreadyInRegisterFile,
+    // It's already in the register file but unboxed.
+    AlreadyInRegisterFileAsUnboxedInt32,
+    AlreadyInRegisterFileAsUnboxedCell,
+    AlreadyInRegisterFileAsUnboxedBoolean,
+    AlreadyInRegisterFileAsUnboxedDouble,
+    // It's in a register.
+    InGPR,
+    UnboxedInt32InGPR,
+    UnboxedBooleanInGPR,
+#if USE(JSVALUE32_64)
+    InPair,
+#endif
+    InFPR,
+    UInt32InGPR,
+    // It's in the register file, but at a different location.
+    DisplacedInRegisterFile,
+    // It's in the register file, at a different location, and it's unboxed.
+    Int32DisplacedInRegisterFile,
+    DoubleDisplacedInRegisterFile,
+    CellDisplacedInRegisterFile,
+    BooleanDisplacedInRegisterFile,
+    // It's a constant.
+    Constant,
+    // Don't know how to recover it.
+    DontKnow
+};
+
+class ValueRecovery {
+public:
+    ValueRecovery()
+        : m_technique(DontKnow)
+    {
+    }
+    
+    static ValueRecovery alreadyInRegisterFile()
+    {
+        ValueRecovery result;
+        result.m_technique = AlreadyInRegisterFile;
+        return result;
+    }
+    
+    static ValueRecovery alreadyInRegisterFileAsUnboxedInt32()
+    {
+        ValueRecovery result;
+        result.m_technique = AlreadyInRegisterFileAsUnboxedInt32;
+        return result;
+    }
+    
+    static ValueRecovery alreadyInRegisterFileAsUnboxedCell()
+    {
+        ValueRecovery result;
+        result.m_technique = AlreadyInRegisterFileAsUnboxedCell;
+        return result;
+    }
+    
+    static ValueRecovery alreadyInRegisterFileAsUnboxedBoolean()
+    {
+        ValueRecovery result;
+        result.m_technique = AlreadyInRegisterFileAsUnboxedBoolean;
+        return result;
+    }
+    
+    static ValueRecovery alreadyInRegisterFileAsUnboxedDouble()
+    {
+        ValueRecovery result;
+        result.m_technique = AlreadyInRegisterFileAsUnboxedDouble;
+        return result;
+    }
+    
+    static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat)
+    {
+        ASSERT(dataFormat != DataFormatNone);
+#if USE(JSVALUE32_64)
+        ASSERT(dataFormat == DataFormatInteger || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean);
+#endif
+        ValueRecovery result;
+        if (dataFormat == DataFormatInteger)
+            result.m_technique = UnboxedInt32InGPR;
+        else if (dataFormat == DataFormatBoolean)
+            result.m_technique = UnboxedBooleanInGPR;
+        else
+            result.m_technique = InGPR;
+        result.m_source.gpr = gpr;
+        return result;
+    }
+    
+    static ValueRecovery uint32InGPR(MacroAssembler::RegisterID gpr)
+    {
+        ValueRecovery result;
+        result.m_technique = UInt32InGPR;
+        result.m_source.gpr = gpr;
+        return result;
+    }
+    
+#if USE(JSVALUE32_64)
+    static ValueRecovery inPair(MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR)
+    {
+        ValueRecovery result;
+        result.m_technique = InPair;
+        result.m_source.pair.tagGPR = tagGPR;
+        result.m_source.pair.payloadGPR = payloadGPR;
+        return result;
+    }
+#endif
+
+    static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr)
+    {
+        ValueRecovery result;
+        result.m_technique = InFPR;
+        result.m_source.fpr = fpr;
+        return result;
+    }
+    
+    static ValueRecovery displacedInRegisterFile(VirtualRegister virtualReg, DataFormat dataFormat)
+    {
+        ValueRecovery result;
+        switch (dataFormat) {
+        case DataFormatInteger:
+            result.m_technique = Int32DisplacedInRegisterFile;
+            break;
+            
+        case DataFormatDouble:
+            result.m_technique = DoubleDisplacedInRegisterFile;
+            break;
+
+        case DataFormatCell:
+            result.m_technique = CellDisplacedInRegisterFile;
+            break;
+            
+        case DataFormatBoolean:
+            result.m_technique = BooleanDisplacedInRegisterFile;
+            break;
+            
+        default:
+            ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage);
+            result.m_technique = DisplacedInRegisterFile;
+            break;
+        }
+        result.m_source.virtualReg = virtualReg;
+        return result;
+    }
+    
+    static ValueRecovery constant(JSValue value)
+    {
+        ValueRecovery result;
+        result.m_technique = Constant;
+        result.m_source.constant = JSValue::encode(value);
+        return result;
+    }
+    
+    ValueRecoveryTechnique technique() const { return m_technique; }
+    
+    bool isConstant() const { return m_technique == Constant; }
+    
+    bool isInRegisters() const
+    {
+        switch (m_technique) {
+        case InGPR:
+        case UnboxedInt32InGPR:
+        case UnboxedBooleanInGPR:
+#if USE(JSVALUE32_64)
+        case InPair:
+#endif
+        case InFPR:
+            return true;
+        default:
+            return false;
+        }
+    }
+    
+    bool isAlreadyInRegisterFile() const
+    {
+        switch (technique()) {
+        case AlreadyInRegisterFile:
+        case AlreadyInRegisterFileAsUnboxedInt32:
+        case AlreadyInRegisterFileAsUnboxedCell:
+        case AlreadyInRegisterFileAsUnboxedBoolean:
+        case AlreadyInRegisterFileAsUnboxedDouble:
+            return true;
+        default:
+            return false;
+        }
+    }
+    
+    MacroAssembler::RegisterID gpr() const
+    {
+        ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR);
+        return m_source.gpr;
+    }
+    
+#if USE(JSVALUE32_64)
+    MacroAssembler::RegisterID tagGPR() const
+    {
+        ASSERT(m_technique == InPair);
+        return m_source.pair.tagGPR;
+    }
+    
+    MacroAssembler::RegisterID payloadGPR() const
+    {
+        ASSERT(m_technique == InPair);
+        return m_source.pair.payloadGPR;
+    }
+#endif
+    
+    MacroAssembler::FPRegisterID fpr() const
+    {
+        ASSERT(m_technique == InFPR);
+        return m_source.fpr;
+    }
+    
+    VirtualRegister virtualRegister() const
+    {
+        ASSERT(m_technique == DisplacedInRegisterFile || m_technique == Int32DisplacedInRegisterFile || m_technique == DoubleDisplacedInRegisterFile || m_technique == CellDisplacedInRegisterFile || m_technique == BooleanDisplacedInRegisterFile);
+        return m_source.virtualReg;
+    }
+    
+    JSValue constant() const
+    {
+        ASSERT(m_technique == Constant);
+        return JSValue::decode(m_source.constant);
+    }
+    
+    void dump(FILE* out) const
+    {
+        switch (technique()) {
+        case AlreadyInRegisterFile:
+            fprintf(out, "-");
+            break;
+        case AlreadyInRegisterFileAsUnboxedInt32:
+            fprintf(out, "(int32)");
+            break;
+        case AlreadyInRegisterFileAsUnboxedCell:
+            fprintf(out, "(cell)");
+            break;
+        case AlreadyInRegisterFileAsUnboxedBoolean:
+            fprintf(out, "(bool)");
+            break;
+        case AlreadyInRegisterFileAsUnboxedDouble:
+            fprintf(out, "(double)");
+            break;
+        case InGPR:
+            fprintf(out, "%%r%d", gpr());
+            break;
+        case UnboxedInt32InGPR:
+            fprintf(out, "int32(%%r%d)", gpr());
+            break;
+        case UnboxedBooleanInGPR:
+            fprintf(out, "bool(%%r%d)", gpr());
+            break;
+        case UInt32InGPR:
+            fprintf(out, "uint32(%%r%d)", gpr());
+            break;
+        case InFPR:
+            fprintf(out, "%%fr%d", fpr());
+            break;
+#if USE(JSVALUE32_64)
+        case InPair:
+            fprintf(out, "pair(%%r%d, %%r%d)", tagGPR(), payloadGPR());
+            break;
+#endif
+        case DisplacedInRegisterFile:
+            fprintf(out, "*%d", virtualRegister());
+            break;
+        case Int32DisplacedInRegisterFile:
+            fprintf(out, "*int32(%d)", virtualRegister());
+            break;
+        case DoubleDisplacedInRegisterFile:
+            fprintf(out, "*double(%d)", virtualRegister());
+            break;
+        case CellDisplacedInRegisterFile:
+            fprintf(out, "*cell(%d)", virtualRegister());
+            break;
+        case BooleanDisplacedInRegisterFile:
+            fprintf(out, "*bool(%d)", virtualRegister());
+            break;
+        case Constant:
+            fprintf(out, "[%s]", constant().description());
+            break;
+        case DontKnow:
+            fprintf(out, "!");
+            break;
+        default:
+            fprintf(out, "?%d", technique());
+            break;
+        }
+    }
+    
+private:
+    ValueRecoveryTechnique m_technique;
+    union {
+        MacroAssembler::RegisterID gpr;
+        MacroAssembler::FPRegisterID fpr;
+#if USE(JSVALUE32_64)
+        struct {
+            MacroAssembler::RegisterID tagGPR;
+            MacroAssembler::RegisterID payloadGPR;
+        } pair;
+#endif
+        VirtualRegister virtualReg;
+        EncodedJSValue constant;
+    } m_source;
+};
+
+} // namespace JSC
+
+#endif // ValueRecovery_h
diff --git a/bytecode/VirtualRegister.h b/bytecode/VirtualRegister.h
new file mode 100644 (file)
index 0000000..b95f8b8
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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 VirtualRegister_h
+#define VirtualRegister_h
+
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+// 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);
+
+} // namespace JSC
+
+#endif // VirtualRegister_h
index c09a83766d6a9b406fb8aa6ee3491b9555e5aaaa..f43b4e6c5881dd1b533175ece3c3d3b72b084000 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2012 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
@@ -33,7 +33,9 @@
 #include "BatchedTransitionOptimizer.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
 #include "BatchedTransitionOptimizer.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
+#include "LowLevelInterpreter.h"
 #include "ScopeChain.h"
 #include "ScopeChain.h"
+#include "StrongInlines.h"
 #include "UString.h"
 
 using namespace std;
 #include "UString.h"
 
 using namespace std;
@@ -115,40 +117,39 @@ namespace JSC {
     expected by the callee.
 */
 
     expected by the callee.
 */
 
-#ifndef NDEBUG
 static bool s_dumpsGeneratedCode = false;
 static bool s_dumpsGeneratedCode = false;
-#endif
+
+void Label::setLocation(unsigned location)
+{
+    m_location = location;
+    
+    unsigned size = m_unresolvedJumps.size();
+    for (unsigned i = 0; i < size; ++i)
+        m_generator->m_instructions[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first;
+}
 
 void BytecodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode)
 {
 
 void BytecodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode)
 {
-#ifndef NDEBUG
     s_dumpsGeneratedCode = dumpsGeneratedCode;
     s_dumpsGeneratedCode = dumpsGeneratedCode;
-#else
-    UNUSED_PARAM(dumpsGeneratedCode);
-#endif
 }
 
 bool BytecodeGenerator::dumpsGeneratedCode()
 {
 }
 
 bool BytecodeGenerator::dumpsGeneratedCode()
 {
-#ifndef NDEBUG
     return s_dumpsGeneratedCode;
     return s_dumpsGeneratedCode;
-#else
-    return false;
-#endif
 }
 
 JSObject* BytecodeGenerator::generate()
 {
 }
 
 JSObject* BytecodeGenerator::generate()
 {
+    SamplingRegion samplingRegion("Bytecode Generation");
+    
     m_codeBlock->setThisRegister(m_thisRegister.index());
 
     m_scopeNode->emitBytecode(*this);
     m_codeBlock->setThisRegister(m_thisRegister.index());
 
     m_scopeNode->emitBytecode(*this);
-
-#ifndef NDEBUG
-    m_codeBlock->setInstructionCount(m_codeBlock->instructions().size());
+    
+    m_codeBlock->instructions() = RefCountedArray<Instruction>(m_instructions);
 
     if (s_dumpsGeneratedCode)
         m_codeBlock->dump(m_scopeChain->globalObject->globalExec());
 
     if (s_dumpsGeneratedCode)
         m_codeBlock->dump(m_scopeChain->globalObject->globalExec());
-#endif
 
     if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode)
         symbolTable().clear();
 
     if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode)
         symbolTable().clear();
@@ -164,10 +165,10 @@ bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, Registe
 {
     int index = m_calleeRegisters.size();
     SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
 {
     int index = m_calleeRegisters.size();
     SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
-    pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.impl(), newEntry);
+    SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry);
 
 
-    if (!result.second) {
-        r0 = &registerFor(result.first->second.getIndex());
+    if (!result.isNewEntry) {
+        r0 = &registerFor(result.iterator->second.getIndex());
         return false;
     }
 
         return false;
     }
 
@@ -175,21 +176,14 @@ bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, Registe
     return true;
 }
 
     return true;
 }
 
-bool BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
+int BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant)
 {
 {
-    int index = m_nextGlobalIndex;
+    int index = symbolTable().size();
     SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
     SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
-    pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.impl(), newEntry);
-
-    if (!result.second)
-        index = result.first->second.getIndex();
-    else {
-        --m_nextGlobalIndex;
-        m_globals.append(index + m_globalVarStorageOffset);
-    }
-
-    r0 = &registerFor(index);
-    return result.second;
+    SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry);
+    if (!result.isNewEntry)
+        index = result.iterator->second.getIndex();
+    return index;
 }
 
 void BytecodeGenerator::preserveLastVar()
 }
 
 void BytecodeGenerator::preserveLastVar()
@@ -198,20 +192,19 @@ void BytecodeGenerator::preserveLastVar()
         m_lastVar = &m_calleeRegisters.last();
 }
 
         m_lastVar = &m_calleeRegisters.last();
 }
 
-BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock)
+BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock, CompilationKind compilationKind)
     : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
     : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
-    , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling())
-    , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo())
+    , m_shouldEmitProfileHooks(scopeChain->globalObject->globalObjectMethodTable()->supportsProfiling(scopeChain->globalObject.get()))
+    , m_shouldEmitRichSourceInfo(scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get()))
     , m_scopeChain(*scopeChain->globalData, scopeChain)
     , m_symbolTable(symbolTable)
     , m_scopeNode(programNode)
     , m_codeBlock(codeBlock)
     , m_scopeChain(*scopeChain->globalData, scopeChain)
     , m_symbolTable(symbolTable)
     , m_scopeNode(programNode)
     , m_codeBlock(codeBlock)
-    , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
+    , m_thisRegister(CallFrame::thisArgumentOffset())
     , m_finallyDepth(0)
     , m_dynamicScopeDepth(0)
     , m_baseScopeDepth(0)
     , m_codeType(GlobalCode)
     , m_finallyDepth(0)
     , m_dynamicScopeDepth(0)
     , m_baseScopeDepth(0)
     , m_codeType(GlobalCode)
-    , m_nextGlobalIndex(-1)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
     , m_hasCreatedActivation(true)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
     , m_hasCreatedActivation(true)
@@ -222,10 +215,11 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s
 #ifndef NDEBUG
     , m_lastOpcodePosition(0)
 #endif
 #ifndef NDEBUG
     , m_lastOpcodePosition(0)
 #endif
-    , m_stack(m_globalData->stack())
+    , m_stack(wtfThreadData().stack())
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
 {
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
 {
+    m_globalData->startedCompiling(m_codeBlock);
     if (m_shouldEmitDebugHooks)
         m_codeBlock->setNeedsFullScopeChain(true);
 
     if (m_shouldEmitDebugHooks)
         m_codeBlock->setNeedsFullScopeChain(true);
 
@@ -234,96 +228,45 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s
 
     // FIXME: Move code that modifies the global object to Interpreter::execute.
     
 
     // FIXME: Move code that modifies the global object to Interpreter::execute.
     
-    m_codeBlock->m_numParameters = 1; // Allocate space for "this"
+    m_codeBlock->setNumParameters(1); // Allocate space for "this"
+    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
+    
+    if (compilationKind == OptimizingCompilation)
+        return;
 
     JSGlobalObject* globalObject = scopeChain->globalObject.get();
     ExecState* exec = globalObject->globalExec();
 
     JSGlobalObject* globalObject = scopeChain->globalObject.get();
     ExecState* exec = globalObject->globalExec();
-    RegisterFile* registerFile = &exec->globalData().interpreter->registerFile();
     
     
-    // Shift register indexes in generated code to elide registers allocated by intermediate stack frames.
-    m_globalVarStorageOffset = -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters - registerFile->size();
-
-    // Add previously defined symbols to bookkeeping.
-    m_globals.grow(symbolTable->size());
-    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(*m_globalData, globalObject);
 
     const VarStack& varStack = programNode->varStack();
     const FunctionStack& functionStack = programNode->functionStack();
     BatchedTransitionOptimizer optimizer(*m_globalData, globalObject);
 
     const VarStack& varStack = programNode->varStack();
     const FunctionStack& functionStack = programNode->functionStack();
-    bool canOptimizeNewGlobals = symbolTable->size() + functionStack.size() + varStack.size() < registerFile->maxGlobals();
-    if (canOptimizeNewGlobals) {
-        // 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];
-            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);
-        }
+    size_t newGlobals = varStack.size() + functionStack.size();
+    if (!newGlobals)
+        return;
+    globalObject->resizeRegisters(symbolTable->size() + newGlobals);
 
 
-        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();
+    for (size_t i = 0; i < functionStack.size(); ++i) {
+        FunctionBodyNode* function = functionStack[i];
+        globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties.
 
 
-        preserveLastVar();
-    } 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), DontDelete);
-        }
-        for (size_t i = 0; i < varStack.size(); ++i) {
-            if (globalObject->symbolTableHasProperty(*varStack[i].first) || globalObject->hasProperty(exec, *varStack[i].first))
-                continue;
-            int attributes = DontDelete;
-            if (varStack[i].second & DeclarationStacks::IsConstant)
-                attributes |= ReadOnly;
-            globalObject->putWithAttributes(exec, *varStack[i].first, jsUndefined(), attributes);
-        }
+        JSValue value = JSFunction::create(exec, makeFunction(exec, function), scopeChain);
+        int index = addGlobalVar(function->ident(), false);
+        globalObject->registerAt(index).set(*m_globalData, globalObject, value);
+    }
 
 
-        preserveLastVar();
+    for (size_t i = 0; i < varStack.size(); ++i) {
+        if (globalObject->hasProperty(exec, *varStack[i].first))
+            continue;
+        addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
     }
     }
-    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
 }
 
 }
 
-BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainNode* scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock)
+BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainNode* scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock, CompilationKind)
     : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
     : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
-    , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling())
-    , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo())
+    , m_shouldEmitProfileHooks(scopeChain->globalObject->globalObjectMethodTable()->supportsProfiling(scopeChain->globalObject.get()))
+    , m_shouldEmitRichSourceInfo(scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get()))
     , m_scopeChain(*scopeChain->globalData, scopeChain)
     , m_symbolTable(symbolTable)
     , m_scopeNode(functionBody)
     , m_scopeChain(*scopeChain->globalData, scopeChain)
     , m_symbolTable(symbolTable)
     , m_scopeNode(functionBody)
@@ -343,10 +286,11 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN
 #ifndef NDEBUG
     , m_lastOpcodePosition(0)
 #endif
 #ifndef NDEBUG
     , m_lastOpcodePosition(0)
 #endif
-    , m_stack(m_globalData->stack())
+    , m_stack(wtfThreadData().stack())
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
 {
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
 {
+    m_globalData->startedCompiling(m_codeBlock);
     if (m_shouldEmitDebugHooks)
         m_codeBlock->setNeedsFullScopeChain(true);
 
     if (m_shouldEmitDebugHooks)
         m_codeBlock->setNeedsFullScopeChain(true);
 
@@ -445,21 +389,20 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN
         if (!functionBody->captures(ident))
             addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
     }
         if (!functionBody->captures(ident))
             addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
     }
-    
+
     if (m_shouldEmitDebugHooks)
         codeBlock->m_numCapturedVars = codeBlock->m_numVars;
 
     FunctionParameters& parameters = *functionBody->parameters();
     if (m_shouldEmitDebugHooks)
         codeBlock->m_numCapturedVars = codeBlock->m_numVars;
 
     FunctionParameters& parameters = *functionBody->parameters();
-    size_t parameterCount = parameters.size();
-    int nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
-    m_parameters.grow(1 + parameterCount); // reserve space for "this"
+    m_parameters.grow(parameters.size() + 1); // reserve space for "this"
 
     // Add "this" as a parameter
 
     // Add "this" as a parameter
-    m_thisRegister.setIndex(nextParameterIndex);
-    ++m_codeBlock->m_numParameters;
+    int nextParameterIndex = CallFrame::thisArgumentOffset();
+    m_thisRegister.setIndex(nextParameterIndex--);
+    m_codeBlock->addParameter();
     
     
-    for (size_t i = 0; i < parameterCount; ++i)
-        addParameter(parameters[i], ++nextParameterIndex);
+    for (size_t i = 0; i < parameters.size(); ++i)
+        addParameter(parameters[i], nextParameterIndex--);
 
     preserveLastVar();
 
 
     preserveLastVar();
 
@@ -475,24 +418,21 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN
         emitOpcode(op_create_this);
         instructions().append(m_thisRegister.index());
         instructions().append(funcProto->index());
         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);
+    } else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) {
+        emitOpcode(op_convert_this);
         instructions().append(m_thisRegister.index());
     }
 }
 
         instructions().append(m_thisRegister.index());
     }
 }
 
-BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
+BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock, CompilationKind)
     : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
     : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
-    , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling())
-    , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo())
+    , m_shouldEmitProfileHooks(scopeChain->globalObject->globalObjectMethodTable()->supportsProfiling(scopeChain->globalObject.get()))
+    , m_shouldEmitRichSourceInfo(scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get()))
     , m_scopeChain(*scopeChain->globalData, scopeChain)
     , m_symbolTable(symbolTable)
     , m_scopeNode(evalNode)
     , m_codeBlock(codeBlock)
     , m_scopeChain(*scopeChain->globalData, scopeChain)
     , m_symbolTable(symbolTable)
     , m_scopeNode(evalNode)
     , m_codeBlock(codeBlock)
-    , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
+    , m_thisRegister(CallFrame::thisArgumentOffset())
     , m_finallyDepth(0)
     , m_dynamicScopeDepth(0)
     , m_baseScopeDepth(codeBlock->baseScopeDepth())
     , m_finallyDepth(0)
     , m_dynamicScopeDepth(0)
     , m_baseScopeDepth(codeBlock->baseScopeDepth())
@@ -507,16 +447,17 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeCh
 #ifndef NDEBUG
     , m_lastOpcodePosition(0)
 #endif
 #ifndef NDEBUG
     , m_lastOpcodePosition(0)
 #endif
-    , m_stack(m_globalData->stack())
+    , m_stack(wtfThreadData().stack())
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
 {
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
 {
+    m_globalData->startedCompiling(m_codeBlock);
     if (m_shouldEmitDebugHooks || m_baseScopeDepth)
         m_codeBlock->setNeedsFullScopeChain(true);
 
     emitOpcode(op_enter);
     codeBlock->setGlobalData(m_globalData);
     if (m_shouldEmitDebugHooks || m_baseScopeDepth)
         m_codeBlock->setNeedsFullScopeChain(true);
 
     emitOpcode(op_enter);
     codeBlock->setGlobalData(m_globalData);
-    m_codeBlock->m_numParameters = 1; // Allocate space for "this"
+    m_codeBlock->setNumParameters(1);
 
     const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
     for (size_t i = 0; i < functionStack.size(); ++i)
 
     const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
     for (size_t i = 0; i < functionStack.size(); ++i)
@@ -533,6 +474,11 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeCh
     preserveLastVar();
 }
 
     preserveLastVar();
 }
 
+BytecodeGenerator::~BytecodeGenerator()
+{
+    m_globalData->finishedCompiling(m_codeBlock);
+}
+
 RegisterID* BytecodeGenerator::emitInitLazyRegister(RegisterID* reg)
 {
     emitOpcode(op_init_lazy_reg);
 RegisterID* BytecodeGenerator::emitInitLazyRegister(RegisterID* reg)
 {
     emitOpcode(op_init_lazy_reg);
@@ -552,13 +498,16 @@ void BytecodeGenerator::addParameter(const Identifier& ident, int 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_codeBlock->m_numParameters;
+    m_codeBlock->addParameter();
 }
 
 RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
 {
     if (ident == propertyNames().thisIdentifier)
         return &m_thisRegister;
 }
 
 RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
 {
     if (ident == propertyNames().thisIdentifier)
         return &m_thisRegister;
+        
+    if (m_codeType == GlobalCode)
+        return 0;
 
     if (!shouldOptimizeLocals())
         return 0;
 
     if (!shouldOptimizeLocals())
         return 0;
@@ -573,6 +522,21 @@ RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
     return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
 }
 
     return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
 }
 
+RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident)
+{
+    if (m_codeType == EvalCode)
+        return 0;
+
+    if (m_codeType == GlobalCode)
+        return 0;
+
+    SymbolTableEntry entry = symbolTable().get(ident.impl());
+    if (entry.isNull())
+        return 0;
+
+    return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
+}
+
 bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
 {
     if (ident != propertyNames().arguments)
 bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
 {
     if (ident != propertyNames().arguments)
@@ -608,18 +572,6 @@ RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg)
     return reg;
 }
 
     return reg;
 }
 
-RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident)
-{
-    if (m_codeType == EvalCode)
-        return 0;
-
-    SymbolTableEntry entry = symbolTable().get(ident.impl());
-    if (entry.isNull())
-        return 0;
-
-    return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
-}
-
 bool BytecodeGenerator::isLocal(const Identifier& ident)
 {
     if (ident == propertyNames().thisIdentifier)
 bool BytecodeGenerator::isLocal(const Identifier& ident)
 {
     if (ident == propertyNames().thisIdentifier)
@@ -678,7 +630,7 @@ PassRefPtr<Label> BytecodeGenerator::newLabel()
         m_labels.removeLast();
 
     // Allocate new label ID.
         m_labels.removeLast();
 
     // Allocate new label ID.
-    m_labels.append(m_codeBlock);
+    m_labels.append(this);
     return &m_labels.last();
 }
 
     return &m_labels.last();
 }
 
@@ -714,6 +666,24 @@ void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
     m_lastOpcodeID = opcodeID;
 }
 
     m_lastOpcodeID = opcodeID;
 }
 
+ValueProfile* BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID)
+{
+#if ENABLE(VALUE_PROFILER)
+    ValueProfile* result = m_codeBlock->addValueProfile(instructions().size());
+#else
+    ValueProfile* result = 0;
+#endif
+    emitOpcode(opcodeID);
+    return result;
+}
+
+void BytecodeGenerator::emitLoopHint()
+{
+#if ENABLE(DFG_JIT)
+    emitOpcode(op_loop_hint);
+#endif
+}
+
 void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
 {
     ASSERT(instructions().size() >= 4);
 void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
 {
     ASSERT(instructions().size() >= 4);
@@ -789,6 +759,40 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar
             instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
             instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
+    } else if (m_lastOpcodeID == op_greater) {
+        int dstIndex;
+        int src1Index;
+        int src2Index;
+
+        retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
+
+        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+            rewindBinaryOp();
+
+            size_t begin = instructions().size();
+            emitOpcode(target->isForward() ? op_jgreater : op_loop_if_greater);
+            instructions().append(src1Index);
+            instructions().append(src2Index);
+            instructions().append(target->bind(begin, instructions().size()));
+            return target;
+        }
+    } else if (m_lastOpcodeID == op_greatereq) {
+        int dstIndex;
+        int src1Index;
+        int src2Index;
+
+        retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
+
+        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+            rewindBinaryOp();
+
+            size_t begin = instructions().size();
+            emitOpcode(target->isForward() ? op_jgreatereq : op_loop_if_greatereq);
+            instructions().append(src1Index);
+            instructions().append(src2Index);
+            instructions().append(target->bind(begin, instructions().size()));
+            return target;
+        }
     } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
         int dstIndex;
         int srcIndex;
     } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
         int dstIndex;
         int srcIndex;
@@ -865,6 +869,40 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
             instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
             instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
+    } else if (m_lastOpcodeID == op_greater && target->isForward()) {
+        int dstIndex;
+        int src1Index;
+        int src2Index;
+
+        retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
+
+        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+            rewindBinaryOp();
+
+            size_t begin = instructions().size();
+            emitOpcode(op_jngreater);
+            instructions().append(src1Index);
+            instructions().append(src2Index);
+            instructions().append(target->bind(begin, instructions().size()));
+            return target;
+        }
+    } else if (m_lastOpcodeID == op_greatereq && target->isForward()) {
+        int dstIndex;
+        int src1Index;
+        int src2Index;
+
+        retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
+
+        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+            rewindBinaryOp();
+
+            size_t begin = instructions().size();
+            emitOpcode(op_jngreatereq);
+            instructions().append(src1Index);
+            instructions().append(src2Index);
+            instructions().append(target->bind(begin, instructions().size()));
+            return target;
+        }
     } else if (m_lastOpcodeID == op_not) {
         int dstIndex;
         int srcIndex;
     } else if (m_lastOpcodeID == op_not) {
         int dstIndex;
         int srcIndex;
@@ -944,24 +982,24 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond
 unsigned BytecodeGenerator::addConstant(const Identifier& ident)
 {
     StringImpl* rep = ident.impl();
 unsigned BytecodeGenerator::addConstant(const Identifier& ident)
 {
     StringImpl* rep = ident.impl();
-    pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
-    if (result.second) // new entry
+    IdentifierMap::AddResult result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
+    if (result.isNewEntry)
         m_codeBlock->addIdentifier(Identifier(m_globalData, rep));
 
         m_codeBlock->addIdentifier(Identifier(m_globalData, rep));
 
-    return result.first->second;
+    return result.iterator->second;
 }
 
 RegisterID* BytecodeGenerator::addConstantValue(JSValue v)
 {
     int index = m_nextConstantOffset;
 
 }
 
 RegisterID* BytecodeGenerator::addConstantValue(JSValue v)
 {
     int index = m_nextConstantOffset;
 
-    pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset);
-    if (result.second) {
+    JSValueMap::AddResult result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset);
+    if (result.isNewEntry) {
         m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
         ++m_nextConstantOffset;
         m_codeBlock->addConstant(JSValue(v));
     } else
         m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
         ++m_nextConstantOffset;
         m_codeBlock->addConstant(JSValue(v));
     } else
-        index = result.first->second;
+        index = result.iterator->second;
 
     return &m_constantPoolRegisters[index];
 }
 
     return &m_constantPoolRegisters[index];
 }
@@ -1108,7 +1146,7 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number)
     // work correctly with NaN as a key.
     if (isnan(number) || number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number))
         return emitLoad(dst, jsNumber(number));
     // 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;
+    JSValue& valueInMap = m_numberMap.add(number, JSValue()).iterator->second;
     if (!valueInMap)
         valueInMap = jsNumber(number);
     return emitLoad(dst, valueInMap);
     if (!valueInMap)
         valueInMap = jsNumber(number);
     return emitLoad(dst, valueInMap);
@@ -1116,7 +1154,7 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number)
 
 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
 {
 
 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
 {
-    JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).first->second;
+    JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).iterator->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));
@@ -1153,7 +1191,7 @@ bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& inde
         JSObject* currentScope = iter->get();
         if (!currentScope->isVariableObject())
             break;
         JSObject* currentScope = iter->get();
         if (!currentScope->isVariableObject())
             break;
-        JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
+        JSVariableObject* currentVariableObject = jsCast<JSVariableObject*>(currentScope);
         SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
 
         // Found the property
         SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
 
         // Found the property
@@ -1216,9 +1254,10 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr
     bool requiresDynamicChecks = false;
     if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) && !globalObject) {
         // We can't optimise at all :-(
     bool requiresDynamicChecks = false;
     if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) && !globalObject) {
         // We can't optimise at all :-(
-        emitOpcode(op_resolve);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(dst->index());
         instructions().append(addConstant(property));
+        instructions().append(profile);
         return dst;
     }
     if (shouldAvoidResolveGlobal()) {
         return dst;
     }
     if (shouldAvoidResolveGlobal()) {
@@ -1227,9 +1266,7 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr
     }
         
     if (globalObject) {
     }
         
     if (globalObject) {
-        bool forceGlobalResolve = false;
-
-        if (index != missingSymbolMarker() && !forceGlobalResolve && !requiresDynamicChecks) {
+        if (index != missingSymbolMarker() && !requiresDynamicChecks) {
             // Directly index the property lookup across multiple scopes.
             return emitGetScopedVar(dst, depth, index, globalObject);
         }
             // Directly index the property lookup across multiple scopes.
             return emitGetScopedVar(dst, depth, index, globalObject);
         }
@@ -1237,24 +1274,24 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr
 #if ENABLE(JIT)
         m_codeBlock->addGlobalResolveInfo(instructions().size());
 #endif
 #if ENABLE(JIT)
         m_codeBlock->addGlobalResolveInfo(instructions().size());
 #endif
-#if ENABLE(INTERPRETER)
         m_codeBlock->addGlobalResolveInstruction(instructions().size());
         m_codeBlock->addGlobalResolveInstruction(instructions().size());
-#endif
-        emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
+        ValueProfile* profile = emitProfiledOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(0);
         instructions().append(0);
         if (requiresDynamicChecks)
             instructions().append(depth);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(0);
         instructions().append(0);
         if (requiresDynamicChecks)
             instructions().append(depth);
+        instructions().append(profile);
         return dst;
     }
 
     if (requiresDynamicChecks) {
         // If we get here we have eval nested inside a |with| just give up
         return dst;
     }
 
     if (requiresDynamicChecks) {
         // If we get here we have eval nested inside a |with| just give up
-        emitOpcode(op_resolve);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(dst->index());
         instructions().append(addConstant(property));
+        instructions().append(profile);
         return dst;
     }
 
         return dst;
     }
 
@@ -1265,26 +1302,38 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr
 
     // In this case we are at least able to drop a few scope chains from the
     // lookup chain, although we still need to hash from then on.
 
     // In this case we are at least able to drop a few scope chains from the
     // lookup chain, although we still need to hash from then on.
-    emitOpcode(op_resolve_skip);
+    ValueProfile* profile = emitProfiledOpcode(op_resolve_skip);
     instructions().append(dst->index());
     instructions().append(addConstant(property));
     instructions().append(depth);
     instructions().append(dst->index());
     instructions().append(addConstant(property));
     instructions().append(depth);
+    instructions().append(profile);
     return dst;
 }
 
 RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue globalObject)
 {
     if (globalObject) {
     return dst;
 }
 
 RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue globalObject)
 {
     if (globalObject) {
-        emitOpcode(op_get_global_var);
+        if (m_lastOpcodeID == op_put_global_var) {
+            int dstIndex;
+            int srcIndex;
+            retrieveLastUnaryOp(dstIndex, srcIndex);
+
+            if (dstIndex == index && srcIndex == dst->index())
+                return dst;
+        }
+
+        ValueProfile* profile = emitProfiledOpcode(op_get_global_var);
         instructions().append(dst->index());
         instructions().append(index);
         instructions().append(dst->index());
         instructions().append(index);
+        instructions().append(profile);
         return dst;
     }
 
         return dst;
     }
 
-    emitOpcode(op_get_scoped_var);
+    ValueProfile* profile = emitProfiledOpcode(op_get_scoped_var);
     instructions().append(dst->index());
     instructions().append(index);
     instructions().append(depth);
     instructions().append(dst->index());
     instructions().append(index);
     instructions().append(depth);
+    instructions().append(profile);
     return dst;
 }
 
     return dst;
 }
 
@@ -1312,10 +1361,11 @@ RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier
     findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
     if (!globalObject || requiresDynamicChecks) {
         // We can't optimise at all :-(
     findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
     if (!globalObject || requiresDynamicChecks) {
         // We can't optimise at all :-(
-        emitOpcode(op_resolve_base);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(false);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(false);
+        instructions().append(profile);
         return dst;
     }
 
         return dst;
     }
 
@@ -1334,13 +1384,14 @@ RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const Iden
     findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
     if (!globalObject || requiresDynamicChecks) {
         // We can't optimise at all :-(
     findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
     if (!globalObject || requiresDynamicChecks) {
         // We can't optimise at all :-(
-        emitOpcode(op_resolve_base);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(true);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(true);
+        instructions().append(profile);
         return dst;
     }
         return dst;
     }
-    
+
     // Global object is the base
     RefPtr<RegisterID> result = emitLoad(dst, JSValue(globalObject));
     emitOpcode(op_ensure_property_exists);
     // Global object is the base
     RefPtr<RegisterID> result = emitLoad(dst, JSValue(globalObject));
     emitOpcode(op_ensure_property_exists);
@@ -1357,10 +1408,11 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
     bool requiresDynamicChecks = false;
     if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) || !globalObject || requiresDynamicChecks) {
         // We can't optimise at all :-(
     bool requiresDynamicChecks = false;
     if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) || !globalObject || requiresDynamicChecks) {
         // We can't optimise at all :-(
-        emitOpcode(op_resolve_with_base);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve_with_base);
         instructions().append(baseDst->index());
         instructions().append(propDst->index());
         instructions().append(addConstant(property));
         instructions().append(baseDst->index());
         instructions().append(propDst->index());
         instructions().append(addConstant(property));
+        instructions().append(profile);
         return baseDst;
     }
 
         return baseDst;
     }
 
@@ -1375,24 +1427,76 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
         return baseDst;
     }
     if (shouldAvoidResolveGlobal()) {
         return baseDst;
     }
     if (shouldAvoidResolveGlobal()) {
-        emitOpcode(op_resolve);
+        ValueProfile* profile = emitProfiledOpcode(op_resolve);
+        instructions().append(propDst->index());
+        instructions().append(addConstant(property));
+        instructions().append(profile);
+        return baseDst;
+    }
+#if ENABLE(JIT)
+    m_codeBlock->addGlobalResolveInfo(instructions().size());
+#endif
+#if ENABLE(CLASSIC_INTERPRETER)
+    m_codeBlock->addGlobalResolveInstruction(instructions().size());
+#endif
+    ValueProfile* profile = emitProfiledOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
+    instructions().append(propDst->index());
+    instructions().append(addConstant(property));
+    instructions().append(0);
+    instructions().append(0);
+    if (requiresDynamicChecks)
+        instructions().append(depth);
+    instructions().append(profile);
+    return baseDst;
+}
+
+RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
+{
+    size_t depth = 0;
+    int index = 0;
+    JSObject* globalObject = 0;
+    bool requiresDynamicChecks = false;
+    if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) || !globalObject || requiresDynamicChecks) {
+        // We can't optimise at all :-(
+        ValueProfile* profile = emitProfiledOpcode(op_resolve_with_this);
+        instructions().append(baseDst->index());
+        instructions().append(propDst->index());
+        instructions().append(addConstant(property));
+        instructions().append(profile);
+        return baseDst;
+    }
+
+    bool forceGlobalResolve = false;
+
+    // Global object is the base
+    emitLoad(baseDst, jsUndefined());
+
+    if (index != missingSymbolMarker() && !forceGlobalResolve) {
+        // Directly index the property lookup across multiple scopes.
+        emitGetScopedVar(propDst, depth, index, globalObject);
+        return baseDst;
+    }
+    if (shouldAvoidResolveGlobal()) {
+        ValueProfile* profile = emitProfiledOpcode(op_resolve);
         instructions().append(propDst->index());
         instructions().append(addConstant(property));
         instructions().append(propDst->index());
         instructions().append(addConstant(property));
+        instructions().append(profile);
         return baseDst;
     }
 #if ENABLE(JIT)
     m_codeBlock->addGlobalResolveInfo(instructions().size());
 #endif
         return baseDst;
     }
 #if ENABLE(JIT)
     m_codeBlock->addGlobalResolveInfo(instructions().size());
 #endif
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
     m_codeBlock->addGlobalResolveInstruction(instructions().size());
 #endif
     m_codeBlock->addGlobalResolveInstruction(instructions().size());
 #endif
-    emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
+    ValueProfile* profile = emitProfiledOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
     instructions().append(propDst->index());
     instructions().append(addConstant(property));
     instructions().append(0);
     instructions().append(0);
     if (requiresDynamicChecks)
         instructions().append(depth);
     instructions().append(propDst->index());
     instructions().append(addConstant(property));
     instructions().append(0);
     instructions().append(0);
     if (requiresDynamicChecks)
         instructions().append(depth);
+    instructions().append(profile);
     return baseDst;
 }
 
     return baseDst;
 }
 
@@ -1403,15 +1507,9 @@ void BytecodeGenerator::emitMethodCheck()
 
 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
 {
 
 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
 {
-#if ENABLE(JIT)
-    m_codeBlock->addStructureStubInfo(StructureStubInfo(access_get_by_id));
-#endif
-    
-#if ENABLE(INTERPRETER)
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
-#endif
 
 
-    emitOpcode(op_get_by_id);
+    ValueProfile* profile = emitProfiledOpcode(op_get_by_id);
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(addConstant(property));
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(addConstant(property));
@@ -1419,6 +1517,7 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
     instructions().append(0);
     instructions().append(0);
     instructions().append(0);
     instructions().append(0);
     instructions().append(0);
     instructions().append(0);
+    instructions().append(profile);
     return dst;
 }
 
     return dst;
 }
 
@@ -1434,12 +1533,7 @@ RegisterID* BytecodeGenerator::emitGetArgumentsLength(RegisterID* dst, RegisterI
 
 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
 
 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
-#if ENABLE(JIT)
-    m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
-#endif
-#if ENABLE(INTERPRETER)
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
-#endif
 
     emitOpcode(op_put_by_id);
     instructions().append(base->index());
 
     emitOpcode(op_put_by_id);
     instructions().append(base->index());
@@ -1455,12 +1549,7 @@ RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& p
 
 RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
 
 RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
-#if ENABLE(JIT)
-    m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
-#endif
-#if ENABLE(INTERPRETER)
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
-#endif
     
     emitOpcode(op_put_by_id);
     instructions().append(base->index());
     
     emitOpcode(op_put_by_id);
     instructions().append(base->index());
@@ -1474,22 +1563,13 @@ RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identif
     return value;
 }
 
     return value;
 }
 
-RegisterID* BytecodeGenerator::emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value)
-{
-    emitOpcode(op_put_getter);
-    instructions().append(base->index());
-    instructions().append(addConstant(property));
-    instructions().append(value->index());
-    return value;
-}
-
-RegisterID* BytecodeGenerator::emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value)
+void BytecodeGenerator::emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter)
 {
 {
-    emitOpcode(op_put_setter);
+    emitOpcode(op_put_getter_setter);
     instructions().append(base->index());
     instructions().append(addConstant(property));
     instructions().append(base->index());
     instructions().append(addConstant(property));
-    instructions().append(value->index());
-    return value;
+    instructions().append(getter->index());
+    instructions().append(setter->index());
 }
 
 RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
 }
 
 RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
@@ -1503,11 +1583,12 @@ RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base,
 
 RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
 
 RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
-    emitOpcode(op_get_argument_by_val);
+    ValueProfile* profile = emitProfiledOpcode(op_get_argument_by_val);
     instructions().append(dst->index());
     ASSERT(base->index() == m_codeBlock->argumentsRegister());
     instructions().append(base->index());
     instructions().append(property->index());
     instructions().append(dst->index());
     ASSERT(base->index() == m_codeBlock->argumentsRegister());
     instructions().append(base->index());
     instructions().append(property->index());
+    instructions().append(profile);
     return dst;
 }
 
     return dst;
 }
 
@@ -1526,10 +1607,11 @@ RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, R
             return dst;
         }
     }
             return dst;
         }
     }
-    emitOpcode(op_get_by_val);
+    ValueProfile* profile = emitProfiledOpcode(op_get_by_val);
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(property->index());
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(property->index());
+    instructions().append(profile);
     return dst;
 }
 
     return dst;
 }
 
@@ -1574,7 +1656,7 @@ unsigned BytecodeGenerator::addConstantBuffer(unsigned length)
 
 JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier)
 {
 
 JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier)
 {
-    JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).first->second;
+    JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).iterator->second;
     if (!stringInMap) {
         stringInMap = jsString(globalData(), identifier.ustring());
         addConstantValue(stringInMap);
     if (!stringInMap) {
         stringInMap = jsString(globalData(), identifier.ustring());
         addConstantValue(stringInMap);
@@ -1644,10 +1726,10 @@ RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode
 
 RegisterID* BytecodeGenerator::emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* function)
 {
 
 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);
+    FunctionOffsetMap::AddResult ptr = m_functionOffsets.add(function, 0);
+    if (ptr.isNewEntry)
+        ptr.iterator->second = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function));
+    return emitNewFunctionInternal(dst, ptr.iterator->second, true);
 }
 
 RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index, bool doNullCheck)
 }
 
 RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index, bool doNullCheck)
@@ -1727,9 +1809,9 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
         emitMove(callArguments.profileHookRegister(), func);
 
     // Generate code for arguments.
         emitMove(callArguments.profileHookRegister(), func);
 
     // Generate code for arguments.
-    unsigned argumentIndex = 0;
+    unsigned argument = 0;
     for (ArgumentListNode* n = callArguments.argumentsNode()->m_listNode; n; n = n->m_next)
     for (ArgumentListNode* n = callArguments.argumentsNode()->m_listNode; n; n = n->m_next)
-        emitNode(callArguments.argumentRegister(argumentIndex++), n);
+        emitNode(callArguments.argumentRegister(argument++), n);
 
     // Reserve space for call frame.
     Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
 
     // Reserve space for call frame.
     Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
@@ -1743,18 +1825,21 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
 
     emitExpressionInfo(divot, startOffset, endOffset);
 
 
     emitExpressionInfo(divot, startOffset, endOffset);
 
-#if ENABLE(JIT)
-    m_codeBlock->addCallLinkInfo();
-#endif
-
     // Emit call.
     emitOpcode(opcodeID);
     instructions().append(func->index()); // func
     // Emit call.
     emitOpcode(opcodeID);
     instructions().append(func->index()); // func
-    instructions().append(callArguments.count()); // argCount
-    instructions().append(callArguments.callFrame()); // registerOffset
+    instructions().append(callArguments.argumentCountIncludingThis()); // argCount
+    instructions().append(callArguments.registerOffset()); // registerOffset
+#if ENABLE(LLINT)
+    instructions().append(m_codeBlock->addLLIntCallLinkInfo());
+#else
+    instructions().append(0);
+#endif
+    instructions().append(0);
     if (dst != ignoredResult()) {
     if (dst != ignoredResult()) {
-        emitOpcode(op_call_put_result);
+        ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
         instructions().append(dst->index()); // dst
         instructions().append(dst->index()); // dst
+        instructions().append(profile);
     }
 
     if (m_shouldEmitProfileHooks) {
     }
 
     if (m_shouldEmitProfileHooks) {
@@ -1765,40 +1850,30 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
     return dst;
 }
 
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitLoadVarargs(RegisterID* argCountDst, RegisterID* thisRegister, RegisterID* arguments)
-{
-    ASSERT(argCountDst->index() < arguments->index());
-    emitOpcode(op_load_varargs);
-    instructions().append(argCountDst->index());
-    instructions().append(arguments->index());
-    instructions().append(thisRegister->index() + RegisterFile::CallFrameHeaderSize); // initial registerOffset
-    return argCountDst;
-}
-
-RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* argCountRegister, unsigned divot, unsigned startOffset, unsigned endOffset)
+RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, RegisterID* profileHookRegister, unsigned divot, unsigned startOffset, unsigned endOffset)
 {
 {
-    ASSERT(func->refCount());
-    ASSERT(thisRegister->refCount());
-    ASSERT(dst != func);
     if (m_shouldEmitProfileHooks) {
     if (m_shouldEmitProfileHooks) {
+        emitMove(profileHookRegister, func);
         emitOpcode(op_profile_will_call);
         emitOpcode(op_profile_will_call);
-        instructions().append(func->index());
+        instructions().append(profileHookRegister->index());
     }
     
     emitExpressionInfo(divot, startOffset, endOffset);
     }
     
     emitExpressionInfo(divot, startOffset, endOffset);
-    
+
     // Emit call.
     emitOpcode(op_call_varargs);
     // Emit call.
     emitOpcode(op_call_varargs);
-    instructions().append(func->index()); // func
-    instructions().append(argCountRegister->index()); // arg count
-    instructions().append(thisRegister->index() + RegisterFile::CallFrameHeaderSize); // initial registerOffset
+    instructions().append(func->index());
+    instructions().append(thisRegister->index());
+    instructions().append(arguments->index());
+    instructions().append(firstFreeRegister->index());
     if (dst != ignoredResult()) {
     if (dst != ignoredResult()) {
-        emitOpcode(op_call_put_result);
-        instructions().append(dst->index()); // dst
+        ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
+        instructions().append(dst->index());
+        instructions().append(profile);
     }
     if (m_shouldEmitProfileHooks) {
         emitOpcode(op_profile_did_call);
     }
     if (m_shouldEmitProfileHooks) {
         emitOpcode(op_profile_did_call);
-        instructions().append(func->index());
+        instructions().append(profileHookRegister->index());
     }
     return dst;
 }
     }
     return dst;
 }
@@ -1809,8 +1884,7 @@ RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
         emitOpcode(op_tear_off_activation);
         instructions().append(m_activationRegister->index());
         instructions().append(m_codeBlock->argumentsRegister());
         emitOpcode(op_tear_off_activation);
         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.
+    } else if (m_codeBlock->usesArguments() && m_codeBlock->numParameters() != 1 && !m_codeBlock->isStrictMode()) {
         emitOpcode(op_tear_off_arguments);
         instructions().append(m_codeBlock->argumentsRegister());
     }
         emitOpcode(op_tear_off_arguments);
         instructions().append(m_codeBlock->argumentsRegister());
     }
@@ -1842,10 +1916,10 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
         emitMove(callArguments.profileHookRegister(), func);
 
     // Generate code for arguments.
         emitMove(callArguments.profileHookRegister(), func);
 
     // Generate code for arguments.
-    unsigned argumentIndex = 0;
+    unsigned argument = 0;
     if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
         for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
     if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
         for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
-            emitNode(callArguments.argumentRegister(argumentIndex++), n);
+            emitNode(callArguments.argumentRegister(argument++), n);
     }
 
     if (m_shouldEmitProfileHooks) {
     }
 
     if (m_shouldEmitProfileHooks) {
@@ -1860,17 +1934,20 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
 
     emitExpressionInfo(divot, startOffset, endOffset);
 
 
     emitExpressionInfo(divot, startOffset, endOffset);
 
-#if ENABLE(JIT)
-    m_codeBlock->addCallLinkInfo();
-#endif
-
     emitOpcode(op_construct);
     instructions().append(func->index()); // func
     emitOpcode(op_construct);
     instructions().append(func->index()); // func
-    instructions().append(callArguments.count()); // argCount
-    instructions().append(callArguments.callFrame()); // registerOffset
+    instructions().append(callArguments.argumentCountIncludingThis()); // argCount
+    instructions().append(callArguments.registerOffset()); // registerOffset
+#if ENABLE(LLINT)
+    instructions().append(m_codeBlock->addLLIntCallLinkInfo());
+#else
+    instructions().append(0);
+#endif
+    instructions().append(0);
     if (dst != ignoredResult()) {
     if (dst != ignoredResult()) {
-        emitOpcode(op_call_put_result);
+        ValueProfile* profile = emitProfiledOpcode(op_call_put_result);
         instructions().append(dst->index()); // dst
         instructions().append(dst->index()); // dst
+        instructions().append(profile);
     }
 
     if (m_shouldEmitProfileHooks) {
     }
 
     if (m_shouldEmitProfileHooks) {
@@ -1935,11 +2012,19 @@ void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, in
     instructions().append(lastLine);
 }
 
     instructions().append(lastLine);
 }
 
-void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst)
+void BytecodeGenerator::pushFinallyContext(StatementNode* finallyBlock)
 {
     ControlFlowContext scope;
     scope.isFinallyBlock = true;
 {
     ControlFlowContext scope;
     scope.isFinallyBlock = true;
-    FinallyContext context = { target, retAddrDst };
+    FinallyContext context = {
+        finallyBlock,
+        m_scopeContextStack.size(),
+        m_switchContextStack.size(),
+        m_forInContextStack.size(),
+        m_labelScopes.size(),
+        m_finallyDepth,
+        m_dynamicScopeDepth
+    };
     scope.finallyContext = context;
     m_scopeContextStack.append(scope);
     m_finallyDepth++;
     scope.finallyContext = context;
     m_scopeContextStack.append(scope);
     m_finallyDepth++;
@@ -2065,9 +2150,63 @@ PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, Contro
             instructions().append(nextInsn->bind(begin, instructions().size()));
             emitLabel(nextInsn.get());
         }
             instructions().append(nextInsn->bind(begin, instructions().size()));
             emitLabel(nextInsn.get());
         }
-
+        
+        Vector<ControlFlowContext> savedScopeContextStack;
+        Vector<SwitchInfo> savedSwitchContextStack;
+        Vector<ForInContext> savedForInContextStack;
+        SegmentedVector<LabelScope, 8> savedLabelScopes;
         while (topScope > bottomScope && topScope->isFinallyBlock) {
         while (topScope > bottomScope && topScope->isFinallyBlock) {
-            emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);
+            // Save the current state of the world while instating the state of the world
+            // for the finally block.
+            FinallyContext finallyContext = topScope->finallyContext;
+            bool flipScopes = finallyContext.scopeContextStackSize != m_scopeContextStack.size();
+            bool flipSwitches = finallyContext.switchContextStackSize != m_switchContextStack.size();
+            bool flipForIns = finallyContext.forInContextStackSize != m_forInContextStack.size();
+            bool flipLabelScopes = finallyContext.labelScopesSize != m_labelScopes.size();
+            int topScopeIndex = -1;
+            int bottomScopeIndex = -1;
+            if (flipScopes) {
+                topScopeIndex = topScope - m_scopeContextStack.begin();
+                bottomScopeIndex = bottomScope - m_scopeContextStack.begin();
+                savedScopeContextStack = m_scopeContextStack;
+                m_scopeContextStack.shrink(finallyContext.scopeContextStackSize);
+            }
+            if (flipSwitches) {
+                savedSwitchContextStack = m_switchContextStack;
+                m_switchContextStack.shrink(finallyContext.switchContextStackSize);
+            }
+            if (flipForIns) {
+                savedForInContextStack = m_forInContextStack;
+                m_forInContextStack.shrink(finallyContext.forInContextStackSize);
+            }
+            if (flipLabelScopes) {
+                savedLabelScopes = m_labelScopes;
+                while (m_labelScopes.size() > finallyContext.labelScopesSize)
+                    m_labelScopes.removeLast();
+            }
+            int savedFinallyDepth = m_finallyDepth;
+            m_finallyDepth = finallyContext.finallyDepth;
+            int savedDynamicScopeDepth = m_dynamicScopeDepth;
+            m_dynamicScopeDepth = finallyContext.dynamicScopeDepth;
+            
+            // Emit the finally block.
+            emitNode(finallyContext.finallyBlock);
+            
+            // Restore the state of the world.
+            if (flipScopes) {
+                m_scopeContextStack = savedScopeContextStack;
+                topScope = &m_scopeContextStack[topScopeIndex]; // assert it's within bounds
+                bottomScope = m_scopeContextStack.begin() + bottomScopeIndex; // don't assert, since it the index might be -1.
+            }
+            if (flipSwitches)
+                m_switchContextStack = savedSwitchContextStack;
+            if (flipForIns)
+                m_forInContextStack = savedForInContextStack;
+            if (flipLabelScopes)
+                m_labelScopes = savedLabelScopes;
+            m_finallyDepth = savedFinallyDepth;
+            m_dynamicScopeDepth = savedDynamicScopeDepth;
+            
             --topScope;
         }
     }
             --topScope;
         }
     }
@@ -2126,7 +2265,11 @@ RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* star
 {
     m_usesExceptions = true;
 #if ENABLE(JIT)
 {
     m_usesExceptions = true;
 #if ENABLE(JIT)
+#if ENABLE(LLINT)
+    HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(bitwise_cast<void*>(&llint_op_catch))) };
+#else
     HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
     HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
+#endif
 #else
     HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
 #endif
 #else
     HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
 #endif
@@ -2143,23 +2286,6 @@ void BytecodeGenerator::emitThrowReferenceError(const UString& message)
     instructions().append(addConstantValue(jsString(globalData(), message))->index());
 }
 
     instructions().append(addConstantValue(jsString(globalData(), message))->index());
 }
 
-PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
-{
-    size_t begin = instructions().size();
-
-    emitOpcode(op_jsr);
-    instructions().append(retAddrDst->index());
-    instructions().append(finally->bind(begin, instructions().size()));
-    emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it.
-    return finally;
-}
-
-void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
-{
-    emitOpcode(op_sret);
-    instructions().append(retAddrSrc->index());
-}
-
 void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value)
 {
     ControlFlowContext context;
 void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value)
 {
     ControlFlowContext context;
@@ -2228,7 +2354,7 @@ static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t
     StringImpl* clause = static_cast<StringNode*>(node)->value().impl();
     ASSERT(clause->length() == 1);
     
     StringImpl* clause = static_cast<StringNode*>(node)->value().impl();
     ASSERT(clause->length() == 1);
     
-    int32_t key = clause->characters()[0];
+    int32_t key = (*clause)[0];
     ASSERT(key >= min);
     ASSERT(key <= max);
     return key - min;
     ASSERT(key >= min);
     ASSERT(key <= max);
     return key - min;
@@ -2303,14 +2429,12 @@ void BytecodeGenerator::setIsNumericCompareFunction(bool isNumericCompareFunctio
     m_codeBlock->setIsNumericCompareFunction(isNumericCompareFunction);
 }
 
     m_codeBlock->setIsNumericCompareFunction(isNumericCompareFunction);
 }
 
-int BytecodeGenerator::argumentNumberFor(const Identifier& ident)
+bool BytecodeGenerator::isArgumentNumber(const Identifier& ident, int argumentNumber)
 {
 {
-    int parameterCount = m_parameters.size(); // includes 'this'
     RegisterID* registerID = registerFor(ident);
     RegisterID* registerID = registerFor(ident);
-    if (!registerID)
-        return 0;
-    int index = registerID->index() + RegisterFile::CallFrameHeaderSize + parameterCount;
-    return (index > 0 && index < parameterCount) ? index : 0;
+    if (!registerID || registerID->index() >= 0)
+         return 0;
+    return registerID->index() == CallFrame::argumentOffset(argumentNumber);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index bc297ee6d7fda2b78b8a57041e9b50c61703edf1..e58fcc79d72307c2162eaafbcbe1d90688b13936 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2012 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
@@ -31,7 +31,7 @@
 #define BytecodeGenerator_h
 
 #include "CodeBlock.h"
 #define BytecodeGenerator_h
 
 #include "CodeBlock.h"
-#include "HashTraits.h"
+#include <wtf/HashTraits.h>
 #include "Instruction.h"
 #include "Label.h"
 #include "LabelScope.h"
 #include "Instruction.h"
 #include "Label.h"
 #include "LabelScope.h"
@@ -47,6 +47,7 @@
 namespace JSC {
 
     class Identifier;
 namespace JSC {
 
     class Identifier;
+    class Label;
     class ScopeChainNode;
 
     class CallArguments {
     class ScopeChainNode;
 
     class CallArguments {
@@ -55,20 +56,27 @@ namespace JSC {
 
         RegisterID* thisRegister() { return m_argv[0].get(); }
         RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
 
         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(); }
+        unsigned registerOffset() { return m_argv.last()->index() + CallFrame::offsetFor(argumentCountIncludingThis()); }
+        unsigned argumentCountIncludingThis() { return m_argv.size(); }
         RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
         ArgumentsNode* argumentsNode() { return m_argumentsNode; }
 
     private:
         RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
         ArgumentsNode* argumentsNode() { return m_argumentsNode; }
 
     private:
+        void newArgument(BytecodeGenerator&);
+
         RefPtr<RegisterID> m_profileHookRegister;
         ArgumentsNode* m_argumentsNode;
         RefPtr<RegisterID> m_profileHookRegister;
         ArgumentsNode* m_argumentsNode;
-        Vector<RefPtr<RegisterID>, 16> m_argv;
+        Vector<RefPtr<RegisterID>, 8> m_argv;
     };
 
     struct FinallyContext {
     };
 
     struct FinallyContext {
-        Label* finallyAddr;
-        RegisterID* retAddrDst;
+        StatementNode* finallyBlock;
+        unsigned scopeContextStackSize;
+        unsigned switchContextStackSize;
+        unsigned forInContextStackSize;
+        unsigned labelScopesSize;
+        int finallyDepth;
+        int dynamicScopeDepth;
     };
 
     struct ControlFlowContext {
     };
 
     struct ControlFlowContext {
@@ -89,13 +97,15 @@ namespace JSC {
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
-        static void setDumpsGeneratedCode(bool dumpsGeneratedCode);
+        JS_EXPORT_PRIVATE static void setDumpsGeneratedCode(bool dumpsGeneratedCode);
         static bool dumpsGeneratedCode();
 
         static bool dumpsGeneratedCode();
 
-        BytecodeGenerator(ProgramNode*, ScopeChainNode*, SymbolTable*, ProgramCodeBlock*);
-        BytecodeGenerator(FunctionBodyNode*, ScopeChainNode*, SymbolTable*, CodeBlock*);
-        BytecodeGenerator(EvalNode*, ScopeChainNode*, SymbolTable*, EvalCodeBlock*);
+        BytecodeGenerator(ProgramNode*, ScopeChainNode*, SymbolTable*, ProgramCodeBlock*, CompilationKind);
+        BytecodeGenerator(FunctionBodyNode*, ScopeChainNode*, SymbolTable*, CodeBlock*, CompilationKind);
+        BytecodeGenerator(EvalNode*, ScopeChainNode*, SymbolTable*, EvalCodeBlock*, CompilationKind);
 
 
+        ~BytecodeGenerator();
+        
         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; }
 
@@ -108,8 +118,7 @@ namespace JSC {
         // require explicit reference counting.
         RegisterID* registerFor(const Identifier&);
 
         // 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&);
+        bool isArgumentNumber(const Identifier&, int);
 
         void setIsNumericCompareFunction(bool isNumericCompareFunction);
 
 
         void setIsNumericCompareFunction(bool isNumericCompareFunction);
 
@@ -121,9 +130,9 @@ namespace JSC {
         RegisterID* constRegisterFor(const Identifier&);
 
         // Searches the scope chain in an attempt to  statically locate the requested
         RegisterID* constRegisterFor(const Identifier&);
 
         // Searches the scope chain in an attempt to  statically locate the requested
-        // property.  Returns false if for any reason the property cannot be safely
-        // optimised at all.  Otherwise it will return the index and depth of the
-        // VariableObject that defines the property.  If the property cannot be found
+        // property. Returns false if for any reason the property cannot be safely
+        // optimised at all. Otherwise it will return the index and depth of the
+        // 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.
         bool findScopedProperty(const Identifier&, int& index, size_t& depth, bool forWriting, bool& includesDynamicScopes, JSObject*& globalObject);
         // statically, depth will contain the depth of the scope chain where dynamic
         // lookup must begin.
         bool findScopedProperty(const Identifier&, int& index, size_t& depth, bool forWriting, bool& includesDynamicScopes, JSObject*& globalObject);
@@ -271,7 +280,7 @@ namespace JSC {
                 return dst;
             }
 
                 return dst;
             }
 
-            return PassRefPtr<RegisterID>(emitNode(n));
+            return emitNode(n);
         }
 
         RegisterID* emitLoad(RegisterID* dst, bool);
         }
 
         RegisterID* emitLoad(RegisterID* dst, bool);
@@ -313,6 +322,7 @@ namespace JSC {
         RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property);
         RegisterID* emitResolveBaseForPut(RegisterID* dst, const Identifier& property);
         RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
         RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property);
         RegisterID* emitResolveBaseForPut(RegisterID* dst, const Identifier& property);
         RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
+        RegisterID* emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
 
         void emitMethodCheck();
 
 
         void emitMethodCheck();
 
@@ -326,12 +336,11 @@ namespace JSC {
         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* 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);
+        void emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter);
 
         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* 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* arguments, RegisterID* firstFreeRegister, RegisterID* profileHookRegister, unsigned divot, unsigned startOffset, unsigned endOffset);
         RegisterID* emitLoadVarargs(RegisterID* argCountDst, RegisterID* thisRegister, RegisterID* args);
 
         RegisterID* emitReturn(RegisterID* src);
         RegisterID* emitLoadVarargs(RegisterID* argCountDst, RegisterID* thisRegister, RegisterID* args);
 
         RegisterID* emitReturn(RegisterID* src);
@@ -342,6 +351,7 @@ namespace JSC {
         void emitToPrimitive(RegisterID* dst, RegisterID* src);
 
         PassRefPtr<Label> emitLabel(Label*);
         void emitToPrimitive(RegisterID* dst, RegisterID* src);
 
         PassRefPtr<Label> emitLabel(Label*);
+        void emitLoopHint();
         PassRefPtr<Label> emitJump(Label* target);
         PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
         PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
         PassRefPtr<Label> emitJump(Label* target);
         PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
         PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
@@ -349,9 +359,6 @@ namespace JSC {
         PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
         PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth);
 
         PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
         PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth);
 
-        PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*);
-        void emitSubroutineReturn(RegisterID* retAddrSrc);
-
         RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget);
         RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
 
         RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget);
         RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
 
@@ -374,7 +381,7 @@ namespace JSC {
         int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; }
         bool hasFinaliser() { return m_finallyDepth != 0; }
 
         int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; }
         bool hasFinaliser() { return m_finallyDepth != 0; }
 
-        void pushFinallyContext(Label* target, RegisterID* returnAddrDst);
+        void pushFinallyContext(StatementNode* finallyBlock);
         void popFinallyContext();
 
         void pushOptimisedForIn(RegisterID* expectedBase, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
         void popFinallyContext();
 
         void pushOptimisedForIn(RegisterID* expectedBase, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
@@ -399,9 +406,14 @@ namespace JSC {
         bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
         
         bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
         bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
         
         bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
+        
+        ScopeChainNode* scopeChain() const { return m_scopeChain.get(); }
 
     private:
 
     private:
+        friend class Label;
+        
         void emitOpcode(OpcodeID);
         void emitOpcode(OpcodeID);
+        ValueProfile* emitProfiledOpcode(OpcodeID);
         void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
         void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
         ALWAYS_INLINE void rewindBinaryOp();
         void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
         void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
         ALWAYS_INLINE void rewindBinaryOp();
@@ -409,18 +421,6 @@ namespace JSC {
 
         PassRefPtr<Label> emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
 
 
         PassRefPtr<Label> emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
 
-        typedef HashMap<EncodedJSValue, unsigned, EncodedJSValueHash, EncodedJSValueHashTraits> JSValueMap;
-
-        struct IdentifierMapIndexHashTraits {
-            typedef int TraitType;
-            typedef IdentifierMapIndexHashTraits StorageTraits;
-            static int emptyValue() { return std::numeric_limits<int>::max(); }
-            static const bool emptyValueIsZero = false;
-            static const bool needsDestruction = false;
-            static const bool needsRef = false;
-        };
-
-        typedef HashMap<RefPtr<StringImpl>, int, IdentifierRepHash, HashTraits<RefPtr<StringImpl> >, IdentifierMapIndexHashTraits> IdentifierMap;
         typedef HashMap<double, JSValue> NumberMap;
         typedef HashMap<StringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
         
         typedef HashMap<double, JSValue> NumberMap;
         typedef HashMap<StringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
         
@@ -446,15 +446,8 @@ namespace JSC {
             return newRegister();
         }
 
             return newRegister();
         }
 
-        // Returns the RegisterID corresponding to ident.
-        RegisterID* addGlobalVar(const Identifier& ident, bool isConstant)
-        {
-            RegisterID* local;
-            addGlobalVar(ident, isConstant, local);
-            return local;
-        }
-        // 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 the index of the added var.
+        int addGlobalVar(const Identifier&, bool isConstant);
 
         void addParameter(const Identifier&, int parameterIndex);
         
 
         void addParameter(const Identifier&, int parameterIndex);
         
@@ -466,12 +459,8 @@ namespace JSC {
             if (index >= 0)
                 return m_calleeRegisters[index];
 
             if (index >= 0)
                 return m_calleeRegisters[index];
 
-            if (m_parameters.size()) {
-                ASSERT(!m_globals.size());
-                return m_parameters[index + m_parameters.size() + RegisterFile::CallFrameHeaderSize];
-            }
-
-            return m_globals[-index - 1];
+            ASSERT(m_parameters.size());
+            return m_parameters[index + m_parameters.size() + RegisterFile::CallFrameHeaderSize];
         }
 
         unsigned addConstant(const Identifier&);
         }
 
         unsigned addConstant(const Identifier&);
@@ -482,12 +471,12 @@ namespace JSC {
         
         FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body)
         {
         
         FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body)
         {
-            return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
+            return FunctionExecutable::create(exec, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
         }
 
         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->isStrictMode(), body->lineNo(), body->lastLine());
+            return FunctionExecutable::create(*globalData, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
         }
 
         JSString* addStringConstant(const Identifier&);
         }
 
         JSString* addStringConstant(const Identifier&);
@@ -502,17 +491,41 @@ namespace JSC {
 
         RegisterID* emitInitLazyRegister(RegisterID*);
 
 
         RegisterID* emitInitLazyRegister(RegisterID*);
 
-        Vector<Instruction>& instructions() { return m_codeBlock->instructions(); }
+        Vector<Instruction>& instructions() { return m_instructions; }
         SymbolTable& symbolTable() { return *m_symbolTable; }
 
         SymbolTable& symbolTable() { return *m_symbolTable; }
 
-        bool shouldOptimizeLocals() { return (m_codeType != EvalCode) && !m_dynamicScopeDepth; }
-        bool canOptimizeNonLocals() { return (m_codeType == FunctionCode) && !m_dynamicScopeDepth && !m_codeBlock->usesEval(); }
+        bool shouldOptimizeLocals()
+        {
+            if (m_dynamicScopeDepth)
+                return false;
+
+            if (m_codeType != FunctionCode)
+                return false;
+
+            return true;
+        }
+
+        bool canOptimizeNonLocals()
+        {
+            if (m_dynamicScopeDepth)
+                return false;
+
+            if (m_codeType == EvalCode)
+                return false;
+
+            if (m_codeType == FunctionCode && m_codeBlock->usesEval())
+                return false;
+
+            return true;
+        }
 
         RegisterID* emitThrowExpressionTooDeepException();
 
         void createArgumentsIfNecessary();
         void createActivationIfNecessary();
         RegisterID* createLazyRegisterIfNecessary(RegisterID*);
 
         RegisterID* emitThrowExpressionTooDeepException();
 
         void createArgumentsIfNecessary();
         void createActivationIfNecessary();
         RegisterID* createLazyRegisterIfNecessary(RegisterID*);
+        
+        Vector<Instruction> m_instructions;
 
         bool m_shouldEmitDebugHooks;
         bool m_shouldEmitProfileHooks;
 
         bool m_shouldEmitDebugHooks;
         bool m_shouldEmitProfileHooks;
@@ -533,7 +546,6 @@ namespace JSC {
         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;
-        SegmentedVector<RegisterID, 32> m_globals;
         SegmentedVector<Label, 32> m_labels;
         SegmentedVector<LabelScope, 8> m_labelScopes;
         RefPtr<RegisterID> m_lastVar;
         SegmentedVector<Label, 32> m_labels;
         SegmentedVector<LabelScope, 8> m_labelScopes;
         RefPtr<RegisterID> m_lastVar;
@@ -546,7 +558,6 @@ namespace JSC {
         Vector<SwitchInfo> m_switchContextStack;
         Vector<ForInContext> m_forInContextStack;
 
         Vector<SwitchInfo> m_switchContextStack;
         Vector<ForInContext> m_forInContextStack;
 
-        int m_nextGlobalIndex;
         int m_firstConstantIndex;
         int m_nextConstantOffset;
         unsigned m_globalConstantIndex;
         int m_firstConstantIndex;
         int m_nextConstantOffset;
         unsigned m_globalConstantIndex;
index 8cab1dbc00dc9ec623b37a20a86c484cc7122f88..21fa46309a2f2875a28da6483bb4a56fe1ee0dad 100644 (file)
@@ -39,21 +39,14 @@ namespace JSC {
 
     class Label {
     public:
 
     class Label {
     public:
-        explicit Label(CodeBlock* codeBlock)
+        explicit Label(BytecodeGenerator* generator)
             : m_refCount(0)
             , m_location(invalidLocation)
             : m_refCount(0)
             , m_location(invalidLocation)
-            , m_codeBlock(codeBlock)
+            , m_generator(generator)
         {
         }
 
         {
         }
 
-        void setLocation(unsigned location)
-        {
-            m_location = location;
-
-            unsigned size = m_unresolvedJumps.size();
-            for (unsigned i = 0; i < size; ++i)
-                m_codeBlock->instructions()[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first;
-        }
+        void setLocation(unsigned);
 
         int bind(int opcode, int offset) const
         {
 
         int bind(int opcode, int offset) const
         {
@@ -81,7 +74,7 @@ namespace JSC {
 
         int m_refCount;
         unsigned m_location;
 
         int m_refCount;
         unsigned m_location;
-        CodeBlock* m_codeBlock;
+        BytecodeGenerator* m_generator;
         mutable JumpVector m_unresolvedJumps;
     };
 
         mutable JumpVector m_unresolvedJumps;
     };
 
index a7abadf40312a26889ec079a9c4ae4ba4d8f5df9..5ada2609c2bede731711719a389fe62b7f74135e 100644 (file)
@@ -1,7 +1,7 @@
 /*
 *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
 *  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) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved.
 *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
 *  Copyright (C) 2007 Maks Orlovich
 *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
 *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
 *  Copyright (C) 2007 Maks Orlovich
 *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
@@ -125,7 +125,7 @@ RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d
 {
     if (dst == generator.ignoredResult())
         return 0;
 {
     if (dst == generator.ignoredResult())
         return 0;
-    return generator.emitNewRegExp(generator.finalDestination(dst), RegExp::create(generator.globalData(), m_pattern.ustring(), regExpFlags(m_flags.ustring())));
+    return generator.emitNewRegExp(generator.finalDestination(dst), RegExp::create(*generator.globalData(), m_pattern.ustring(), regExpFlags(m_flags.ustring())));
 }
 
 // ------------------------------ ThisNode -------------------------------------
 }
 
 // ------------------------------ ThisNode -------------------------------------
@@ -200,18 +200,18 @@ bool ArrayNode::isSimpleArray() const
     return true;
 }
 
     return true;
 }
 
-ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const
+ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData, int lineNumber) const
 {
     ASSERT(!m_elision && !m_optional);
     ElementNode* ptr = m_element;
     if (!ptr)
         return 0;
 {
     ASSERT(!m_elision && !m_optional);
     ElementNode* ptr = m_element;
     if (!ptr)
         return 0;
-    ArgumentListNode* head = new (globalData) ArgumentListNode(globalData, ptr->value());
+    ArgumentListNode* head = new (globalData) ArgumentListNode(lineNumber, ptr->value());
     ArgumentListNode* tail = head;
     ptr = ptr->next();
     for (; ptr; ptr = ptr->next()) {
         ASSERT(!ptr->elision());
     ArgumentListNode* tail = head;
     ptr = ptr->next();
     for (; ptr; ptr = ptr->next()) {
         ASSERT(!ptr->elision());
-        tail = new (globalData) ArgumentListNode(globalData, tail, ptr->value());
+        tail = new (globalData) ArgumentListNode(lineNumber, tail, ptr->value());
     }
     return head;
 }
     }
     return head;
 }
@@ -236,27 +236,79 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe
     
     generator.emitNewObject(newObj.get());
     
     
     generator.emitNewObject(newObj.get());
     
-    for (PropertyListNode* p = this; p; p = p->m_next) {
-        RegisterID* value = generator.emitNode(p->m_node->m_assign);
-        
-        switch (p->m_node->m_type) {
-            case PropertyNode::Constant: {
-                generator.emitDirectPutById(newObj.get(), p->m_node->name(), value);
-                break;
-            }
-            case PropertyNode::Getter: {
-                generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
-                break;
+    // Fast case: this loop just handles regular value properties.
+    PropertyListNode* p = this;
+    for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next)
+        generator.emitDirectPutById(newObj.get(), p->m_node->name(), generator.emitNode(p->m_node->m_assign));
+
+    // Were there any get/set properties?
+    if (p) {
+        typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
+        typedef HashMap<StringImpl*, GetterSetterPair> GetterSetterMap;
+        GetterSetterMap map;
+
+        // Build a map, pairing get/set values together.
+        for (PropertyListNode* q = p; q; q = q->m_next) {
+            PropertyNode* node = q->m_node;
+            if (node->m_type == PropertyNode::Constant)
+                continue;
+
+            GetterSetterPair pair(node, static_cast<PropertyNode*>(0));
+            GetterSetterMap::AddResult result = map.add(node->name().impl(), pair);
+            if (!result.isNewEntry)
+                result.iterator->second.second = node;
+        }
+
+        // Iterate over the remaining properties in the list.
+        for (; p; p = p->m_next) {
+            PropertyNode* node = p->m_node;
+            RegisterID* value = generator.emitNode(node->m_assign);
+
+            // Handle regular values.
+            if (node->m_type == PropertyNode::Constant) {
+                generator.emitDirectPutById(newObj.get(), node->name(), value);
+                continue;
             }
             }
-            case PropertyNode::Setter: {
-                generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
-                break;
+
+            // This is a get/set property, find its entry in the map.
+            ASSERT(node->m_type == PropertyNode::Getter || node->m_type == PropertyNode::Setter);
+            GetterSetterMap::iterator it = map.find(node->name().impl());
+            ASSERT(it != map.end());
+            GetterSetterPair& pair = it->second;
+
+            // Was this already generated as a part of its partner?
+            if (pair.second == node)
+                continue;
+    
+            // Generate the paired node now.
+            RefPtr<RegisterID> getterReg;
+            RefPtr<RegisterID> setterReg;
+
+            if (node->m_type == PropertyNode::Getter) {
+                getterReg = value;
+                if (pair.second) {
+                    ASSERT(pair.second->m_type == PropertyNode::Setter);
+                    setterReg = generator.emitNode(pair.second->m_assign);
+                } else {
+                    setterReg = generator.newTemporary();
+                    generator.emitLoad(setterReg.get(), jsUndefined());
+                }
+            } else {
+                ASSERT(node->m_type == PropertyNode::Setter);
+                setterReg = value;
+                if (pair.second) {
+                    ASSERT(pair.second->m_type == PropertyNode::Getter);
+                    getterReg = generator.emitNode(pair.second->m_assign);
+                } else {
+                    getterReg = generator.newTemporary();
+                    generator.emitLoad(getterReg.get(), jsUndefined());
+                }
             }
             }
-            default:
-                ASSERT_NOT_REACHED();
+
+            generator.emitPutGetterSetter(newObj.get(), node->name(), getterReg.get(), setterReg.get());
         }
     }
         }
     }
-    
+
     return generator.moveToDestinationIfNeeded(dst, newObj.get());
 }
 
     return generator.moveToDestinationIfNeeded(dst, newObj.get());
 }
 
@@ -313,21 +365,32 @@ RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
     return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
     return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
-CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode)
+inline CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode)
     : m_argumentsNode(argumentsNode)
 {
     if (generator.shouldEmitProfileHooks())
         m_profileHookRegister = generator.newTemporary();
     : m_argumentsNode(argumentsNode)
 {
     if (generator.shouldEmitProfileHooks())
         m_profileHookRegister = generator.newTemporary();
-    m_argv.append(generator.newTemporary());
+
+    size_t argumentCountIncludingThis = 1; // 'this' register.
     if (argumentsNode) {
     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);
-        }
+        for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
+            ++argumentCountIncludingThis;
+    }
+
+    m_argv.grow(argumentCountIncludingThis);
+    for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
+        m_argv[i] = generator.newTemporary();
+        ASSERT(static_cast<size_t>(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->index() + 1);
     }
 }
 
     }
 }
 
+inline void CallArguments::newArgument(BytecodeGenerator& generator)
+{
+    RefPtr<RegisterID> tmp = generator.newTemporary();
+    ASSERT(m_argv.isEmpty() || tmp->index() == m_argv.last()->index() + 1); // Calling convention assumes that all arguments are contiguous.
+    m_argv.append(tmp.release());
+}
+
 // ------------------------------ EvalFunctionCallNode ----------------------------------
 
 RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 // ------------------------------ EvalFunctionCallNode ----------------------------------
 
 RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
@@ -335,7 +398,7 @@ RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, Reg
     RefPtr<RegisterID> func = generator.tempDestination(dst);
     CallArguments callArguments(generator, m_args);
     generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
     RefPtr<RegisterID> func = generator.tempDestination(dst);
     CallArguments callArguments(generator, m_args);
     generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
-    generator.emitResolveWithBase(callArguments.thisRegister(), func.get(), generator.propertyNames().eval);
+    generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.propertyNames().eval);
     return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
     return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
@@ -354,9 +417,10 @@ 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> function = generator.emitMove(generator.tempDestination(dst), local.get());
         CallArguments callArguments(generator, m_args);
         generator.emitLoad(callArguments.thisRegister(), jsUndefined());
         CallArguments callArguments(generator, m_args);
         generator.emitLoad(callArguments.thisRegister(), jsUndefined());
-        return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), local.get(), callArguments, divot(), startOffset(), endOffset());
+        return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), function.get(), callArguments, divot(), startOffset(), endOffset());
     }
 
     int index = 0;
     }
 
     int index = 0;
@@ -374,7 +438,7 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator,
     CallArguments callArguments(generator, m_args);
     int identifierStart = divot() - startOffset();
     generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0);
     CallArguments callArguments(generator, m_args);
     int identifierStart = divot() - startOffset();
     generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0);
-    generator.emitResolveWithBase(callArguments.thisRegister(), func.get(), m_ident);
+    generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), m_ident);
     return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
     return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
@@ -425,7 +489,6 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
             generator.emitJump(end.get());
 
             m_args->m_listNode = oldList;
             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);
         } else {
             RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
             CallArguments callArguments(generator, m_args);
@@ -471,7 +534,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
                 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);
                 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());
+                    m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.globalData(), 0);
                     RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
                     CallArguments callArguments(generator, m_args);
                     generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
                     RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
                     CallArguments callArguments(generator, m_args);
                     generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
@@ -492,26 +555,24 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
             }
         } else {
             ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
             }
         } else {
             ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
-            RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
-            RefPtr<RegisterID> argsCountRegister = generator.newTemporary();
-            RefPtr<RegisterID> thisRegister = generator.newTemporary();
-            RefPtr<RegisterID> argsRegister = generator.newTemporary();
-            generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
+            RefPtr<RegisterID> profileHookRegister;
+            if (generator.shouldEmitProfileHooks())
+                profileHookRegister = generator.newTemporary();
+            RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+            RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
+            RefPtr<RegisterID> argsRegister;
             ArgumentListNode* args = m_args->m_listNode->m_next;
             ArgumentListNode* args = m_args->m_listNode->m_next;
-            bool isArgumentsApply = false;
-            if (args->m_expr->isResolveNode()) {
-                ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr);
-                isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier());
-                if (isArgumentsApply)
-                    generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments());
-            }
-            if (!isArgumentsApply)
-                generator.emitNode(argsRegister.get(), args->m_expr);
+            if (args->m_expr->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(args->m_expr)->identifier()))
+                argsRegister = generator.uncheckedRegisterForArguments();
+            else
+                argsRegister = generator.emitNode(args->m_expr);
+
+            // Function.prototype.apply ignores extra arguments, but we still
+            // need to evaluate them for side effects.
             while ((args = args->m_next))
                 generator.emitNode(args->m_expr);
 
             while ((args = args->m_next))
                 generator.emitNode(args->m_expr);
 
-            generator.emitLoadVarargs(argsCountRegister.get(), thisRegister.get(), argsRegister.get());
-            generator.emitCallVarargs(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset());
+            generator.emitCallVarargs(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), startOffset(), endOffset());
         }
         generator.emitJump(end.get());
     }
         }
         generator.emitJump(end.get());
     }
@@ -744,7 +805,7 @@ RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, Regist
     size_t depth = 0;
     JSObject* globalObject = 0;
     bool requiresDynamicChecks = false;
     size_t depth = 0;
     JSObject* globalObject = 0;
     bool requiresDynamicChecks = false;
-    if (generator.findScopedProperty(m_ident, index, depth, false, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
+    if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
         RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
         emitPreIncOrDec(generator, propDst.get(), m_operator);
         generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
         RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
         emitPreIncOrDec(generator, propDst.get(), m_operator);
         generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
@@ -813,7 +874,15 @@ RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
     return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
 }
 
     return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
 }
 
-
+// ------------------------------ BitwiseNotNode -----------------------------------
+RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
+    RegisterID* src1 = generator.emitNode(m_expr);
+    return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1), src1, src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32()));
+}
 // ------------------------------ LogicalNotNode -----------------------------------
 
 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
 // ------------------------------ LogicalNotNode -----------------------------------
 
 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
@@ -985,13 +1054,6 @@ RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, Register
     return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
 }
 
     return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
 }
 
-RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
-    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
-    RegisterID* src2 = generator.emitNode(m_expr2);
-    return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
-}
-
 RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
 RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
@@ -1149,10 +1211,9 @@ static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& gen
 RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     if (RegisterID* local = generator.registerFor(m_ident)) {
 RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     if (RegisterID* local = generator.registerFor(m_ident)) {
-        if (generator.isLocalConstant(m_ident)) {
+        if (generator.isLocalConstant(m_ident))
             return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
             return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
-        }
-        
+
         if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
             RefPtr<RegisterID> result = generator.newTemporary();
             generator.emitMove(result.get(), local);
         if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
             RefPtr<RegisterID> result = generator.newTemporary();
             generator.emitMove(result.get(), local);
@@ -1223,8 +1284,9 @@ RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID
     RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
     RegisterID* result = generator.emitNode(value.get(), m_right);
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
     RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
     RegisterID* result = generator.emitNode(value.get(), m_right);
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitPutById(base.get(), m_ident, result);
-    return generator.moveToDestinationIfNeeded(dst, result);
+    RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
+    generator.emitPutById(base.get(), m_ident, forwardResult);
+    return generator.moveToDestinationIfNeeded(dst, forwardResult);
 }
 
 // ------------------------------ ReadModifyDotNode -----------------------------------
 }
 
 // ------------------------------ ReadModifyDotNode -----------------------------------
@@ -1258,8 +1320,9 @@ RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, Regist
     RegisterID* result = generator.emitNode(value.get(), m_right);
 
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
     RegisterID* result = generator.emitNode(value.get(), m_right);
 
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitPutByVal(base.get(), property.get(), result);
-    return generator.moveToDestinationIfNeeded(dst, result);
+    RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
+    generator.emitPutByVal(base.get(), property.get(), forwardResult);
+    return generator.moveToDestinationIfNeeded(dst, forwardResult);
 }
 
 // ------------------------------ ReadModifyBracketNode -----------------------------------
 }
 
 // ------------------------------ ReadModifyBracketNode -----------------------------------
@@ -1293,6 +1356,7 @@ RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
 
 RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
 {
 
 RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
 {
+    // FIXME: This code does not match the behavior of const in Firefox.
     if (RegisterID* local = generator.constRegisterFor(m_ident)) {
         if (!m_init)
             return local;
     if (RegisterID* local = generator.constRegisterFor(m_ident)) {
         if (!m_init)
             return local;
@@ -1300,17 +1364,30 @@ RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
         return generator.emitNode(local, m_init);
     }
 
         return generator.emitNode(local, m_init);
     }
 
-    if (generator.codeType() != EvalCode) {
-        if (m_init)
-            return generator.emitNode(m_init);
-        else
-            return generator.emitResolve(generator.newTemporary(), m_ident);
+    RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
+
+    ScopeChainIterator iter = generator.scopeChain()->begin();
+    ScopeChainIterator end = generator.scopeChain()->end();
+    size_t depth = 0;
+    for (; iter != end; ++iter, ++depth) {
+        JSObject* currentScope = iter->get();
+        if (!currentScope->isVariableObject())
+            continue;
+        JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
+        SymbolTableEntry entry = currentVariableObject->symbolTable().get(m_ident.impl());
+        if (entry.isNull())
+            continue;
+
+        return generator.emitPutScopedVar(generator.scopeDepth() + depth, entry.getIndex(), value.get(), currentVariableObject->isGlobalObject() ? currentVariableObject : 0);
     }
     }
-    // FIXME: While this code should only be hit in eval code, it will potentially
-    // assign to the wrong base if m_ident exists in an intervening dynamic scope.
+
+    if (generator.codeType() != EvalCode)
+        return value.get();
+
+    // FIXME: While this code should only be hit in an eval block, it will assign
+    // to the wrong base if m_ident exists in an intervening with scope.
     RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
     RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
-    RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
-    return generator.emitPutById(base.get(), m_ident, value);
+    return generator.emitPutById(base.get(), m_ident, value.get());
 }
 
 RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
 }
 
 RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
@@ -1462,7 +1539,7 @@ RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
 
     RefPtr<Label> topOfLoop = generator.newLabel();
     generator.emitLabel(topOfLoop.get());
 
     RefPtr<Label> topOfLoop = generator.newLabel();
     generator.emitLabel(topOfLoop.get());
-
+    generator.emitLoopHint();
     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    
     RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    
     RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
@@ -1490,6 +1567,7 @@ RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
 
     RefPtr<Label> topOfLoop = generator.newLabel();
     generator.emitLabel(topOfLoop.get());
 
     RefPtr<Label> topOfLoop = generator.newLabel();
     generator.emitLabel(topOfLoop.get());
+    generator.emitLoopHint();
     
     generator.emitNode(dst, m_statement);
 
     
     generator.emitNode(dst, m_statement);
 
@@ -1525,6 +1603,7 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 
     RefPtr<Label> topOfLoop = generator.newLabel();
     generator.emitLabel(topOfLoop.get());
 
     RefPtr<Label> topOfLoop = generator.newLabel();
     generator.emitLabel(topOfLoop.get());
+    generator.emitLoopHint();
 
     RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
 
 
     RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
 
@@ -1572,6 +1651,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
 
     RefPtr<Label> loopStart = generator.newLabel();
     generator.emitLabel(loopStart.get());
 
     RefPtr<Label> loopStart = generator.newLabel();
     generator.emitLabel(loopStart.get());
+    generator.emitLoopHint();
 
     RegisterID* propertyName;
     bool optimizedForinAccess = false;
 
     RegisterID* propertyName;
     bool optimizedForinAccess = false;
@@ -1664,7 +1744,7 @@ RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d
     RefPtr<RegisterID> returnRegister;
     if (generator.scopeDepth()) {
         RefPtr<Label> l0 = generator.newLabel();
     RefPtr<RegisterID> returnRegister;
     if (generator.scopeDepth()) {
         RefPtr<Label> l0 = generator.newLabel();
-        if (generator.hasFinaliser() && !r0->isTemporary()) {
+        if (generator.hasFinaliser()) {
             returnRegister = generator.emitMove(generator.newTemporary(), r0);
             r0 = returnRegister.get();
         }
             returnRegister = generator.emitMove(generator.newTemporary(), r0);
             r0 = returnRegister.get();
         }
@@ -1733,7 +1813,7 @@ static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>&
             }
             const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
             if (singleCharacterSwitch &= value.length() == 1) {
             }
             const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
             if (singleCharacterSwitch &= value.length() == 1) {
-                int32_t intVal = value.impl()->characters()[0];
+                int32_t intVal = value[0];
                 if (intVal < min_num)
                     min_num = intVal;
                 if (intVal > max_num)
                 if (intVal < min_num)
                     min_num = intVal;
                 if (intVal > max_num)
@@ -1894,13 +1974,8 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
 
     RefPtr<Label> tryStartLabel = generator.newLabel();
     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
 
     RefPtr<Label> tryStartLabel = generator.newLabel();
-    RefPtr<Label> finallyStart;
-    RefPtr<RegisterID> finallyReturnAddr;
-    if (m_finallyBlock) {
-        finallyStart = generator.newLabel();
-        finallyReturnAddr = generator.newTemporary();
-        generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
-    }
+    if (m_finallyBlock)
+        generator.pushFinallyContext(m_finallyBlock);
 
     generator.emitLabel(tryStartLabel.get());
     generator.emitNode(dst, m_tryBlock);
 
     generator.emitLabel(tryStartLabel.get());
     generator.emitNode(dst, m_tryBlock);
@@ -1914,13 +1989,7 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
         // Uncaught exception path: the catch block.
         RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
         RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
         // Uncaught exception path: the catch block.
         RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
         RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
-        if (m_catchHasEval) {
-            RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
-            generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
-            generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get());
-            generator.emitPushScope(exceptionRegister.get());
-        } else
-            generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
+        generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
         generator.emitNode(dst, m_catchBlock);
         generator.emitPopScope();
         generator.emitLabel(catchEndLabel.get());
         generator.emitNode(dst, m_catchBlock);
         generator.emitPopScope();
         generator.emitLabel(catchEndLabel.get());
@@ -1928,27 +1997,18 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 
     if (m_finallyBlock) {
         generator.popFinallyContext();
 
     if (m_finallyBlock) {
         generator.popFinallyContext();
-        // there may be important registers live at the time we jump
-        // to a finally block (such as for a return or throw) so we
-        // ref the highest register ever used as a conservative
-        // approach to not clobbering anything important
-        RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
+
         RefPtr<Label> finallyEndLabel = generator.newLabel();
 
         RefPtr<Label> finallyEndLabel = generator.newLabel();
 
-        // Normal path: invoke the finally block, then jump over it.
-        generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+        // Normal path: run the finally code, and jump to the end.
+        generator.emitNode(dst, m_finallyBlock);
         generator.emitJump(finallyEndLabel.get());
 
         // Uncaught exception path: invoke the finally block, then re-throw the exception.
         RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
         RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
         generator.emitJump(finallyEndLabel.get());
 
         // Uncaught exception path: invoke the finally block, then re-throw the exception.
         RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
         RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
-        generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
-        generator.emitThrow(tempExceptionRegister.get());
-
-        // The finally block.
-        generator.emitLabel(finallyStart.get());
         generator.emitNode(dst, m_finallyBlock);
         generator.emitNode(dst, m_finallyBlock);
-        generator.emitSubroutineReturn(finallyReturnAddr.get());
+        generator.emitThrow(tempExceptionRegister.get());
 
         generator.emitLabel(finallyEndLabel.get());
     }
 
         generator.emitLabel(finallyEndLabel.get());
     }
@@ -1960,8 +2020,8 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 
 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
 
 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
-    if (m_data->m_statements)
-        m_data->m_statements->emitBytecode(generator, dst);
+    if (m_statements)
+        m_statements->emitBytecode(generator, dst);
 }
 
 // ------------------------------ ProgramNode -----------------------------
 }
 
 // ------------------------------ ProgramNode -----------------------------
@@ -2025,9 +2085,12 @@ RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, Registe
         if (returnValueExpression && returnValueExpression->isSubtract()) {
             ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs();
             ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs();
         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);
+            if (lhsExpression->isResolveNode()
+                && rhsExpression->isResolveNode()
+                && generator.isArgumentNumber(static_cast<ResolveNode*>(lhsExpression)->identifier(), 0)
+                && generator.isArgumentNumber(static_cast<ResolveNode*>(rhsExpression)->identifier(), 1)) {
+                
+                generator.setIsNumericCompareFunction(true);
             }
         }
     }
             }
         }
     }
index 394bba56a452ba761d05dc50f66ae35c056e5321..1e49c96bf832fcd64d12d6d6ccf72dba739df301 100644 (file)
--- a/config.h
+++ b/config.h
 #endif
 
 #include <wtf/Platform.h>
 #endif
 
 #include <wtf/Platform.h>
-
-/* See note in wtf/Platform.h for more info on EXPORT_MACROS. */
-#if USE(EXPORT_MACROS)
-
 #include <wtf/ExportMacros.h>
 #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
+// WTF cannot depend on JSC even if USE(JSC).
+#if USE(JSC) && !defined(BUILDING_WTF)
+#include "JSExportMacros.h"
+#elif PLATFORM(CHROMIUM)
+// Chromium doesn't have runtime/ in its include paths.
+#include "runtime/JSExportMacros.h"
 #endif
 
 #endif
 
-#define JS_EXPORTDATA JS_EXPORT_PRIVATE
-#define JS_EXPORTCLASS JS_EXPORT_PRIVATE
-
-#else /* !USE(EXPORT_MACROS) */
+#if OS(WINDOWS)
 
 
-#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC)
-#if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF)
-#define JS_EXPORTDATA __declspec(dllexport)
-#else
-#define JS_EXPORTDATA __declspec(dllimport)
-#endif
-#define JS_EXPORTCLASS JS_EXPORTDATA
-#else
-#define JS_EXPORTDATA
-#define JS_EXPORTCLASS
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500
 #endif
 
 #endif
 
-#define WTF_EXPORT_PRIVATE
-#define JS_EXPORT_PRIVATE
-
-#endif /* USE(EXPORT_MACROS) */
-
-#if OS(WINDOWS)
+#ifndef WINVER
+#define WINVER 0x0500
+#endif
 
 // If we don't define these, they get defined in windef.h. 
 // We want to use std::min and std::max
 
 // If we don't define these, they get defined in windef.h. 
 // We want to use std::min and std::max
 
 #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
-
-/* FIXME: if all platforms have these, do they really need #defines? */
-#define HAVE_STDINT_H 1
-
 #define WTF_CHANGES 1
 
 #ifdef __cplusplus
 #define WTF_CHANGES 1
 
 #ifdef __cplusplus
 #endif
 
 // this breaks compilation of <QFontDatabase>, at least, so turn it off for now
 #endif
 
 // this breaks compilation of <QFontDatabase>, at least, so turn it off for now
-// Also generates errors on wx on Windows, because these functions
-// are used from wx headers. 
-#if !PLATFORM(QT) && !PLATFORM(WX)
+// Also generates errors on wx on Windows and QNX, because these functions
+// are used from wx and QNX headers. 
+#if !PLATFORM(QT) && !PLATFORM(WX) && !OS(QNX)
 #include <wtf/DisallowCType.h>
 #endif
 
 #include <wtf/DisallowCType.h>
 #endif
 
 #else
 #define SKIP_STATIC_CONSTRUCTORS_ON_GCC 1
 #endif
 #else
 #define SKIP_STATIC_CONSTRUCTORS_ON_GCC 1
 #endif
-
-#if PLATFORM(CHROMIUM)
-#if !defined(WTF_USE_V8)
-#define WTF_USE_V8 1
-#endif
-#endif /* PLATFORM(CHROMIUM) */
-
-#if !defined(WTF_USE_V8)
-#define WTF_USE_V8 0
-#endif /* !defined(WTF_USE_V8) */
-
-/* Using V8 implies not using JSC and vice versa */
-#define WTF_USE_JSC !WTF_USE_V8
index 59b574aaf561fe8e0f0000fe027fcd0453cc414b..cb2809d76de2583f21eeaf085b6cefd6c23732f9 100755 (executable)
@@ -179,7 +179,6 @@ sub calcCompactHashSize()
 
 # Paul Hsieh's SuperFastHash
 # http://www.azillionmonkeys.com/qed/hash.html
 
 # Paul Hsieh's SuperFastHash
 # http://www.azillionmonkeys.com/qed/hash.html
-# Ported from UString..
 sub hashValue($) {
   my @chars = split(/ */, $_[0]);
 
 sub hashValue($) {
   my @chars = split(/ */, $_[0]);
 
@@ -207,7 +206,7 @@ sub hashValue($) {
   }
 
   # Handle end case
   }
 
   # Handle end case
-  if ($rem !=0) {
+  if ($rem != 0) {
     $hash += ord($chars[$s]);
     $hash ^= (leftShift($hash, 11)% $EXP2_32);
     $hash += $hash >> 17;
     $hash += ord($chars[$s]);
     $hash ^= (leftShift($hash, 11)% $EXP2_32);
     $hash += $hash >> 17;
@@ -221,11 +220,15 @@ sub hashValue($) {
   $hash += ($hash >> 15);
   $hash = $hash% $EXP2_32;
   $hash ^= (leftShift($hash, 10)% $EXP2_32);
   $hash += ($hash >> 15);
   $hash = $hash% $EXP2_32;
   $hash ^= (leftShift($hash, 10)% $EXP2_32);
-  
-  # 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 = 0x80000000  if ($hash == 0);
+
+  # Save 8 bits for StringImpl to use as flags.
+  $hash &= 0xffffff;
+
+  # This avoids ever returning a hash code of 0, since that is used to
+  # signal "hash not computed yet". Setting the high bit maintains
+  # reasonable fidelity to a hash code of 0 because it is likely to yield
+  # exactly 0 when hash lookup masks out the high bits.
+  $hash = (0x80000000 >> 8) if ($hash == 0);
 
   return $hash;
 }
 
   return $hash;
 }
@@ -247,11 +250,6 @@ sub output() {
         print "\nnamespace JSC {\n";
     }
     my $count = scalar @keys + 1;
         print "\nnamespace JSC {\n";
     }
     my $count = scalar @keys + 1;
-    print "#if ENABLE(JIT)\n";
-    print "#define THUNK_GENERATOR(generator) , generator\n";
-    print "#else\n";
-    print "#define THUNK_GENERATOR(generator)\n";
-    print "#endif\n";
     print "\nstatic const struct HashTableValue ${nameEntries}\[$count\] = {\n";
     my $i = 0;
     foreach my $key (@keys) {
     print "\nstatic const struct HashTableValue ${nameEntries}\[$count\] = {\n";
     my $i = 0;
     foreach my $key (@keys) {
@@ -271,29 +269,38 @@ sub output() {
             $firstValue = $values[$i]{"value"};
             $secondValue = "0";
         }
             $firstValue = $values[$i]{"value"};
             $secondValue = "0";
         }
-        my $thunkGenerator = "0";
-        if ($key eq "charCodeAt") {
-            $thunkGenerator = "charCodeAtThunkGenerator";
-        }
-        if ($key eq "charAt") {
-            $thunkGenerator = "charAtThunkGenerator";
-        }
-        if ($key eq "sqrt") {
-            $thunkGenerator = "sqrtThunkGenerator";
+
+        my $intrinsic = "NoIntrinsic";
+        $intrinsic = "CharCodeAtIntrinsic" if ($key eq "charCodeAt");
+        $intrinsic = "CharAtIntrinsic" if ($key eq "charAt");
+        $intrinsic = "FromCharCodeIntrinsic" if ($key eq "fromCharCode");
+        if ($name eq "mathTable") {
+            $intrinsic = "MinIntrinsic" if ($key eq "min");
+            $intrinsic = "MaxIntrinsic" if ($key eq "max");
+            $intrinsic = "SqrtIntrinsic" if ($key eq "sqrt");
+            $intrinsic = "PowIntrinsic" if ($key eq "pow");
+            $intrinsic = "AbsIntrinsic" if ($key eq "abs");
+            $intrinsic = "FloorIntrinsic" if ($key eq "floor");
+            $intrinsic = "CeilIntrinsic" if ($key eq "ceil");
+            $intrinsic = "RoundIntrinsic" if ($key eq "round");
+            $intrinsic = "ExpIntrinsic" if ($key eq "exp");
+            $intrinsic = "LogIntrinsic" if ($key eq "log");
         }
         }
-        if ($key eq "pow") {
-            $thunkGenerator = "powThunkGenerator";
+        if ($name eq "arrayPrototypeTable") {
+            $intrinsic = "ArrayPushIntrinsic" if ($key eq "push");
+            $intrinsic = "ArrayPopIntrinsic" if ($key eq "pop");
         }
         }
-        if ($key eq "fromCharCode") {
-            $thunkGenerator = "fromCharCodeThunkGenerator";
+        if ($name eq "regExpPrototypeTable") {
+            $intrinsic = "RegExpExecIntrinsic" if ($key eq "exec");
+            $intrinsic = "RegExpTestIntrinsic" if ($key eq "test");
         }
         }
-        print "   { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue THUNK_GENERATOR($thunkGenerator) },\n";
+
+        print "   { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue, $intrinsic },\n";
         $i++;
     }
         $i++;
     }
-    print "   { 0, 0, 0, 0 THUNK_GENERATOR(0) }\n";
+    print "   { 0, 0, 0, 0, NoIntrinsic }\n";
     print "};\n\n";
     print "};\n\n";
-    print "#undef THUNK_GENERATOR\n";
-    print "extern JSC_CONST_HASHTABLE HashTable $name =\n";
+    print "extern const struct HashTable $name =\n";
     print "    \{ $compactSize, $compactHashSizeMask, $nameEntries, 0 \};\n";
     print "} // namespace\n";
 }
     print "    \{ $compactSize, $compactHashSizeMask, $nameEntries, 0 \};\n";
     print "} // namespace\n";
 }
index 64f60029d9b6d3a55e6f1047a9f1813520042731..49c28a324af5d8fa55d8e89d34595a9bd9350024 100644 (file)
@@ -33,9 +33,9 @@ namespace {
 
 using namespace JSC;
 
 
 using namespace JSC;
 
-class Recompiler {
+class Recompiler : public MarkedBlock::VoidFunctor {
 public:
 public:
-    Recompiler(Debugger*);
+    Recompiler(JSC::Debugger*);
     ~Recompiler();
     void operator()(JSCell*);
 
     ~Recompiler();
     void operator()(JSCell*);
 
@@ -43,12 +43,12 @@ private:
     typedef HashSet<FunctionExecutable*> FunctionExecutableSet;
     typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap;
     
     typedef HashSet<FunctionExecutable*> FunctionExecutableSet;
     typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap;
     
-    Debugger* m_debugger;
+    JSC::Debugger* m_debugger;
     FunctionExecutableSet m_functionExecutables;
     SourceProviderMap m_sourceProviders;
 };
 
     FunctionExecutableSet m_functionExecutables;
     SourceProviderMap m_sourceProviders;
 };
 
-inline Recompiler::Recompiler(Debugger* debugger)
+inline Recompiler::Recompiler(JSC::Debugger* debugger)
     : m_debugger(debugger)
 {
 }
     : m_debugger(debugger)
 {
 }
@@ -67,7 +67,7 @@ inline void Recompiler::operator()(JSCell* cell)
     if (!cell->inherits(&JSFunction::s_info))
         return;
 
     if (!cell->inherits(&JSFunction::s_info))
         return;
 
-    JSFunction* function = asFunction(cell);
+    JSFunction* function = jsCast<JSFunction*>(cell);
     if (function->executable()->isHostFunction())
         return;
 
     if (function->executable()->isHostFunction())
         return;
 
@@ -75,7 +75,7 @@ inline void Recompiler::operator()(JSCell* cell)
 
     // Check if the function is already in the set - if so,
     // we've already retranslated it, nothing to do here.
 
     // 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)
+    if (!m_functionExecutables.add(executable).isNewEntry)
         return;
 
     ExecState* exec = function->scope()->globalObject->JSGlobalObject::globalExec();
         return;
 
     ExecState* exec = function->scope()->globalObject->JSGlobalObject::globalExec();
@@ -118,7 +118,7 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
         return;
 
     Recompiler recompiler(this);
         return;
 
     Recompiler recompiler(this);
-    globalData->heap.forEach(recompiler);
+    globalData->heap.objectSpace().forEachCell(recompiler);
 }
 
 JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
 }
 
 JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
index ec5cf37374e09b490ff96c10ff5ed4bdcedced79..a237329187803eda957a37d3a0a907aff0b89232 100644 (file)
@@ -34,7 +34,7 @@ namespace JSC {
     class SourceProvider;
     class UString;
 
     class SourceProvider;
     class UString;
 
-    class Debugger {
+    class JS_EXPORT_PRIVATE Debugger {
     public:
         virtual ~Debugger();
 
     public:
         virtual ~Debugger();
 
@@ -58,7 +58,7 @@ namespace JSC {
     };
 
     // This function exists only for backwards compatibility with existing WebScriptDebugger clients.
     };
 
     // This function exists only for backwards compatibility with existing WebScriptDebugger clients.
-    JSValue evaluateInGlobalCallFrame(const UString&, JSValue& exception, JSGlobalObject*);
+    JS_EXPORT_PRIVATE JSValue evaluateInGlobalCallFrame(const UString&, JSValue& exception, JSGlobalObject*);
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index 8711b5ce93df9204118cd780c59219e1f1c5ce84..2a83f5138fe440e6af7fbc1f81cc072627b80a49 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-DebuggerActivation::DebuggerActivation(JSGlobalData& globalData, JSObject* activation)
-    : JSNonFinalObject(globalData, globalData.debuggerActivationStructure.get())
-{
-    ASSERT(activation);
-    ASSERT(activation->isActivationObject());
-    m_activation.set(globalData, this, static_cast<JSActivation*>(activation));
-}
-
-void DebuggerActivation::visitChildren(SlotVisitor& visitor)
-{
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
-    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
-    JSObject::visitChildren(visitor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(DebuggerActivation);
 
 
-    if (m_activation)
-        visitor.append(&m_activation);
-}
+const ClassInfo DebuggerActivation::s_info = { "DebuggerActivation", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(DebuggerActivation) };
 
 
-UString DebuggerActivation::className() const
+DebuggerActivation::DebuggerActivation(JSGlobalData& globalData)
+    : JSNonFinalObject(globalData, globalData.debuggerActivationStructure.get())
 {
 {
-    return m_activation->className();
 }
 
 }
 
-bool DebuggerActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+void DebuggerActivation::finishCreation(JSGlobalData& globalData, JSObject* activation)
 {
 {
-    return m_activation->getOwnPropertySlot(exec, propertyName, slot);
+    Base::finishCreation(globalData);
+    ASSERT(activation);
+    ASSERT(activation->isActivationObject());
+    m_activation.set(globalData, this, jsCast<JSActivation*>(activation));
 }
 
 }
 
-void DebuggerActivation::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void DebuggerActivation::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    m_activation->put(exec, propertyName, value, slot);
+    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    JSObject::visitChildren(thisObject, visitor);
+
+    if (thisObject->m_activation)
+        visitor.append(&thisObject->m_activation);
 }
 
 }
 
-void DebuggerActivation::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
+UString DebuggerActivation::className(const JSObject* object)
 {
 {
-    m_activation->putWithAttributes(exec, propertyName, value, attributes);
+    const DebuggerActivation* thisObject = jsCast<const DebuggerActivation*>(object);
+    return thisObject->m_activation->methodTable()->className(thisObject->m_activation.get());
 }
 
 }
 
-bool DebuggerActivation::deleteProperty(ExecState* exec, const Identifier& propertyName)
+bool DebuggerActivation::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
-    return m_activation->deleteProperty(exec, propertyName);
+    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(cell);
+    return thisObject->m_activation->methodTable()->getOwnPropertySlot(thisObject->m_activation.get(), exec, propertyName, slot);
 }
 
 }
 
-void DebuggerActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void DebuggerActivation::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
-    m_activation->getPropertyNames(exec, propertyNames, mode);
+    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(cell);
+    thisObject->m_activation->methodTable()->put(thisObject->m_activation.get(), exec, propertyName, value, slot);
 }
 
 }
 
-bool DebuggerActivation::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+void DebuggerActivation::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
 {
-    return m_activation->getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(object);
+    thisObject->m_activation->methodTable()->putDirectVirtual(thisObject->m_activation.get(), exec, propertyName, value, attributes);
 }
 
 }
 
-void DebuggerActivation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
+bool DebuggerActivation::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
 {
 {
-    m_activation->defineGetter(exec, propertyName, getterFunction, attributes);
+    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(cell);
+    return thisObject->m_activation->methodTable()->deleteProperty(thisObject->m_activation.get(), exec, propertyName);
 }
 
 }
 
-void DebuggerActivation::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
+void DebuggerActivation::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
-    m_activation->defineSetter(exec, propertyName, setterFunction, attributes);
+    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(object);
+    thisObject->m_activation->methodTable()->getPropertyNames(thisObject->m_activation.get(), exec, propertyNames, mode);
 }
 
 }
 
-JSValue DebuggerActivation::lookupGetter(ExecState* exec, const Identifier& propertyName)
+bool DebuggerActivation::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return m_activation->lookupGetter(exec, propertyName);
+    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(object);
+    return thisObject->m_activation->methodTable()->getOwnPropertyDescriptor(thisObject->m_activation.get(), exec, propertyName, descriptor);
 }
 
 }
 
-JSValue DebuggerActivation::lookupSetter(ExecState* exec, const Identifier& propertyName)
+bool DebuggerActivation::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
 {
 {
-    return m_activation->lookupSetter(exec, propertyName);
+    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(object);
+    return thisObject->m_activation->methodTable()->defineOwnProperty(thisObject->m_activation.get(), exec, propertyName, descriptor, shouldThrow);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 574986a0fd662f681f3a06eb4be20e7dc0aff3a9..6560c3d1110628caff03f96ed199ad606022d642 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class JSActivation;
-
     class DebuggerActivation : public JSNonFinalObject {
     public:
     class DebuggerActivation : public JSNonFinalObject {
     public:
-        DebuggerActivation(JSGlobalData&, JSObject*);
+        typedef JSNonFinalObject Base;
+
+        static DebuggerActivation* create(JSGlobalData& globalData, JSObject* object)
+        {
+            DebuggerActivation* activation = new (NotNull, allocateCell<DebuggerActivation>(globalData.heap)) DebuggerActivation(globalData);
+            activation->finishCreation(globalData, object);
+            return activation;
+        }
+
+        static void visitChildren(JSCell*, SlotVisitor&);
+        static UString className(const JSObject*);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
+        static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+        static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
+        static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
+        static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+        static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
 
 
-        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 void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
-        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
-        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
-        virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes);
-        virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes);
-        virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
-        virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
+        JS_EXPORTDATA static const ClassInfo s_info;
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) 
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); 
         }
 
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags;
 
         }
 
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags;
 
+        JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, JSObject* activation);
+
     private:
     private:
+        JS_EXPORT_PRIVATE DebuggerActivation(JSGlobalData&);
         WriteBarrier<JSActivation> m_activation;
     };
 
         WriteBarrier<JSActivation> m_activation;
     };
 
index 08fba4a6b4cb8a00991d55749907f5e2f8076155..a48e7d15612ccb7c29d0def9d03e67d0be831d74 100644 (file)
@@ -47,7 +47,7 @@ const UString* DebuggerCallFrame::functionName() const
     JSObject* function = m_callFrame->callee();
     if (!function || !function->inherits(&JSFunction::s_info))
         return 0;
     JSObject* function = m_callFrame->callee();
     if (!function || !function->inherits(&JSFunction::s_info))
         return 0;
-    return &asFunction(function)->name(m_callFrame);
+    return &jsCast<JSFunction*>(function)->name(m_callFrame);
 }
     
 UString DebuggerCallFrame::calculatedFunctionName() const
 }
     
 UString DebuggerCallFrame::calculatedFunctionName() const
@@ -56,10 +56,11 @@ UString DebuggerCallFrame::calculatedFunctionName() const
         return UString();
 
     JSObject* function = m_callFrame->callee();
         return UString();
 
     JSObject* function = m_callFrame->callee();
-    if (!function || !function->inherits(&JSFunction::s_info))
+
+    if (!function)
         return UString();
 
         return UString();
 
-    return asFunction(function)->calculatedDisplayName(m_callFrame);
+    return getCalculatedDisplayName(m_callFrame, function);
 }
 
 DebuggerCallFrame::Type DebuggerCallFrame::type() const
 }
 
 DebuggerCallFrame::Type DebuggerCallFrame::type() const
index f6b415cecbd09462d3cd3a49c992dcb766b7ab30..8605af54d3fa44f2c5be2229981282309560a57d 100644 (file)
@@ -50,11 +50,11 @@ namespace JSC {
 
         JSGlobalObject* dynamicGlobalObject() const { return m_callFrame->dynamicGlobalObject(); }
         ScopeChainNode* scopeChain() const { return m_callFrame->scopeChain(); }
 
         JSGlobalObject* dynamicGlobalObject() const { return m_callFrame->dynamicGlobalObject(); }
         ScopeChainNode* scopeChain() const { return m_callFrame->scopeChain(); }
-        const UString* functionName() const;
-        UString calculatedFunctionName() const;
-        Type type() const;
-        JSObject* thisObject() const;
-        JSValue evaluate(const UString&, JSValue& exception) const;
+        JS_EXPORT_PRIVATE const UString* functionName() const;
+        JS_EXPORT_PRIVATE UString calculatedFunctionName() const;
+        JS_EXPORT_PRIVATE Type type() const;
+        JS_EXPORT_PRIVATE JSObject* thisObject() const;
+        JS_EXPORT_PRIVATE JSValue evaluate(const UString&, JSValue& exception) const;
         JSValue exception() const { return m_exception; }
 
     private:
         JSValue exception() const { return m_exception; }
 
     private:
diff --git a/dfg/DFGAbstractState.cpp b/dfg/DFGAbstractState.cpp
new file mode 100644 (file)
index 0000000..6df40ca
--- /dev/null
@@ -0,0 +1,1219 @@
+/*
+ * 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 "DFGAbstractState.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeBlock.h"
+#include "DFGBasicBlock.h"
+
+namespace JSC { namespace DFG {
+
+#define CFA_PROFILING 0
+
+#if CFA_PROFILING
+#define PROFILE(flag) SamplingFlags::ScopedFlag scopedFlag(flag)
+#else
+#define PROFILE(flag) do { } while (false)
+#endif
+
+// Profiling flags
+#define FLAG_FOR_BLOCK_INITIALIZATION  17
+#define FLAG_FOR_BLOCK_END             18
+#define FLAG_FOR_EXECUTION             19
+#define FLAG_FOR_MERGE_TO_SUCCESSORS   20
+#define FLAG_FOR_STRUCTURE_CLOBBERING  21
+
+AbstractState::AbstractState(Graph& graph)
+    : m_codeBlock(graph.m_codeBlock)
+    , m_graph(graph)
+    , m_variables(m_codeBlock->numParameters(), graph.m_localVars)
+    , m_block(0)
+{
+    m_nodes.resize(graph.size());
+}
+
+AbstractState::~AbstractState() { }
+
+void AbstractState::beginBasicBlock(BasicBlock* basicBlock)
+{
+    PROFILE(FLAG_FOR_BLOCK_INITIALIZATION);
+    
+    ASSERT(!m_block);
+    
+    ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->valuesAtHead.numberOfLocals());
+    ASSERT(basicBlock->variablesAtTail.numberOfLocals() == basicBlock->valuesAtTail.numberOfLocals());
+    ASSERT(basicBlock->variablesAtHead.numberOfLocals() == basicBlock->variablesAtTail.numberOfLocals());
+    
+    for (size_t i = 0; i < basicBlock->size(); i++)
+        m_nodes[basicBlock->at(i)].clear();
+
+    m_variables = basicBlock->valuesAtHead;
+    m_haveStructures = false;
+    for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) {
+        if (m_variables.argument(i).m_structure.isNeitherClearNorTop()) {
+            m_haveStructures = true;
+            break;
+        }
+    }
+    for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) {
+        if (m_variables.local(i).m_structure.isNeitherClearNorTop()) {
+            m_haveStructures = true;
+            break;
+        }
+    }
+    
+    basicBlock->cfaShouldRevisit = false;
+    basicBlock->cfaHasVisited = true;
+    m_block = basicBlock;
+    m_isValid = true;
+}
+
+void AbstractState::initialize(Graph& graph)
+{
+    PROFILE(FLAG_FOR_BLOCK_INITIALIZATION);
+    BasicBlock* root = graph.m_blocks[0].get();
+    root->cfaShouldRevisit = true;
+    for (size_t i = 0; i < root->valuesAtHead.numberOfArguments(); ++i) {
+        Node& node = graph[root->variablesAtHead.argument(i)];
+        ASSERT(node.op() == SetArgument);
+        if (!node.shouldGenerate()) {
+            // The argument is dead. We don't do any checks for such arguments, and so
+            // for the purpose of the analysis, they contain no value.
+            root->valuesAtHead.argument(i).clear();
+            continue;
+        }
+        
+        if (graph.argumentIsCaptured(i)) {
+            root->valuesAtHead.argument(i).makeTop();
+            continue;
+        }
+        
+        PredictedType prediction = node.variableAccessData()->prediction();
+        if (isInt32Prediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictInt32);
+        else if (isArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictArray);
+        else if (isBooleanPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictBoolean);
+        else if (isInt8ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictInt8Array);
+        else if (isInt16ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictInt16Array);
+        else if (isInt32ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictInt32Array);
+        else if (isUint8ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictUint8Array);
+        else if (isUint8ClampedArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictUint8ClampedArray);
+        else if (isUint16ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictUint16Array);
+        else if (isUint32ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictUint32Array);
+        else if (isFloat32ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictFloat32Array);
+        else if (isFloat64ArrayPrediction(prediction))
+            root->valuesAtHead.argument(i).set(PredictFloat64Array);
+        else
+            root->valuesAtHead.argument(i).makeTop();
+    }
+    for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) {
+        if (!graph.localIsCaptured(i))
+            continue;
+        root->valuesAtHead.local(i).makeTop();
+    }
+}
+
+bool AbstractState::endBasicBlock(MergeMode mergeMode)
+{
+    PROFILE(FLAG_FOR_BLOCK_END);
+    ASSERT(m_block);
+    
+    BasicBlock* block = m_block; // Save the block for successor merging.
+    
+    if (!m_isValid) {
+        reset();
+        return false;
+    }
+    
+    bool changed = false;
+    
+    if (mergeMode != DontMerge || !ASSERT_DISABLED) {
+        for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+            dataLog("        Merging state for argument %zu.\n", argument);
+#endif
+            AbstractValue& destination = block->valuesAtTail.argument(argument);
+            if (m_graph.argumentIsCaptured(argument)) {
+                if (!destination.isTop()) {
+                    destination.makeTop();
+                    changed = true;
+                }
+            } else
+                changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument));
+        }
+        
+        for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+            dataLog("        Merging state for local %zu.\n", local);
+#endif
+            AbstractValue& destination = block->valuesAtTail.local(local);
+            if (m_graph.localIsCaptured(local)) {
+                if (!destination.isTop()) {
+                    destination.makeTop();
+                    changed = true;
+                }
+            } else
+                changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local));
+        }
+    }
+    
+    ASSERT(mergeMode != DontMerge || !changed);
+    
+    reset();
+    
+    if (mergeMode != MergeToSuccessors)
+        return changed;
+    
+    return mergeToSuccessors(m_graph, block);
+}
+
+void AbstractState::reset()
+{
+    m_block = 0;
+    m_isValid = false;
+}
+
+bool AbstractState::execute(unsigned indexInBlock)
+{
+    PROFILE(FLAG_FOR_EXECUTION);
+    ASSERT(m_block);
+    ASSERT(m_isValid);
+        
+    NodeIndex nodeIndex = m_block->at(indexInBlock);
+    Node& node = m_graph[nodeIndex];
+        
+    if (!node.shouldGenerate())
+        return true;
+        
+    switch (node.op()) {
+    case JSConstant:
+    case WeakJSConstant: {
+        JSValue value = m_graph.valueOfJSConstant(nodeIndex);
+        // Have to be careful here! It's tempting to call set(value), but
+        // that would be wrong, since that would constitute a proof that this
+        // value will always have the same structure. The whole point of a value
+        // having a structure is that it may change in the future - for example
+        // between when we compile the code and when we run it.
+        forNode(nodeIndex).set(predictionFromValue(value));
+        break;
+    }
+            
+    case GetLocal: {
+        if (m_graph.isCaptured(node.local()))
+            forNode(nodeIndex).makeTop();
+        else
+            forNode(nodeIndex) = m_variables.operand(node.local());
+        break;
+    }
+        
+    case SetLocal: {
+        if (m_graph.isCaptured(node.local()))
+            break;
+        
+        if (node.variableAccessData()->shouldUseDoubleFormat()) {
+            forNode(node.child1()).filter(PredictNumber);
+            m_variables.operand(node.local()).set(PredictDouble);
+            break;
+        }
+        
+        PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction();
+        if (isInt32Prediction(predictedType))
+            forNode(node.child1()).filter(PredictInt32);
+        else if (isArrayPrediction(predictedType))
+            forNode(node.child1()).filter(PredictArray);
+        else if (isBooleanPrediction(predictedType))
+            forNode(node.child1()).filter(PredictBoolean);
+        
+        m_variables.operand(node.local()) = forNode(node.child1());
+        break;
+    }
+            
+    case SetArgument:
+        // Assert that the state of arguments has been set.
+        ASSERT(!m_block->valuesAtHead.operand(node.local()).isClear());
+        break;
+            
+    case BitAnd:
+    case BitOr:
+    case BitXor:
+    case BitRShift:
+    case BitLShift:
+    case BitURShift:
+        forNode(node.child1()).filter(PredictInt32);
+        forNode(node.child2()).filter(PredictInt32);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+        
+    case UInt32ToNumber:
+        if (!node.canSpeculateInteger())
+            forNode(nodeIndex).set(PredictDouble);
+        else
+            forNode(nodeIndex).set(PredictInt32);
+        break;
+            
+    case DoubleAsInt32:
+        forNode(node.child1()).filter(PredictNumber);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+            
+    case ValueToInt32:
+        if (m_graph[node.child1()].shouldSpeculateInteger())
+            forNode(node.child1()).filter(PredictInt32);
+        else if (m_graph[node.child1()].shouldSpeculateNumber())
+            forNode(node.child1()).filter(PredictNumber);
+        else if (m_graph[node.child1()].shouldSpeculateBoolean())
+            forNode(node.child1()).filter(PredictBoolean);
+        
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+        
+    case Int32ToDouble:
+        forNode(node.child1()).filter(PredictNumber);
+        forNode(nodeIndex).set(PredictDouble);
+        break;
+        
+    case CheckNumber:
+        forNode(node.child1()).filter(PredictNumber);
+        break;
+            
+    case ValueAdd:
+    case ArithAdd: {
+        if (m_graph.addShouldSpeculateInteger(node)) {
+            forNode(node.child1()).filter(PredictInt32);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) {
+            forNode(node.child1()).filter(PredictNumber);
+            forNode(node.child2()).filter(PredictNumber);
+            forNode(nodeIndex).set(PredictDouble);
+            break;
+        }
+        if (node.op() == ValueAdd) {
+            clobberStructures(indexInBlock);
+            forNode(nodeIndex).set(PredictString | PredictInt32 | PredictNumber);
+            break;
+        }
+        // We don't handle this yet. :-(
+        m_isValid = false;
+        break;
+    }
+            
+    case ArithSub: {
+        if (m_graph.addShouldSpeculateInteger(node)) {
+            forNode(node.child1()).filter(PredictInt32);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        forNode(node.child1()).filter(PredictNumber);
+        forNode(node.child2()).filter(PredictNumber);
+        forNode(nodeIndex).set(PredictDouble);
+        break;
+    }
+        
+    case ArithNegate: {
+        if (m_graph.negateShouldSpeculateInteger(node)) {
+            forNode(node.child1()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        forNode(node.child1()).filter(PredictNumber);
+        forNode(nodeIndex).set(PredictDouble);
+        break;
+    }
+        
+    case ArithMul:
+    case ArithDiv:
+    case ArithMin:
+    case ArithMax:
+    case ArithMod: {
+        if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]) && node.canSpeculateInteger()) {
+            forNode(node.child1()).filter(PredictInt32);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        forNode(node.child1()).filter(PredictNumber);
+        forNode(node.child2()).filter(PredictNumber);
+        forNode(nodeIndex).set(PredictDouble);
+        break;
+    }
+            
+    case ArithAbs:
+        if (m_graph[node.child1()].shouldSpeculateInteger() && node.canSpeculateInteger()) {
+            forNode(node.child1()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        forNode(node.child1()).filter(PredictNumber);
+        forNode(nodeIndex).set(PredictDouble);
+        break;
+            
+    case ArithSqrt:
+        forNode(node.child1()).filter(PredictNumber);
+        forNode(nodeIndex).set(PredictDouble);
+        break;
+            
+    case LogicalNot: {
+        Node& child = m_graph[node.child1()];
+        if (isBooleanPrediction(child.prediction()))
+            forNode(node.child1()).filter(PredictBoolean);
+        else if (child.shouldSpeculateFinalObjectOrOther())
+            forNode(node.child1()).filter(PredictFinalObject | PredictOther);
+        else if (child.shouldSpeculateArrayOrOther())
+            forNode(node.child1()).filter(PredictArray | PredictOther);
+        else if (child.shouldSpeculateInteger())
+            forNode(node.child1()).filter(PredictInt32);
+        else if (child.shouldSpeculateNumber())
+            forNode(node.child1()).filter(PredictNumber);
+        else
+            clobberStructures(indexInBlock);
+        forNode(nodeIndex).set(PredictBoolean);
+        break;
+    }
+        
+    case IsUndefined:
+    case IsBoolean:
+    case IsNumber:
+    case IsString:
+    case IsObject:
+    case IsFunction: {
+        forNode(nodeIndex).set(PredictBoolean);
+        break;
+    }
+            
+    case CompareLess:
+    case CompareLessEq:
+    case CompareGreater:
+    case CompareGreaterEq:
+    case CompareEq: {
+        forNode(nodeIndex).set(PredictBoolean);
+        
+        Node& left = m_graph[node.child1()];
+        Node& right = m_graph[node.child2()];
+        PredictedType filter;
+        if (Node::shouldSpeculateInteger(left, right))
+            filter = PredictInt32;
+        else if (Node::shouldSpeculateNumber(left, right))
+            filter = PredictNumber;
+        else if (node.op() == CompareEq) {
+            if ((m_graph.isConstant(node.child1().index())
+                 && m_graph.valueOfJSConstant(node.child1().index()).isNull())
+                || (m_graph.isConstant(node.child2().index())
+                    && m_graph.valueOfJSConstant(node.child2().index()).isNull())) {
+                // We know that this won't clobber the world. But that's all we know.
+                break;
+            }
+            
+            if (Node::shouldSpeculateFinalObject(left, right))
+                filter = PredictFinalObject;
+            else if (Node::shouldSpeculateArray(left, right))
+                filter = PredictArray;
+            else if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther()) {
+                forNode(node.child1()).filter(PredictFinalObject);
+                forNode(node.child2()).filter(PredictFinalObject | PredictOther);
+                break;
+            } else if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther()) {
+                forNode(node.child1()).filter(PredictFinalObject | PredictOther);
+                forNode(node.child2()).filter(PredictFinalObject);
+                break;
+            } else if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther()) {
+                forNode(node.child1()).filter(PredictFinalObject);
+                forNode(node.child2()).filter(PredictFinalObject | PredictOther);
+                break;
+            } else if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther()) {
+                forNode(node.child1()).filter(PredictFinalObject | PredictOther);
+                forNode(node.child2()).filter(PredictFinalObject);
+                break;
+            } else {
+                filter = PredictTop;
+                clobberStructures(indexInBlock);
+            }
+        } else {
+            filter = PredictTop;
+            clobberStructures(indexInBlock);
+        }
+        forNode(node.child1()).filter(filter);
+        forNode(node.child2()).filter(filter);
+        break;
+    }
+            
+    case CompareStrictEq:
+        forNode(nodeIndex).set(PredictBoolean);
+        break;
+        
+    case StringCharCodeAt:
+        forNode(node.child1()).filter(PredictString);
+        forNode(node.child2()).filter(PredictInt32);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+        
+    case StringCharAt:
+        forNode(node.child1()).filter(PredictString);
+        forNode(node.child2()).filter(PredictInt32);
+        forNode(nodeIndex).set(PredictString);
+        break;
+            
+    case GetByVal: {
+        if (!node.prediction() || !m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction()) {
+            m_isValid = false;
+            break;
+        }
+        if (!isActionableArrayPrediction(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {
+            clobberStructures(indexInBlock);
+            forNode(nodeIndex).makeTop();
+            break;
+        }
+        if (m_graph[node.child1()].prediction() == PredictString) {
+            forNode(node.child1()).filter(PredictString);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictString);
+            break;
+        }
+        
+        if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
+            forNode(node.child1()).filter(PredictInt8Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
+            forNode(node.child1()).filter(PredictInt16Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
+            forNode(node.child1()).filter(PredictInt32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
+            forNode(node.child1()).filter(PredictUint8Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
+            forNode(node.child1()).filter(PredictUint8ClampedArray);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
+            forNode(node.child1()).filter(PredictUint16Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
+            forNode(node.child1()).filter(PredictUint32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            if (node.shouldSpeculateInteger())
+                forNode(nodeIndex).set(PredictInt32);
+            else
+                forNode(nodeIndex).set(PredictDouble);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
+            forNode(node.child1()).filter(PredictFloat32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictDouble);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
+            forNode(node.child1()).filter(PredictFloat64Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictDouble);
+            break;
+        }
+        ASSERT(m_graph[node.child1()].shouldSpeculateArray());
+        forNode(node.child1()).filter(PredictArray);
+        forNode(node.child2()).filter(PredictInt32);
+        forNode(nodeIndex).makeTop();
+        break;
+    }
+            
+    case PutByVal:
+    case PutByValAlias: {
+        if (!m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction()) {
+            m_isValid = false;
+            break;
+        }
+        if (!m_graph[node.child2()].shouldSpeculateInteger() || !isActionableMutableArrayPrediction(m_graph[node.child1()].prediction())) {
+            ASSERT(node.op() == PutByVal);
+            clobberStructures(indexInBlock);
+            forNode(nodeIndex).makeTop();
+            break;
+        }
+        
+        if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
+            forNode(node.child1()).filter(PredictInt8Array);
+            forNode(node.child2()).filter(PredictInt32);
+            if (m_graph[node.child3()].shouldSpeculateInteger())
+                forNode(node.child3()).filter(PredictInt32);
+            else
+                forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
+            forNode(node.child1()).filter(PredictInt16Array);
+            forNode(node.child2()).filter(PredictInt32);
+            if (m_graph[node.child3()].shouldSpeculateInteger())
+                forNode(node.child3()).filter(PredictInt32);
+            else
+                forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
+            forNode(node.child1()).filter(PredictInt32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            if (m_graph[node.child3()].shouldSpeculateInteger())
+                forNode(node.child3()).filter(PredictInt32);
+            else
+                forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
+            forNode(node.child1()).filter(PredictUint8Array);
+            forNode(node.child2()).filter(PredictInt32);
+            if (m_graph[node.child3()].shouldSpeculateInteger())
+                forNode(node.child3()).filter(PredictInt32);
+            else
+                forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
+            forNode(node.child1()).filter(PredictUint8ClampedArray);
+            forNode(node.child2()).filter(PredictInt32);
+            if (m_graph[node.child3()].shouldSpeculateInteger())
+                forNode(node.child3()).filter(PredictInt32);
+            else
+                forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
+            forNode(node.child1()).filter(PredictUint16Array);
+            forNode(node.child2()).filter(PredictInt32);
+            if (m_graph[node.child3()].shouldSpeculateInteger())
+                forNode(node.child3()).filter(PredictInt32);
+            else
+                forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
+            forNode(node.child1()).filter(PredictUint32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            if (m_graph[node.child3()].shouldSpeculateInteger())
+                forNode(node.child3()).filter(PredictInt32);
+            else
+                forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
+            forNode(node.child1()).filter(PredictFloat32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
+            forNode(node.child1()).filter(PredictFloat64Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        ASSERT(m_graph[node.child1()].shouldSpeculateArray());
+        forNode(node.child1()).filter(PredictArray);
+        forNode(node.child2()).filter(PredictInt32);
+        break;
+    }
+            
+    case ArrayPush:
+        forNode(node.child1()).filter(PredictArray);
+        forNode(nodeIndex).set(PredictNumber);
+        break;
+            
+    case ArrayPop:
+        forNode(node.child1()).filter(PredictArray);
+        forNode(nodeIndex).makeTop();
+        break;
+            
+    case RegExpExec:
+    case RegExpTest:
+        forNode(node.child1()).filter(PredictCell);
+        forNode(node.child2()).filter(PredictCell);
+        forNode(nodeIndex).makeTop();
+        break;
+            
+    case Jump:
+        break;
+            
+    case Branch: {
+        // There is probably profit to be found in doing sparse conditional constant
+        // propagation, and to take it one step further, where a variable's value
+        // is specialized on each direction of a branch. For now, we don't do this.
+        Node& child = m_graph[node.child1()];
+        if (child.shouldSpeculateBoolean())
+            forNode(node.child1()).filter(PredictBoolean);
+        else if (child.shouldSpeculateFinalObjectOrOther())
+            forNode(node.child1()).filter(PredictFinalObject | PredictOther);
+        else if (child.shouldSpeculateArrayOrOther())
+            forNode(node.child1()).filter(PredictArray | PredictOther);
+        else if (child.shouldSpeculateInteger())
+            forNode(node.child1()).filter(PredictInt32);
+        else if (child.shouldSpeculateNumber())
+            forNode(node.child1()).filter(PredictNumber);
+        break;
+    }
+            
+    case Return:
+    case Throw:
+    case ThrowReferenceError:
+        m_isValid = false;
+        break;
+            
+    case ToPrimitive: {
+        Node& child = m_graph[node.child1()];
+        if (child.shouldSpeculateInteger()) {
+            forNode(node.child1()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictInt32);
+            break;
+        }
+
+        AbstractValue& source = forNode(node.child1());
+        AbstractValue& destination = forNode(nodeIndex);
+            
+        PredictedType type = source.m_type;
+        if (type & ~(PredictNumber | PredictString | PredictBoolean)) {
+            type &= (PredictNumber | PredictString | PredictBoolean);
+            type |= PredictString;
+        }
+        destination.set(type);
+        break;
+    }
+            
+    case StrCat:
+        forNode(nodeIndex).set(PredictString);
+        break;
+            
+    case NewArray:
+    case NewArrayBuffer:
+        forNode(nodeIndex).set(m_codeBlock->globalObject()->arrayStructure());
+        m_haveStructures = true;
+        break;
+            
+    case NewRegexp:
+        forNode(nodeIndex).set(m_codeBlock->globalObject()->regExpStructure());
+        m_haveStructures = true;
+        break;
+            
+    case ConvertThis: {
+        Node& child = m_graph[node.child1()];
+        AbstractValue& source = forNode(node.child1());
+        AbstractValue& destination = forNode(nodeIndex);
+            
+        if (isObjectPrediction(source.m_type)) {
+            // This is the simple case. We already know that the source is an
+            // object, so there's nothing to do. I don't think this case will
+            // be hit, but then again, you never know.
+            destination = source;
+            break;
+        }
+        
+        if (isOtherPrediction(child.prediction())) {
+            source.filter(PredictOther);
+            destination.set(PredictObjectOther);
+            break;
+        }
+        
+        if (isObjectPrediction(child.prediction())) {
+            source.filter(PredictObjectMask);
+            destination = source;
+            break;
+        }
+            
+        destination = source;
+        destination.merge(PredictObjectOther);
+        break;
+    }
+            
+    case CreateThis: {
+        Node& child = m_graph[node.child1()];
+        AbstractValue& source = forNode(node.child1());
+        AbstractValue& destination = forNode(nodeIndex);
+            
+        if (child.shouldSpeculateFinalObject())
+            source.filter(PredictFinalObject);
+            
+        destination.set(PredictFinalObject);
+        break;
+    }
+            
+    case NewObject:
+        forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->emptyObjectStructure());
+        m_haveStructures = true;
+        break;
+        
+    case CreateActivation:
+        forNode(nodeIndex).set(m_graph.m_globalData.activationStructure.get());
+        m_haveStructures = true;
+        break;
+        
+    case TearOffActivation:
+        // Does nothing that is user-visible.
+        break;
+        
+    case NewFunction:
+    case NewFunctionExpression:
+    case NewFunctionNoCheck:
+        forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->functionStructure());
+        break;
+        
+    case GetCallee:
+        forNode(nodeIndex).set(PredictFunction);
+        break;
+            
+    case GetScopeChain:
+        forNode(nodeIndex).set(PredictCellOther);
+        break;
+            
+    case GetScopedVar:
+        forNode(nodeIndex).makeTop();
+        break;
+            
+    case PutScopedVar:
+        clobberStructures(indexInBlock);
+        break;
+            
+    case GetById:
+    case GetByIdFlush:
+        if (!node.prediction()) {
+            m_isValid = false;
+            break;
+        }
+        if (isCellPrediction(m_graph[node.child1()].prediction()))
+            forNode(node.child1()).filter(PredictCell);
+        clobberStructures(indexInBlock);
+        forNode(nodeIndex).makeTop();
+        break;
+            
+    case GetArrayLength:
+        forNode(node.child1()).filter(PredictArray);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+
+    case GetStringLength:
+        forNode(node.child1()).filter(PredictString);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+        
+    case GetInt8ArrayLength:
+        forNode(node.child1()).filter(PredictInt8Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetInt16ArrayLength:
+        forNode(node.child1()).filter(PredictInt16Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetInt32ArrayLength:
+        forNode(node.child1()).filter(PredictInt32Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetUint8ArrayLength:
+        forNode(node.child1()).filter(PredictUint8Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetUint8ClampedArrayLength:
+        forNode(node.child1()).filter(PredictUint8ClampedArray);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetUint16ArrayLength:
+        forNode(node.child1()).filter(PredictUint16Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetUint32ArrayLength:
+        forNode(node.child1()).filter(PredictUint32Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetFloat32ArrayLength:
+        forNode(node.child1()).filter(PredictFloat32Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+    case GetFloat64ArrayLength:
+        forNode(node.child1()).filter(PredictFloat64Array);
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+            
+    case CheckStructure:
+        // FIXME: We should be able to propagate the structure sets of constants (i.e. prototypes).
+        forNode(node.child1()).filter(node.structureSet());
+        m_haveStructures = true;
+        break;
+            
+    case PutStructure:
+        clobberStructures(indexInBlock);
+        forNode(node.child1()).set(node.structureTransitionData().newStructure);
+        m_haveStructures = true;
+        break;
+    case GetPropertyStorage:
+        forNode(node.child1()).filter(PredictCell);
+        forNode(nodeIndex).clear(); // The result is not a JS value.
+        break;
+    case GetIndexedPropertyStorage: {
+        PredictedType basePrediction = m_graph[node.child2()].prediction();
+        if (!(basePrediction & PredictInt32) && basePrediction) {
+            forNode(nodeIndex).clear();
+            break;
+        }
+        if (m_graph[node.child1()].prediction() == PredictString) {
+            forNode(node.child1()).filter(PredictString);
+            forNode(nodeIndex).clear();
+            break;
+        }
+        
+        if (m_graph[node.child1()].shouldSpeculateInt8Array()) {
+            forNode(node.child1()).filter(PredictInt8Array);
+            forNode(nodeIndex).clear();
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateInt16Array()) {
+            forNode(node.child1()).filter(PredictInt16Array);
+            forNode(nodeIndex).clear();
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateInt32Array()) {
+            forNode(node.child1()).filter(PredictInt32Array);
+            forNode(nodeIndex).clear();
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint8Array()) {
+            forNode(node.child1()).filter(PredictUint8Array);
+            forNode(nodeIndex).clear();
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) {
+            forNode(node.child1()).filter(PredictUint8ClampedArray);
+            forNode(nodeIndex).clear();
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint16Array()) {
+            forNode(node.child1()).filter(PredictUint16Array);
+            forNode(nodeIndex).set(PredictOther);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateUint32Array()) {
+            forNode(node.child1()).filter(PredictUint32Array);
+            forNode(nodeIndex).clear();
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
+            forNode(node.child1()).filter(PredictFloat32Array);
+            forNode(nodeIndex).clear();
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
+            forNode(node.child1()).filter(PredictFloat64Array);
+            forNode(nodeIndex).clear();
+            break;
+        }
+        forNode(node.child1()).filter(PredictArray);
+        forNode(nodeIndex).clear();
+        break; 
+    }
+    case GetByOffset:
+        forNode(node.child1()).filter(PredictCell);
+        forNode(nodeIndex).makeTop();
+        break;
+            
+    case PutByOffset:
+        forNode(node.child1()).filter(PredictCell);
+        break;
+            
+    case CheckFunction:
+        forNode(node.child1()).filter(PredictFunction);
+        // FIXME: Should be able to propagate the fact that we know what the function is.
+        break;
+            
+    case PutById:
+    case PutByIdDirect:
+        forNode(node.child1()).filter(PredictCell);
+        clobberStructures(indexInBlock);
+        break;
+            
+    case GetGlobalVar:
+        forNode(nodeIndex).makeTop();
+        break;
+            
+    case PutGlobalVar:
+        break;
+            
+    case CheckHasInstance:
+        forNode(node.child1()).filter(PredictCell);
+        // Sadly, we don't propagate the fact that we've done CheckHasInstance
+        break;
+            
+    case InstanceOf:
+        // Again, sadly, we don't propagate the fact that we've done InstanceOf
+        if (!(m_graph[node.child1()].prediction() & ~PredictCell) && !(forNode(node.child1()).m_type & ~PredictCell))
+            forNode(node.child1()).filter(PredictCell);
+        forNode(node.child3()).filter(PredictCell);
+        forNode(nodeIndex).set(PredictBoolean);
+        break;
+            
+    case Phi:
+    case Flush:
+        break;
+            
+    case Breakpoint:
+        break;
+            
+    case Call:
+    case Construct:
+    case Resolve:
+    case ResolveBase:
+    case ResolveBaseStrictPut:
+    case ResolveGlobal:
+        clobberStructures(indexInBlock);
+        forNode(nodeIndex).makeTop();
+        break;
+            
+    case ForceOSRExit:
+        m_isValid = false;
+        break;
+            
+    case Phantom:
+    case InlineStart:
+    case Nop:
+        break;
+        
+    case LastNodeType:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+    
+    return m_isValid;
+}
+
+inline void AbstractState::clobberStructures(unsigned indexInBlock)
+{
+    PROFILE(FLAG_FOR_STRUCTURE_CLOBBERING);
+    if (!m_haveStructures)
+        return;
+    for (size_t i = indexInBlock + 1; i--;)
+        forNode(m_block->at(i)).clobberStructures();
+    for (size_t i = 0; i < m_variables.numberOfArguments(); ++i)
+        m_variables.argument(i).clobberStructures();
+    for (size_t i = 0; i < m_variables.numberOfLocals(); ++i)
+        m_variables.local(i).clobberStructures();
+    m_haveStructures = false;
+}
+
+inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex nodeIndex)
+{
+    if (nodeIndex == NoNode)
+        return false;
+        
+    AbstractValue source;
+        
+    Node& node = m_graph[nodeIndex];
+    if (!node.refCount())
+        return false;
+    
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+    dataLog("          It's live, node @%u.\n", nodeIndex);
+#endif
+    
+    switch (node.op()) {
+    case Phi:
+    case SetArgument:
+    case Flush:
+        // The block transfers the value from head to tail.
+        source = inVariable;
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("          Transfering from head to tail.\n");
+#endif
+        break;
+            
+    case GetLocal:
+        // The block refines the value with additional speculations.
+        source = forNode(nodeIndex);
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("          Refining.\n");
+#endif
+        break;
+            
+    case SetLocal:
+        // The block sets the variable, and potentially refines it, both
+        // before and after setting it.
+        if (node.variableAccessData()->shouldUseDoubleFormat())
+            source.set(PredictDouble);
+        else
+            source = forNode(node.child1());
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("          Setting.\n");
+#endif
+        break;
+        
+    default:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+    
+    if (destination == source) {
+        // Abstract execution did not change the output value of the variable, for this
+        // basic block, on this iteration.
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("          Not changed!\n");
+#endif
+        return false;
+    }
+    
+    // Abstract execution reached a new conclusion about the speculations reached about
+    // this variable after execution of this basic block. Update the state, and return
+    // true to indicate that the fixpoint must go on!
+    destination = source;
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+    dataLog("          Changed!\n");
+#endif
+    return true;
+}
+
+inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to)
+{
+    ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments());
+    ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals());
+    
+    bool changed = false;
+    
+    for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) {
+        AbstractValue& destination = to->valuesAtHead.argument(argument);
+        if (m_graph.argumentIsCaptured(argument)) {
+            if (destination.isTop())
+                continue;
+            destination.makeTop();
+            changed = true;
+            continue;
+        }
+        changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.argument(argument), to->variablesAtHead.argument(argument), from->variablesAtTail.argument(argument));
+    }
+    
+    for (size_t local = 0; local < from->variablesAtTail.numberOfLocals(); ++local) {
+        AbstractValue& destination = to->valuesAtHead.local(local);
+        if (m_graph.localIsCaptured(local)) {
+            if (destination.isTop())
+                continue;
+            destination.makeTop();
+            changed = true;
+            continue;
+        }
+        changed |= mergeVariableBetweenBlocks(destination, from->valuesAtTail.local(local), to->variablesAtHead.local(local), from->variablesAtTail.local(local));
+    }
+
+    if (!to->cfaHasVisited)
+        changed = true;
+    
+    to->cfaShouldRevisit |= changed;
+    
+    return changed;
+}
+
+inline bool AbstractState::mergeToSuccessors(Graph& graph, BasicBlock* basicBlock)
+{
+    PROFILE(FLAG_FOR_MERGE_TO_SUCCESSORS);
+
+    Node& terminal = graph[basicBlock->last()];
+    
+    ASSERT(terminal.isTerminal());
+    
+    switch (terminal.op()) {
+    case Jump:
+        return merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get());
+        
+    case Branch:
+        return merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get())
+            | merge(basicBlock, graph.m_blocks[terminal.notTakenBlockIndex()].get());
+        
+    case Return:
+    case Throw:
+    case ThrowReferenceError:
+        return false;
+        
+    default:
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+}
+
+inline bool AbstractState::mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, NodeIndex destinationNodeIndex, NodeIndex sourceNodeIndex)
+{
+    if (destinationNodeIndex == NoNode)
+        return false;
+    
+    ASSERT_UNUSED(sourceNodeIndex, sourceNodeIndex != NoNode);
+    
+    // FIXME: We could do some sparse conditional propagation here!
+    
+    return destination.merge(source);
+}
+
+#ifndef NDEBUG
+void AbstractState::dump(FILE* out)
+{
+    bool first = true;
+    for (size_t i = 0; i < m_block->size(); ++i) {
+        NodeIndex index = m_block->at(i);
+        AbstractValue& value = m_nodes[index];
+        if (value.isClear())
+            continue;
+        if (first)
+            first = false;
+        else
+            fprintf(out, " ");
+        fprintf(out, "@%lu:", static_cast<unsigned long>(index));
+        value.dump(out);
+    }
+}
+#endif
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/dfg/DFGAbstractState.h b/dfg/DFGAbstractState.h
new file mode 100644 (file)
index 0000000..3325e07
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * 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 DFGAbstractState_h
+#define DFGAbstractState_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAbstractValue.h"
+#include "DFGGraph.h"
+#include "DFGNode.h"
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class CodeBlock;
+
+namespace DFG {
+
+struct BasicBlock;
+
+// This implements the notion of an abstract state for flow-sensitive intraprocedural
+// control flow analysis (CFA), with a focus on the elimination of redundant type checks.
+// It also implements most of the mechanisms of abstract interpretation that such an
+// analysis would use. This class should be used in two idioms:
+//
+// 1) Performing the CFA. In this case, AbstractState should be run over all basic
+//    blocks repeatedly until convergence is reached. Convergence is defined by
+//    endBasicBlock(AbstractState::MergeToSuccessors) returning false for all blocks.
+//
+// 2) Rematerializing the results of a previously executed CFA. In this case,
+//    AbstractState should be run over whatever basic block you're interested in up
+//    to the point of the node at which you'd like to interrogate the known type
+//    of all other nodes. At this point it's safe to discard the AbstractState entirely,
+//    call reset(), or to run it to the end of the basic block and call
+//    endBasicBlock(AbstractState::DontMerge). The latter option is safest because
+//    it performs some useful integrity checks.
+//
+// After the CFA is run, the inter-block state is saved at the heads and tails of all
+// basic blocks. This allows the intra-block state to be rematerialized by just
+// executing the CFA for that block. If you need to know inter-block state only, then
+// you only need to examine the BasicBlock::m_valuesAtHead or m_valuesAtTail fields.
+//
+// Running this analysis involves the following, modulo the inter-block state
+// merging and convergence fixpoint:
+//
+// AbstractState state(codeBlock, graph);
+// state.beginBasicBlock(basicBlock);
+// bool endReached = true;
+// for (NodeIndex idx = basicBlock.begin; idx < basicBlock.end; ++idx) {
+//     if (!state.execute(idx))
+//         break;
+// }
+// bool result = state.endBasicBlock(<either Merge or DontMerge>);
+
+class AbstractState {
+public:
+    enum MergeMode {
+        // Don't merge the state in AbstractState with basic blocks.
+        DontMerge,
+        
+        // Merge the state in AbstractState with the tail of the basic
+        // block being analyzed.
+        MergeToTail,
+        
+        // Merge the state in AbstractState with the tail of the basic
+        // block, and with the heads of successor blocks.
+        MergeToSuccessors
+    };
+    
+    AbstractState(Graph&);
+    
+    ~AbstractState();
+    
+    AbstractValue& forNode(NodeIndex nodeIndex)
+    {
+        return m_nodes[nodeIndex];
+    }
+    
+    AbstractValue& forNode(Edge nodeUse)
+    {
+        return forNode(nodeUse.index());
+    }
+    
+    // Call this before beginning CFA to initialize the abstract values of
+    // arguments, and to indicate which blocks should be listed for CFA
+    // execution.
+    static void initialize(Graph&);
+
+    // Start abstractly executing the given basic block. Initializes the
+    // notion of abstract state to what we believe it to be at the head
+    // of the basic block, according to the basic block's data structures.
+    // This method also sets cfaShouldRevisit to false.
+    void beginBasicBlock(BasicBlock*);
+    
+    // Finish abstractly executing a basic block. If MergeToTail or
+    // MergeToSuccessors is passed, then this merges everything we have
+    // learned about how the state changes during this block's execution into
+    // the block's data structures. There are three return modes, depending
+    // on the value of mergeMode:
+    //
+    // DontMerge:
+    //    Always returns false.
+    //
+    // MergeToTail:
+    //    Returns true if the state of the block at the tail was changed.
+    //    This means that you must call mergeToSuccessors(), and if that
+    //    returns true, then you must revisit (at least) the successor
+    //    blocks. False will always be returned if the block is terminal
+    //    (i.e. ends in Throw or Return, or has a ForceOSRExit inside it).
+    //
+    // MergeToSuccessors:
+    //    Returns true if the state of the block at the tail was changed,
+    //    and, if the state at the heads of successors was changed.
+    //    A true return means that you must revisit (at least) the successor
+    //    blocks. This also sets cfaShouldRevisit to true for basic blocks
+    //    that must be visited next.
+    bool endBasicBlock(MergeMode);
+    
+    // Reset the AbstractState. This throws away any results, and at this point
+    // you can safely call beginBasicBlock() on any basic block.
+    void reset();
+    
+    // Abstractly executes the given node. The new abstract state is stored into an
+    // abstract register file stored in *this. Loads of local variables (that span
+    // basic blocks) interrogate the basic block's notion of the state at the head.
+    // Stores to local variables are handled in endBasicBlock(). This returns true
+    // if execution should continue past this node. Notably, it will return true
+    // for block terminals, so long as those terminals are not Return or variants
+    // of Throw.
+    bool execute(unsigned);
+    
+    // Is the execution state still valid? This will be false if execute() has
+    // returned false previously.
+    bool isValid() const { return m_isValid; }
+    
+    // Merge the abstract state stored at the first block's tail into the second
+    // block's head. Returns true if the second block's state changed. If so,
+    // that block must be abstractly interpreted again. This also sets
+    // to->cfaShouldRevisit to true, if it returns true, or if to has not been
+    // visited yet.
+    bool merge(BasicBlock* from, BasicBlock* to);
+    
+    // Merge the abstract state stored at the block's tail into all of its
+    // successors. Returns true if any of the successors' states changed. Note
+    // that this is automatically called in endBasicBlock() if MergeMode is
+    // MergeToSuccessors.
+    bool mergeToSuccessors(Graph&, BasicBlock*);
+
+#ifndef NDEBUG
+    void dump(FILE* out);
+#endif
+    
+private:
+    void clobberStructures(unsigned);
+    
+    bool mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex);
+    
+    static bool mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, NodeIndex destinationNodeIndex, NodeIndex sourceNodeIndex);
+    
+    CodeBlock* m_codeBlock;
+    Graph& m_graph;
+    
+    Vector<AbstractValue, 64> m_nodes;
+    Operands<AbstractValue> m_variables;
+    BasicBlock* m_block;
+    bool m_haveStructures;
+    
+    bool m_isValid;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGAbstractState_h
+
diff --git a/dfg/DFGAbstractValue.h b/dfg/DFGAbstractValue.h
new file mode 100644 (file)
index 0000000..682c7a9
--- /dev/null
@@ -0,0 +1,489 @@
+/*
+ * 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 DFGAbstractValue_h
+#define DFGAbstractValue_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "JSCell.h"
+#include "PredictedType.h"
+#include "StructureSet.h"
+
+namespace JSC { namespace DFG {
+
+class StructureAbstractValue {
+public:
+    StructureAbstractValue()
+        : m_structure(0)
+    {
+    }
+    
+    StructureAbstractValue(Structure* structure)
+        : m_structure(structure)
+    {
+    }
+    
+    StructureAbstractValue(const StructureSet& set)
+    {
+        switch (set.size()) {
+        case 0:
+            m_structure = 0;
+            break;
+            
+        case 1:
+            m_structure = set[0];
+            break;
+            
+        default:
+            m_structure = topValue();
+            break;
+        }
+    }
+    
+    void clear()
+    {
+        m_structure = 0;
+    }
+    
+    void makeTop()
+    {
+        m_structure = topValue();
+    }
+    
+    static StructureAbstractValue top()
+    {
+        StructureAbstractValue value;
+        value.makeTop();
+        return value;
+    }
+    
+    void add(Structure* structure)
+    {
+        ASSERT(!contains(structure) && !isTop());
+        if (m_structure)
+            makeTop();
+        else
+            m_structure = structure;
+    }
+    
+    bool addAll(const StructureSet& other)
+    {
+        if (isTop() || !other.size())
+            return false;
+        if (other.size() > 1) {
+            makeTop();
+            return true;
+        }
+        if (!m_structure) {
+            m_structure = other[0];
+            return true;
+        }
+        if (m_structure == other[0])
+            return false;
+        makeTop();
+        return true;
+    }
+    
+    bool addAll(const StructureAbstractValue& other)
+    {
+        if (!other.m_structure)
+            return false;
+        if (isTop())
+            return false;
+        if (other.isTop()) {
+            makeTop();
+            return true;
+        }
+        if (m_structure) {
+            if (m_structure == other.m_structure)
+                return false;
+            makeTop();
+            return true;
+        }
+        m_structure = other.m_structure;
+        return true;
+    }
+    
+    bool contains(Structure* structure) const
+    {
+        if (isTop())
+            return true;
+        if (m_structure == structure)
+            return true;
+        return false;
+    }
+    
+    bool isSubsetOf(const StructureSet& other) const
+    {
+        if (isTop())
+            return false;
+        if (!m_structure)
+            return true;
+        return other.contains(m_structure);
+    }
+    
+    bool doesNotContainAnyOtherThan(Structure* structure) const
+    {
+        if (isTop())
+            return false;
+        if (!m_structure)
+            return true;
+        return m_structure == structure;
+    }
+    
+    bool isSupersetOf(const StructureSet& other) const
+    {
+        if (isTop())
+            return true;
+        if (!other.size())
+            return true;
+        if (other.size() > 1)
+            return false;
+        return m_structure == other[0];
+    }
+    
+    bool isSubsetOf(const StructureAbstractValue& other) const
+    {
+        if (other.isTop())
+            return true;
+        if (isTop())
+            return false;
+        if (m_structure) {
+            if (other.m_structure)
+                return m_structure == other.m_structure;
+            return false;
+        }
+        return true;
+    }
+    
+    bool isSupersetOf(const StructureAbstractValue& other) const
+    {
+        return other.isSubsetOf(*this);
+    }
+    
+    void filter(const StructureSet& other)
+    {
+        if (!m_structure)
+            return;
+        
+        if (isTop()) {
+            switch (other.size()) {
+            case 0:
+                m_structure = 0;
+                return;
+                
+            case 1:
+                m_structure = other[0];
+                return;
+                
+            default:
+                return;
+            }
+        }
+        
+        if (other.contains(m_structure))
+            return;
+        
+        m_structure = 0;
+    }
+    
+    void filter(const StructureAbstractValue& other)
+    {
+        if (isTop()) {
+            m_structure = other.m_structure;
+            return;
+        }
+        if (m_structure == other.m_structure)
+            return;
+        if (other.isTop())
+            return;
+        m_structure = 0;
+    }
+    
+    void filter(PredictedType other)
+    {
+        if (!(other & PredictCell)) {
+            clear();
+            return;
+        }
+        
+        if (isClearOrTop())
+            return;
+
+        if (!(predictionFromStructure(m_structure) & other))
+            m_structure = 0;
+    }
+    
+    bool isClear() const
+    {
+        return !m_structure;
+    }
+    
+    bool isTop() const { return m_structure == topValue(); }
+    
+    bool isClearOrTop() const { return m_structure <= topValue(); }
+    bool isNeitherClearNorTop() const { return !isClearOrTop(); }
+    
+    size_t size() const
+    {
+        ASSERT(!isTop());
+        return !!m_structure;
+    }
+    
+    Structure* at(size_t i) const
+    {
+        ASSERT(!isTop());
+        ASSERT(m_structure);
+        ASSERT_UNUSED(i, !i);
+        return m_structure;
+    }
+    
+    Structure* operator[](size_t i) const
+    {
+        return at(i);
+    }
+    
+    Structure* last() const
+    {
+        return at(0);
+    }
+    
+    PredictedType predictionFromStructures() const
+    {
+        if (isTop())
+            return PredictCell;
+        if (isClear())
+            return PredictNone;
+        return predictionFromStructure(m_structure);
+    }
+    
+    bool operator==(const StructureAbstractValue& other) const
+    {
+        return m_structure == other.m_structure;
+    }
+    
+    void dump(FILE* out) const
+    {
+        if (isTop()) {
+            fprintf(out, "TOP");
+            return;
+        }
+        
+        fprintf(out, "[");
+        if (m_structure)
+            fprintf(out, "%p", m_structure);
+        fprintf(out, "]");
+    }
+
+private:
+    static Structure* topValue() { return reinterpret_cast<Structure*>(1); }
+    
+    // This can only remember one structure at a time.
+    Structure* m_structure;
+};
+
+struct AbstractValue {
+    AbstractValue()
+        : m_type(PredictNone)
+    {
+    }
+    
+    void clear()
+    {
+        m_type = PredictNone;
+        m_structure.clear();
+        checkConsistency();
+    }
+    
+    bool isClear()
+    {
+        return m_type == PredictNone && m_structure.isClear();
+    }
+    
+    void makeTop()
+    {
+        m_type = PredictTop;
+        m_structure.makeTop();
+        checkConsistency();
+    }
+    
+    void clobberStructures()
+    {
+        if (m_type & PredictCell)
+            m_structure.makeTop();
+        else
+            ASSERT(m_structure.isClear());
+        checkConsistency();
+    }
+    
+    bool isTop() const
+    {
+        return m_type == PredictTop && m_structure.isTop();
+    }
+    
+    static AbstractValue top()
+    {
+        AbstractValue result;
+        result.makeTop();
+        return result;
+    }
+    
+    void set(JSValue value)
+    {
+        m_structure.clear();
+        if (value.isCell())
+            m_structure.add(value.asCell()->structure());
+        
+        m_type = predictionFromValue(value);
+        
+        checkConsistency();
+    }
+    
+    void set(Structure* structure)
+    {
+        m_structure.clear();
+        m_structure.add(structure);
+        
+        m_type = predictionFromStructure(structure);
+        
+        checkConsistency();
+    }
+    
+    void set(PredictedType type)
+    {
+        if (type & PredictCell)
+            m_structure.makeTop();
+        else
+            m_structure.clear();
+        m_type = type;
+        checkConsistency();
+    }
+    
+    bool operator==(const AbstractValue& other) const
+    {
+        return m_type == other.m_type && m_structure == other.m_structure;
+    }
+    
+    bool merge(const AbstractValue& other)
+    {
+        bool result = mergePrediction(m_type, other.m_type) | m_structure.addAll(other.m_structure);
+        checkConsistency();
+        return result;
+    }
+    
+    void merge(PredictedType type)
+    {
+        mergePrediction(m_type, type);
+        
+        if (type & PredictCell)
+            m_structure.makeTop();
+
+        checkConsistency();
+    }
+    
+    void filter(const StructureSet& other)
+    {
+        m_type &= other.predictionFromStructures();
+        m_structure.filter(other);
+        
+        // It's possible that prior to the above two statements we had (Foo, TOP), where
+        // Foo is a PredictedType that is disjoint with the passed StructureSet. In that
+        // case, we will now have (None, [someStructure]). In general, we need to make
+        // sure that new information gleaned from the PredictedType needs to be fed back
+        // into the information gleaned from the StructureSet.
+        m_structure.filter(m_type);
+        checkConsistency();
+    }
+    
+    void filter(PredictedType type)
+    {
+        if (type == PredictTop)
+            return;
+        m_type &= type;
+        
+        // It's possible that prior to this filter() call we had, say, (Final, TOP), and
+        // the passed type is Array. At this point we'll have (None, TOP). The best way
+        // to ensure that the structure filtering does the right thing is to filter on
+        // the new type (None) rather than the one passed (Array).
+        m_structure.filter(m_type);
+        checkConsistency();
+    }
+    
+    bool validate(JSValue value) const
+    {
+        if (isTop())
+            return true;
+        
+        if (mergePredictions(m_type, predictionFromValue(value)) != m_type)
+            return false;
+        
+        if (value.isEmpty()) {
+            ASSERT(m_type & PredictEmpty);
+            return true;
+        }
+        
+        if (m_structure.isTop())
+            return true;
+        
+        if (value.isCell()) {
+            ASSERT(m_type & PredictCell);
+            return m_structure.contains(value.asCell()->structure());
+        }
+        
+        return true;
+    }
+    
+    void checkConsistency() const
+    {
+        if (!(m_type & PredictCell))
+            ASSERT(m_structure.isClear());
+        
+        // Note that it's possible for a prediction like (Final, []). This really means that
+        // the value is bottom and that any code that uses the value is unreachable. But
+        // we don't want to get pedantic about this as it would only increase the computational
+        // complexity of the code.
+    }
+    
+    void dump(FILE* out) const
+    {
+        fprintf(out, "(%s, ", predictionToString(m_type));
+        m_structure.dump(out);
+        fprintf(out, ")");
+    }
+
+    StructureAbstractValue m_structure;
+    PredictedType m_type;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGAbstractValue_h
+
+
diff --git a/dfg/DFGAdjacencyList.h b/dfg/DFGAdjacencyList.h
new file mode 100644 (file)
index 0000000..e2b096b
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * 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 DFGAdjacencyList_h
+#define DFGAdjacencyList_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGCommon.h"
+#include "DFGEdge.h"
+
+namespace JSC { namespace DFG {
+
+class AdjacencyList {
+public:
+    enum Kind {
+        Fixed,
+        Variable
+    };
+
+    AdjacencyList(Kind kind)
+#if !ASSERT_DISABLED
+        : m_kind(kind)
+#endif
+    {
+        if (kind == Variable) {
+            m_words[0].m_encodedWord = UINT_MAX;
+            m_words[1].m_encodedWord = UINT_MAX;
+        }
+    }
+    
+    AdjacencyList(Kind kind, NodeIndex child1, NodeIndex child2, NodeIndex child3)
+#if !ASSERT_DISABLED
+        : m_kind(Fixed)
+#endif
+    {
+        ASSERT_UNUSED(kind, kind == Fixed);
+        initialize(child1, child2, child3);
+    }
+    
+    AdjacencyList(Kind kind, unsigned firstChild, unsigned numChildren)
+#if !ASSERT_DISABLED
+        : m_kind(Variable)
+#endif
+    {
+        ASSERT_UNUSED(kind, kind == Variable);
+        setFirstChild(firstChild);
+        setNumChildren(numChildren);
+    }
+    
+    const Edge& child(unsigned i) const
+    {
+        ASSERT(i < 3);
+        ASSERT(m_kind == Fixed);
+        return m_words[i];
+    }    
+    
+    Edge& child(unsigned i)
+    {
+        ASSERT(i < 3);
+        ASSERT(m_kind == Fixed);
+        return m_words[i];
+    }
+    
+    void setChild(unsigned i, Edge nodeUse)
+    {
+        ASSERT(i < 30);
+        ASSERT(m_kind == Fixed);
+        m_words[i] = nodeUse;
+    }
+    
+    Edge child1() const { return child(0); }
+    Edge child2() const { return child(1); }
+    Edge child3() const { return child(2); }
+
+    Edge& child1() { return child(0); }
+    Edge& child2() { return child(1); }
+    Edge& child3() { return child(2); }
+    
+    void setChild1(Edge nodeUse) { setChild(0, nodeUse); }
+    void setChild2(Edge nodeUse) { setChild(1, nodeUse); }
+    void setChild3(Edge nodeUse) { setChild(2, nodeUse); }
+    
+    Edge child1Unchecked() const { return m_words[0]; }
+    
+    void initialize(Edge child1, Edge child2, Edge child3)
+    {
+        child(0) = child1;
+        child(1) = child2;
+        child(2) = child3;
+    }
+    
+    void initialize(NodeIndex child1, NodeIndex child2, NodeIndex child3)
+    {
+        initialize(Edge(child1), Edge(child2), Edge(child3));
+    }
+
+    unsigned firstChild() const
+    {
+        ASSERT(m_kind == Variable);
+        return m_words[0].m_encodedWord;
+    }
+    void setFirstChild(unsigned firstChild)
+    {
+        ASSERT(m_kind == Variable);
+        m_words[0].m_encodedWord = firstChild;
+    }
+    
+    unsigned numChildren() const
+    {
+        ASSERT(m_kind == Variable);
+        return m_words[1].m_encodedWord;
+    }
+    void setNumChildren(unsigned numChildren)
+    {
+        ASSERT(m_kind == Variable);
+        m_words[1].m_encodedWord = numChildren;
+    }
+    
+private:
+    Edge m_words[3];
+#if !ASSERT_DISABLED
+    Kind m_kind;
+#endif
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGAdjacencyList_h
diff --git a/dfg/DFGAliasTracker.h b/dfg/DFGAliasTracker.h
deleted file mode 100644 (file)
index 8710169..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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/DFGArgumentPosition.h b/dfg/DFGArgumentPosition.h
new file mode 100644 (file)
index 0000000..ed447ff
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGArgumentPosition_h
+#define DFGArgumentPosition_h
+
+#include "DFGDoubleFormatState.h"
+#include "DFGVariableAccessData.h"
+#include "PredictedType.h"
+
+namespace JSC { namespace DFG {
+
+class ArgumentPosition {
+public:
+    ArgumentPosition()
+        : m_prediction(PredictNone)
+        , m_doubleFormatState(EmptyDoubleFormatState)
+    {
+    }
+    
+    void addVariable(VariableAccessData* variable)
+    {
+        m_variables.append(variable);
+    }
+    
+    bool mergeArgumentAwareness()
+    {
+        bool changed = false;
+        for (unsigned i = 0; i < m_variables.size(); ++i) {
+            changed |= mergePrediction(m_prediction, m_variables[i]->argumentAwarePrediction());
+            changed |= mergeDoubleFormatState(m_doubleFormatState, m_variables[i]->doubleFormatState());
+        }
+        if (!changed)
+            return false;
+        changed = false;
+        for (unsigned i = 0; i < m_variables.size(); ++i) {
+            changed |= m_variables[i]->mergeArgumentAwarePrediction(m_prediction);
+            changed |= m_variables[i]->mergeDoubleFormatState(m_doubleFormatState);
+        }
+        return changed;
+    }
+    
+private:
+    PredictedType m_prediction;
+    DoubleFormatState m_doubleFormatState;
+    
+    Vector<VariableAccessData*, 2> m_variables;
+};
+
+} } // namespace JSC::DFG
+
+#endif // DFGArgumentPosition_h
+
diff --git a/dfg/DFGAssemblyHelpers.cpp b/dfg/DFGAssemblyHelpers.cpp
new file mode 100644 (file)
index 0000000..15f6d19
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * 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 "DFGAssemblyHelpers.h"
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+const double AssemblyHelpers::twoToThe32 = (double)0x100000000ull;
+
+Vector<BytecodeAndMachineOffset>& AssemblyHelpers::decodedCodeMapFor(CodeBlock* codeBlock)
+{
+    ASSERT(codeBlock == codeBlock->baselineVersion());
+    ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
+    ASSERT(codeBlock->jitCodeMap());
+    
+    HashMap<CodeBlock*, Vector<BytecodeAndMachineOffset> >::AddResult result = m_decodedCodeMaps.add(codeBlock, Vector<BytecodeAndMachineOffset>());
+    
+    if (result.isNewEntry)
+        codeBlock->jitCodeMap()->decode(result.iterator->second);
+    
+    return result.iterator->second;
+}
+
+#if ENABLE(SAMPLING_FLAGS)
+void AssemblyHelpers::setSamplingFlag(int32_t flag)
+{
+    ASSERT(flag >= 1);
+    ASSERT(flag <= 32);
+    or32(TrustedImm32(1u << (flag - 1)), AbsoluteAddress(SamplingFlags::addressOfFlags()));
+}
+
+void AssemblyHelpers::clearSamplingFlag(int32_t flag)
+{
+    ASSERT(flag >= 1);
+    ASSERT(flag <= 32);
+    and32(TrustedImm32(~(1u << (flag - 1))), AbsoluteAddress(SamplingFlags::addressOfFlags()));
+}
+#endif
+
+#if DFG_ENABLE(JIT_ASSERT)
+#if USE(JSVALUE64)
+void AssemblyHelpers::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 AssemblyHelpers::jitAssertIsJSInt32(GPRReg gpr)
+{
+    Jump checkJSInt32 = branchPtr(AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
+    breakpoint();
+    checkJSInt32.link(this);
+}
+
+void AssemblyHelpers::jitAssertIsJSNumber(GPRReg gpr)
+{
+    Jump checkJSNumber = branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister);
+    breakpoint();
+    checkJSNumber.link(this);
+}
+
+void AssemblyHelpers::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);
+}
+
+void AssemblyHelpers::jitAssertIsCell(GPRReg gpr)
+{
+    Jump checkCell = branchTestPtr(MacroAssembler::Zero, gpr, GPRInfo::tagMaskRegister);
+    breakpoint();
+    checkCell.link(this);
+}
+#elif USE(JSVALUE32_64)
+void AssemblyHelpers::jitAssertIsInt32(GPRReg gpr)
+{
+    UNUSED_PARAM(gpr);
+}
+
+void AssemblyHelpers::jitAssertIsJSInt32(GPRReg gpr)
+{
+    Jump checkJSInt32 = branch32(Equal, gpr, TrustedImm32(JSValue::Int32Tag));
+    breakpoint();
+    checkJSInt32.link(this);
+}
+
+void AssemblyHelpers::jitAssertIsJSNumber(GPRReg gpr)
+{
+    Jump checkJSInt32 = branch32(Equal, gpr, TrustedImm32(JSValue::Int32Tag));
+    Jump checkJSDouble = branch32(Below, gpr, TrustedImm32(JSValue::LowestTag));
+    breakpoint();
+    checkJSInt32.link(this);
+    checkJSDouble.link(this);
+}
+
+void AssemblyHelpers::jitAssertIsJSDouble(GPRReg gpr)
+{
+    Jump checkJSDouble = branch32(Below, gpr, TrustedImm32(JSValue::LowestTag));
+    breakpoint();
+    checkJSDouble.link(this);
+}
+
+void AssemblyHelpers::jitAssertIsCell(GPRReg gpr)
+{
+    Jump checkCell = branch32(Equal, gpr, TrustedImm32(JSValue::CellTag));
+    breakpoint();
+    checkCell.link(this);
+}
+#endif // USE(JSVALUE32_64)
+
+void AssemblyHelpers::jitAssertHasValidCallFrame()
+{
+    Jump checkCFR = branchTestPtr(Zero, GPRInfo::callFrameRegister, TrustedImm32(7));
+    breakpoint();
+    checkCFR.link(this);
+}
+#endif // DFG_ENABLE(JIT_ASSERT)
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/dfg/DFGAssemblyHelpers.h b/dfg/DFGAssemblyHelpers.h
new file mode 100644 (file)
index 0000000..c01ee23
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * 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 DFGAssemblyHelpers_h
+#define DFGAssemblyHelpers_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeBlock.h"
+#include "DFGFPRInfo.h"
+#include "DFGGPRInfo.h"
+#include "DFGNode.h"
+#include "JSGlobalData.h"
+#include "MacroAssembler.h"
+
+namespace JSC { namespace DFG {
+
+typedef void (*V_DFGDebugOperation_EP)(ExecState*, void*);
+
+class AssemblyHelpers : public MacroAssembler {
+public:
+    AssemblyHelpers(JSGlobalData* globalData, CodeBlock* codeBlock)
+        : m_globalData(globalData)
+        , m_codeBlock(codeBlock)
+        , m_baselineCodeBlock(codeBlock->baselineVersion())
+    {
+        ASSERT(m_codeBlock);
+        ASSERT(m_baselineCodeBlock);
+        ASSERT(!m_baselineCodeBlock->alternative());
+        ASSERT(m_baselineCodeBlock->getJITType() == JITCode::BaselineJIT);
+    }
+    
+    CodeBlock* codeBlock() { return m_codeBlock; }
+    JSGlobalData* globalData() { return m_globalData; }
+    AssemblerType_T& assembler() { return m_assembler; }
+    
+#if CPU(X86_64) || CPU(X86)
+    void preserveReturnAddressAfterCall(GPRReg reg)
+    {
+        pop(reg);
+    }
+
+    void restoreReturnAddressBeforeReturn(GPRReg reg)
+    {
+        push(reg);
+    }
+
+    void restoreReturnAddressBeforeReturn(Address address)
+    {
+        push(address);
+    }
+#endif // CPU(X86_64) || CPU(X86)
+
+#if CPU(ARM)
+    ALWAYS_INLINE void preserveReturnAddressAfterCall(RegisterID reg)
+    {
+        move(linkRegister, reg);
+    }
+
+    ALWAYS_INLINE void restoreReturnAddressBeforeReturn(RegisterID reg)
+    {
+        move(reg, linkRegister);
+    }
+
+    ALWAYS_INLINE void restoreReturnAddressBeforeReturn(Address address)
+    {
+        loadPtr(address, linkRegister);
+    }
+#endif
+
+    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)));
+    }
+
+    Jump branchIfNotCell(GPRReg reg)
+    {
+#if USE(JSVALUE64)
+        return branchTestPtr(MacroAssembler::NonZero, reg, GPRInfo::tagMaskRegister);
+#else
+        return branch32(MacroAssembler::NotEqual, reg, TrustedImm32(JSValue::CellTag));
+#endif
+    }
+    
+    static Address addressForGlobalVar(GPRReg global, int32_t varNumber)
+    {
+        return Address(global, varNumber * sizeof(Register));
+    }
+
+    static Address tagForGlobalVar(GPRReg global, int32_t varNumber)
+    {
+        return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+    }
+
+    static Address payloadForGlobalVar(GPRReg global, int32_t varNumber)
+    {
+        return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+    }
+
+    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));
+    }
+
+    Jump branchIfNotObject(GPRReg structureReg)
+    {
+        return branch8(Below, Address(structureReg, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType));
+    }
+
+    static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg)
+    {
+        if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0 && preserve4 != GPRInfo::regT0)
+            return GPRInfo::regT0;
+
+        if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1 && preserve4 != GPRInfo::regT1)
+            return GPRInfo::regT1;
+
+        if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2 && preserve4 != GPRInfo::regT2)
+            return GPRInfo::regT2;
+
+        if (preserve1 != GPRInfo::regT3 && preserve2 != GPRInfo::regT3 && preserve3 != GPRInfo::regT3 && preserve4 != GPRInfo::regT3)
+            return GPRInfo::regT3;
+
+        return GPRInfo::regT4;
+    }
+
+    // Add a debug call. This call has no effect on JIT code execution state.
+    void debugCall(V_DFGDebugOperation_EP function, void* argument)
+    {
+        size_t scratchSize = sizeof(EncodedJSValue) * (GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters);
+        ScratchBuffer* scratchBuffer = m_globalData->scratchBufferForSize(scratchSize);
+        EncodedJSValue* buffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer());
+
+        for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i)
+            storePtr(GPRInfo::toRegister(i), buffer + i);
+        for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
+            move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
+            storeDouble(FPRInfo::toRegister(i), GPRInfo::regT0);
+        }
+
+        // Tell GC mark phase how much of the scratch buffer is active during call.
+        move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), GPRInfo::regT0);
+        storePtr(TrustedImmPtr(scratchSize), GPRInfo::regT0);
+
+#if CPU(X86_64) || CPU(ARM_THUMB2)
+        move(TrustedImmPtr(argument), GPRInfo::argumentGPR1);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        GPRReg scratch = selectScratchGPR(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1);
+#elif CPU(X86)
+        poke(GPRInfo::callFrameRegister, 0);
+        poke(TrustedImmPtr(argument), 1);
+        GPRReg scratch = GPRInfo::regT0;
+#else
+#error "DFG JIT not supported on this platform."
+#endif
+        move(TrustedImmPtr(reinterpret_cast<void*>(function)), scratch);
+        call(scratch);
+
+        move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), GPRInfo::regT0);
+        storePtr(TrustedImmPtr(0), GPRInfo::regT0);
+
+        for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
+            move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
+            loadDouble(GPRInfo::regT0, FPRInfo::toRegister(i));
+        }
+        for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i)
+            loadPtr(buffer + i, GPRInfo::toRegister(i));
+    }
+
+    // These methods JIT generate dynamic, debug-only checks - akin to ASSERTs.
+#if DFG_ENABLE(JIT_ASSERT)
+    void jitAssertIsInt32(GPRReg);
+    void jitAssertIsJSInt32(GPRReg);
+    void jitAssertIsJSNumber(GPRReg);
+    void jitAssertIsJSDouble(GPRReg);
+    void jitAssertIsCell(GPRReg);
+    void jitAssertHasValidCallFrame();
+#else
+    void jitAssertIsInt32(GPRReg) { }
+    void jitAssertIsJSInt32(GPRReg) { }
+    void jitAssertIsJSNumber(GPRReg) { }
+    void jitAssertIsJSDouble(GPRReg) { }
+    void jitAssertIsCell(GPRReg) { }
+    void jitAssertHasValidCallFrame() { }
+#endif
+
+    // These methods convert between doubles, and doubles boxed and JSValues.
+#if USE(JSVALUE64)
+    GPRReg boxDouble(FPRReg fpr, GPRReg gpr)
+    {
+        moveDoubleToPtr(fpr, gpr);
+        subPtr(GPRInfo::tagTypeNumberRegister, gpr);
+        jitAssertIsJSDouble(gpr);
+        return gpr;
+    }
+    FPRReg unboxDouble(GPRReg gpr, FPRReg fpr)
+    {
+        jitAssertIsJSDouble(gpr);
+        addPtr(GPRInfo::tagTypeNumberRegister, gpr);
+        movePtrToDouble(gpr, fpr);
+        return fpr;
+    }
+#endif
+
+#if USE(JSVALUE32_64) && CPU(X86)
+    void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR)
+    {
+        movePackedToInt32(fpr, payloadGPR);
+        rshiftPacked(TrustedImm32(32), fpr);
+        movePackedToInt32(fpr, tagGPR);
+    }
+    void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, FPRReg scratchFPR)
+    {
+        jitAssertIsJSDouble(tagGPR);
+        moveInt32ToPacked(payloadGPR, fpr);
+        moveInt32ToPacked(tagGPR, scratchFPR);
+        lshiftPacked(TrustedImm32(32), scratchFPR);
+        orPacked(scratchFPR, fpr);
+    }
+#endif
+
+#if USE(JSVALUE32_64) && CPU(ARM)
+    void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR)
+    {
+        m_assembler.vmov(payloadGPR, tagGPR, fpr);
+    }
+    void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, FPRReg scratchFPR)
+    {
+        jitAssertIsJSDouble(tagGPR);
+        UNUSED_PARAM(scratchFPR);
+        m_assembler.vmov(fpr, payloadGPR, tagGPR);
+    }
+#endif
+    
+    enum ExceptionCheckKind { NormalExceptionCheck, InvertedExceptionCheck };
+    Jump emitExceptionCheck(ExceptionCheckKind kind = NormalExceptionCheck)
+    {
+#if USE(JSVALUE64)
+        return branchTestPtr(kind == NormalExceptionCheck ? NonZero : Zero, AbsoluteAddress(&globalData()->exception));
+#elif USE(JSVALUE32_64)
+        return branch32(kind == NormalExceptionCheck ? NotEqual : Equal, AbsoluteAddress(reinterpret_cast<char*>(&globalData()->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
+#endif
+    }
+
+#if ENABLE(SAMPLING_COUNTERS)
+    static void emitCount(MacroAssembler& jit, AbstractSamplingCounter& counter, int32_t increment = 1)
+    {
+        jit.add64(TrustedImm32(increment), AbsoluteAddress(counter.addressOfCounter()));
+    }
+    void emitCount(AbstractSamplingCounter& counter, int32_t increment = 1)
+    {
+        add64(TrustedImm32(increment), AbsoluteAddress(counter.addressOfCounter()));
+    }
+#endif
+
+#if ENABLE(SAMPLING_FLAGS)
+    void setSamplingFlag(int32_t);
+    void clearSamplingFlag(int32_t flag);
+#endif
+
+    JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin)
+    {
+        return codeBlock()->globalObjectFor(codeOrigin);
+    }
+    
+    JSObject* globalThisObjectFor(CodeOrigin codeOrigin)
+    {
+        JSGlobalObject* object = globalObjectFor(codeOrigin);
+        return object->methodTable()->toThisObject(object, 0);
+    }
+    
+    bool strictModeFor(CodeOrigin codeOrigin)
+    {
+        if (!codeOrigin.inlineCallFrame)
+            return codeBlock()->isStrictMode();
+        return codeOrigin.inlineCallFrame->callee->jsExecutable()->isStrictMode();
+    }
+    
+    CodeBlock* baselineCodeBlockFor(const CodeOrigin& codeOrigin)
+    {
+        return baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, baselineCodeBlock());
+    }
+    
+    CodeBlock* baselineCodeBlock()
+    {
+        return m_baselineCodeBlock;
+    }
+    
+    Vector<BytecodeAndMachineOffset>& decodedCodeMapFor(CodeBlock*);
+    
+    static const double twoToThe32;
+
+protected:
+    JSGlobalData* m_globalData;
+    CodeBlock* m_codeBlock;
+    CodeBlock* m_baselineCodeBlock;
+
+    HashMap<CodeBlock*, Vector<BytecodeAndMachineOffset> > m_decodedCodeMaps;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGAssemblyHelpers_h
+
diff --git a/dfg/DFGBasicBlock.h b/dfg/DFGBasicBlock.h
new file mode 100644 (file)
index 0000000..92df58d
--- /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 DFGBasicBlock_h
+#define DFGBasicBlock_h
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAbstractValue.h"
+#include "DFGNode.h"
+#include "Operands.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace JSC { namespace DFG {
+
+typedef Vector <BlockIndex, 2> PredecessorList;
+
+struct BasicBlock : Vector<NodeIndex, 8> {
+    BasicBlock(unsigned bytecodeBegin, unsigned numArguments, unsigned numLocals)
+        : bytecodeBegin(bytecodeBegin)
+        , isOSRTarget(false)
+        , cfaHasVisited(false)
+        , cfaShouldRevisit(false)
+#if !ASSERT_DISABLED
+        , isLinked(false)
+#endif
+        , isReachable(false)
+        , variablesAtHead(numArguments, numLocals)
+        , variablesAtTail(numArguments, numLocals)
+        , valuesAtHead(numArguments, numLocals)
+        , valuesAtTail(numArguments, numLocals)
+    {
+    }
+    
+    void ensureLocals(unsigned newNumLocals)
+    {
+        variablesAtHead.ensureLocals(newNumLocals);
+        variablesAtTail.ensureLocals(newNumLocals);
+        valuesAtHead.ensureLocals(newNumLocals);
+        valuesAtTail.ensureLocals(newNumLocals);
+    }
+
+    // This value is used internally for block linking and OSR entry. It is mostly meaningless
+    // for other purposes due to inlining.
+    unsigned bytecodeBegin;
+    
+    bool isOSRTarget;
+    bool cfaHasVisited;
+    bool cfaShouldRevisit;
+#if !ASSERT_DISABLED
+    bool isLinked;
+#endif
+    bool isReachable;
+    
+    Vector<NodeIndex> phis;
+    PredecessorList m_predecessors;
+    
+    Operands<NodeIndex, NodeIndexTraits> variablesAtHead;
+    Operands<NodeIndex, NodeIndexTraits> variablesAtTail;
+    
+    Operands<AbstractValue> valuesAtHead;
+    Operands<AbstractValue> valuesAtTail;
+};
+
+struct UnlinkedBlock {
+    BlockIndex m_blockIndex;
+    bool m_needsNormalLinking;
+    bool m_needsEarlyReturnLinking;
+    
+    UnlinkedBlock() { }
+    
+    explicit UnlinkedBlock(BlockIndex blockIndex)
+        : m_blockIndex(blockIndex)
+        , m_needsNormalLinking(true)
+        , m_needsEarlyReturnLinking(false)
+    {
+    }
+};
+    
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGBasicBlock_h
+
diff --git a/dfg/DFGByteCodeCache.h b/dfg/DFGByteCodeCache.h
new file mode 100644 (file)
index 0000000..f6a745c
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * 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 DFGByteCodeCache_h
+#define DFGByteCodeCache_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeBlock.h"
+#include "Executable.h"
+#include "JSFunction.h"
+#include <wtf/HashMap.h>
+
+namespace JSC { namespace DFG {
+
+class CodeBlockKey {
+public:
+    CodeBlockKey()
+        : m_executable(0)
+        , m_kind(CodeForCall) // CodeForCall = empty value
+    {
+    }
+    
+    CodeBlockKey(WTF::HashTableDeletedValueType)
+        : m_executable(0)
+        , m_kind(CodeForConstruct) // CodeForConstruct = deleted value
+    {
+    }
+    
+    CodeBlockKey(FunctionExecutable* executable, CodeSpecializationKind kind)
+        : m_executable(executable)
+        , m_kind(kind)
+    {
+    }
+    
+    bool operator==(const CodeBlockKey& other) const
+    {
+        return m_executable == other.m_executable
+            && m_kind == other.m_kind;
+    }
+    
+    unsigned hash() const
+    {
+        return WTF::PtrHash<FunctionExecutable*>::hash(m_executable) ^ static_cast<unsigned>(m_kind);
+    }
+    
+    FunctionExecutable* executable() const { return m_executable; }
+    CodeSpecializationKind kind() const { return m_kind; }
+
+    bool isHashTableDeletedValue() const
+    {
+        return !m_executable && m_kind == CodeForConstruct;
+    }
+
+private:
+    FunctionExecutable* m_executable;
+    CodeSpecializationKind m_kind;
+};
+
+struct CodeBlockKeyHash {
+    static unsigned hash(const CodeBlockKey& key) { return key.hash(); }
+    static bool equal(const CodeBlockKey& a, const CodeBlockKey& b) { return a == b; }
+    
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::DFG::CodeBlockKey> {
+    typedef JSC::DFG::CodeBlockKeyHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::DFG::CodeBlockKey> : SimpleClassHashTraits<JSC::DFG::CodeBlockKey> { };
+
+} // namespace WTF
+
+namespace JSC { namespace DFG {
+
+struct ByteCodeCacheValue {
+    FunctionCodeBlock* codeBlock;
+    bool owned;
+    bool oldValueOfShouldDiscardBytecode;
+    
+    // All uses of this struct initialize everything manually. But gcc isn't
+    // smart enough to see that, so this constructor is just here to make the
+    // compiler happy.
+    ByteCodeCacheValue()
+        : codeBlock(0)
+        , owned(false)
+        , oldValueOfShouldDiscardBytecode(false)
+    {
+    }
+};
+
+template<bool (*filterFunction)(CodeBlock*, CodeSpecializationKind)>
+class ByteCodeCache {
+public:
+    typedef HashMap<CodeBlockKey, ByteCodeCacheValue> Map;
+    
+    ByteCodeCache() { }
+    
+    ~ByteCodeCache()
+    {
+        Map::iterator begin = m_map.begin();
+        Map::iterator end = m_map.end();
+        for (Map::iterator iter = begin; iter != end; ++iter) {
+            if (!iter->second.codeBlock)
+                continue;
+            if (iter->second.owned) {
+                delete iter->second.codeBlock;
+                continue;
+            }
+        }
+    }
+    
+    CodeBlock* get(const CodeBlockKey& key, ScopeChainNode* scope)
+    {
+        Map::iterator iter = m_map.find(key);
+        if (iter != m_map.end())
+            return iter->second.codeBlock;
+        
+        ByteCodeCacheValue value;
+        
+        // First see if there is already a parsed code block that still has some
+        // bytecode in it.
+        value.codeBlock = key.executable()->codeBlockWithBytecodeFor(key.kind());
+        if (value.codeBlock) {
+            value.owned = false;
+        } else {
+            // Nope, so try to parse one.
+            JSObject* exception;
+            value.owned = true;
+            value.codeBlock = key.executable()->produceCodeBlockFor(scope, OptimizingCompilation, key.kind(), exception).leakPtr();
+        }
+        
+        // Check if there is any reason to reject this from our cache. If so, then
+        // poison it.
+        if (!!value.codeBlock && !filterFunction(value.codeBlock, key.kind())) {
+            if (value.owned)
+                delete value.codeBlock;
+            value.codeBlock = 0;
+        }
+        
+        m_map.add(key, value);
+        
+        return value.codeBlock;
+    }
+
+private:
+    Map m_map;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGByteCodeCache_h
index 7c333de88d7e94133f2bb3c1131e25dba4967a31..a34f5d38cfd64b03eeeea1caccc4e92535f93b84 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #if ENABLE(DFG_JIT)
 
 
 #if ENABLE(DFG_JIT)
 
-#include "DFGAliasTracker.h"
-#include "DFGScoreBoard.h"
+#include "CallLinkStatus.h"
 #include "CodeBlock.h"
 #include "CodeBlock.h"
+#include "DFGByteCodeCache.h"
+#include "DFGCapabilities.h"
+#include "GetByIdStatus.h"
+#include "MethodCallLinkStatus.h"
+#include "PutByIdStatus.h"
+#include <wtf/HashMap.h>
+#include <wtf/MathExtras.h>
 
 namespace JSC { namespace DFG {
 
 
 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 ===
 //
 // 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)
+    ByteCodeParser(Graph& graph)
+        : m_globalData(&graph.m_globalData)
+        , m_codeBlock(graph.m_codeBlock)
+        , m_profiledBlock(graph.m_profiledBlock)
         , m_graph(graph)
         , m_graph(graph)
+        , m_currentBlock(0)
         , m_currentIndex(0)
         , m_currentIndex(0)
-        , m_parseFailed(false)
+        , m_currentProfilingIndex(0)
         , m_constantUndefined(UINT_MAX)
         , m_constantNull(UINT_MAX)
         , m_constantUndefined(UINT_MAX)
         , m_constantNull(UINT_MAX)
+        , m_constantNaN(UINT_MAX)
         , m_constant1(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)
+        , m_constants(m_codeBlock->numberOfConstantRegisters())
+        , m_numArguments(m_codeBlock->numParameters())
+        , m_numLocals(m_codeBlock->m_numCalleeRegisters)
+        , m_preservedVars(m_codeBlock->m_numVars)
+        , m_parameterSlots(0)
+        , m_numPassedVarArgs(0)
+        , m_globalResolveNumber(0)
+        , m_inlineStackTop(0)
+        , m_haveBuiltOperandMaps(false)
+        , m_emptyJSValueIndex(UINT_MAX)
     {
     {
+        ASSERT(m_profiledBlock);
+        
+        for (int i = 0; i < m_codeBlock->m_numVars; ++i)
+            m_preservedVars.set(i);
     }
     }
-
+    
     // Parse a full CodeBlock of bytecode.
     bool parse();
     // Parse a full CodeBlock of bytecode.
     bool parse();
-
+    
 private:
 private:
+    // Just parse from m_currentIndex to the end of the current CodeBlock.
+    void parseCodeBlock();
+
+    // Helper for min and max.
+    bool handleMinMax(bool usesResult, int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis);
+    
+    // Handle calls. This resolves issues surrounding inlining and intrinsics.
+    void handleCall(Interpreter*, Instruction* currentInstruction, NodeType op, CodeSpecializationKind);
+    void emitFunctionCheck(JSFunction* expectedFunction, NodeIndex callTarget, int registerOffset, CodeSpecializationKind);
+    // Handle inlining. Return true if it succeeded, false if we need to plant a call.
+    bool handleInlining(bool usesResult, int callTarget, NodeIndex callTargetNodeIndex, int resultOperand, bool certainAboutExpectedFunction, JSFunction*, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind);
+    // Handle setting the result of an intrinsic.
+    void setIntrinsicResult(bool usesResult, int resultOperand, NodeIndex);
+    // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
+    bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, PredictedType prediction);
+    // Prepare to parse a block.
+    void prepareToParseBlock();
     // Parse a single basic block of bytecode instructions.
     bool parseBlock(unsigned limit);
     // Parse a single basic block of bytecode instructions.
     bool parseBlock(unsigned limit);
-    // Setup predecessor links in the graph's BasicBlocks.
-    void setupPredecessors();
+    // Find reachable code and setup predecessor links in the graph's BasicBlocks.
+    void determineReachability();
+    // Enqueue a block onto the worklist, if necessary.
+    void handleSuccessor(Vector<BlockIndex, 16>& worklist, BlockIndex, BlockIndex successor);
+    // Link block successors.
+    void linkBlock(BasicBlock*, Vector<BlockIndex>& possibleTargets);
+    void linkBlocks(Vector<UnlinkedBlock>& unlinkedBlocks, Vector<BlockIndex>& possibleTargets);
     // Link GetLocal & SetLocal nodes, to ensure live values are generated.
     enum PhiStackType {
         LocalPhiStack,
     // Link GetLocal & SetLocal nodes, to ensure live values are generated.
     enum PhiStackType {
         LocalPhiStack,
@@ -77,11 +111,21 @@ private:
     };
     template<PhiStackType stackType>
     void processPhiStack();
     };
     template<PhiStackType stackType>
     void processPhiStack();
+    
+    void fixVariableAccessPredictions();
     // Add spill locations to nodes.
     void allocateVirtualRegisters();
     // Add spill locations to nodes.
     void allocateVirtualRegisters();
-
+    
+    VariableAccessData* newVariableAccessData(int operand)
+    {
+        ASSERT(operand < FirstConstantRegisterIndex);
+        
+        m_graph.m_variableAccessData.append(VariableAccessData(static_cast<VirtualRegister>(operand)));
+        return &m_graph.m_variableAccessData.last();
+    }
+    
     // Get/Set the operands/result of a bytecode instruction.
     // Get/Set the operands/result of a bytecode instruction.
-    NodeIndex get(int operand)
+    NodeIndex getDirect(int operand)
     {
         // Is this a constant?
         if (operand >= FirstConstantRegisterIndex) {
     {
         // Is this a constant?
         if (operand >= FirstConstantRegisterIndex) {
@@ -97,10 +141,12 @@ private:
         // Must be a local.
         return getLocal((unsigned)operand);
     }
         // Must be a local.
         return getLocal((unsigned)operand);
     }
-    void set(int operand, NodeIndex value, PredictedType prediction = PredictNone)
+    NodeIndex get(int operand)
+    {
+        return getDirect(m_inlineStackTop->remapOperand(operand));
+    }
+    void setDirect(int operand, NodeIndex value)
     {
     {
-        m_graph.predict(operand, prediction);
-
         // Is this an argument?
         if (operandIsArgument(operand)) {
             setArgument(operand, value);
         // Is this an argument?
         if (operandIsArgument(operand)) {
             setArgument(operand, value);
@@ -110,90 +156,257 @@ private:
         // Must be a local.
         setLocal((unsigned)operand, value);
     }
         // Must be a local.
         setLocal((unsigned)operand, value);
     }
+    void set(int operand, NodeIndex value)
+    {
+        setDirect(m_inlineStackTop->remapOperand(operand), value);
+    }
+    
+    NodeIndex injectLazyOperandPrediction(NodeIndex nodeIndex)
+    {
+        Node& node = m_graph[nodeIndex];
+        ASSERT(node.op() == GetLocal);
+        ASSERT(node.codeOrigin.bytecodeIndex == m_currentIndex);
+        PredictedType prediction = 
+            m_inlineStackTop->m_lazyOperands.prediction(
+                LazyOperandValueProfileKey(m_currentIndex, node.local()));
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Lazy operand [@%u, bc#%u, r%d] prediction: %s\n",
+                nodeIndex, m_currentIndex, node.local(), predictionToString(prediction));
+#endif
+        node.variableAccessData()->predict(prediction);
+        return nodeIndex;
+    }
 
     // Used in implementing get/set, above, where the operand is a local variable.
     NodeIndex getLocal(unsigned operand)
     {
 
     // 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;
-
+        NodeIndex nodeIndex = m_currentBlock->variablesAtTail.local(operand);
+        
         if (nodeIndex != NoNode) {
         if (nodeIndex != NoNode) {
-            Node& node = m_graph[nodeIndex];
-            if (node.op == GetLocal)
+            Node* nodePtr = &m_graph[nodeIndex];
+            if (nodePtr->op() == Flush) {
+                // Two possibilities: either the block wants the local to be live
+                // but has not loaded its value, or it has loaded its value, in
+                // which case we're done.
+                nodeIndex = nodePtr->child1().index();
+                Node& flushChild = m_graph[nodeIndex];
+                if (flushChild.op() == Phi) {
+                    VariableAccessData* variableAccessData = flushChild.variableAccessData();
+                    nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex));
+                    m_currentBlock->variablesAtTail.local(operand) = nodeIndex;
+                    return nodeIndex;
+                }
+                nodePtr = &flushChild;
+            }
+            
+            ASSERT(&m_graph[nodeIndex] == nodePtr);
+            ASSERT(nodePtr->op() != Flush);
+
+            if (m_graph.localIsCaptured(operand)) {
+                // We wish to use the same variable access data as the previous access,
+                // but for all other purposes we want to issue a load since for all we
+                // know, at this stage of compilation, the local has been clobbered.
+                
+                // Make sure we link to the Phi node, not to the GetLocal.
+                if (nodePtr->op() == GetLocal)
+                    nodeIndex = nodePtr->child1().index();
+                
+                return injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
+            }
+            
+            if (nodePtr->op() == GetLocal)
                 return nodeIndex;
                 return nodeIndex;
-            ASSERT(node.op == SetLocal);
-            return node.child1;
+            ASSERT(nodePtr->op() == SetLocal);
+            return nodePtr->child1().index();
         }
 
         // Check for reads of temporaries from prior blocks,
         // expand m_preservedVars to cover these.
         }
 
         // 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_preservedVars.set(operand);
+        
+        VariableAccessData* variableAccessData = newVariableAccessData(operand);
+        
+        NodeIndex phi = addToGraph(Phi, OpInfo(variableAccessData));
         m_localPhiStack.append(PhiStackEntry(m_currentBlock, phi, operand));
         m_localPhiStack.append(PhiStackEntry(m_currentBlock, phi, operand));
-        nodeIndex = addToGraph(GetLocal, OpInfo(operand), phi);
-        m_currentBlock->m_locals[operand].value = nodeIndex;
+        nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), phi));
+        m_currentBlock->variablesAtTail.local(operand) = nodeIndex;
+        
+        m_currentBlock->variablesAtHead.setLocalFirstTime(operand, nodeIndex);
+        
         return nodeIndex;
     }
     void setLocal(unsigned operand, NodeIndex value)
     {
         return nodeIndex;
     }
     void setLocal(unsigned operand, NodeIndex value)
     {
-        m_currentBlock->m_locals[operand].value = addToGraph(SetLocal, OpInfo(operand), value);
+        VariableAccessData* variableAccessData = newVariableAccessData(operand);
+        NodeIndex nodeIndex = addToGraph(SetLocal, OpInfo(variableAccessData), value);
+        m_currentBlock->variablesAtTail.local(operand) = nodeIndex;
+        
+        bool shouldFlush = m_graph.localIsCaptured(operand);
+        
+        if (!shouldFlush) {
+            // If this is in argument position, then it should be flushed.
+            for (InlineStackEntry* stack = m_inlineStackTop; ; stack = stack->m_caller) {
+                InlineCallFrame* inlineCallFrame = stack->m_inlineCallFrame;
+                if (!inlineCallFrame)
+                    break;
+                if (static_cast<int>(operand) >= inlineCallFrame->stackOffset - RegisterFile::CallFrameHeaderSize)
+                    continue;
+                if (static_cast<int>(operand) == inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset())
+                    continue;
+                if (operand < inlineCallFrame->stackOffset - RegisterFile::CallFrameHeaderSize - inlineCallFrame->arguments.size())
+                    continue;
+                int argument = operandToArgument(operand - inlineCallFrame->stackOffset);
+                stack->m_argumentPositions[argument]->addVariable(variableAccessData);
+                shouldFlush = true;
+                break;
+            }
+        }
+        
+        if (shouldFlush)
+            addToGraph(Flush, OpInfo(variableAccessData), nodeIndex);
     }
 
     // Used in implementing get/set, above, where the operand is an argument.
     NodeIndex getArgument(unsigned operand)
     {
     }
 
     // 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;
+        unsigned argument = operandToArgument(operand);
         ASSERT(argument < m_numArguments);
         ASSERT(argument < m_numArguments);
-
-        NodeIndex nodeIndex = m_currentBlock->m_arguments[argument].value;
+        
+        NodeIndex nodeIndex = m_currentBlock->variablesAtTail.argument(argument);
 
         if (nodeIndex != NoNode) {
 
         if (nodeIndex != NoNode) {
-            Node& node = m_graph[nodeIndex];
-            if (node.op == GetLocal)
+            Node* nodePtr = &m_graph[nodeIndex];
+            if (nodePtr->op() == Flush) {
+                // Two possibilities: either the block wants the local to be live
+                // but has not loaded its value, or it has loaded its value, in
+                // which case we're done.
+                nodeIndex = nodePtr->child1().index();
+                Node& flushChild = m_graph[nodeIndex];
+                if (flushChild.op() == Phi) {
+                    VariableAccessData* variableAccessData = flushChild.variableAccessData();
+                    nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex));
+                    m_currentBlock->variablesAtTail.local(operand) = nodeIndex;
+                    return nodeIndex;
+                }
+                nodePtr = &flushChild;
+            }
+            
+            ASSERT(&m_graph[nodeIndex] == nodePtr);
+            ASSERT(nodePtr->op() != Flush);
+            
+            if (nodePtr->op() == SetArgument) {
+                // We're getting an argument in the first basic block; link
+                // the GetLocal to the SetArgument.
+                ASSERT(nodePtr->local() == static_cast<VirtualRegister>(operand));
+                nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
+                m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
                 return nodeIndex;
                 return nodeIndex;
-            ASSERT(node.op == SetLocal);
-            return node.child1;
+            }
+            
+            if (m_graph.argumentIsCaptured(argument)) {
+                if (nodePtr->op() == GetLocal)
+                    nodeIndex = nodePtr->child1().index();
+                return injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex));
+            }
+            
+            if (nodePtr->op() == GetLocal)
+                return nodeIndex;
+            
+            ASSERT(nodePtr->op() == SetLocal);
+            return nodePtr->child1().index();
         }
         }
+        
+        VariableAccessData* variableAccessData = newVariableAccessData(operand);
 
 
-        NodeIndex phi = addToGraph(Phi);
+        NodeIndex phi = addToGraph(Phi, OpInfo(variableAccessData));
         m_argumentPhiStack.append(PhiStackEntry(m_currentBlock, phi, argument));
         m_argumentPhiStack.append(PhiStackEntry(m_currentBlock, phi, argument));
-        nodeIndex = addToGraph(GetLocal, OpInfo(operand), phi);
-        m_currentBlock->m_arguments[argument].value = nodeIndex;
+        nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), phi));
+        m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
+        
+        m_currentBlock->variablesAtHead.setArgumentFirstTime(argument, nodeIndex);
+        
         return nodeIndex;
     }
     void setArgument(int operand, NodeIndex value)
     {
         return nodeIndex;
     }
     void setArgument(int operand, NodeIndex value)
     {
-        unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
+        unsigned argument = operandToArgument(operand);
         ASSERT(argument < m_numArguments);
         ASSERT(argument < m_numArguments);
-
-        m_currentBlock->m_arguments[argument].value = addToGraph(SetLocal, OpInfo(operand), value);
+        
+        VariableAccessData* variableAccessData = newVariableAccessData(operand);
+        InlineStackEntry* stack = m_inlineStackTop;
+        while (stack->m_inlineCallFrame) // find the machine stack entry.
+            stack = stack->m_caller;
+        stack->m_argumentPositions[argument]->addVariable(variableAccessData);
+        NodeIndex nodeIndex = addToGraph(SetLocal, OpInfo(variableAccessData), value);
+        m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
+        // Always flush arguments.
+        addToGraph(Flush, OpInfo(variableAccessData), nodeIndex);
+    }
+    
+    VariableAccessData* flushArgument(int operand)
+    {
+        // FIXME: This should check if the same operand had already been flushed to
+        // some other local variable.
+        
+        operand = m_inlineStackTop->remapOperand(operand);
+        
+        ASSERT(operand < FirstConstantRegisterIndex);
+        
+        NodeIndex nodeIndex;
+        int index;
+        if (operandIsArgument(operand)) {
+            index = operandToArgument(operand);
+            nodeIndex = m_currentBlock->variablesAtTail.argument(index);
+        } else {
+            index = operand;
+            nodeIndex = m_currentBlock->variablesAtTail.local(index);
+            m_preservedVars.set(operand);
+        }
+        
+        if (nodeIndex != NoNode) {
+            Node& node = m_graph[nodeIndex];
+            switch (node.op()) {
+            case Flush:
+                nodeIndex = node.child1().index();
+                break;
+            case GetLocal:
+                nodeIndex = node.child1().index();
+                break;
+            default:
+                break;
+            }
+            
+            ASSERT(m_graph[nodeIndex].op() != Flush
+                   && m_graph[nodeIndex].op() != GetLocal);
+            
+            // Emit a Flush regardless of whether we already flushed it.
+            // This gives us guidance to see that the variable also needs to be flushed
+            // for arguments, even if it already had to be flushed for other reasons.
+            VariableAccessData* variableAccessData = node.variableAccessData();
+            addToGraph(Flush, OpInfo(variableAccessData), nodeIndex);
+            return variableAccessData;
+        }
+        
+        VariableAccessData* variableAccessData = newVariableAccessData(operand);
+        NodeIndex phi = addToGraph(Phi, OpInfo(variableAccessData));
+        nodeIndex = addToGraph(Flush, OpInfo(variableAccessData), phi);
+        if (operandIsArgument(operand)) {
+            m_argumentPhiStack.append(PhiStackEntry(m_currentBlock, phi, index));
+            m_currentBlock->variablesAtTail.argument(index) = nodeIndex;
+            m_currentBlock->variablesAtHead.setArgumentFirstTime(index, nodeIndex);
+        } else {
+            m_localPhiStack.append(PhiStackEntry(m_currentBlock, phi, index));
+            m_currentBlock->variablesAtTail.local(index) = nodeIndex;
+            m_currentBlock->variablesAtHead.setLocalFirstTime(index, nodeIndex);
+        }
+        return variableAccessData;
     }
 
     // Get an operand, and perform a ToInt32/ToNumber conversion on it.
     NodeIndex getToInt32(int operand)
     {
     }
 
     // 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));
     }
         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)
 
     // Perform an ES5 ToInt32 operation - returns a node of type NodeResultInt32.
     NodeIndex toInt32(NodeIndex index)
@@ -203,86 +416,32 @@ private:
         if (node.hasInt32Result())
             return 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;
-        }
+        if (node.op() == UInt32ToNumber)
+            return node.child1().index();
 
         // Check for numeric constants boxed as JSValues.
 
         // Check for numeric constants boxed as JSValues.
-        if (node.op == JSConstant) {
+        if (node.op() == JSConstant) {
             JSValue v = valueOfJSConstant(index);
             if (v.isInt32())
             JSValue v = valueOfJSConstant(index);
             if (v.isInt32())
-                return getInt32Constant(v.asInt32(), node.constantNumber());
+                return getJSConstant(node.constantNumber());
             if (v.isNumber())
             if (v.isNumber())
-                return getInt32Constant(JSC::toInt32(v.uncheckedGetNumber()), node.constantNumber());
+                return getJSConstantForValue(JSValue(JSC::toInt32(v.asNumber())));
         }
 
         return addToGraph(ValueToInt32, index);
     }
 
         }
 
         return addToGraph(ValueToInt32, index);
     }
 
-    // Perform an ES5 ToNumber operation - returns a node of type NodeResultDouble.
-    NodeIndex toNumber(NodeIndex index)
+    NodeIndex getJSConstantForValue(JSValue constantValue)
     {
     {
-        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);
+        unsigned constantIndex = m_codeBlock->addOrFindConstant(constantValue);
+        if (constantIndex >= m_constants.size())
+            m_constants.append(ConstantRecord());
+        
+        ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
+        
+        return getJSConstant(constantIndex);
     }
 
     }
 
-
-    // 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;
     NodeIndex getJSConstant(unsigned constant)
     {
         NodeIndex index = m_constants[constant].asJSValue;
@@ -297,44 +456,34 @@ private:
     // Helper functions to get/set the this value.
     NodeIndex getThis()
     {
     // Helper functions to get/set the this value.
     NodeIndex getThis()
     {
-        return getArgument(m_codeBlock->thisRegister());
+        return get(m_inlineStackTop->m_codeBlock->thisRegister());
     }
     void setThis(NodeIndex value)
     {
     }
     void setThis(NodeIndex value)
     {
-        setArgument(m_codeBlock->thisRegister(), value);
+        set(m_inlineStackTop->m_codeBlock->thisRegister(), value);
     }
 
     // Convenience methods for checking nodes for constants.
     }
 
     // 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)
     {
     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();
+        return m_graph[index].op() == JSConstant;
     }
     }
-    double valueOfDoubleConstant(NodeIndex index)
+    bool isInt32Constant(NodeIndex nodeIndex)
     {
     {
-        ASSERT(isDoubleConstant(index));
-        return m_graph[index].numericConstant();
+        return isJSConstant(nodeIndex) && valueOfJSConstant(nodeIndex).isInt32();
     }
     }
+    // Convenience methods for getting constant values.
     JSValue valueOfJSConstant(NodeIndex index)
     {
         ASSERT(isJSConstant(index));
         return m_codeBlock->getConstant(FirstConstantRegisterIndex + m_graph[index].constantNumber());
     }
     JSValue valueOfJSConstant(NodeIndex index)
     {
         ASSERT(isJSConstant(index));
         return m_codeBlock->getConstant(FirstConstantRegisterIndex + m_graph[index].constantNumber());
     }
-
+    int32_t valueOfInt32Constant(NodeIndex nodeIndex)
+    {
+        ASSERT(isInt32Constant(nodeIndex));
+        return valueOfJSConstant(nodeIndex).asInt32();
+    }
+    
     // This method returns a JSConstant with the value 'undefined'.
     NodeIndex constantUndefined()
     {
     // This method returns a JSConstant with the value 'undefined'.
     NodeIndex constantUndefined()
     {
@@ -395,7 +544,7 @@ private:
             for (m_constant1 = 0; m_constant1 < numberOfConstants; ++m_constant1) {
                 JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1);
                 if (testMe.isInt32() && testMe.asInt32() == 1)
             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);
+                    return getJSConstant(m_constant1);
             }
 
             // Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constants.
             }
 
             // Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constants.
@@ -408,76 +557,306 @@ private:
         // 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);
         // 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);
+        return getJSConstant(m_constant1);
     }
     }
+    
+    // This method returns a DoubleConstant with the value NaN.
+    NodeIndex constantNaN()
+    {
+        JSValue nan = jsNaN();
+        
+        // Has m_constantNaN been set up yet?
+        if (m_constantNaN == UINT_MAX) {
+            // Search the constant pool for the value NaN, if we find it, we can just reuse this!
+            unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
+            for (m_constantNaN = 0; m_constantNaN < numberOfConstants; ++m_constantNaN) {
+                JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN);
+                if (JSValue::encode(testMe) == JSValue::encode(nan))
+                    return getJSConstant(m_constantNaN);
+            }
 
 
+            // Add the value nan to the CodeBlock's constants, and add a corresponding slot in m_constants.
+            ASSERT(m_constants.size() == numberOfConstants);
+            m_codeBlock->addConstant(nan);
+            m_constants.append(ConstantRecord());
+            ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
+        }
+
+        // m_constantNaN must refer to an entry in the CodeBlock's constant pool that has the value nan.
+        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN).isDouble());
+        ASSERT(isnan(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN).asDouble()));
+        return getJSConstant(m_constantNaN);
+    }
+    
+    NodeIndex cellConstant(JSCell* cell)
+    {
+        HashMap<JSCell*, NodeIndex>::AddResult result = m_cellConstantNodes.add(cell, NoNode);
+        if (result.isNewEntry)
+            result.iterator->second = addToGraph(WeakJSConstant, OpInfo(cell));
+        
+        return result.iterator->second;
+    }
+    
+    CodeOrigin currentCodeOrigin()
+    {
+        return CodeOrigin(m_currentIndex, m_inlineStackTop->m_inlineCallFrame, m_currentProfilingIndex - m_currentIndex);
+    }
 
     // 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();
 
     // 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));
+        m_graph.append(Node(op, currentCodeOrigin(), child1, child2, child3));
+        ASSERT(op != Phi);
+        m_currentBlock->append(resultIndex);
 
 
-        if (op & NodeMustGenerate)
+        if (defaultFlags(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.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));
+        m_graph.append(Node(op, currentCodeOrigin(), info, child1, child2, child3));
+        if (op == Phi)
+            m_currentBlock->phis.append(resultIndex);
+        else
+            m_currentBlock->append(resultIndex);
 
 
-        if (op & NodeMustGenerate)
+        if (defaultFlags(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.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));
+        m_graph.append(Node(op, currentCodeOrigin(), info1, info2, child1, child2, child3));
+        ASSERT(op != Phi);
+        m_currentBlock->append(resultIndex);
 
 
-        if (op & NodeMustGenerate)
+        if (defaultFlags(op) & NodeMustGenerate)
             m_graph.ref(resultIndex);
         return resultIndex;
     }
             m_graph.ref(resultIndex);
         return resultIndex;
     }
-
-    void predictArray(NodeIndex nodeIndex)
+    
+    NodeIndex addToGraph(Node::VarArgTag, NodeType op, OpInfo info1, OpInfo info2)
     {
     {
-        Node* nodePtr = &m_graph[nodeIndex];
-
-        if (nodePtr->op == GetLocal)
-            m_graph.predict(nodePtr->local(), PredictArray);
+        NodeIndex resultIndex = (NodeIndex)m_graph.size();
+        m_graph.append(Node(Node::VarArg, op, currentCodeOrigin(), info1, info2, m_graph.m_varArgChildren.size() - m_numPassedVarArgs, m_numPassedVarArgs));
+        ASSERT(op != Phi);
+        m_currentBlock->append(resultIndex);
+        
+        m_numPassedVarArgs = 0;
+        
+        if (defaultFlags(op) & NodeMustGenerate)
+            m_graph.ref(resultIndex);
+        return resultIndex;
     }
 
     }
 
-    void predictInt32(NodeIndex nodeIndex)
+    NodeIndex insertPhiNode(OpInfo info, BasicBlock* block)
     {
     {
-        Node* nodePtr = &m_graph[nodeIndex];
+        NodeIndex resultIndex = (NodeIndex)m_graph.size();
+        m_graph.append(Node(Phi, currentCodeOrigin(), info));
+        block->phis.append(resultIndex);
 
 
-        if (nodePtr->op == ValueToNumber)
-            nodePtr = &m_graph[nodePtr->child1];
+        return resultIndex;
+    }
 
 
-        if (nodePtr->op == ValueToInt32)
-            nodePtr = &m_graph[nodePtr->child1];
+    void addVarArgChild(NodeIndex child)
+    {
+        m_graph.m_varArgChildren.append(Edge(child));
+        m_numPassedVarArgs++;
+    }
+    
+    NodeIndex addCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op)
+    {
+        Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
 
 
-        if (nodePtr->op == NumberToInt32)
-            nodePtr = &m_graph[nodePtr->child1];
+        PredictedType prediction = PredictNone;
+        if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
+            m_currentProfilingIndex = m_currentIndex + OPCODE_LENGTH(op_call);
+            prediction = getPrediction();
+        }
+        
+        addVarArgChild(get(currentInstruction[1].u.operand));
+        int argCount = currentInstruction[2].u.operand;
+        if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
+            m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
+
+        int registerOffset = currentInstruction[3].u.operand;
+        int dummyThisArgument = op == Call ? 0 : 1;
+        for (int i = 0 + dummyThisArgument; i < argCount; ++i)
+            addVarArgChild(get(registerOffset + argumentToOperand(i)));
+
+        NodeIndex call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction));
+        if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
+            set(putInstruction[1].u.operand, call);
+        return call;
+    }
+    
+    PredictedType getPredictionWithoutOSRExit(NodeIndex nodeIndex, unsigned bytecodeIndex)
+    {
+        UNUSED_PARAM(nodeIndex);
+        
+        PredictedType prediction = m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(bytecodeIndex);
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
+#endif
+        
+        return prediction;
+    }
 
 
-        if (nodePtr->op == GetLocal)
-            m_graph.predict(nodePtr->local(), PredictInt32);
+    PredictedType getPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
+    {
+        PredictedType prediction = getPredictionWithoutOSRExit(nodeIndex, bytecodeIndex);
+        
+        if (prediction == PredictNone) {
+            // We have no information about what values this node generates. Give up
+            // on executing this code, since we're likely to do more damage than good.
+            addToGraph(ForceOSRExit);
+        }
+        
+        return prediction;
+    }
+    
+    PredictedType getPredictionWithoutOSRExit()
+    {
+        return getPredictionWithoutOSRExit(m_graph.size(), m_currentProfilingIndex);
+    }
+    
+    PredictedType getPrediction()
+    {
+        return getPrediction(m_graph.size(), m_currentProfilingIndex);
     }
 
     }
 
+    NodeIndex makeSafe(NodeIndex nodeIndex)
+    {
+        Node& node = m_graph[nodeIndex];
+        
+        bool likelyToTakeSlowCase;
+        if (!isX86() && node.op() == ArithMod)
+            likelyToTakeSlowCase = false;
+        else
+            likelyToTakeSlowCase = m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex);
+        
+        if (!likelyToTakeSlowCase
+            && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)
+            && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
+            return nodeIndex;
+        
+        switch (m_graph[nodeIndex].op()) {
+        case UInt32ToNumber:
+        case ArithAdd:
+        case ArithSub:
+        case ArithNegate:
+        case ValueAdd:
+        case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double.
+            m_graph[nodeIndex].mergeFlags(NodeMayOverflow);
+            break;
+            
+        case ArithMul:
+            if (m_inlineStackTop->m_profiledBlock->likelyToTakeDeepestSlowCase(m_currentIndex)
+                || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)) {
+#if DFG_ENABLE(DEBUG_VERBOSE)
+                dataLog("Making ArithMul @%u take deepest slow case.\n", nodeIndex);
+#endif
+                m_graph[nodeIndex].mergeFlags(NodeMayOverflow | NodeMayNegZero);
+            } else if (m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
+                       || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)) {
+#if DFG_ENABLE(DEBUG_VERBOSE)
+                dataLog("Making ArithMul @%u take faster slow case.\n", nodeIndex);
+#endif
+                m_graph[nodeIndex].mergeFlags(NodeMayNegZero);
+            }
+            break;
+            
+        default:
+            ASSERT_NOT_REACHED();
+            break;
+        }
+        
+        return nodeIndex;
+    }
+    
+    NodeIndex makeDivSafe(NodeIndex nodeIndex)
+    {
+        ASSERT(m_graph[nodeIndex].op() == ArithDiv);
+        
+        // The main slow case counter for op_div in the old JIT counts only when
+        // the operands are not numbers. We don't care about that since we already
+        // have speculations in place that take care of that separately. We only
+        // care about when the outcome of the division is not an integer, which
+        // is what the special fast case counter tells us.
+        
+        if (!m_inlineStackTop->m_profiledBlock->likelyToTakeSpecialFastCase(m_currentIndex)
+            && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)
+            && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
+            return nodeIndex;
+        
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Making %s @%u safe at bc#%u because special fast-case counter is at %u and exit profiles say %d, %d\n", Graph::opName(m_graph[nodeIndex].op()), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->specialFastCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero));
+#endif
+        
+        // FIXME: It might be possible to make this more granular. The DFG certainly can
+        // distinguish between negative zero and overflow in its exit profiles.
+        m_graph[nodeIndex].mergeFlags(NodeMayOverflow | NodeMayNegZero);
+        
+        return nodeIndex;
+    }
+    
+    bool willNeedFlush(StructureStubInfo& stubInfo)
+    {
+        PolymorphicAccessStructureList* list;
+        int listSize;
+        switch (stubInfo.accessType) {
+        case access_get_by_id_self_list:
+            list = stubInfo.u.getByIdSelfList.structureList;
+            listSize = stubInfo.u.getByIdSelfList.listSize;
+            break;
+        case access_get_by_id_proto_list:
+            list = stubInfo.u.getByIdProtoList.structureList;
+            listSize = stubInfo.u.getByIdProtoList.listSize;
+            break;
+        default:
+            return false;
+        }
+        for (int i = 0; i < listSize; ++i) {
+            if (!list->list[i].isDirect)
+                return true;
+        }
+        return false;
+    }
+    
+    bool structureChainIsStillValid(bool direct, Structure* previousStructure, StructureChain* chain)
+    {
+        if (direct)
+            return true;
+        
+        if (!previousStructure->storedPrototype().isNull() && previousStructure->storedPrototype().asCell()->structure() != chain->head()->get())
+            return false;
+        
+        for (WriteBarrier<Structure>* it = chain->head(); *it; ++it) {
+            if (!(*it)->storedPrototype().isNull() && (*it)->storedPrototype().asCell()->structure() != it[1].get())
+                return false;
+        }
+        
+        return true;
+    }
+    
+    void buildOperandMapsIfNecessary();
+    
     JSGlobalData* m_globalData;
     CodeBlock* m_codeBlock;
     JSGlobalData* m_globalData;
     CodeBlock* m_codeBlock;
+    CodeBlock* m_profiledBlock;
     Graph& m_graph;
 
     // The current block being generated.
     BasicBlock* m_currentBlock;
     // The bytecode index of the current instruction being generated.
     unsigned m_currentIndex;
     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;
+    // The bytecode index of the value profile of the current instruction being generated.
+    unsigned m_currentProfilingIndex;
 
     // 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
 
     // 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
@@ -486,7 +865,10 @@ private:
     // constant pool, as necessary.
     unsigned m_constantUndefined;
     unsigned m_constantNull;
     // constant pool, as necessary.
     unsigned m_constantUndefined;
     unsigned m_constantNull;
+    unsigned m_constantNaN;
     unsigned m_constant1;
     unsigned m_constant1;
+    HashMap<JSCell*, unsigned> m_cellConstants;
+    HashMap<JSCell*, NodeIndex> m_cellConstantNodes;
 
     // 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.
 
     // 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.
@@ -503,149 +885,746 @@ private:
         NodeIndex asJSValue;
     };
 
         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;
+    // 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 set of registers we need to preserve across BasicBlock boundaries;
+    // typically equal to the set of vars, but we expand this to cover all
+    // temporaries that persist across blocks (dues to ?:, &&, ||, etc).
+    BitVector m_preservedVars;
+    // The number of slots (in units of sizeof(Register)) that we need to
+    // preallocate for calls emanating from this frame. This includes the
+    // size of the CallFrame, only if this is not a leaf function.  (I.e.
+    // this is 0 if and only if this function is a leaf.)
+    unsigned m_parameterSlots;
+    // The number of var args passed to the next var arg node.
+    unsigned m_numPassedVarArgs;
+    // The index in the global resolve info.
+    unsigned m_globalResolveNumber;
+
+    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;
+    
+    struct InlineStackEntry {
+        ByteCodeParser* m_byteCodeParser;
+        
+        CodeBlock* m_codeBlock;
+        CodeBlock* m_profiledBlock;
+        InlineCallFrame* m_inlineCallFrame;
+        VirtualRegister m_calleeVR; // absolute virtual register, not relative to call frame
+        
+        ScriptExecutable* executable() { return m_codeBlock->ownerExecutable(); }
+        
+        QueryableExitProfile m_exitProfile;
+        
+        // Remapping of identifier and constant numbers from the code block being
+        // inlined (inline callee) to the code block that we're inlining into
+        // (the machine code block, which is the transitive, though not necessarily
+        // direct, caller).
+        Vector<unsigned> m_identifierRemap;
+        Vector<unsigned> m_constantRemap;
+        
+        // Blocks introduced by this code block, which need successor linking.
+        // May include up to one basic block that includes the continuation after
+        // the callsite in the caller. These must be appended in the order that they
+        // are created, but their bytecodeBegin values need not be in order as they
+        // are ignored.
+        Vector<UnlinkedBlock> m_unlinkedBlocks;
+        
+        // Potential block linking targets. Must be sorted by bytecodeBegin, and
+        // cannot have two blocks that have the same bytecodeBegin. For this very
+        // reason, this is not equivalent to 
+        Vector<BlockIndex> m_blockLinkingTargets;
+        
+        // If the callsite's basic block was split into two, then this will be
+        // the head of the callsite block. It needs its successors linked to the
+        // m_unlinkedBlocks, but not the other way around: there's no way for
+        // any blocks in m_unlinkedBlocks to jump back into this block.
+        BlockIndex m_callsiteBlockHead;
+        
+        // Does the callsite block head need linking? This is typically true
+        // but will be false for the machine code block's inline stack entry
+        // (since that one is not inlined) and for cases where an inline callee
+        // did the linking for us.
+        bool m_callsiteBlockHeadNeedsLinking;
+        
+        VirtualRegister m_returnValue;
+        
+        // Predictions about variable types collected from the profiled code block,
+        // which are based on OSR exit profiles that past DFG compilatins of this
+        // code block had gathered.
+        LazyOperandValueProfileParser m_lazyOperands;
+        
+        // Did we see any returns? We need to handle the (uncommon but necessary)
+        // case where a procedure that does not return was inlined.
+        bool m_didReturn;
+        
+        // Did we have any early returns?
+        bool m_didEarlyReturn;
+        
+        // Pointers to the argument position trackers for this slice of code.
+        Vector<ArgumentPosition*> m_argumentPositions;
+        
+        InlineStackEntry* m_caller;
+        
+        InlineStackEntry(ByteCodeParser*, CodeBlock*, CodeBlock* profiledBlock, BlockIndex callsiteBlockHead, VirtualRegister calleeVR, JSFunction* callee, VirtualRegister returnValueVR, VirtualRegister inlineCallFrameStart, CodeSpecializationKind);
+        
+        ~InlineStackEntry()
+        {
+            m_byteCodeParser->m_inlineStackTop = m_caller;
+        }
+        
+        int remapOperand(int operand) const
+        {
+            if (!m_inlineCallFrame)
+                return operand;
+            
+            if (operand >= FirstConstantRegisterIndex) {
+                int result = m_constantRemap[operand - FirstConstantRegisterIndex];
+                ASSERT(result >= FirstConstantRegisterIndex);
+                return result;
+            }
+            
+            return operand + m_inlineCallFrame->stackOffset;
+        }
+    };
+    
+    InlineStackEntry* m_inlineStackTop;
+
+    // Have we built operand maps? We initialize them lazily, and only when doing
+    // inlining.
+    bool m_haveBuiltOperandMaps;
+    // Mapping between identifier names and numbers.
+    IdentifierMap m_identifierMap;
+    // Mapping between values and constant numbers.
+    JSValueMap m_jsValueMap;
+    // Index of the empty value, or UINT_MAX if there is no mapping. This is a horrible
+    // work-around for the fact that JSValueMap can't handle "empty" values.
+    unsigned m_emptyJSValueIndex;
+    
+    // Cache of code blocks that we've generated bytecode for.
+    ByteCodeCache<canInlineFunctionFor> m_codeBlockCache;
+};
+
+#define NEXT_OPCODE(name) \
+    m_currentIndex += OPCODE_LENGTH(name); \
+    continue
+
+#define LAST_OPCODE(name) \
+    m_currentIndex += OPCODE_LENGTH(name); \
+    return shouldContinueParsing
+
+
+void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op, CodeSpecializationKind kind)
+{
+    ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
+    
+    NodeIndex callTarget = get(currentInstruction[1].u.operand);
+    enum { ConstantFunction, LinkedFunction, UnknownFunction } callType;
+            
+    CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
+        m_inlineStackTop->m_profiledBlock, m_currentIndex);
+    
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("For call at @%lu bc#%u: ", m_graph.size(), m_currentIndex);
+    if (callLinkStatus.isSet()) {
+        if (callLinkStatus.couldTakeSlowPath())
+            dataLog("could take slow path, ");
+        dataLog("target = %p\n", callLinkStatus.callTarget());
+    } else
+        dataLog("not set.\n");
+#endif
+    
+    if (m_graph.isFunctionConstant(callTarget))
+        callType = ConstantFunction;
+    else if (callLinkStatus.isSet() && !callLinkStatus.couldTakeSlowPath()
+             && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
+        callType = LinkedFunction;
+    else
+        callType = UnknownFunction;
+    if (callType != UnknownFunction) {
+        int argumentCountIncludingThis = currentInstruction[2].u.operand;
+        int registerOffset = currentInstruction[3].u.operand;
+
+        // Do we have a result?
+        bool usesResult = false;
+        int resultOperand = 0; // make compiler happy
+        unsigned nextOffset = m_currentIndex + OPCODE_LENGTH(op_call);
+        Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
+        PredictedType prediction = PredictNone;
+        if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
+            resultOperand = putInstruction[1].u.operand;
+            usesResult = true;
+            m_currentProfilingIndex = nextOffset;
+            prediction = getPrediction();
+            nextOffset += OPCODE_LENGTH(op_call_put_result);
+        }
+        JSFunction* expectedFunction;
+        Intrinsic intrinsic;
+        bool certainAboutExpectedFunction;
+        if (callType == ConstantFunction) {
+            expectedFunction = m_graph.valueOfFunctionConstant(callTarget);
+            intrinsic = expectedFunction->executable()->intrinsicFor(kind);
+            certainAboutExpectedFunction = true;
+        } else {
+            ASSERT(callType == LinkedFunction);
+            expectedFunction = callLinkStatus.callTarget();
+            intrinsic = expectedFunction->executable()->intrinsicFor(kind);
+            certainAboutExpectedFunction = false;
+        }
+                
+        if (intrinsic != NoIntrinsic) {
+            if (!certainAboutExpectedFunction)
+                emitFunctionCheck(expectedFunction, callTarget, registerOffset, kind);
+            
+            if (handleIntrinsic(usesResult, resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction)) {
+                if (!certainAboutExpectedFunction) {
+                    // Need to keep the call target alive for OSR. We could easily optimize this out if we wanted
+                    // to, since at this point we know that the call target is a constant. It's just that OSR isn't
+                    // smart enough to figure that out, since it doesn't understand CheckFunction.
+                    addToGraph(Phantom, callTarget);
+                }
+                
+                return;
+            }
+        } else if (handleInlining(usesResult, currentInstruction[1].u.operand, callTarget, resultOperand, certainAboutExpectedFunction, expectedFunction, registerOffset, argumentCountIncludingThis, nextOffset, kind))
+            return;
+    }
+            
+    addCall(interpreter, currentInstruction, op);
+}
+
+void ByteCodeParser::emitFunctionCheck(JSFunction* expectedFunction, NodeIndex callTarget, int registerOffset, CodeSpecializationKind kind)
+{
+    NodeIndex thisArgument;
+    if (kind == CodeForCall)
+        thisArgument = get(registerOffset + argumentToOperand(0));
+    else
+        thisArgument = NoNode;
+    addToGraph(CheckFunction, OpInfo(expectedFunction), callTarget, thisArgument);
+}
+
+bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex callTargetNodeIndex, int resultOperand, bool certainAboutExpectedFunction, JSFunction* expectedFunction, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind kind)
+{
+    // First, the really simple checks: do we have an actual JS function?
+    if (!expectedFunction)
+        return false;
+    if (expectedFunction->isHostFunction())
+        return false;
+    
+    FunctionExecutable* executable = expectedFunction->jsExecutable();
+    
+    // Does the number of arguments we're passing match the arity of the target? We could
+    // inline arity check failures, but for simplicity we currently don't.
+    if (static_cast<int>(executable->parameterCount()) + 1 != argumentCountIncludingThis)
+        return false;
+    
+    // Have we exceeded inline stack depth, or are we trying to inline a recursive call?
+    // If either of these are detected, then don't inline.
+    unsigned depth = 0;
+    for (InlineStackEntry* entry = m_inlineStackTop; entry; entry = entry->m_caller) {
+        ++depth;
+        if (depth >= Options::maximumInliningDepth)
+            return false; // Depth exceeded.
+        
+        if (entry->executable() == executable)
+            return false; // Recursion detected.
+    }
+    
+    // Does the code block's size match the heuristics/requirements for being
+    // an inline candidate?
+    CodeBlock* profiledBlock = executable->profiledCodeBlockFor(kind);
+    if (!mightInlineFunctionFor(profiledBlock, kind))
+        return false;
+    
+    // If we get here then it looks like we should definitely inline this code. Proceed
+    // with parsing the code to get bytecode, so that we can then parse the bytecode.
+    // Note that if LLInt is enabled, the bytecode will always be available. Also note
+    // that if LLInt is enabled, we may inline a code block that has never been JITted
+    // before!
+    CodeBlock* codeBlock = m_codeBlockCache.get(CodeBlockKey(executable, kind), expectedFunction->scope());
+    if (!codeBlock)
+        return false;
+    
+    ASSERT(canInlineFunctionFor(codeBlock, kind));
+
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("Inlining executable %p.\n", executable);
+#endif
+    
+    // Now we know without a doubt that we are committed to inlining. So begin the process
+    // by checking the callee (if necessary) and making sure that arguments and the callee
+    // are flushed.
+    if (!certainAboutExpectedFunction)
+        emitFunctionCheck(expectedFunction, callTargetNodeIndex, registerOffset, kind);
+    
+    // FIXME: Don't flush constants!
+    
+    Vector<VariableAccessData*, 8> arguments;
+    for (int i = 1; i < argumentCountIncludingThis; ++i)
+        arguments.append(flushArgument(registerOffset + argumentToOperand(i)));
+    
+    int inlineCallFrameStart = m_inlineStackTop->remapOperand(registerOffset) - RegisterFile::CallFrameHeaderSize;
+    
+    // Make sure that the area used by the call frame is reserved.
+    for (int arg = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > inlineCallFrameStart;)
+        m_preservedVars.set(arg);
+    
+    // Make sure that we have enough locals.
+    unsigned newNumLocals = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
+    if (newNumLocals > m_numLocals) {
+        m_numLocals = newNumLocals;
+        for (size_t i = 0; i < m_graph.m_blocks.size(); ++i)
+            m_graph.m_blocks[i]->ensureLocals(newNumLocals);
+    }
+
+    InlineStackEntry inlineStackEntry(this, codeBlock, profiledBlock, m_graph.m_blocks.size() - 1, (VirtualRegister)m_inlineStackTop->remapOperand(callTarget), expectedFunction, (VirtualRegister)m_inlineStackTop->remapOperand(usesResult ? resultOperand : InvalidVirtualRegister), (VirtualRegister)inlineCallFrameStart, kind);
+    
+    // Link up the argument variable access datas to their argument positions.
+    for (int i = 1; i < argumentCountIncludingThis; ++i)
+        inlineStackEntry.m_argumentPositions[i]->addVariable(arguments[i - 1]);
+    
+    // This is where the actual inlining really happens.
+    unsigned oldIndex = m_currentIndex;
+    unsigned oldProfilingIndex = m_currentProfilingIndex;
+    m_currentIndex = 0;
+    m_currentProfilingIndex = 0;
+
+    addToGraph(InlineStart);
+    
+    parseCodeBlock();
+    
+    m_currentIndex = oldIndex;
+    m_currentProfilingIndex = oldProfilingIndex;
+    
+    // If the inlined code created some new basic blocks, then we have linking to do.
+    if (inlineStackEntry.m_callsiteBlockHead != m_graph.m_blocks.size() - 1) {
+        
+        ASSERT(!inlineStackEntry.m_unlinkedBlocks.isEmpty());
+        if (inlineStackEntry.m_callsiteBlockHeadNeedsLinking)
+            linkBlock(m_graph.m_blocks[inlineStackEntry.m_callsiteBlockHead].get(), inlineStackEntry.m_blockLinkingTargets);
+        else
+            ASSERT(m_graph.m_blocks[inlineStackEntry.m_callsiteBlockHead]->isLinked);
+        
+        // It's possible that the callsite block head is not owned by the caller.
+        if (!inlineStackEntry.m_caller->m_unlinkedBlocks.isEmpty()) {
+            // It's definitely owned by the caller, because the caller created new blocks.
+            // Assert that this all adds up.
+            ASSERT(inlineStackEntry.m_caller->m_unlinkedBlocks.last().m_blockIndex == inlineStackEntry.m_callsiteBlockHead);
+            ASSERT(inlineStackEntry.m_caller->m_unlinkedBlocks.last().m_needsNormalLinking);
+            inlineStackEntry.m_caller->m_unlinkedBlocks.last().m_needsNormalLinking = false;
+        } else {
+            // It's definitely not owned by the caller. Tell the caller that he does not
+            // need to link his callsite block head, because we did it for him.
+            ASSERT(inlineStackEntry.m_caller->m_callsiteBlockHeadNeedsLinking);
+            ASSERT(inlineStackEntry.m_caller->m_callsiteBlockHead == inlineStackEntry.m_callsiteBlockHead);
+            inlineStackEntry.m_caller->m_callsiteBlockHeadNeedsLinking = false;
+        }
+        
+        linkBlocks(inlineStackEntry.m_unlinkedBlocks, inlineStackEntry.m_blockLinkingTargets);
+    } else
+        ASSERT(inlineStackEntry.m_unlinkedBlocks.isEmpty());
+    
+    // If there was a return, but no early returns, then we're done. We allow parsing of
+    // the caller to continue in whatever basic block we're in right now.
+    if (!inlineStackEntry.m_didEarlyReturn && inlineStackEntry.m_didReturn) {
+        BasicBlock* lastBlock = m_graph.m_blocks.last().get();
+        ASSERT(lastBlock->isEmpty() || !m_graph.last().isTerminal());
+        
+        // If we created new blocks then the last block needs linking, but in the
+        // caller. It doesn't need to be linked to, but it needs outgoing links.
+        if (!inlineStackEntry.m_unlinkedBlocks.isEmpty()) {
+#if DFG_ENABLE(DEBUG_VERBOSE)
+            dataLog("Reascribing bytecode index of block %p from bc#%u to bc#%u (inline return case).\n", lastBlock, lastBlock->bytecodeBegin, m_currentIndex);
+#endif
+            // For debugging purposes, set the bytecodeBegin. Note that this doesn't matter
+            // for release builds because this block will never serve as a potential target
+            // in the linker's binary search.
+            lastBlock->bytecodeBegin = m_currentIndex;
+            m_inlineStackTop->m_caller->m_unlinkedBlocks.append(UnlinkedBlock(m_graph.m_blocks.size() - 1));
+        }
+        
+        m_currentBlock = m_graph.m_blocks.last().get();
+
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Done inlining executable %p, continuing code generation at epilogue.\n", executable);
+#endif
+        return true;
+    }
+    
+    // If we get to this point then all blocks must end in some sort of terminals.
+    ASSERT(m_graph.last().isTerminal());
+    
+    // Link the early returns to the basic block we're about to create.
+    for (size_t i = 0; i < inlineStackEntry.m_unlinkedBlocks.size(); ++i) {
+        if (!inlineStackEntry.m_unlinkedBlocks[i].m_needsEarlyReturnLinking)
+            continue;
+        BasicBlock* block = m_graph.m_blocks[inlineStackEntry.m_unlinkedBlocks[i].m_blockIndex].get();
+        ASSERT(!block->isLinked);
+        Node& node = m_graph[block->last()];
+        ASSERT(node.op() == Jump);
+        ASSERT(node.takenBlockIndex() == NoBlock);
+        node.setTakenBlockIndex(m_graph.m_blocks.size());
+        inlineStackEntry.m_unlinkedBlocks[i].m_needsEarlyReturnLinking = false;
+#if !ASSERT_DISABLED
+        block->isLinked = true;
+#endif
+    }
+    
+    // Need to create a new basic block for the continuation at the caller.
+    OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(nextOffset, m_numArguments, m_numLocals));
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("Creating inline epilogue basic block %p, #%zu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame));
+#endif
+    m_currentBlock = block.get();
+    ASSERT(m_inlineStackTop->m_caller->m_blockLinkingTargets.isEmpty() || m_graph.m_blocks[m_inlineStackTop->m_caller->m_blockLinkingTargets.last()]->bytecodeBegin < nextOffset);
+    m_inlineStackTop->m_caller->m_unlinkedBlocks.append(UnlinkedBlock(m_graph.m_blocks.size()));
+    m_inlineStackTop->m_caller->m_blockLinkingTargets.append(m_graph.m_blocks.size());
+    m_graph.m_blocks.append(block.release());
+    prepareToParseBlock();
+    
+    // At this point we return and continue to generate code for the caller, but
+    // in the new basic block.
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("Done inlining executable %p, continuing code generation in new block.\n", executable);
+#endif
+    return true;
+}
+
+void ByteCodeParser::setIntrinsicResult(bool usesResult, int resultOperand, NodeIndex nodeIndex)
+{
+    if (!usesResult)
+        return;
+    set(resultOperand, nodeIndex);
+}
+
+bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis)
+{
+    if (argumentCountIncludingThis == 1) { // Math.min()
+        setIntrinsicResult(usesResult, resultOperand, constantNaN());
+        return true;
+    }
+     
+    if (argumentCountIncludingThis == 2) { // Math.min(x)
+        // FIXME: what we'd really like is a ValueToNumber, except we don't support that right now. Oh well.
+        NodeIndex result = get(registerOffset + argumentToOperand(1));
+        addToGraph(CheckNumber, result);
+        setIntrinsicResult(usesResult, resultOperand, result);
+        return true;
+    }
+    
+    if (argumentCountIncludingThis == 3) { // Math.min(x, y)
+        setIntrinsicResult(usesResult, resultOperand, addToGraph(op, get(registerOffset + argumentToOperand(1)), get(registerOffset + argumentToOperand(2))));
+        return true;
+    }
+    
+    // Don't handle >=3 arguments for now.
+    return false;
+}
+
+// FIXME: We dead-code-eliminate unused Math intrinsics, but that's invalid because
+// they need to perform the ToNumber conversion, which can have side-effects.
+bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, PredictedType prediction)
+{
+    switch (intrinsic) {
+    case AbsIntrinsic: {
+        if (argumentCountIncludingThis == 1) { // Math.abs()
+            setIntrinsicResult(usesResult, resultOperand, constantNaN());
+            return true;
+        }
+
+        if (!MacroAssembler::supportsFloatingPointAbs())
+            return false;
+
+        NodeIndex nodeIndex = addToGraph(ArithAbs, get(registerOffset + argumentToOperand(1)));
+        if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
+            m_graph[nodeIndex].mergeFlags(NodeMayOverflow);
+        setIntrinsicResult(usesResult, resultOperand, nodeIndex);
+        return true;
+    }
+
+    case MinIntrinsic:
+        return handleMinMax(usesResult, resultOperand, ArithMin, registerOffset, argumentCountIncludingThis);
+        
+    case MaxIntrinsic:
+        return handleMinMax(usesResult, resultOperand, ArithMax, registerOffset, argumentCountIncludingThis);
+        
+    case SqrtIntrinsic: {
+        if (argumentCountIncludingThis == 1) { // Math.sqrt()
+            setIntrinsicResult(usesResult, resultOperand, constantNaN());
+            return true;
+        }
+        
+        if (!MacroAssembler::supportsFloatingPointSqrt())
+            return false;
+        
+        setIntrinsicResult(usesResult, resultOperand, addToGraph(ArithSqrt, get(registerOffset + argumentToOperand(1))));
+        return true;
+    }
+        
+    case ArrayPushIntrinsic: {
+        if (argumentCountIncludingThis != 2)
+            return false;
+        
+        NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1)));
+        if (usesResult)
+            set(resultOperand, arrayPush);
+        
+        return true;
+    }
+        
+    case ArrayPopIntrinsic: {
+        if (argumentCountIncludingThis != 1)
+            return false;
+        
+        NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)));
+        if (usesResult)
+            set(resultOperand, arrayPop);
+        return true;
+    }
+
+    case CharCodeAtIntrinsic: {
+        if (argumentCountIncludingThis != 2)
+            return false;
+
+        int thisOperand = registerOffset + argumentToOperand(0);
+        if (!(m_graph[get(thisOperand)].prediction() & PredictString))
+            return false;
+        
+        int indexOperand = registerOffset + argumentToOperand(1);
+        NodeIndex storage = addToGraph(GetIndexedPropertyStorage, get(thisOperand), getToInt32(indexOperand));
+        NodeIndex charCode = addToGraph(StringCharCodeAt, get(thisOperand), getToInt32(indexOperand), storage);
 
 
-    // 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;
+        if (usesResult)
+            set(resultOperand, charCode);
+        return true;
+    }
 
 
-    struct PhiStackEntry {
-        PhiStackEntry(BasicBlock* block, NodeIndex phi, unsigned varNo)
-            : m_block(block)
-            , m_phi(phi)
-            , m_varNo(varNo)
-        {
-        }
+    case CharAtIntrinsic: {
+        if (argumentCountIncludingThis != 2)
+            return false;
 
 
-        BasicBlock* m_block;
-        NodeIndex m_phi;
-        unsigned m_varNo;
-    };
-    Vector<PhiStackEntry, 16> m_argumentPhiStack;
-    Vector<PhiStackEntry, 16> m_localPhiStack;
+        int thisOperand = registerOffset + argumentToOperand(0);
+        if (!(m_graph[get(thisOperand)].prediction() & PredictString))
+            return false;
 
 
-    // These maps are used to unique ToNumber and ToInt32 operations.
-    typedef HashMap<NodeIndex, NodeIndex> UnaryOpMap;
-    UnaryOpMap m_int32ToNumberNodes;
-    UnaryOpMap m_numberToInt32Nodes;
-};
+        int indexOperand = registerOffset + argumentToOperand(1);
+        NodeIndex storage = addToGraph(GetIndexedPropertyStorage, get(thisOperand), getToInt32(indexOperand));
+        NodeIndex charCode = addToGraph(StringCharAt, get(thisOperand), getToInt32(indexOperand), storage);
 
 
-#define NEXT_OPCODE(name) \
-    m_currentIndex += OPCODE_LENGTH(name); \
-    continue
+        if (usesResult)
+            set(resultOperand, charCode);
+        return true;
+    }
 
 
-#define LAST_OPCODE(name) \
-    m_currentIndex += OPCODE_LENGTH(name); \
-    return !m_parseFailed
+    case RegExpExecIntrinsic: {
+        if (argumentCountIncludingThis != 2)
+            return false;
+        
+        NodeIndex regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1)));
+        if (usesResult)
+            set(resultOperand, regExpExec);
+        
+        return true;
+    }
+        
+    case RegExpTestIntrinsic: {
+        if (argumentCountIncludingThis != 2)
+            return false;
+        
+        NodeIndex regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1)));
+        if (usesResult)
+            set(resultOperand, regExpExec);
+        
+        return true;
+    }
+        
+    default:
+        return false;
+    }
+}
+
+void ByteCodeParser::prepareToParseBlock()
+{
+    for (unsigned i = 0; i < m_constants.size(); ++i)
+        m_constants[i] = ConstantRecord();
+    m_cellConstantNodes.clear();
+}
 
 bool ByteCodeParser::parseBlock(unsigned limit)
 {
 
 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();
+    bool shouldContinueParsing = true;
+    
+    Interpreter* interpreter = m_globalData->interpreter;
+    Instruction* instructionsBegin = m_inlineStackTop->m_codeBlock->instructions().begin();
+    unsigned blockBegin = m_currentIndex;
+    
+    // If we are the first basic block, introduce markers for arguments. This allows
+    // us to track if a use of an argument may use the actual argument passed, as
+    // opposed to using a value we set explicitly.
+    if (m_currentBlock == m_graph.m_blocks[0].get() && !m_inlineStackTop->m_inlineCallFrame) {
+        m_graph.m_arguments.resize(m_numArguments);
+        for (unsigned argument = 0; argument < m_numArguments; ++argument) {
+            NodeIndex setArgument = addToGraph(SetArgument, OpInfo(newVariableAccessData(argumentToOperand(argument))));
+            m_graph.m_arguments[argument] = setArgument;
+            m_currentBlock->variablesAtHead.setArgumentFirstTime(argument, setArgument);
+            m_currentBlock->variablesAtTail.setArgumentFirstTime(argument, setArgument);
+        }
     }
 
     }
 
-    AliasTracker aliases(m_graph);
-
-    Interpreter* interpreter = m_globalData->interpreter;
-    Instruction* instructionsBegin = m_codeBlock->instructions().begin();
     while (true) {
     while (true) {
+        m_currentProfilingIndex = m_currentIndex;
+
         // Don't extend over jump destinations.
         if (m_currentIndex == limit) {
         // Don't extend over jump destinations.
         if (m_currentIndex == limit) {
-            addToGraph(Jump, OpInfo(m_currentIndex));
-            return !m_parseFailed;
+            // Ordinarily we want to plant a jump. But refuse to do this if the block is
+            // empty. This is a special case for inlining, which might otherwise create
+            // some empty blocks in some cases. When parseBlock() returns with an empty
+            // block, it will get repurposed instead of creating a new one. Note that this
+            // logic relies on every bytecode resulting in one or more nodes, which would
+            // be true anyway except for op_loop_hint, which emits a Phantom to force this
+            // to be true.
+            if (!m_currentBlock->isEmpty())
+                addToGraph(Jump, OpInfo(m_currentIndex));
+            else {
+#if DFG_ENABLE(DEBUG_VERBOSE)
+                dataLog("Refusing to plant jump at limit %u because block %p is empty.\n", limit, m_currentBlock);
+#endif
+            }
+            return shouldContinueParsing;
         }
         }
-
+        
         // Switch on the current bytecode opcode.
         Instruction* currentInstruction = instructionsBegin + m_currentIndex;
         // Switch on the current bytecode opcode.
         Instruction* currentInstruction = instructionsBegin + m_currentIndex;
-        switch (interpreter->getOpcodeID(currentInstruction->u.opcode)) {
+        OpcodeID opcodeID = interpreter->getOpcodeID(currentInstruction->u.opcode);
+        switch (opcodeID) {
 
         // === Function entry opcodes ===
 
         case op_enter:
             // Initialize all locals to undefined.
 
         // === Function entry opcodes ===
 
         case op_enter:
             // Initialize all locals to undefined.
-            for (int i = 0; i < m_codeBlock->m_numVars; ++i)
+            for (int i = 0; i < m_inlineStackTop->m_codeBlock->m_numVars; ++i)
                 set(i, constantUndefined());
             NEXT_OPCODE(op_enter);
 
         case op_convert_this: {
             NodeIndex op1 = getThis();
                 set(i, constantUndefined());
             NEXT_OPCODE(op_enter);
 
         case op_convert_this: {
             NodeIndex op1 = getThis();
-            setThis(addToGraph(ConvertThis, op1));
+            if (m_graph[op1].op() == ConvertThis)
+                setThis(op1);
+            else
+                setThis(addToGraph(ConvertThis, op1));
             NEXT_OPCODE(op_convert_this);
         }
 
             NEXT_OPCODE(op_convert_this);
         }
 
+        case op_create_this: {
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(CreateThis, op1));
+            NEXT_OPCODE(op_create_this);
+        }
+            
+        case op_new_object: {
+            set(currentInstruction[1].u.operand, addToGraph(NewObject));
+            NEXT_OPCODE(op_new_object);
+        }
+            
+        case op_new_array: {
+            int startOperand = currentInstruction[2].u.operand;
+            int numOperands = currentInstruction[3].u.operand;
+            for (int operandIdx = startOperand; operandIdx < startOperand + numOperands; ++operandIdx)
+                addVarArgChild(get(operandIdx));
+            set(currentInstruction[1].u.operand, addToGraph(Node::VarArg, NewArray, OpInfo(0), OpInfo(0)));
+            NEXT_OPCODE(op_new_array);
+        }
+            
+        case op_new_array_buffer: {
+            int startConstant = currentInstruction[2].u.operand;
+            int numConstants = currentInstruction[3].u.operand;
+            set(currentInstruction[1].u.operand, addToGraph(NewArrayBuffer, OpInfo(startConstant), OpInfo(numConstants)));
+            NEXT_OPCODE(op_new_array_buffer);
+        }
+            
+        case op_new_regexp: {
+            set(currentInstruction[1].u.operand, addToGraph(NewRegexp, OpInfo(currentInstruction[2].u.operand)));
+            NEXT_OPCODE(op_new_regexp);
+        }
+            
+        case op_get_callee: {
+            if (m_inlineStackTop->m_inlineCallFrame)
+                set(currentInstruction[1].u.operand, getDirect(m_inlineStackTop->m_calleeVR));
+            else
+                set(currentInstruction[1].u.operand, addToGraph(GetCallee));
+            NEXT_OPCODE(op_get_callee);
+        }
+
         // === Bitwise operations ===
 
         case op_bitand: {
             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
         // === 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);
+            set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2));
             NEXT_OPCODE(op_bitand);
         }
 
         case op_bitor: {
             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
             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);
+            set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2));
             NEXT_OPCODE(op_bitor);
         }
 
         case op_bitxor: {
             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
             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);
+            set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2));
             NEXT_OPCODE(op_bitxor);
         }
 
         case op_rshift: {
             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
             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);
             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);
+            set(currentInstruction[1].u.operand, result);
             NEXT_OPCODE(op_rshift);
         }
 
         case op_lshift: {
             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
             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);
             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);
+            set(currentInstruction[1].u.operand, result);
             NEXT_OPCODE(op_lshift);
         }
 
         case op_urshift: {
             NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
             NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
             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,
             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,
@@ -660,13 +1639,13 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 if (valueOfInt32Constant(op2) & 0x1f)
                     result = addToGraph(BitURShift, op1, op2);
                 else
                 if (valueOfInt32Constant(op2) & 0x1f)
                     result = addToGraph(BitURShift, op1, op2);
                 else
-                    result = addToGraph(UInt32ToNumber, op1);
+                    result = makeSafe(addToGraph(UInt32ToNumber, op1));
             }  else {
                 // Cannot optimize at this stage; shift & potentially rebox as a double.
                 result = addToGraph(BitURShift, op1, op2);
             }  else {
                 // Cannot optimize at this stage; shift & potentially rebox as a double.
                 result = addToGraph(BitURShift, op1, op2);
-                result = addToGraph(UInt32ToNumber, result);
+                result = makeSafe(addToGraph(UInt32ToNumber, result));
             }
             }
-            set(currentInstruction[1].u.operand, result, PredictInt32);
+            set(currentInstruction[1].u.operand, result);
             NEXT_OPCODE(op_urshift);
         }
 
             NEXT_OPCODE(op_urshift);
         }
 
@@ -674,104 +1653,167 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_pre_inc: {
             unsigned srcDst = currentInstruction[1].u.operand;
 
         case op_pre_inc: {
             unsigned srcDst = currentInstruction[1].u.operand;
-            NodeIndex op = getToNumber(srcDst);
-            predictInt32(op);
-            set(srcDst, addToGraph(ArithAdd, op, one()));
+            NodeIndex op = get(srcDst);
+            set(srcDst, makeSafe(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;
             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);
+            ASSERT(result != srcDst); // Required for assumptions we make during OSR.
+            NodeIndex op = get(srcDst);
             set(result, op);
             set(result, op);
-            set(srcDst, addToGraph(ArithAdd, op, one()));
+            set(srcDst, makeSafe(addToGraph(ArithAdd, op, one())));
             NEXT_OPCODE(op_post_inc);
         }
 
         case op_pre_dec: {
             unsigned srcDst = currentInstruction[1].u.operand;
             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()));
+            NodeIndex op = get(srcDst);
+            set(srcDst, makeSafe(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;
             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);
+            NodeIndex op = get(srcDst);
             set(result, op);
             set(result, op);
-            set(srcDst, addToGraph(ArithSub, op, one()));
+            set(srcDst, makeSafe(addToGraph(ArithSub, op, one())));
             NEXT_OPCODE(op_post_dec);
         }
 
         // === Arithmetic operations ===
 
         case op_add: {
             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);
             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)));
+            if (m_graph[op1].hasNumberResult() && m_graph[op2].hasNumberResult())
+                set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, op1, op2)));
             else
             else
-                set(currentInstruction[1].u.operand, addToGraph(ValueAdd, op1, op2));
+                set(currentInstruction[1].u.operand, makeSafe(addToGraph(ValueAdd, op1, op2)));
             NEXT_OPCODE(op_add);
         }
 
         case op_sub: {
             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));
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithSub, op1, op2)));
             NEXT_OPCODE(op_sub);
         }
 
             NEXT_OPCODE(op_sub);
         }
 
+        case op_negate: {
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithNegate, op1)));
+            NEXT_OPCODE(op_negate);
+        }
+
         case op_mul: {
         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));
+            // Multiply requires that the inputs are not truncated, unfortunately.
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMul, op1, op2)));
             NEXT_OPCODE(op_mul);
         }
 
         case op_mod: {
             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));
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithMod, op1, op2)));
             NEXT_OPCODE(op_mod);
         }
 
         case op_div: {
             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));
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, makeDivSafe(addToGraph(ArithDiv, op1, op2)));
             NEXT_OPCODE(op_div);
         }
 
         // === Misc operations ===
 
             NEXT_OPCODE(op_div);
         }
 
         // === Misc operations ===
 
+#if ENABLE(DEBUG_WITH_BREAKPOINT)
+        case op_debug:
+            addToGraph(Breakpoint);
+            NEXT_OPCODE(op_debug);
+#endif
         case op_mov: {
             NodeIndex op = get(currentInstruction[2].u.operand);
             set(currentInstruction[1].u.operand, op);
             NEXT_OPCODE(op_mov);
         }
 
         case op_mov: {
             NodeIndex op = get(currentInstruction[2].u.operand);
             set(currentInstruction[1].u.operand, op);
             NEXT_OPCODE(op_mov);
         }
 
+        case op_check_has_instance:
+            addToGraph(CheckHasInstance, get(currentInstruction[1].u.operand));
+            NEXT_OPCODE(op_check_has_instance);
+
+        case op_instanceof: {
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            NodeIndex baseValue = get(currentInstruction[3].u.operand);
+            NodeIndex prototype = get(currentInstruction[4].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(InstanceOf, value, baseValue, prototype));
+            NEXT_OPCODE(op_instanceof);
+        }
+            
+        case op_is_undefined: {
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(IsUndefined, value));
+            NEXT_OPCODE(op_is_undefined);
+        }
+
+        case op_is_boolean: {
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(IsBoolean, value));
+            NEXT_OPCODE(op_is_boolean);
+        }
+
+        case op_is_number: {
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(IsNumber, value));
+            NEXT_OPCODE(op_is_number);
+        }
+
+        case op_is_string: {
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(IsString, value));
+            NEXT_OPCODE(op_is_string);
+        }
+
+        case op_is_object: {
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(IsObject, value));
+            NEXT_OPCODE(op_is_object);
+        }
+
+        case op_is_function: {
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(IsFunction, value));
+            NEXT_OPCODE(op_is_function);
+        }
+
         case op_not: {
         case op_not: {
-            ARITHMETIC_OP();
             NodeIndex value = get(currentInstruction[2].u.operand);
             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, value));
             NEXT_OPCODE(op_not);
         }
             NodeIndex value = get(currentInstruction[2].u.operand);
             set(currentInstruction[1].u.operand, addToGraph(LogicalNot, value));
             NEXT_OPCODE(op_not);
         }
+            
+        case op_to_primitive: {
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(ToPrimitive, value));
+            NEXT_OPCODE(op_to_primitive);
+        }
+            
+        case op_strcat: {
+            int startOperand = currentInstruction[2].u.operand;
+            int numOperands = currentInstruction[3].u.operand;
+            for (int operandIdx = startOperand; operandIdx < startOperand + numOperands; ++operandIdx)
+                addVarArgChild(get(operandIdx));
+            set(currentInstruction[1].u.operand, addToGraph(Node::VarArg, StrCat, OpInfo(0), OpInfo(0)));
+            NEXT_OPCODE(op_strcat);
+        }
 
         case op_less: {
 
         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));
             NodeIndex op1 = get(currentInstruction[2].u.operand);
             NodeIndex op2 = get(currentInstruction[3].u.operand);
             set(currentInstruction[1].u.operand, addToGraph(CompareLess, op1, op2));
@@ -779,15 +1821,27 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
 
         case op_lesseq: {
         }
 
         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);
         }
 
             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_greater: {
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(CompareGreater, op1, op2));
+            NEXT_OPCODE(op_greater);
+        }
+
+        case op_greatereq: {
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(CompareGreaterEq, op1, op2));
+            NEXT_OPCODE(op_greatereq);
+        }
+
         case op_eq: {
         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));
             NodeIndex op1 = get(currentInstruction[2].u.operand);
             NodeIndex op2 = get(currentInstruction[3].u.operand);
             set(currentInstruction[1].u.operand, addToGraph(CompareEq, op1, op2));
@@ -795,14 +1849,12 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
 
         case op_eq_null: {
         }
 
         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: {
             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));
             NodeIndex op1 = get(currentInstruction[2].u.operand);
             NodeIndex op2 = get(currentInstruction[3].u.operand);
             set(currentInstruction[1].u.operand, addToGraph(CompareStrictEq, op1, op2));
@@ -810,7 +1862,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
 
         case op_neq: {
         }
 
         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)));
             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)));
@@ -818,14 +1869,12 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
 
         case op_neq_null: {
         }
 
         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: {
             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)));
             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)));
@@ -835,14 +1884,13 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         // === Property access operations ===
 
         case op_get_by_val: {
         // === Property access operations ===
 
         case op_get_by_val: {
+            PredictedType prediction = getPrediction();
+            
             NodeIndex base = get(currentInstruction[2].u.operand);
             NodeIndex property = get(currentInstruction[3].u.operand);
             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));
+            NodeIndex propertyStorage = addToGraph(GetIndexedPropertyStorage, base, property);
+            NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(prediction), base, property, propertyStorage);
             set(currentInstruction[1].u.operand, getByVal);
             set(currentInstruction[1].u.operand, getByVal);
-            aliases.recordGetByVal(getByVal);
 
             NEXT_OPCODE(op_get_by_val);
         }
 
             NEXT_OPCODE(op_get_by_val);
         }
@@ -851,46 +1899,197 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             NodeIndex base = get(currentInstruction[1].u.operand);
             NodeIndex property = get(currentInstruction[2].u.operand);
             NodeIndex value = get(currentInstruction[3].u.operand);
             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);
+            addToGraph(PutByVal, base, property, value);
 
             NEXT_OPCODE(op_put_by_val);
         }
 
             NEXT_OPCODE(op_put_by_val);
         }
-
+            
+        case op_method_check: {
+            m_currentProfilingIndex += OPCODE_LENGTH(op_method_check);
+            Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
+            
+            PredictedType prediction = getPrediction();
+            
+            ASSERT(interpreter->getOpcodeID(getInstruction->u.opcode) == op_get_by_id);
+            
+            NodeIndex base = get(getInstruction[2].u.operand);
+            unsigned identifier = m_inlineStackTop->m_identifierRemap[getInstruction[3].u.operand];
+                
+            // Check if the method_check was monomorphic. If so, emit a CheckXYZMethod
+            // node, which is a lot more efficient.
+            GetByIdStatus getByIdStatus = GetByIdStatus::computeFor(
+                m_inlineStackTop->m_profiledBlock,
+                m_currentIndex,
+                m_codeBlock->identifier(identifier));
+            MethodCallLinkStatus methodCallStatus = MethodCallLinkStatus::computeFor(
+                m_inlineStackTop->m_profiledBlock, m_currentIndex);
+            
+            if (methodCallStatus.isSet()
+                && !getByIdStatus.wasSeenInJIT()
+                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
+                // It's monomorphic as far as we can tell, since the method_check was linked
+                // but the slow path (i.e. the normal get_by_id) never fired.
+
+                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.structure())), base);
+                if (methodCallStatus.needsPrototypeCheck())
+                    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.prototypeStructure())), cellConstant(methodCallStatus.prototype()));
+                
+                // Keep the base of the access alive past the speculations.
+                addToGraph(Phantom, base);
+                
+                set(getInstruction[1].u.operand, cellConstant(methodCallStatus.function()));
+            } else
+                set(getInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifier), OpInfo(prediction), base));
+            
+            m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id);
+            continue;
+        }
+        case op_get_scoped_var: {
+            PredictedType prediction = getPrediction();
+            int dst = currentInstruction[1].u.operand;
+            int slot = currentInstruction[2].u.operand;
+            int depth = currentInstruction[3].u.operand;
+            NodeIndex getScopeChain = addToGraph(GetScopeChain, OpInfo(depth));
+            NodeIndex getScopedVar = addToGraph(GetScopedVar, OpInfo(slot), OpInfo(prediction), getScopeChain);
+            set(dst, getScopedVar);
+            NEXT_OPCODE(op_get_scoped_var);
+        }
+        case op_put_scoped_var: {
+            int slot = currentInstruction[1].u.operand;
+            int depth = currentInstruction[2].u.operand;
+            int source = currentInstruction[3].u.operand;
+            NodeIndex getScopeChain = addToGraph(GetScopeChain, OpInfo(depth));
+            addToGraph(PutScopedVar, OpInfo(slot), getScopeChain, get(source));
+            NEXT_OPCODE(op_put_scoped_var);
+        }
         case op_get_by_id: {
         case op_get_by_id: {
+            PredictedType prediction = getPredictionWithoutOSRExit();
+            
             NodeIndex base = get(currentInstruction[2].u.operand);
             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);
+            unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
+            
+            Identifier identifier = m_codeBlock->identifier(identifierNumber);
+            GetByIdStatus getByIdStatus = GetByIdStatus::computeFor(
+                m_inlineStackTop->m_profiledBlock, m_currentIndex, identifier);
+            
+            if (getByIdStatus.isSimpleDirect()
+                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
+                ASSERT(getByIdStatus.structureSet().size());
+                
+                // The implementation of GetByOffset does not know to terminate speculative
+                // execution if it doesn't have a prediction, so we do it manually.
+                if (prediction == PredictNone)
+                    addToGraph(ForceOSRExit);
+                
+                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base);
+                NodeIndex propertyStorage;
+                size_t offsetOffset;
+                if (getByIdStatus.structureSet().allAreUsingInlinePropertyStorage()) {
+                    propertyStorage = base;
+                    ASSERT(!(sizeof(JSObject) % sizeof(EncodedJSValue)));
+                    offsetOffset = sizeof(JSObject) / sizeof(EncodedJSValue);
+                } else {
+                    propertyStorage = addToGraph(GetPropertyStorage, base);
+                    offsetOffset = 0;
+                }
+                set(currentInstruction[1].u.operand, addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), propertyStorage));
+                
+                StorageAccessData storageAccessData;
+                storageAccessData.offset = getByIdStatus.offset() + offsetOffset;
+                storageAccessData.identifierNumber = identifierNumber;
+                m_graph.m_storageAccessData.append(storageAccessData);
+            } else
+                set(currentInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
 
             NEXT_OPCODE(op_get_by_id);
         }
 
             NEXT_OPCODE(op_get_by_id);
         }
-
-        case op_put_by_id: {
+        case op_put_by_id:
+        case op_put_by_id_transition_direct:
+        case op_put_by_id_transition_normal: {
             NodeIndex value = get(currentInstruction[3].u.operand);
             NodeIndex base = get(currentInstruction[1].u.operand);
             NodeIndex value = get(currentInstruction[3].u.operand);
             NodeIndex base = get(currentInstruction[1].u.operand);
-            unsigned identifier = currentInstruction[2].u.operand;
+            unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
             bool direct = currentInstruction[8].u.operand;
 
             bool direct = currentInstruction[8].u.operand;
 
-            if (direct) {
-                NodeIndex putByIdDirect = addToGraph(PutByIdDirect, OpInfo(identifier), base, value);
-                aliases.recordPutByIdDirect(putByIdDirect);
+            PutByIdStatus putByIdStatus = PutByIdStatus::computeFor(
+                m_inlineStackTop->m_profiledBlock,
+                m_currentIndex,
+                m_codeBlock->identifier(identifierNumber));
+            if (!putByIdStatus.isSet())
+                addToGraph(ForceOSRExit);
+            
+            bool hasExitSite = m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache);
+            
+            if (!hasExitSite && putByIdStatus.isSimpleReplace()) {
+                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
+                addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
+                
+                StorageAccessData storageAccessData;
+                storageAccessData.offset = putByIdStatus.offset();
+                storageAccessData.identifierNumber = identifierNumber;
+                m_graph.m_storageAccessData.append(storageAccessData);
+            } else if (!hasExitSite
+                       && putByIdStatus.isSimpleTransition()
+                       && putByIdStatus.oldStructure()->propertyStorageCapacity() == putByIdStatus.newStructure()->propertyStorageCapacity()
+                       && structureChainIsStillValid(
+                           direct,
+                           putByIdStatus.oldStructure(),
+                           putByIdStatus.structureChain())) {
+
+                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
+                if (!direct) {
+                    if (!putByIdStatus.oldStructure()->storedPrototype().isNull())
+                        addToGraph(
+                            CheckStructure,
+                            OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure()->storedPrototype().asCell()->structure())),
+                            cellConstant(putByIdStatus.oldStructure()->storedPrototype().asCell()));
+                    
+                    for (WriteBarrier<Structure>* it = putByIdStatus.structureChain()->head(); *it; ++it) {
+                        JSValue prototype = (*it)->storedPrototype();
+                        if (prototype.isNull())
+                            continue;
+                        ASSERT(prototype.isCell());
+                        addToGraph(
+                            CheckStructure,
+                            OpInfo(m_graph.addStructureSet(prototype.asCell()->structure())),
+                            cellConstant(prototype.asCell()));
+                    }
+                }
+                addToGraph(
+                    PutStructure,
+                    OpInfo(
+                        m_graph.addStructureTransitionData(
+                            StructureTransitionData(
+                                putByIdStatus.oldStructure(),
+                                putByIdStatus.newStructure()))),
+                    base);
+                
+                addToGraph(
+                    PutByOffset,
+                    OpInfo(m_graph.m_storageAccessData.size()),
+                    base,
+                    addToGraph(GetPropertyStorage, base),
+                    value);
+                
+                StorageAccessData storageAccessData;
+                storageAccessData.offset = putByIdStatus.offset();
+                storageAccessData.identifierNumber = identifierNumber;
+                m_graph.m_storageAccessData.append(storageAccessData);
             } else {
             } else {
-                NodeIndex putById = addToGraph(PutById, OpInfo(identifier), base, value);
-                aliases.recordPutById(putById);
+                if (direct)
+                    addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
+                else
+                    addToGraph(PutById, OpInfo(identifierNumber), base, value);
             }
 
             NEXT_OPCODE(op_put_by_id);
         }
 
         case op_get_global_var: {
             }
 
             NEXT_OPCODE(op_put_by_id);
         }
 
         case op_get_global_var: {
-            NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand));
+            PredictedType prediction = getPrediction();
+            
+            NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand), OpInfo(prediction));
             set(currentInstruction[1].u.operand, getGlobalVar);
             NEXT_OPCODE(op_get_global_var);
         }
             set(currentInstruction[1].u.operand, getGlobalVar);
             NEXT_OPCODE(op_get_global_var);
         }
@@ -959,6 +2158,42 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             LAST_OPCODE(op_jneq_null);
         }
 
             LAST_OPCODE(op_jneq_null);
         }
 
+        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_jgreater: {
+            unsigned relativeOffset = currentInstruction[3].u.operand;
+            NodeIndex op1 = get(currentInstruction[1].u.operand);
+            NodeIndex op2 = get(currentInstruction[2].u.operand);
+            NodeIndex condition = addToGraph(CompareGreater, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jgreater)), condition);
+            LAST_OPCODE(op_jgreater);
+        }
+
+        case op_jgreatereq: {
+            unsigned relativeOffset = currentInstruction[3].u.operand;
+            NodeIndex op1 = get(currentInstruction[1].u.operand);
+            NodeIndex op2 = get(currentInstruction[2].u.operand);
+            NodeIndex condition = addToGraph(CompareGreaterEq, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jgreatereq)), condition);
+            LAST_OPCODE(op_jgreatereq);
+        }
+
         case op_jnless: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
             NodeIndex op1 = get(currentInstruction[1].u.operand);
         case op_jnless: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
             NodeIndex op1 = get(currentInstruction[1].u.operand);
@@ -977,22 +2212,22 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             LAST_OPCODE(op_jnlesseq);
         }
 
             LAST_OPCODE(op_jnlesseq);
         }
 
-        case op_jless: {
+        case op_jngreater: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
             NodeIndex op1 = get(currentInstruction[1].u.operand);
             NodeIndex op2 = get(currentInstruction[2].u.operand);
             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);
+            NodeIndex condition = addToGraph(CompareGreater, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jngreater)), OpInfo(m_currentIndex + relativeOffset), condition);
+            LAST_OPCODE(op_jngreater);
         }
 
         }
 
-        case op_jlesseq: {
+        case op_jngreatereq: {
             unsigned relativeOffset = currentInstruction[3].u.operand;
             NodeIndex op1 = get(currentInstruction[1].u.operand);
             NodeIndex op2 = get(currentInstruction[2].u.operand);
             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);
+            NodeIndex condition = addToGraph(CompareGreaterEq, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jngreatereq)), OpInfo(m_currentIndex + relativeOffset), condition);
+            LAST_OPCODE(op_jngreatereq);
         }
 
         case op_loop_if_less: {
         }
 
         case op_loop_if_less: {
@@ -1013,15 +2248,173 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             LAST_OPCODE(op_loop_if_lesseq);
         }
 
             LAST_OPCODE(op_loop_if_lesseq);
         }
 
-        case op_ret: {
+        case op_loop_if_greater: {
+            unsigned relativeOffset = currentInstruction[3].u.operand;
+            NodeIndex op1 = get(currentInstruction[1].u.operand);
+            NodeIndex op2 = get(currentInstruction[2].u.operand);
+            NodeIndex condition = addToGraph(CompareGreater, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_greater)), condition);
+            LAST_OPCODE(op_loop_if_greater);
+        }
+
+        case op_loop_if_greatereq: {
+            unsigned relativeOffset = currentInstruction[3].u.operand;
+            NodeIndex op1 = get(currentInstruction[1].u.operand);
+            NodeIndex op2 = get(currentInstruction[2].u.operand);
+            NodeIndex condition = addToGraph(CompareGreaterEq, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_greatereq)), condition);
+            LAST_OPCODE(op_loop_if_greatereq);
+        }
+
+        case op_ret:
+            if (m_inlineStackTop->m_inlineCallFrame) {
+                if (m_inlineStackTop->m_returnValue != InvalidVirtualRegister)
+                    setDirect(m_inlineStackTop->m_returnValue, get(currentInstruction[1].u.operand));
+                m_inlineStackTop->m_didReturn = true;
+                if (m_inlineStackTop->m_unlinkedBlocks.isEmpty()) {
+                    // If we're returning from the first block, then we're done parsing.
+                    ASSERT(m_inlineStackTop->m_callsiteBlockHead == m_graph.m_blocks.size() - 1);
+                    shouldContinueParsing = false;
+                    LAST_OPCODE(op_ret);
+                } else {
+                    // If inlining created blocks, and we're doing a return, then we need some
+                    // special linking.
+                    ASSERT(m_inlineStackTop->m_unlinkedBlocks.last().m_blockIndex == m_graph.m_blocks.size() - 1);
+                    m_inlineStackTop->m_unlinkedBlocks.last().m_needsNormalLinking = false;
+                }
+                if (m_currentIndex + OPCODE_LENGTH(op_ret) != m_inlineStackTop->m_codeBlock->instructions().size() || m_inlineStackTop->m_didEarlyReturn) {
+                    ASSERT(m_currentIndex + OPCODE_LENGTH(op_ret) <= m_inlineStackTop->m_codeBlock->instructions().size());
+                    addToGraph(Jump, OpInfo(NoBlock));
+                    m_inlineStackTop->m_unlinkedBlocks.last().m_needsEarlyReturnLinking = true;
+                    m_inlineStackTop->m_didEarlyReturn = true;
+                }
+                LAST_OPCODE(op_ret);
+            }
             addToGraph(Return, get(currentInstruction[1].u.operand));
             LAST_OPCODE(op_ret);
             addToGraph(Return, get(currentInstruction[1].u.operand));
             LAST_OPCODE(op_ret);
+            
+        case op_end:
+            ASSERT(!m_inlineStackTop->m_inlineCallFrame);
+            addToGraph(Return, get(currentInstruction[1].u.operand));
+            LAST_OPCODE(op_end);
+
+        case op_throw:
+            addToGraph(Throw, get(currentInstruction[1].u.operand));
+            LAST_OPCODE(op_throw);
+            
+        case op_throw_reference_error:
+            addToGraph(ThrowReferenceError);
+            LAST_OPCODE(op_throw_reference_error);
+            
+        case op_call:
+            handleCall(interpreter, currentInstruction, Call, CodeForCall);
+            NEXT_OPCODE(op_call);
+            
+        case op_construct:
+            handleCall(interpreter, currentInstruction, Construct, CodeForConstruct);
+            NEXT_OPCODE(op_construct);
+            
+        case op_call_put_result:
+            NEXT_OPCODE(op_call_put_result);
+
+        case op_resolve: {
+            PredictedType prediction = getPrediction();
+            
+            unsigned identifier = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
+
+            NodeIndex resolve = addToGraph(Resolve, OpInfo(identifier), OpInfo(prediction));
+            set(currentInstruction[1].u.operand, resolve);
+
+            NEXT_OPCODE(op_resolve);
+        }
+
+        case op_resolve_base: {
+            PredictedType prediction = getPrediction();
+            
+            unsigned identifier = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
+
+            NodeIndex resolve = addToGraph(currentInstruction[3].u.operand ? ResolveBaseStrictPut : ResolveBase, OpInfo(identifier), OpInfo(prediction));
+            set(currentInstruction[1].u.operand, resolve);
+
+            NEXT_OPCODE(op_resolve_base);
+        }
+            
+        case op_resolve_global: {
+            PredictedType prediction = getPrediction();
+            
+            NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(prediction));
+            m_graph.m_resolveGlobalData.append(ResolveGlobalData());
+            ResolveGlobalData& data = m_graph.m_resolveGlobalData.last();
+            data.identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
+            data.resolveInfoIndex = m_globalResolveNumber++;
+            set(currentInstruction[1].u.operand, resolve);
+
+            NEXT_OPCODE(op_resolve_global);
+        }
+
+        case op_loop_hint: {
+            // Baseline->DFG OSR jumps between loop hints. The DFG assumes that Baseline->DFG
+            // OSR can only happen at basic block boundaries. Assert that these two statements
+            // are compatible.
+            ASSERT_UNUSED(blockBegin, m_currentIndex == blockBegin);
+            
+            // We never do OSR into an inlined code block. That could not happen, since OSR
+            // looks up the code block that is the replacement for the baseline JIT code
+            // block. Hence, machine code block = true code block = not inline code block.
+            if (!m_inlineStackTop->m_caller)
+                m_currentBlock->isOSRTarget = true;
+            
+            // Emit a phantom node to ensure that there is a placeholder node for this bytecode
+            // op.
+            addToGraph(Phantom);
+            
+            NEXT_OPCODE(op_loop_hint);
+        }
+            
+        case op_init_lazy_reg: {
+            set(currentInstruction[1].u.operand, getJSConstantForValue(JSValue()));
+            NEXT_OPCODE(op_init_lazy_reg);
+        }
+            
+        case op_create_activation: {
+            set(currentInstruction[1].u.operand, addToGraph(CreateActivation, get(currentInstruction[1].u.operand)));
+            NEXT_OPCODE(op_create_activation);
+        }
+            
+        case op_tear_off_activation: {
+            // This currently ignores arguments because we don't support them yet.
+            addToGraph(TearOffActivation, get(currentInstruction[1].u.operand));
+            NEXT_OPCODE(op_tear_off_activation);
+        }
+            
+        case op_new_func: {
+            if (!currentInstruction[3].u.operand) {
+                set(currentInstruction[1].u.operand,
+                    addToGraph(NewFunctionNoCheck, OpInfo(currentInstruction[2].u.operand)));
+            } else {
+                set(currentInstruction[1].u.operand,
+                    addToGraph(
+                        NewFunction,
+                        OpInfo(currentInstruction[2].u.operand),
+                        get(currentInstruction[1].u.operand)));
+            }
+            NEXT_OPCODE(op_new_func);
+        }
+            
+        case op_new_func_exp: {
+            set(currentInstruction[1].u.operand,
+                addToGraph(NewFunctionExpression, OpInfo(currentInstruction[2].u.operand)));
+            NEXT_OPCODE(op_new_func_exp);
         }
 
         default:
         }
 
         default:
-            // Parse failed!
+            // Parse failed! This should not happen because the capabilities checker
+            // should have caught it.
+            ASSERT_NOT_REACHED();
             return false;
         }
             return false;
         }
+        
+        ASSERT(canCompileOpcode(opcodeID));
     }
 }
 
     }
 }
 
@@ -1034,162 +2427,469 @@ void ByteCodeParser::processPhiStack()
         PhiStackEntry entry = phiStack.last();
         phiStack.removeLast();
         
         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;
         PredecessorList& predecessors = entry.m_block->m_predecessors;
         unsigned varNo = entry.m_varNo;
+        VariableAccessData* dataForPhi = m_graph[entry.m_phi].variableAccessData();
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("   Handling phi entry for var %u, phi @%u.\n", entry.m_varNo, entry.m_phi);
+#endif
 
         for (size_t i = 0; i < predecessors.size(); ++i) {
 
         for (size_t i = 0; i < predecessors.size(); ++i) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+            dataLog("     Dealing with predecessor block %u.\n", predecessors[i]);
+#endif
+            
             BasicBlock* predecessorBlock = m_graph.m_blocks[predecessors[i]].get();
 
             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;
+            NodeIndex& var = (stackType == ArgumentPhiStack) ? predecessorBlock->variablesAtTail.argument(varNo) : predecessorBlock->variablesAtTail.local(varNo);
+            
+            NodeIndex valueInPredecessor = var;
             if (valueInPredecessor == NoNode) {
             if (valueInPredecessor == NoNode) {
-                valueInPredecessor = addToGraph(Phi);
-                var.value = valueInPredecessor;
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                dataLog("      Did not find node, adding phi.\n");
+#endif
+
+                valueInPredecessor = insertPhiNode(OpInfo(newVariableAccessData(stackType == ArgumentPhiStack ? argumentToOperand(varNo) : static_cast<int>(varNo))), predecessorBlock);
+                var = valueInPredecessor;
+                if (stackType == ArgumentPhiStack)
+                    predecessorBlock->variablesAtHead.setArgumentFirstTime(varNo, valueInPredecessor);
+                else
+                    predecessorBlock->variablesAtHead.setLocalFirstTime(varNo, valueInPredecessor);
                 phiStack.append(PhiStackEntry(predecessorBlock, valueInPredecessor, varNo));
                 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);
+            } else if (m_graph[valueInPredecessor].op() == GetLocal) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                dataLog("      Found GetLocal @%u.\n", valueInPredecessor);
+#endif
 
 
-            if (phiNode.refCount())
+                // We want to ensure that the VariableAccessDatas are identical between the
+                // GetLocal and its block-local Phi. Strictly speaking we only need the two
+                // to be unified. But for efficiency, we want the code that creates GetLocals
+                // and Phis to try to reuse VariableAccessDatas as much as possible.
+                ASSERT(m_graph[valueInPredecessor].variableAccessData() == m_graph[m_graph[valueInPredecessor].child1().index()].variableAccessData());
+                
+                valueInPredecessor = m_graph[valueInPredecessor].child1().index();
+            } else {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                dataLog("      Found @%u.\n", valueInPredecessor);
+#endif
+            }
+            ASSERT(m_graph[valueInPredecessor].op() == SetLocal
+                   || m_graph[valueInPredecessor].op() == Phi
+                   || m_graph[valueInPredecessor].op() == Flush
+                   || (m_graph[valueInPredecessor].op() == SetArgument
+                       && stackType == ArgumentPhiStack));
+            
+            VariableAccessData* dataForPredecessor = m_graph[valueInPredecessor].variableAccessData();
+            
+            dataForPredecessor->unify(dataForPhi);
+
+            Node* phiNode = &m_graph[entry.m_phi];
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+            dataLog("      Ref count of @%u = %u.\n", entry.m_phi, phiNode->refCount());
+#endif
+            if (phiNode->refCount()) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                dataLog("      Reffing @%u.\n", valueInPredecessor);
+#endif
                 m_graph.ref(valueInPredecessor);
                 m_graph.ref(valueInPredecessor);
+            }
 
 
-            if (phiNode.child1 == NoNode) {
-                phiNode.child1 = valueInPredecessor;
+            if (!phiNode->child1()) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                dataLog("      Setting @%u->child1 = @%u.\n", entry.m_phi, valueInPredecessor);
+#endif
+                phiNode->children.setChild1(Edge(valueInPredecessor));
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                dataLog("      Children of @%u: ", entry.m_phi);
+                phiNode->dumpChildren(WTF::dataFile());
+                dataLog(".\n");
+#endif
                 continue;
             }
                 continue;
             }
-            if (phiNode.child2 == NoNode) {
-                phiNode.child2 = valueInPredecessor;
+            if (!phiNode->child2()) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                dataLog("      Setting @%u->child2 = @%u.\n", entry.m_phi, valueInPredecessor);
+#endif
+                phiNode->children.setChild2(Edge(valueInPredecessor));
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                dataLog("      Children of @%u: ", entry.m_phi);
+                phiNode->dumpChildren(WTF::dataFile());
+                dataLog(".\n");
+#endif
                 continue;
             }
                 continue;
             }
-            if (phiNode.child3 == NoNode) {
-                phiNode.child3 = valueInPredecessor;
+            if (!phiNode->child3()) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                dataLog("      Setting @%u->child3 = @%u.\n", entry.m_phi, valueInPredecessor);
+#endif
+                phiNode->children.setChild3(Edge(valueInPredecessor));
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                dataLog("      Children of @%u: ", entry.m_phi);
+                phiNode->dumpChildren(WTF::dataFile());
+                dataLog(".\n");
+#endif
                 continue;
             }
                 continue;
             }
+            
+            NodeIndex newPhi = insertPhiNode(OpInfo(dataForPhi), entry.m_block);
+            
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+            dataLog("      Splitting @%u, created @%u.\n", entry.m_phi, newPhi);
+#endif
 
 
-            NodeIndex newPhi = addToGraph(Phi);
+            phiNode = &m_graph[entry.m_phi]; // reload after vector resize
             Node& newPhiNode = m_graph[newPhi];
             Node& newPhiNode = m_graph[newPhi];
-            if (phiNode.refCount())
+            if (phiNode->refCount())
                 m_graph.ref(newPhi);
 
                 m_graph.ref(newPhi);
 
-            newPhiNode.child1 = phiNode.child1;
-            newPhiNode.child2 = phiNode.child2;
-            newPhiNode.child3 = phiNode.child3;
+            newPhiNode.children = phiNode->children;
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+            dataLog("      Children of @%u: ", newPhi);
+            newPhiNode.dumpChildren(WTF::dataFile());
+            dataLog(".\n");
+#endif
+
+            phiNode->children.initialize(newPhi, valueInPredecessor, NoNode);
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+            dataLog("      Children of @%u: ", entry.m_phi);
+            phiNode->dumpChildren(WTF::dataFile());
+            dataLog(".\n");
+#endif
+        }
+    }
+}
+
+void ByteCodeParser::fixVariableAccessPredictions()
+{
+    for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
+        VariableAccessData* data = &m_graph.m_variableAccessData[i];
+        data->find()->predict(data->nonUnifiedPrediction());
+    }
+}
+
+void ByteCodeParser::linkBlock(BasicBlock* block, Vector<BlockIndex>& possibleTargets)
+{
+    ASSERT(!block->isLinked);
+    ASSERT(!block->isEmpty());
+    Node& node = m_graph[block->last()];
+    ASSERT(node.isTerminal());
+    
+    switch (node.op()) {
+    case Jump:
+        node.setTakenBlockIndex(m_graph.blockIndexForBytecodeOffset(possibleTargets, node.takenBytecodeOffsetDuringParsing()));
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Linked basic block %p to %p, #%u.\n", block, m_graph.m_blocks[node.takenBlockIndex()].get(), node.takenBlockIndex());
+#endif
+        break;
+        
+    case Branch:
+        node.setTakenBlockIndex(m_graph.blockIndexForBytecodeOffset(possibleTargets, node.takenBytecodeOffsetDuringParsing()));
+        node.setNotTakenBlockIndex(m_graph.blockIndexForBytecodeOffset(possibleTargets, node.notTakenBytecodeOffsetDuringParsing()));
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Linked basic block %p to %p, #%u and %p, #%u.\n", block, m_graph.m_blocks[node.takenBlockIndex()].get(), node.takenBlockIndex(), m_graph.m_blocks[node.notTakenBlockIndex()].get(), node.notTakenBlockIndex());
+#endif
+        break;
+        
+    default:
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Marking basic block %p as linked.\n", block);
+#endif
+        break;
+    }
+    
+#if !ASSERT_DISABLED
+    block->isLinked = true;
+#endif
+}
 
 
-            phiNode.child1 = newPhi;
-            phiNode.child1 = valueInPredecessor;
-            phiNode.child3 = NoNode;
+void ByteCodeParser::linkBlocks(Vector<UnlinkedBlock>& unlinkedBlocks, Vector<BlockIndex>& possibleTargets)
+{
+    for (size_t i = 0; i < unlinkedBlocks.size(); ++i) {
+        if (unlinkedBlocks[i].m_needsNormalLinking) {
+            linkBlock(m_graph.m_blocks[unlinkedBlocks[i].m_blockIndex].get(), possibleTargets);
+            unlinkedBlocks[i].m_needsNormalLinking = false;
         }
     }
 }
 
         }
     }
 }
 
-void ByteCodeParser::setupPredecessors()
+void ByteCodeParser::handleSuccessor(Vector<BlockIndex, 16>& worklist, BlockIndex blockIndex, BlockIndex successorIndex)
 {
 {
-    for (BlockIndex index = 0; index < m_graph.m_blocks.size(); ++index) {
+    BasicBlock* successor = m_graph.m_blocks[successorIndex].get();
+    if (!successor->isReachable) {
+        successor->isReachable = true;
+        worklist.append(successorIndex);
+    }
+    
+    successor->m_predecessors.append(blockIndex);
+}
+
+void ByteCodeParser::determineReachability()
+{
+    Vector<BlockIndex, 16> worklist;
+    worklist.append(0);
+    m_graph.m_blocks[0]->isReachable = true;
+    while (!worklist.isEmpty()) {
+        BlockIndex index = worklist.last();
+        worklist.removeLast();
+        
         BasicBlock* block = m_graph.m_blocks[index].get();
         BasicBlock* block = m_graph.m_blocks[index].get();
-        ASSERT(block->end != NoNode);
-        Node& node = m_graph[block->end - 1];
+        ASSERT(block->isLinked);
+        
+        Node& node = m_graph[block->last()];
         ASSERT(node.isTerminal());
         ASSERT(node.isTerminal());
-
+        
         if (node.isJump())
         if (node.isJump())
-            m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
+            handleSuccessor(worklist, index, node.takenBlockIndex());
         else if (node.isBranch()) {
         else if (node.isBranch()) {
-            m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
-            m_graph.blockForBytecodeOffset(node.notTakenBytecodeOffset()).m_predecessors.append(index);
+            handleSuccessor(worklist, index, node.takenBlockIndex());
+            handleSuccessor(worklist, index, node.notTakenBlockIndex());
         }
     }
 }
 
         }
     }
 }
 
-void ByteCodeParser::allocateVirtualRegisters()
+void ByteCodeParser::buildOperandMapsIfNecessary()
 {
 {
-    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;
+    if (m_haveBuiltOperandMaps)
+        return;
+    
+    for (size_t i = 0; i < m_codeBlock->numberOfIdentifiers(); ++i)
+        m_identifierMap.add(m_codeBlock->identifier(i).impl(), i);
+    for (size_t i = 0; i < m_codeBlock->numberOfConstantRegisters(); ++i) {
+        JSValue value = m_codeBlock->getConstant(i + FirstConstantRegisterIndex);
+        if (!value)
+            m_emptyJSValueIndex = i + FirstConstantRegisterIndex;
+        else
+            m_jsValueMap.add(JSValue::encode(value), i + FirstConstantRegisterIndex);
+    }
+    
+    m_haveBuiltOperandMaps = true;
+}
 
 
-        // 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);
+ByteCodeParser::InlineStackEntry::InlineStackEntry(ByteCodeParser* byteCodeParser, CodeBlock* codeBlock, CodeBlock* profiledBlock, BlockIndex callsiteBlockHead, VirtualRegister calleeVR, JSFunction* callee, VirtualRegister returnValueVR, VirtualRegister inlineCallFrameStart, CodeSpecializationKind kind)
+    : m_byteCodeParser(byteCodeParser)
+    , m_codeBlock(codeBlock)
+    , m_profiledBlock(profiledBlock)
+    , m_calleeVR(calleeVR)
+    , m_exitProfile(profiledBlock->exitProfile())
+    , m_callsiteBlockHead(callsiteBlockHead)
+    , m_returnValue(returnValueVR)
+    , m_lazyOperands(profiledBlock->lazyOperandValueProfiles())
+    , m_didReturn(false)
+    , m_didEarlyReturn(false)
+    , m_caller(byteCodeParser->m_inlineStackTop)
+{
+    m_argumentPositions.resize(codeBlock->numParameters());
+    for (unsigned i = codeBlock->numParameters(); i--;) {
+        byteCodeParser->m_graph.m_argumentPositions.append(ArgumentPosition());
+        ArgumentPosition* argumentPosition = &byteCodeParser->m_graph.m_argumentPositions.last();
+        m_argumentPositions[i] = argumentPosition;
+    }
+        
+    if (m_caller) {
+        // Inline case.
+        ASSERT(codeBlock != byteCodeParser->m_codeBlock);
+        ASSERT(callee);
+        ASSERT(calleeVR != InvalidVirtualRegister);
+        ASSERT(inlineCallFrameStart != InvalidVirtualRegister);
+        ASSERT(callsiteBlockHead != NoBlock);
+        
+        InlineCallFrame inlineCallFrame;
+        inlineCallFrame.executable.set(*byteCodeParser->m_globalData, byteCodeParser->m_codeBlock->ownerExecutable(), codeBlock->ownerExecutable());
+        inlineCallFrame.stackOffset = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize;
+        inlineCallFrame.callee.set(*byteCodeParser->m_globalData, byteCodeParser->m_codeBlock->ownerExecutable(), callee);
+        inlineCallFrame.caller = byteCodeParser->currentCodeOrigin();
+        inlineCallFrame.arguments.resize(codeBlock->numParameters()); // Set the number of arguments including this, but don't configure the value recoveries, yet.
+        inlineCallFrame.isCall = isCall(kind);
+        byteCodeParser->m_codeBlock->inlineCallFrames().append(inlineCallFrame);
+        m_inlineCallFrame = &byteCodeParser->m_codeBlock->inlineCallFrames().last();
+        
+        byteCodeParser->buildOperandMapsIfNecessary();
+        
+        m_identifierRemap.resize(codeBlock->numberOfIdentifiers());
+        m_constantRemap.resize(codeBlock->numberOfConstantRegisters());
+
+        for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i) {
+            StringImpl* rep = codeBlock->identifier(i).impl();
+            IdentifierMap::AddResult result = byteCodeParser->m_identifierMap.add(rep, byteCodeParser->m_codeBlock->numberOfIdentifiers());
+            if (result.isNewEntry)
+                byteCodeParser->m_codeBlock->addIdentifier(Identifier(byteCodeParser->m_globalData, rep));
+            m_identifierRemap[i] = result.iterator->second;
+        }
+        for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i) {
+            JSValue value = codeBlock->getConstant(i + FirstConstantRegisterIndex);
+            if (!value) {
+                if (byteCodeParser->m_emptyJSValueIndex == UINT_MAX) {
+                    byteCodeParser->m_emptyJSValueIndex = byteCodeParser->m_codeBlock->numberOfConstantRegisters() + FirstConstantRegisterIndex;
+                    byteCodeParser->m_codeBlock->addConstant(JSValue());
+                    byteCodeParser->m_constants.append(ConstantRecord());
+                }
+                m_constantRemap[i] = byteCodeParser->m_emptyJSValueIndex;
+                continue;
+            }
+            JSValueMap::AddResult result = byteCodeParser->m_jsValueMap.add(JSValue::encode(value), byteCodeParser->m_codeBlock->numberOfConstantRegisters() + FirstConstantRegisterIndex);
+            if (result.isNewEntry) {
+                byteCodeParser->m_codeBlock->addConstant(value);
+                byteCodeParser->m_constants.append(ConstantRecord());
+            }
+            m_constantRemap[i] = result.iterator->second;
         }
         }
-
-        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_callsiteBlockHeadNeedsLinking = true;
+    } else {
+        // Machine code block case.
+        ASSERT(codeBlock == byteCodeParser->m_codeBlock);
+        ASSERT(!callee);
+        ASSERT(calleeVR == InvalidVirtualRegister);
+        ASSERT(returnValueVR == InvalidVirtualRegister);
+        ASSERT(inlineCallFrameStart == InvalidVirtualRegister);
+        ASSERT(callsiteBlockHead == NoBlock);
+
+        m_inlineCallFrame = 0;
+
+        m_identifierRemap.resize(codeBlock->numberOfIdentifiers());
+        m_constantRemap.resize(codeBlock->numberOfConstantRegisters());
+
+        for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i)
+            m_identifierRemap[i] = i;
+        for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i)
+            m_constantRemap[i] = i + FirstConstantRegisterIndex;
+
+        m_callsiteBlockHeadNeedsLinking = false;
     }
     }
-
-    // '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;
+    
+    for (size_t i = 0; i < m_constantRemap.size(); ++i)
+        ASSERT(m_constantRemap[i] >= static_cast<unsigned>(FirstConstantRegisterIndex));
+    
+    byteCodeParser->m_inlineStackTop = this;
 }
 
 }
 
-bool ByteCodeParser::parse()
+void ByteCodeParser::parseCodeBlock()
 {
 {
-    // Set during construction.
-    ASSERT(!m_currentIndex);
-
-    for (unsigned jumpTargetIndex = 0; jumpTargetIndex <= m_codeBlock->numberOfJumpTargets(); ++jumpTargetIndex) {
+    CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock;
+    
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("Parsing code block %p. codeType = %s, numCapturedVars = %u, needsFullScopeChain = %s, needsActivation = %s, isStrictMode = %s\n",
+            codeBlock,
+            codeTypeToString(codeBlock->codeType()),
+            codeBlock->m_numCapturedVars,
+            codeBlock->needsFullScopeChain()?"true":"false",
+            codeBlock->ownerExecutable()->needsActivation()?"true":"false",
+            codeBlock->ownerExecutable()->isStrictMode()?"true":"false");
+#endif
+    
+    for (unsigned jumpTargetIndex = 0; jumpTargetIndex <= 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.
         // 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();
+        unsigned limit = jumpTargetIndex < codeBlock->numberOfJumpTargets() ? codeBlock->jumpTarget(jumpTargetIndex) : codeBlock->instructions().size();
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Parsing bytecode with limit %p bc#%u at inline depth %u.\n", m_inlineStackTop->executable(), limit, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame));
+#endif
         ASSERT(m_currentIndex < limit);
 
         // Loop until we reach the current limit (i.e. next jump target).
         do {
         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 (!m_currentBlock) {
+                // Check if we can use the last block.
+                if (!m_graph.m_blocks.isEmpty() && m_graph.m_blocks.last()->isEmpty()) {
+                    // This must be a block belonging to us.
+                    ASSERT(m_inlineStackTop->m_unlinkedBlocks.last().m_blockIndex == m_graph.m_blocks.size() - 1);
+                    // Either the block is linkable or it isn't. If it's linkable then it's the last
+                    // block in the blockLinkingTargets list. If it's not then the last block will
+                    // have a lower bytecode index that the one we're about to give to this block.
+                    if (m_inlineStackTop->m_blockLinkingTargets.isEmpty() || m_graph.m_blocks[m_inlineStackTop->m_blockLinkingTargets.last()]->bytecodeBegin != m_currentIndex) {
+                        // Make the block linkable.
+                        ASSERT(m_inlineStackTop->m_blockLinkingTargets.isEmpty() || m_graph.m_blocks[m_inlineStackTop->m_blockLinkingTargets.last()]->bytecodeBegin < m_currentIndex);
+                        m_inlineStackTop->m_blockLinkingTargets.append(m_graph.m_blocks.size() - 1);
+                    }
+                    // Change its bytecode begin and continue.
+                    m_currentBlock = m_graph.m_blocks.last().get();
+#if DFG_ENABLE(DEBUG_VERBOSE)
+                    dataLog("Reascribing bytecode index of block %p from bc#%u to bc#%u (peephole case).\n", m_currentBlock, m_currentBlock->bytecodeBegin, m_currentIndex);
+#endif
+                    m_currentBlock->bytecodeBegin = m_currentIndex;
+                } else {
+                    OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(m_currentIndex, m_numArguments, m_numLocals));
+#if DFG_ENABLE(DEBUG_VERBOSE)
+                    dataLog("Creating basic block %p, #%zu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame));
+#endif
+                    m_currentBlock = block.get();
+                    ASSERT(m_inlineStackTop->m_unlinkedBlocks.isEmpty() || m_graph.m_blocks[m_inlineStackTop->m_unlinkedBlocks.last().m_blockIndex]->bytecodeBegin < m_currentIndex);
+                    m_inlineStackTop->m_unlinkedBlocks.append(UnlinkedBlock(m_graph.m_blocks.size()));
+                    m_inlineStackTop->m_blockLinkingTargets.append(m_graph.m_blocks.size());
+                    m_graph.m_blocks.append(block.release());
+                    prepareToParseBlock();
+                }
+            }
+
+            bool shouldContinueParsing = parseBlock(limit);
 
 
-            if (!parseBlock(limit))
-                return false;
             // We should not have gone beyond the limit.
             ASSERT(m_currentIndex <= limit);
             // We should not have gone beyond the limit.
             ASSERT(m_currentIndex <= limit);
-
-            m_currentBlock->end = m_graph.size();
+            
+            // We should have planted a terminal, or we just gave up because
+            // we realized that the jump target information is imprecise, or we
+            // are at the end of an inline function, or we realized that we
+            // should stop parsing because there was a return in the first
+            // basic block.
+            ASSERT(m_currentBlock->isEmpty() || m_graph.last().isTerminal() || (m_currentIndex == codeBlock->instructions().size() && m_inlineStackTop->m_inlineCallFrame) || !shouldContinueParsing);
+
+            if (!shouldContinueParsing)
+                return;
+            
+            m_currentBlock = 0;
         } while (m_currentIndex < limit);
     }
 
     // Should have reached the end of the instructions.
         } while (m_currentIndex < limit);
     }
 
     // Should have reached the end of the instructions.
-    ASSERT(m_currentIndex == m_codeBlock->instructions().size());
+    ASSERT(m_currentIndex == codeBlock->instructions().size());
+}
 
 
-    setupPredecessors();
+bool ByteCodeParser::parse()
+{
+    // Set during construction.
+    ASSERT(!m_currentIndex);
+    
+#if DFG_ENABLE(ALL_VARIABLES_CAPTURED)
+    // We should be pretending that the code has an activation.
+    ASSERT(m_graph.needsActivation());
+#endif
+    
+    InlineStackEntry inlineStackEntry(this, m_codeBlock, m_profiledBlock, NoBlock, InvalidVirtualRegister, 0, InvalidVirtualRegister, InvalidVirtualRegister, CodeForCall);
+    
+    parseCodeBlock();
+
+    linkBlocks(inlineStackEntry.m_unlinkedBlocks, inlineStackEntry.m_blockLinkingTargets);
+    determineReachability();
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+    dataLog("Processing local variable phis.\n");
+#endif
+    
+    m_currentProfilingIndex = m_currentIndex;
+    
     processPhiStack<LocalPhiStack>();
     processPhiStack<LocalPhiStack>();
-    processPhiStack<ArgumentPhiStack>();
-
-    allocateVirtualRegisters();
-
-#if DFG_DEBUG_VERBOSE
-    m_graph.dump(m_codeBlock);
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+    dataLog("Processing argument phis.\n");
 #endif
 #endif
+    processPhiStack<ArgumentPhiStack>();
+    
+    fixVariableAccessPredictions();
+    
+    m_graph.m_preservedVars = m_preservedVars;
+    m_graph.m_localVars = m_numLocals;
+    m_graph.m_parameterSlots = m_parameterSlots;
 
     return true;
 }
 
 
     return true;
 }
 
-bool parse(Graph& graph, JSGlobalData* globalData, CodeBlock* codeBlock)
+bool parse(Graph& graph)
 {
 #if DFG_DEBUG_LOCAL_DISBALE
     UNUSED_PARAM(graph);
 {
 #if DFG_DEBUG_LOCAL_DISBALE
     UNUSED_PARAM(graph);
-    UNUSED_PARAM(globalData);
-    UNUSED_PARAM(codeBlock);
     return false;
 #else
     return false;
 #else
-    return ByteCodeParser(globalData, codeBlock, graph).parse();
+    return ByteCodeParser(graph).parse();
 #endif
 }
 
 #endif
 }
 
index d4efe61db2d1c973ec53c638c8ef17585232d811..558cf01679cd89fcc7a2010238cbb4e2b58e57a0 100644 (file)
@@ -39,7 +39,7 @@ namespace DFG {
 
 // Populate the Graph with a basic block of code from the CodeBlock,
 // starting at the provided bytecode index.
 
 // Populate the Graph with a basic block of code from the CodeBlock,
 // starting at the provided bytecode index.
-bool parse(Graph&, JSGlobalData*, CodeBlock*);
+bool parse(Graph&);
 
 } } // namespace JSC::DFG
 
 
 } } // namespace JSC::DFG
 
diff --git a/dfg/DFGCCallHelpers.h b/dfg/DFGCCallHelpers.h
new file mode 100644 (file)
index 0000000..256608f
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+ * 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 DFGCCallHelpers_h
+#define DFGCCallHelpers_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAssemblyHelpers.h"
+#include "DFGGPRInfo.h"
+
+namespace JSC { namespace DFG {
+
+class CCallHelpers : public AssemblyHelpers {
+public:
+    CCallHelpers(JSGlobalData* globalData, CodeBlock* codeBlock)
+        : AssemblyHelpers(globalData, codeBlock)
+    {
+    }
+
+    // These methods used to sort arguments into the correct registers.
+    // On X86 we use cdecl calling conventions, which pass all arguments on the
+    // stack. On other architectures we may need to sort values into the
+    // correct registers.
+#if !NUMBER_OF_ARGUMENT_REGISTERS
+    unsigned m_callArgumentOffset;
+    void resetCallArguments() { m_callArgumentOffset = 0; }
+
+    // These methods are using internally to implement the callOperation methods.
+    void addCallArgument(GPRReg value)
+    {
+        poke(value, m_callArgumentOffset++);
+    }
+    void addCallArgument(TrustedImm32 imm)
+    {
+        poke(imm, m_callArgumentOffset++);
+    }
+    void addCallArgument(TrustedImmPtr pointer)
+    {
+        poke(pointer, m_callArgumentOffset++);
+    }
+    void addCallArgument(FPRReg value)
+    {
+        storeDouble(value, Address(stackPointerRegister, m_callArgumentOffset * sizeof(void*)));
+        m_callArgumentOffset += sizeof(double) / sizeof(void*);
+    }
+
+    ALWAYS_INLINE void setupArguments(FPRReg arg1)
+    {
+        resetCallArguments();
+        addCallArgument(arg1);
+    }
+
+    ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
+    {
+        resetCallArguments();
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+    }
+
+    ALWAYS_INLINE void setupArguments(GPRReg arg1)
+    {
+        resetCallArguments();
+        addCallArgument(arg1);
+    }
+
+    ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2)
+    {
+        resetCallArguments();
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+    }
+
+    ALWAYS_INLINE void setupArgumentsExecState()
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+        addCallArgument(arg4);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+        addCallArgument(arg4);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+        addCallArgument(arg4);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+        addCallArgument(arg4);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+        addCallArgument(arg4);
+        addCallArgument(arg5);
+    }
+#endif // !NUMBER_OF_ARGUMENT_REGISTERS
+    // These methods are suitable for any calling convention that provides for
+    // at least 4 argument registers, e.g. X86_64, ARMv7.
+#if NUMBER_OF_ARGUMENT_REGISTERS >= 4
+    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.
+            move(srcA, destA);
+            move(srcB, destB);
+        } else if (srcA != destB) {
+            // Handle the non-swap case - just put srcB in place first.
+            move(srcB, destB);
+            move(srcA, destA);
+        } else
+            swap(destA, destB);
+    }
+#if CPU(X86_64)
+    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.
+            moveDouble(srcA, destA);
+            moveDouble(srcB, destB);
+            return;
+        }
+        
+        if (srcA != destB) {
+            // Handle the non-swap case - just put srcB in place first.
+            moveDouble(srcB, destB);
+            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;
+        }
+        moveDouble(destA, temp);
+        moveDouble(destB, destA);
+        moveDouble(temp, destB);
+    }
+#endif
+    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) {
+            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) {
+            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) {
+            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) {
+            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)
+            swap(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
+    }
+
+#if CPU(X86_64)
+    ALWAYS_INLINE void setupArguments(FPRReg arg1)
+    {
+        moveDouble(arg1, FPRInfo::argumentFPR0);
+    }
+
+    ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
+    {
+        setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(arg1, arg2);
+    }
+#else
+    ALWAYS_INLINE void setupArguments(FPRReg arg1)
+    {
+        assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
+    }
+
+    ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
+    {
+        assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1);
+        assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg2);
+    }
+#endif
+
+    ALWAYS_INLINE void setupArguments(GPRReg arg1)
+    {
+        move(arg1, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2)
+    {
+        setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1, arg2);
+    }
+
+    ALWAYS_INLINE void setupArgumentsExecState()
+    {
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1)
+    {
+        move(arg1, GPRInfo::argumentGPR1);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1)
+    {
+        move(arg1, GPRInfo::argumentGPR1);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2)
+    {
+        setupStubArguments(arg1, arg2);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2)
+    {
+        move(arg1, GPRInfo::argumentGPR1);
+        move(arg2, GPRInfo::argumentGPR2);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+    
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, ImmPtr arg2)
+    {
+        move(arg1, GPRInfo::argumentGPR1);
+        move(arg2, GPRInfo::argumentGPR2);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2)
+    {
+        move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
+        move(arg1, GPRInfo::argumentGPR1);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+    
+    ALWAYS_INLINE void setupArgumentsWithExecState(ImmPtr arg1, GPRReg arg2)
+    {
+        move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample!
+        move(arg1, GPRInfo::argumentGPR1);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
+    {
+        move(arg1, GPRInfo::argumentGPR1);
+        move(arg2, GPRInfo::argumentGPR2);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2)
+    {
+        move(arg1, GPRInfo::argumentGPR1);
+        move(arg2, GPRInfo::argumentGPR2);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3)
+    {
+        setupStubArguments(arg1, arg2, arg3);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3)
+    {
+        setupStubArguments(arg1, arg2);
+        move(arg3, GPRInfo::argumentGPR3);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
+    {
+        move(arg1, GPRInfo::argumentGPR1);
+        move(arg2, GPRInfo::argumentGPR2);
+        move(arg3, GPRInfo::argumentGPR3);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
+    {
+        move(arg1, GPRInfo::argumentGPR1);
+        move(arg2, GPRInfo::argumentGPR2);
+        move(arg3, GPRInfo::argumentGPR3);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3)
+    {
+        setupStubArguments(arg1, arg2);
+        move(arg3, GPRInfo::argumentGPR3);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3)
+    {
+        move(arg1, GPRInfo::argumentGPR1);
+        move(arg2, GPRInfo::argumentGPR2);
+        move(arg3, GPRInfo::argumentGPR3);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
+#endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4
+    // These methods are suitable for any calling convention that provides for
+    // exactly 4 argument registers, e.g. ARMv7.
+#if NUMBER_OF_ARGUMENT_REGISTERS == 4
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
+    {
+        poke(arg4);
+        setupArgumentsWithExecState(arg1, arg2, arg3);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
+    {
+        poke(arg4);
+        setupArgumentsWithExecState(arg1, arg2, arg3);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
+    {
+        poke(arg4);
+        setupArgumentsWithExecState(arg1, arg2, arg3);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
+    {
+        poke(arg4);
+        setupArgumentsWithExecState(arg1, arg2, arg3);
+    }
+
+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+    {
+        poke(arg5, 1);
+        poke(arg4);
+        setupArgumentsWithExecState(arg1, arg2, arg3);
+    }
+#endif // NUMBER_OF_ARGUMENT_REGISTERS == 4
+
+    void setupResults(GPRReg destA, GPRReg destB)
+    {
+        GPRReg srcA = GPRInfo::returnValueGPR;
+        GPRReg srcB = GPRInfo::returnValueGPR2;
+
+        if (srcB != destA) {
+            // Handle the easy cases - two simple moves.
+            move(srcA, destA);
+            move(srcB, destB);
+        } else if (srcA != destB) {
+            // Handle the non-swap case - just put srcB in place first.
+            move(srcB, destB);
+            move(srcA, destA);
+        } else
+            swap(destA, destB);
+    }
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGCCallHelpers_h
+
diff --git a/dfg/DFGCFAPhase.cpp b/dfg/DFGCFAPhase.cpp
new file mode 100644 (file)
index 0000000..6e69c10
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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 "DFGCFAPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAbstractState.h"
+#include "DFGGraph.h"
+#include "DFGPhase.h"
+
+namespace JSC { namespace DFG {
+
+class CFAPhase : public Phase {
+public:
+    CFAPhase(Graph& graph)
+        : Phase(graph, "control flow analysis")
+        , m_state(graph)
+    {
+    }
+    
+    void run()
+    {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        m_count = 0;
+#endif
+        
+        // This implements a pseudo-worklist-based forward CFA, except that the visit order
+        // of blocks is the bytecode program order (which is nearly topological), and
+        // instead of a worklist we just walk all basic blocks checking if cfaShouldRevisit
+        // is set to true. This is likely to balance the efficiency properties of both
+        // worklist-based and forward fixpoint-based approaches. Like a worklist-based
+        // approach, it won't visit code if it's meaningless to do so (nothing changed at
+        // the head of the block or the predecessors have not been visited). Like a forward
+        // fixpoint-based approach, it has a high probability of only visiting a block
+        // after all predecessors have been visited. Only loops will cause this analysis to
+        // revisit blocks, and the amount of revisiting is proportional to loop depth.
+        
+        AbstractState::initialize(m_graph);
+        
+        do {
+            m_changed = false;
+            performForwardCFA();
+        } while (m_changed);
+    }
+    
+private:
+    void performBlockCFA(BlockIndex blockIndex)
+    {
+        BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+        if (!block->cfaShouldRevisit)
+            return;
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("   Block #%u (bc#%u):\n", blockIndex, block->bytecodeBegin);
+#endif
+        m_state.beginBasicBlock(block);
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("      head vars: ");
+        dumpOperands(block->valuesAtHead, WTF::dataFile());
+        dataLog("\n");
+#endif
+        for (unsigned i = 0; i < block->size(); ++i) {
+            NodeIndex nodeIndex = block->at(i);
+            if (!m_graph[nodeIndex].shouldGenerate())
+                continue;
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+            dataLog("      %s @%u: ", Graph::opName(m_graph[nodeIndex].op()), nodeIndex);
+            m_state.dump(WTF::dataFile());
+            dataLog("\n");
+#endif
+            if (!m_state.execute(i))
+                break;
+        }
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("      tail regs: ");
+        m_state.dump(WTF::dataFile());
+        dataLog("\n");
+#endif
+        m_changed |= m_state.endBasicBlock(AbstractState::MergeToSuccessors);
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("      tail vars: ");
+        dumpOperands(block->valuesAtTail, WTF::dataFile());
+        dataLog("\n");
+#endif
+    }
+    
+    void performForwardCFA()
+    {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("CFA [%u]\n", ++m_count);
+#endif
+        
+        for (BlockIndex block = 0; block < m_graph.m_blocks.size(); ++block)
+            performBlockCFA(block);
+    }
+
+private:
+    AbstractState m_state;
+    
+    bool m_changed;
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+    unsigned m_count;
+#endif
+};
+
+void performCFA(Graph& graph)
+{
+    runPhase<CFAPhase>(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
diff --git a/dfg/DFGCFAPhase.h b/dfg/DFGCFAPhase.h
new file mode 100644 (file)
index 0000000..2b626c8
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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 DFGCFAPhase_h
+#define DFGCFAPhase_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// Global control flow analysis. This phase transforms the combination of type
+// predictions and type guards into type proofs, and flows them globally within
+// the code block. It's also responsible for identifying dead code, and in the
+// future should be used as a hook for constant propagation.
+
+void performCFA(Graph&);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGCFAPhase_h
+
diff --git a/dfg/DFGCSEPhase.cpp b/dfg/DFGCSEPhase.cpp
new file mode 100644 (file)
index 0000000..020b1cf
--- /dev/null
@@ -0,0 +1,713 @@
+/*
+ * 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 "DFGCSEPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGGraph.h"
+#include "DFGPhase.h"
+
+namespace JSC { namespace DFG {
+
+class CSEPhase : public Phase {
+public:
+    CSEPhase(Graph& graph)
+        : Phase(graph, "common subexpression elimination")
+    {
+        // Replacements are used to implement local common subexpression elimination.
+        m_replacements.resize(m_graph.size());
+        
+        for (unsigned i = 0; i < m_graph.size(); ++i)
+            m_replacements[i] = NoNode;
+    }
+    
+    void run()
+    {
+        for (unsigned block = 0; block < m_graph.m_blocks.size(); ++block)
+            performBlockCSE(*m_graph.m_blocks[block]);
+    }
+    
+private:
+    
+    NodeIndex canonicalize(NodeIndex nodeIndex)
+    {
+        if (nodeIndex == NoNode)
+            return NoNode;
+        
+        if (m_graph[nodeIndex].op() == ValueToInt32)
+            nodeIndex = m_graph[nodeIndex].child1().index();
+        
+        return nodeIndex;
+    }
+    NodeIndex canonicalize(Edge nodeUse)
+    {
+        return canonicalize(nodeUse.indexUnchecked());
+    }
+    
+    unsigned endIndexForPureCSE()
+    {
+        unsigned result = m_lastSeen[m_graph[m_compileIndex].op()];
+        if (result == UINT_MAX)
+            result = 0;
+        else
+            result++;
+        ASSERT(result <= m_indexInBlock);
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("  limit %u: ", result);
+#endif
+        return result;
+    }
+    
+    NodeIndex pureCSE(Node& node)
+    {
+        NodeIndex child1 = canonicalize(node.child1());
+        NodeIndex child2 = canonicalize(node.child2());
+        NodeIndex child3 = canonicalize(node.child3());
+        
+        for (unsigned i = endIndexForPureCSE(); i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            if (index == child1 || index == child2 || index == child3)
+                break;
+
+            Node& otherNode = m_graph[index];
+            if (node.op() != otherNode.op())
+                continue;
+            
+            if (node.arithNodeFlags() != otherNode.arithNodeFlags())
+                continue;
+            
+            NodeIndex otherChild = canonicalize(otherNode.child1());
+            if (otherChild == NoNode)
+                return index;
+            if (otherChild != child1)
+                continue;
+            
+            otherChild = canonicalize(otherNode.child2());
+            if (otherChild == NoNode)
+                return index;
+            if (otherChild != child2)
+                continue;
+            
+            otherChild = canonicalize(otherNode.child3());
+            if (otherChild == NoNode)
+                return index;
+            if (otherChild != child3)
+                continue;
+            
+            return index;
+        }
+        return NoNode;
+    }
+    
+    bool isPredictedNumerical(Node& node)
+    {
+        PredictedType left = m_graph[node.child1()].prediction();
+        PredictedType right = m_graph[node.child2()].prediction();
+        return isNumberPrediction(left) && isNumberPrediction(right);
+    }
+    
+    bool logicalNotIsPure(Node& node)
+    {
+        PredictedType prediction = m_graph[node.child1()].prediction();
+        return isBooleanPrediction(prediction) || !prediction;
+    }
+    
+    bool byValIsPure(Node& node)
+    {
+        return m_graph[node.child2()].shouldSpeculateInteger()
+            && ((node.op() == PutByVal || node.op() == PutByValAlias)
+                ? isActionableMutableArrayPrediction(m_graph[node.child1()].prediction())
+                : isActionableArrayPrediction(m_graph[node.child1()].prediction()));
+    }
+    
+    bool clobbersWorld(NodeIndex nodeIndex)
+    {
+        Node& node = m_graph[nodeIndex];
+        if (node.flags() & NodeClobbersWorld)
+            return true;
+        if (!(node.flags() & NodeMightClobber))
+            return false;
+        switch (node.op()) {
+        case ValueAdd:
+        case CompareLess:
+        case CompareLessEq:
+        case CompareGreater:
+        case CompareGreaterEq:
+        case CompareEq:
+            return !isPredictedNumerical(node);
+        case LogicalNot:
+            return !logicalNotIsPure(node);
+        case GetByVal:
+            return !byValIsPure(node);
+        default:
+            ASSERT_NOT_REACHED();
+            return true; // If by some oddity we hit this case in release build it's safer to have CSE assume the worst.
+        }
+    }
+    
+    NodeIndex impureCSE(Node& node)
+    {
+        NodeIndex child1 = canonicalize(node.child1());
+        NodeIndex child2 = canonicalize(node.child2());
+        NodeIndex child3 = canonicalize(node.child3());
+        
+        for (unsigned i = m_indexInBlock; i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            if (index == child1 || index == child2 || index == child3)
+                break;
+
+            Node& otherNode = m_graph[index];
+            if (node.op() == otherNode.op()
+                && node.arithNodeFlags() == otherNode.arithNodeFlags()) {
+                NodeIndex otherChild = canonicalize(otherNode.child1());
+                if (otherChild == NoNode)
+                    return index;
+                if (otherChild == child1) {
+                    otherChild = canonicalize(otherNode.child2());
+                    if (otherChild == NoNode)
+                        return index;
+                    if (otherChild == child2) {
+                        otherChild = canonicalize(otherNode.child3());
+                        if (otherChild == NoNode)
+                            return index;
+                        if (otherChild == child3)
+                            return index;
+                    }
+                }
+            }
+            if (clobbersWorld(index))
+                break;
+        }
+        return NoNode;
+    }
+    
+    NodeIndex globalVarLoadElimination(unsigned varNumber, JSGlobalObject* globalObject)
+    {
+        for (unsigned i = m_indexInBlock; i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            Node& node = m_graph[index];
+            switch (node.op()) {
+            case GetGlobalVar:
+                if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+                    return index;
+                break;
+            case PutGlobalVar:
+                if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+                    return node.child1().index();
+                break;
+            default:
+                break;
+            }
+            if (clobbersWorld(index))
+                break;
+        }
+        return NoNode;
+    }
+    
+    NodeIndex getByValLoadElimination(NodeIndex child1, NodeIndex child2)
+    {
+        for (unsigned i = m_indexInBlock; i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            if (index == child1 || index == canonicalize(child2)) 
+                break;
+
+            Node& node = m_graph[index];
+            switch (node.op()) {
+            case GetByVal:
+                if (!byValIsPure(node))
+                    return NoNode;
+                if (node.child1() == child1 && canonicalize(node.child2()) == canonicalize(child2))
+                    return index;
+                break;
+            case PutByVal:
+            case PutByValAlias:
+                if (!byValIsPure(node))
+                    return NoNode;
+                if (node.child1() == child1 && canonicalize(node.child2()) == canonicalize(child2))
+                    return node.child3().index();
+                // We must assume that the PutByVal will clobber the location we're getting from.
+                // FIXME: We can do better; if we know that the PutByVal is accessing an array of a
+                // different type than the GetByVal, then we know that they won't clobber each other.
+                return NoNode;
+            case PutStructure:
+            case PutByOffset:
+                // GetByVal currently always speculates that it's accessing an
+                // array with an integer index, which means that it's impossible
+                // for a structure change or a put to property storage to affect
+                // the GetByVal.
+                break;
+            case ArrayPush:
+                // A push cannot affect previously existing elements in the array.
+                break;
+            default:
+                if (clobbersWorld(index))
+                    return NoNode;
+                break;
+            }
+        }
+        return NoNode;
+    }
+
+    bool checkFunctionElimination(JSFunction* function, NodeIndex child1)
+    {
+        for (unsigned i = endIndexForPureCSE(); i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            if (index == child1) 
+                break;
+
+            Node& node = m_graph[index];
+            if (node.op() == CheckFunction && node.child1() == child1 && node.function() == function)
+                return true;
+        }
+        return false;
+    }
+
+    bool checkStructureLoadElimination(const StructureSet& structureSet, NodeIndex child1)
+    {
+        for (unsigned i = m_indexInBlock; i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            if (index == child1) 
+                break;
+
+            Node& node = m_graph[index];
+            switch (node.op()) {
+            case CheckStructure:
+                if (node.child1() == child1
+                    && structureSet.isSupersetOf(node.structureSet()))
+                    return true;
+                break;
+                
+            case PutStructure:
+                if (node.child1() == child1
+                    && structureSet.contains(node.structureTransitionData().newStructure))
+                    return true;
+                if (structureSet.contains(node.structureTransitionData().previousStructure))
+                    return false;
+                break;
+                
+            case PutByOffset:
+                // Setting a property cannot change the structure.
+                break;
+                
+            case PutByVal:
+            case PutByValAlias:
+                if (byValIsPure(node)) {
+                    // If PutByVal speculates that it's accessing an array with an
+                    // integer index, then it's impossible for it to cause a structure
+                    // change.
+                    break;
+                }
+                return false;
+                
+            default:
+                if (clobbersWorld(index))
+                    return false;
+                break;
+            }
+        }
+        return false;
+    }
+    
+    NodeIndex getByOffsetLoadElimination(unsigned identifierNumber, NodeIndex child1)
+    {
+        for (unsigned i = m_indexInBlock; i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            if (index == child1) 
+                break;
+
+            Node& node = m_graph[index];
+            switch (node.op()) {
+            case GetByOffset:
+                if (node.child1() == child1
+                    && m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber)
+                    return index;
+                break;
+                
+            case PutByOffset:
+                if (m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber) {
+                    if (node.child2() == child1)
+                        return node.child3().index();
+                    return NoNode;
+                }
+                break;
+                
+            case PutStructure:
+                // Changing the structure cannot change the outcome of a property get.
+                break;
+                
+            case PutByVal:
+            case PutByValAlias:
+                if (byValIsPure(node)) {
+                    // If PutByVal speculates that it's accessing an array with an
+                    // integer index, then it's impossible for it to cause a structure
+                    // change.
+                    break;
+                }
+                return NoNode;
+                
+            default:
+                if (clobbersWorld(index))
+                    return NoNode;
+                break;
+            }
+        }
+        return NoNode;
+    }
+    
+    NodeIndex getPropertyStorageLoadElimination(NodeIndex child1)
+    {
+        for (unsigned i = m_indexInBlock; i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            if (index == child1) 
+                break;
+
+            Node& node = m_graph[index];
+            switch (node.op()) {
+            case GetPropertyStorage:
+                if (node.child1() == child1)
+                    return index;
+                break;
+                
+            case PutByOffset:
+            case PutStructure:
+                // Changing the structure or putting to the storage cannot
+                // change the property storage pointer.
+                break;
+                
+            case PutByVal:
+            case PutByValAlias:
+                if (byValIsPure(node)) {
+                    // If PutByVal speculates that it's accessing an array with an
+                    // integer index, then it's impossible for it to cause a structure
+                    // change.
+                    break;
+                }
+                return NoNode;
+                
+            default:
+                if (clobbersWorld(index))
+                    return NoNode;
+                break;
+            }
+        }
+        return NoNode;
+    }
+
+    NodeIndex getIndexedPropertyStorageLoadElimination(NodeIndex child1, bool hasIntegerIndexPrediction)
+    {
+        for (unsigned i = m_indexInBlock; i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            if (index == child1) 
+                break;
+
+            Node& node = m_graph[index];
+            switch (node.op()) {
+            case GetIndexedPropertyStorage: {
+                PredictedType basePrediction = m_graph[node.child2()].prediction();
+                bool nodeHasIntegerIndexPrediction = !(!(basePrediction & PredictInt32) && basePrediction);
+                if (node.child1() == child1 && hasIntegerIndexPrediction == nodeHasIntegerIndexPrediction)
+                    return index;
+                break;
+            }
+
+            case PutByOffset:
+            case PutStructure:
+                // Changing the structure or putting to the storage cannot
+                // change the property storage pointer.
+                break;
+                
+            case PutByValAlias:
+                // PutByValAlias can't change the indexed storage pointer
+                break;
+                
+            case PutByVal:
+                if (isFixedIndexedStorageObjectPrediction(m_graph[node.child1()].prediction()) && byValIsPure(node))
+                    break;
+                return NoNode;
+
+            default:
+                if (clobbersWorld(index))
+                    return NoNode;
+                break;
+            }
+        }
+        return NoNode;
+    }
+    
+    NodeIndex getScopeChainLoadElimination(unsigned depth)
+    {
+        for (unsigned i = endIndexForPureCSE(); i--;) {
+            NodeIndex index = m_currentBlock->at(i);
+            Node& node = m_graph[index];
+            if (node.op() == GetScopeChain
+                && node.scopeChainDepth() == depth)
+                return index;
+        }
+        return NoNode;
+    }
+    
+    void performSubstitution(Edge& child, bool addRef = true)
+    {
+        // Check if this operand is actually unused.
+        if (!child)
+            return;
+        
+        // Check if there is any replacement.
+        NodeIndex replacement = m_replacements[child.index()];
+        if (replacement == NoNode)
+            return;
+        
+        child.setIndex(replacement);
+        
+        // There is definitely a replacement. Assert that the replacement does not
+        // have a replacement.
+        ASSERT(m_replacements[child.index()] == NoNode);
+        
+        if (addRef)
+            m_graph[child].ref();
+    }
+    
+    void setReplacement(NodeIndex replacement)
+    {
+        if (replacement == NoNode)
+            return;
+        
+        // Be safe. Don't try to perform replacements if the predictions don't
+        // agree.
+        if (m_graph[m_compileIndex].prediction() != m_graph[replacement].prediction())
+            return;
+        
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("   Replacing @%u -> @%u", m_compileIndex, replacement);
+#endif
+        
+        Node& node = m_graph[m_compileIndex];
+        node.setOpAndDefaultFlags(Phantom);
+        node.setRefCount(1);
+        
+        // At this point we will eliminate all references to this node.
+        m_replacements[m_compileIndex] = replacement;
+    }
+    
+    void eliminate()
+    {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("   Eliminating @%u", m_compileIndex);
+#endif
+        
+        Node& node = m_graph[m_compileIndex];
+        ASSERT(node.refCount() == 1);
+        ASSERT(node.mustGenerate());
+        node.setOpAndDefaultFlags(Phantom);
+    }
+    
+    void performNodeCSE(Node& node)
+    {
+        bool shouldGenerate = node.shouldGenerate();
+
+        if (node.flags() & NodeHasVarArgs) {
+            for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
+                performSubstitution(m_graph.m_varArgChildren[childIdx], shouldGenerate);
+        } else {
+            performSubstitution(node.children.child1(), shouldGenerate);
+            performSubstitution(node.children.child2(), shouldGenerate);
+            performSubstitution(node.children.child3(), shouldGenerate);
+        }
+        
+        if (!shouldGenerate)
+            return;
+        
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("   %s @%u: ", Graph::opName(m_graph[m_compileIndex].op()), m_compileIndex);
+#endif
+        
+        // NOTE: there are some nodes that we deliberately don't CSE even though we
+        // probably could, like StrCat and ToPrimitive. That's because there is no
+        // evidence that doing CSE on these nodes would result in a performance
+        // progression. Hence considering these nodes in CSE would just mean that this
+        // code does more work with no win. Of course, we may want to reconsider this,
+        // since StrCat is trivially CSE-able. It's not trivially doable for
+        // ToPrimitive, but we could change that with some speculations if we really
+        // needed to.
+        
+        switch (node.op()) {
+        
+        // Handle the pure nodes. These nodes never have any side-effects.
+        case BitAnd:
+        case BitOr:
+        case BitXor:
+        case BitRShift:
+        case BitLShift:
+        case BitURShift:
+        case ArithAdd:
+        case ArithSub:
+        case ArithNegate:
+        case ArithMul:
+        case ArithMod:
+        case ArithDiv:
+        case ArithAbs:
+        case ArithMin:
+        case ArithMax:
+        case ArithSqrt:
+        case GetInt8ArrayLength:
+        case GetInt16ArrayLength:
+        case GetInt32ArrayLength:
+        case GetUint8ArrayLength:
+        case GetUint8ClampedArrayLength:
+        case GetUint16ArrayLength:
+        case GetUint32ArrayLength:
+        case GetFloat32ArrayLength:
+        case GetFloat64ArrayLength:
+        case GetCallee:
+        case GetStringLength:
+        case StringCharAt:
+        case StringCharCodeAt:
+        case Int32ToDouble:
+        case IsUndefined:
+        case IsBoolean:
+        case IsNumber:
+        case IsString:
+        case IsObject:
+        case IsFunction:
+        case DoubleAsInt32:
+            setReplacement(pureCSE(node));
+            break;
+            
+        case GetArrayLength:
+            setReplacement(impureCSE(node));
+            break;
+            
+        case GetScopeChain:
+            setReplacement(getScopeChainLoadElimination(node.scopeChainDepth()));
+            break;
+
+        // Handle nodes that are conditionally pure: these are pure, and can
+        // be CSE'd, so long as the prediction is the one we want.
+        case ValueAdd:
+        case CompareLess:
+        case CompareLessEq:
+        case CompareGreater:
+        case CompareGreaterEq:
+        case CompareEq: {
+            if (isPredictedNumerical(node)) {
+                NodeIndex replacementIndex = pureCSE(node);
+                if (replacementIndex != NoNode && isPredictedNumerical(m_graph[replacementIndex]))
+                    setReplacement(replacementIndex);
+            }
+            break;
+        }
+            
+        case LogicalNot: {
+            if (logicalNotIsPure(node)) {
+                NodeIndex replacementIndex = pureCSE(node);
+                if (replacementIndex != NoNode && logicalNotIsPure(m_graph[replacementIndex]))
+                    setReplacement(replacementIndex);
+            }
+            break;
+        }
+            
+        // Finally handle heap accesses. These are not quite pure, but we can still
+        // optimize them provided that some subtle conditions are met.
+        case GetGlobalVar:
+            setReplacement(globalVarLoadElimination(node.varNumber(), codeBlock()->globalObjectFor(node.codeOrigin)));
+            break;
+            
+        case GetByVal:
+            if (byValIsPure(node))
+                setReplacement(getByValLoadElimination(node.child1().index(), node.child2().index()));
+            break;
+            
+        case PutByVal:
+            if (byValIsPure(node) && getByValLoadElimination(node.child1().index(), node.child2().index()) != NoNode)
+                node.setOp(PutByValAlias);
+            break;
+            
+        case CheckStructure:
+            if (checkStructureLoadElimination(node.structureSet(), node.child1().index()))
+                eliminate();
+            break;
+
+        case CheckFunction:
+            if (checkFunctionElimination(node.function(), node.child1().index()))
+                eliminate();
+            break;
+                
+        case GetIndexedPropertyStorage: {
+            PredictedType basePrediction = m_graph[node.child2()].prediction();
+            bool nodeHasIntegerIndexPrediction = !(!(basePrediction & PredictInt32) && basePrediction);
+            setReplacement(getIndexedPropertyStorageLoadElimination(node.child1().index(), nodeHasIntegerIndexPrediction));
+            break;
+        }
+
+        case GetPropertyStorage:
+            setReplacement(getPropertyStorageLoadElimination(node.child1().index()));
+            break;
+
+        case GetByOffset:
+            setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber, node.child1().index()));
+            break;
+            
+        default:
+            // do nothing.
+            break;
+        }
+        
+        m_lastSeen[node.op()] = m_indexInBlock;
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("\n");
+#endif
+    }
+    
+    void performBlockCSE(BasicBlock& block)
+    {
+        m_currentBlock = &block;
+        for (unsigned i = 0; i < LastNodeType; ++i)
+            m_lastSeen[i] = UINT_MAX;
+
+        for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) {
+            m_compileIndex = block[m_indexInBlock];
+            performNodeCSE(m_graph[m_compileIndex]);
+        }
+    }
+    
+    BasicBlock* m_currentBlock;
+    NodeIndex m_compileIndex;
+    unsigned m_indexInBlock;
+    Vector<NodeIndex, 16> m_replacements;
+    FixedArray<unsigned, LastNodeType> m_lastSeen;
+};
+
+void performCSE(Graph& graph)
+{
+    runPhase<CSEPhase>(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+
diff --git a/dfg/DFGCSEPhase.h b/dfg/DFGCSEPhase.h
new file mode 100644 (file)
index 0000000..3f13f10
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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 DFGCSEPhase_h
+#define DFGCSEPhase_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// Block-local common subexpression elimination. This is an optional phase, but
+// it is rather profitable. It has fairly accurate heap modeling and will match
+// a wide range of subexpression similarities. It's known to produce big wins
+// on a few benchmarks, and is relatively cheap to run.
+
+void performCSE(Graph&);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGCSEPhase_h
+
diff --git a/dfg/DFGCapabilities.cpp b/dfg/DFGCapabilities.cpp
new file mode 100644 (file)
index 0000000..450a5d8
--- /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. 
+ */
+
+#include "config.h"
+#include "DFGCapabilities.h"
+
+#include "CodeBlock.h"
+#include "DFGCommon.h"
+#include "Interpreter.h"
+
+namespace JSC { namespace DFG {
+
+#if ENABLE(DFG_JIT)
+
+static inline void debugFail(CodeBlock* codeBlock, OpcodeID opcodeID)
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("Cannot handle code block %p because of opcode %s.\n", codeBlock, opcodeNames[opcodeID]);
+#else
+    UNUSED_PARAM(codeBlock);
+    UNUSED_PARAM(opcodeID);
+#endif
+}
+
+template<bool (*canHandleOpcode)(OpcodeID)>
+bool canHandleOpcodes(CodeBlock* codeBlock)
+{
+    Interpreter* interpreter = codeBlock->globalData()->interpreter;
+    Instruction* instructionsBegin = codeBlock->instructions().begin();
+    unsigned instructionCount = codeBlock->instructions().size();
+    
+    for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount; ) {
+        switch (interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode)) {
+#define DEFINE_OP(opcode, length)               \
+        case opcode:                            \
+            if (!canHandleOpcode(opcode)) {     \
+                debugFail(codeBlock, opcode);   \
+                return false;                   \
+            }                                   \
+            bytecodeOffset += length;           \
+            break;
+            FOR_EACH_OPCODE_ID(DEFINE_OP)
+#undef DEFINE_OP
+        default:
+            ASSERT_NOT_REACHED();
+            break;
+        }
+    }
+    
+    return true;
+}
+
+bool canCompileOpcodes(CodeBlock* codeBlock)
+{
+    if (!MacroAssembler::supportsFloatingPoint())
+        return false;
+    return canHandleOpcodes<canCompileOpcode>(codeBlock);
+}
+
+bool canInlineOpcodes(CodeBlock* codeBlock)
+{
+    return canHandleOpcodes<canInlineOpcode>(codeBlock);
+}
+
+#endif
+
+} } // namespace JSC::DFG
+
diff --git a/dfg/DFGCapabilities.h b/dfg/DFGCapabilities.h
new file mode 100644 (file)
index 0000000..b807979
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * 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 DFGCapabilities_h
+#define DFGCapabilities_h
+
+#include "Intrinsic.h"
+#include "DFGNode.h"
+#include "Executable.h"
+#include "Options.h"
+#include "Interpreter.h"
+#include <wtf/Platform.h>
+
+namespace JSC { namespace DFG {
+
+#if ENABLE(DFG_JIT)
+// Fast check functions; if they return true it is still necessary to
+// check opcodes.
+inline bool mightCompileEval(CodeBlock* codeBlock)
+{
+    return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount;
+}
+inline bool mightCompileProgram(CodeBlock* codeBlock)
+{
+    return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount;
+}
+inline bool mightCompileFunctionForCall(CodeBlock* codeBlock)
+{
+    return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount;
+}
+inline bool mightCompileFunctionForConstruct(CodeBlock* codeBlock)
+{
+    return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount;
+}
+
+inline bool mightInlineFunctionForCall(CodeBlock* codeBlock)
+{
+    return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount
+        && !codeBlock->ownerExecutable()->needsActivation();
+}
+inline bool mightInlineFunctionForConstruct(CodeBlock* codeBlock)
+{
+    return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount
+        && !codeBlock->ownerExecutable()->needsActivation();
+}
+
+// Opcode checking.
+inline bool canCompileOpcode(OpcodeID opcodeID)
+{
+    switch (opcodeID) {
+    case op_enter:
+    case op_convert_this:
+    case op_create_this:
+    case op_get_callee:
+    case op_bitand:
+    case op_bitor:
+    case op_bitxor:
+    case op_rshift:
+    case op_lshift:
+    case op_urshift:
+    case op_pre_inc:
+    case op_post_inc:
+    case op_pre_dec:
+    case op_post_dec:
+    case op_add:
+    case op_sub:
+    case op_negate:
+    case op_mul:
+    case op_mod:
+    case op_div:
+#if ENABLE(DEBUG_WITH_BREAKPOINT)
+    case op_debug:
+#endif
+    case op_mov:
+    case op_check_has_instance:
+    case op_instanceof:
+    case op_is_undefined:
+    case op_is_boolean:
+    case op_is_number:
+    case op_is_string:
+    case op_is_object:
+    case op_is_function:
+    case op_not:
+    case op_less:
+    case op_lesseq:
+    case op_greater:
+    case op_greatereq:
+    case op_eq:
+    case op_eq_null:
+    case op_stricteq:
+    case op_neq:
+    case op_neq_null:
+    case op_nstricteq:
+    case op_get_by_val:
+    case op_put_by_val:
+    case op_method_check:
+    case op_get_scoped_var:
+    case op_put_scoped_var:
+    case op_get_by_id:
+    case op_put_by_id:
+    case op_put_by_id_transition_direct:
+    case op_put_by_id_transition_normal:
+    case op_get_global_var:
+    case op_put_global_var:
+    case op_jmp:
+    case op_loop:
+    case op_jtrue:
+    case op_jfalse:
+    case op_loop_if_true:
+    case op_loop_if_false:
+    case op_jeq_null:
+    case op_jneq_null:
+    case op_jless:
+    case op_jlesseq:
+    case op_jgreater:
+    case op_jgreatereq:
+    case op_jnless:
+    case op_jnlesseq:
+    case op_jngreater:
+    case op_jngreatereq:
+    case op_loop_hint:
+    case op_loop_if_less:
+    case op_loop_if_lesseq:
+    case op_loop_if_greater:
+    case op_loop_if_greatereq:
+    case op_ret:
+    case op_end:
+    case op_call_put_result:
+    case op_resolve:
+    case op_resolve_base:
+    case op_resolve_global:
+    case op_new_object:
+    case op_new_array:
+    case op_new_array_buffer:
+    case op_strcat:
+    case op_to_primitive:
+    case op_throw:
+    case op_throw_reference_error:
+    case op_call:
+    case op_construct:
+    case op_new_regexp: 
+    case op_init_lazy_reg:
+    case op_create_activation:
+    case op_tear_off_activation:
+    case op_new_func:
+    case op_new_func_exp:
+        return true;
+        
+    default:
+        return false;
+    }
+}
+
+inline bool canInlineOpcode(OpcodeID opcodeID)
+{
+    switch (opcodeID) {
+        
+    // These opcodes would be easy to support with inlining, but we currently don't do it.
+    // The issue is that the scope chain will not be set correctly.
+    case op_get_scoped_var:
+    case op_put_scoped_var:
+    case op_resolve:
+    case op_resolve_base:
+    case op_resolve_global:
+        
+    // Constant buffers aren't copied correctly. This is easy to fix, but for
+    // now we just disable inlining for functions that use them.
+    case op_new_array_buffer:
+        
+    // Inlining doesn't correctly remap regular expression operands.
+    case op_new_regexp:
+        return false;
+        
+    // We don't support inlining code that creates activations or has nested functions.
+    case op_init_lazy_reg:
+    case op_create_activation:
+    case op_tear_off_activation:
+    case op_new_func:
+    case op_new_func_exp:
+        return false;
+        
+    default:
+        return canCompileOpcode(opcodeID);
+    }
+}
+
+bool canCompileOpcodes(CodeBlock*);
+bool canInlineOpcodes(CodeBlock*);
+#else // ENABLE(DFG_JIT)
+inline bool mightCompileEval(CodeBlock*) { return false; }
+inline bool mightCompileProgram(CodeBlock*) { return false; }
+inline bool mightCompileFunctionForCall(CodeBlock*) { return false; }
+inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; }
+inline bool mightInlineFunctionForCall(CodeBlock*) { return false; }
+inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; }
+
+inline bool canCompileOpcode(OpcodeID) { return false; }
+inline bool canInlineOpcode(OpcodeID) { return false; }
+inline bool canCompileOpcodes(CodeBlock*) { return false; }
+inline bool canInlineOpcodes(CodeBlock*) { return false; }
+#endif // ENABLE(DFG_JIT)
+
+inline bool canCompileEval(CodeBlock* codeBlock)
+{
+    return mightCompileEval(codeBlock) && canCompileOpcodes(codeBlock);
+}
+
+inline bool canCompileProgram(CodeBlock* codeBlock)
+{
+    return mightCompileProgram(codeBlock) && canCompileOpcodes(codeBlock);
+}
+
+inline bool canCompileFunctionForCall(CodeBlock* codeBlock)
+{
+    return mightCompileFunctionForCall(codeBlock) && canCompileOpcodes(codeBlock);
+}
+
+inline bool canCompileFunctionForConstruct(CodeBlock* codeBlock)
+{
+    return mightCompileFunctionForConstruct(codeBlock) && canCompileOpcodes(codeBlock);
+}
+
+inline bool canInlineFunctionForCall(CodeBlock* codeBlock)
+{
+    return mightInlineFunctionForCall(codeBlock) && canInlineOpcodes(codeBlock);
+}
+
+inline bool canInlineFunctionForConstruct(CodeBlock* codeBlock)
+{
+    return mightInlineFunctionForConstruct(codeBlock) && canInlineOpcodes(codeBlock);
+}
+
+inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
+{
+    if (kind == CodeForCall)
+        return mightInlineFunctionForCall(codeBlock);
+    ASSERT(kind == CodeForConstruct);
+    return mightInlineFunctionForConstruct(codeBlock);
+}
+
+inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind)
+{
+    if (kind == CodeForCall)
+        return canInlineFunctionForCall(codeBlock);
+    ASSERT(kind == CodeForConstruct);
+    return canInlineFunctionForConstruct(codeBlock);
+}
+
+} } // namespace JSC::DFG
+
+#endif // DFGCapabilities_h
+
diff --git a/dfg/DFGCommon.h b/dfg/DFGCommon.h
new file mode 100644 (file)
index 0000000..828bcb2
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGCommon_h
+#define DFGCommon_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeOrigin.h"
+#include "VirtualRegister.h"
+
+/* DFG_ENABLE() - turn on a specific features in the DFG JIT */
+#define DFG_ENABLE(DFG_FEATURE) (defined DFG_ENABLE_##DFG_FEATURE && DFG_ENABLE_##DFG_FEATURE)
+
+// Emit various logging information for debugging, including dumping the dataflow graphs.
+#define DFG_ENABLE_DEBUG_VERBOSE 0
+// Emit dumps during propagation, in addition to just after.
+#define DFG_ENABLE_DEBUG_PROPAGATION_VERBOSE 0
+// Emit logging for OSR exit value recoveries at every node, not just nodes that
+// actually has speculation checks.
+#define DFG_ENABLE_VERBOSE_VALUE_RECOVERIES 0
+// Enable generation of dynamic checks into the instruction stream.
+#if !ASSERT_DISABLED
+#define DFG_ENABLE_JIT_ASSERT 1
+#else
+#define DFG_ENABLE_JIT_ASSERT 0
+#endif
+// Consistency check contents compiler data structures.
+#define DFG_ENABLE_CONSISTENCY_CHECK 0
+// Emit a breakpoint into the head of every generated function, to aid debugging in GDB.
+#define DFG_ENABLE_JIT_BREAK_ON_EVERY_FUNCTION 0
+// Emit a breakpoint into the head of every generated block, to aid debugging in GDB.
+#define DFG_ENABLE_JIT_BREAK_ON_EVERY_BLOCK 0
+// Emit a breakpoint into the head of every generated node, to aid debugging in GDB.
+#define DFG_ENABLE_JIT_BREAK_ON_EVERY_NODE 0
+// Emit a pair of xorPtr()'s on regT0 with the node index to make it easy to spot node boundaries in disassembled code.
+#define DFG_ENABLE_XOR_DEBUG_AID 0
+// Emit a breakpoint into the speculation failure code.
+#define DFG_ENABLE_JIT_BREAK_ON_SPECULATION_FAILURE 0
+// Log every speculation failure.
+#define DFG_ENABLE_VERBOSE_SPECULATION_FAILURE 0
+// Disable the DFG JIT without having to touch Platform.h
+#define DFG_DEBUG_LOCAL_DISBALE 0
+// Enable OSR entry from baseline JIT.
+#define DFG_ENABLE_OSR_ENTRY ENABLE(DFG_JIT)
+// Generate stats on how successful we were in making use of the DFG jit, and remaining on the hot path.
+#define DFG_ENABLE_SUCCESS_STATS 0
+// Enable verification that the DFG is able to insert code for control flow edges.
+#define DFG_ENABLE_EDGE_CODE_VERIFICATION 0
+// Pretend that all variables in the top-level code block got captured. Great
+// for testing code gen for activations.
+#define DFG_ENABLE_ALL_VARIABLES_CAPTURED 0
+
+namespace JSC { namespace DFG {
+
+// Type for a reference to another node in the graph.
+typedef uint32_t NodeIndex;
+static const NodeIndex NoNode = UINT_MAX;
+
+typedef uint32_t BlockIndex;
+static const BlockIndex NoBlock = UINT_MAX;
+
+struct NodeIndexTraits {
+    static NodeIndex defaultValue() { return NoNode; }
+    static void dump(NodeIndex value, FILE* out)
+    {
+        if (value == NoNode)
+            fprintf(out, "-");
+        else
+            fprintf(out, "@%u", value);
+    }
+};
+
+enum UseKind {
+    UntypedUse,
+    DoubleUse,
+    LastUseKind // Must always be the last entry in the enum, as it is used to denote the number of enum elements.
+};
+
+inline const char* useKindToString(UseKind useKind)
+{
+    switch (useKind) {
+    case UntypedUse:
+        return "";
+    case DoubleUse:
+        return "d";
+    default:
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+}
+
+inline bool isX86()
+{
+#if CPU(X86_64) || CPU(X86)
+    return true;
+#else
+    return false;
+#endif
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGCommon_h
+
diff --git a/dfg/DFGCorrectableJumpPoint.cpp b/dfg/DFGCorrectableJumpPoint.cpp
new file mode 100644 (file)
index 0000000..cfab2bd
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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 "DFGCorrectableJumpPoint.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeBlock.h"
+
+namespace JSC { namespace DFG {
+
+CodeLocationJump CorrectableJumpPoint::codeLocationForRepatch(CodeBlock* codeBlock) const
+{
+    ASSERT(m_mode == CorrectedJump);
+    return CodeLocationJump(codeBlock->getJITCode().dataAddressAtOffset(m_codeOffset));
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
diff --git a/dfg/DFGCorrectableJumpPoint.h b/dfg/DFGCorrectableJumpPoint.h
new file mode 100644 (file)
index 0000000..bfa1496
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * 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 DFGCorrectableJumpPoint_h
+#define DFGCorrectableJumpPoint_h
+
+#if ENABLE(DFG_JIT)
+
+#include "LinkBuffer.h"
+#include "MacroAssembler.h"
+
+namespace JSC { namespace DFG {
+
+// This is a type-safe union of MacroAssembler::Jump and CodeLocationJump.
+// Furthermore, it supports the notion of branching (possibly conditionally, but
+// also possibly jumping unconditionally) to an out-of-line patchable jump.
+// Thus it goes through three states:
+//
+// 1) Label of unpatchable branch or jump (i.e. MacroAssembler::Jump).
+// 2) Label of patchable jump (i.e. MacroAssembler::PatchableJump).
+// 3) Corrected post-linking label of patchable jump (i.e. CodeLocationJump).
+//
+// The setting of state (1) corresponds to planting the in-line unpatchable
+// branch or jump. The state transition (1)->(2) corresponds to linking the
+// in-line branch or jump to the out-of-line patchable jump, and recording
+// the latter's label. The state transition (2)->(3) corresponds to recording
+// the out-of-line patchable jump's location after branch compaction has
+// completed.
+//
+// You can also go directly from the first state to the third state, if you
+// wish to use this class for in-line patchable jumps.
+
+class CorrectableJumpPoint {
+public:
+    CorrectableJumpPoint(MacroAssembler::Jump check)
+        : m_codeOffset(check.m_label.m_offset)
+#ifndef NDEBUG
+        , m_mode(InitialJump)
+#endif
+    {
+#if CPU(ARM_THUMB2)
+        m_type = check.m_type;
+        m_condition = check.m_condition;
+#endif
+    }
+    
+    void switchToLateJump(MacroAssembler::PatchableJump check)
+    {
+#ifndef NDEBUG
+        ASSERT(m_mode == InitialJump);
+        m_mode = LateJump;
+#endif
+        // Late jumps should only ever be real jumps.
+#if CPU(ARM_THUMB2)
+        ASSERT(check.m_jump.m_type == ARMv7Assembler::JumpNoConditionFixedSize);
+        ASSERT(check.m_jump.m_condition == ARMv7Assembler::ConditionInvalid);
+        m_type = ARMv7Assembler::JumpNoConditionFixedSize;
+        m_condition = ARMv7Assembler::ConditionInvalid;
+#endif
+        m_codeOffset = check.m_jump.m_label.m_offset;
+    }
+    
+    void correctInitialJump(LinkBuffer& linkBuffer)
+    {
+        ASSERT(m_mode == InitialJump);
+#if CPU(ARM_THUMB2)
+        ASSERT(m_type == ARMv7Assembler::JumpNoConditionFixedSize);
+        ASSERT(m_condition == ARMv7Assembler::ConditionInvalid);
+#endif
+        correctJump(linkBuffer);
+    }
+    
+    void correctLateJump(LinkBuffer& linkBuffer)
+    {
+        ASSERT(m_mode == LateJump);
+        correctJump(linkBuffer);
+    }
+    
+    MacroAssembler::Jump initialJump() const
+    {
+        ASSERT(m_mode == InitialJump);
+        return getJump();
+    }
+    
+    MacroAssembler::Jump lateJump() const
+    {
+        ASSERT(m_mode == LateJump);
+        return getJump();
+    }
+    
+    CodeLocationJump codeLocationForRepatch(CodeBlock*) const;
+    
+private:
+    void correctJump(LinkBuffer& linkBuffer)
+    {
+#ifndef NDEBUG
+        m_mode = CorrectedJump;
+#endif
+        MacroAssembler::Label label;
+        label.m_label.m_offset = m_codeOffset;
+        m_codeOffset = linkBuffer.offsetOf(label);
+    }
+    
+    MacroAssembler::Jump getJump() const
+    {
+        MacroAssembler::Jump jump;
+        jump.m_label.m_offset = m_codeOffset;
+#if CPU(ARM_THUMB2)
+        jump.m_type = m_type;
+        jump.m_condition = m_condition;
+#endif
+        return jump;
+    }
+    
+    unsigned m_codeOffset;
+
+#if CPU(ARM_THUMB2)
+    ARMv7Assembler::JumpType m_type : 8;
+    ARMv7Assembler::Condition m_condition : 8;
+#endif
+
+#ifndef NDEBUG
+    enum Mode {
+        InitialJump,
+        LateJump,
+        CorrectedJump
+    };
+
+    Mode m_mode;
+#endif
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGCorrectableJumpPoint_h
diff --git a/dfg/DFGDoubleFormatState.h b/dfg/DFGDoubleFormatState.h
new file mode 100644 (file)
index 0000000..2aa0f3d
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGDoubleFormatState_h
+#define DFGDoubleFormatState_h
+
+namespace JSC { namespace DFG {
+
+enum DoubleFormatState {
+    EmptyDoubleFormatState, // bottom
+    UsingDoubleFormat,
+    NotUsingDoubleFormat,
+    CantUseDoubleFormat // top
+};
+
+inline DoubleFormatState mergeDoubleFormatStates(DoubleFormatState a, DoubleFormatState b)
+{
+    switch (a) {
+    case EmptyDoubleFormatState:
+        return b;
+    case UsingDoubleFormat:
+        switch (b) {
+        case EmptyDoubleFormatState:
+        case UsingDoubleFormat:
+            return UsingDoubleFormat;
+        case NotUsingDoubleFormat:
+        case CantUseDoubleFormat:
+            return CantUseDoubleFormat;
+        }
+    case NotUsingDoubleFormat:
+        switch (b) {
+        case EmptyDoubleFormatState:
+        case NotUsingDoubleFormat:
+            return NotUsingDoubleFormat;
+        case UsingDoubleFormat:
+        case CantUseDoubleFormat:
+            return CantUseDoubleFormat;
+        }
+    case CantUseDoubleFormat:
+        return CantUseDoubleFormat;
+    }
+    ASSERT_NOT_REACHED();
+    return CantUseDoubleFormat;
+}
+
+inline bool mergeDoubleFormatState(DoubleFormatState& dest, DoubleFormatState src)
+{
+    DoubleFormatState newState = mergeDoubleFormatStates(dest, src);
+    if (newState == dest)
+        return false;
+    dest = newState;
+    return true;
+}
+
+inline const char* doubleFormatStateToString(DoubleFormatState state)
+{
+    switch (state) {
+    case EmptyDoubleFormatState:
+        return "Empty";
+    case UsingDoubleFormat:
+        return "DoubleFormat";
+    case NotUsingDoubleFormat:
+        return "ValueFormat";
+    case CantUseDoubleFormat:
+        return "ForceValue";
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+} } // namespace JSC::DFG
+
+#endif // DFGDoubleFormatState_h
+
diff --git a/dfg/DFGDriver.cpp b/dfg/DFGDriver.cpp
new file mode 100644 (file)
index 0000000..205e94e
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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 "DFGDriver.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGByteCodeParser.h"
+#include "DFGCFAPhase.h"
+#include "DFGCSEPhase.h"
+#include "DFGFixupPhase.h"
+#include "DFGJITCompiler.h"
+#include "DFGPredictionPropagationPhase.h"
+#include "DFGRedundantPhiEliminationPhase.h"
+#include "DFGVirtualRegisterAllocationPhase.h"
+
+namespace JSC { namespace DFG {
+
+enum CompileMode { CompileFunction, CompileOther };
+inline bool compile(CompileMode compileMode, JSGlobalData& globalData, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck)
+{
+    SamplingRegion samplingRegion("DFG Compilation (Driver)");
+    
+    ASSERT(codeBlock);
+    ASSERT(codeBlock->alternative());
+    ASSERT(codeBlock->alternative()->getJITType() == JITCode::BaselineJIT);
+
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("DFG compiling code block %p(%p), number of instructions = %u.\n", codeBlock, codeBlock->alternative(), codeBlock->instructionCount());
+#endif
+    
+    Graph dfg(globalData, codeBlock);
+    if (!parse(dfg))
+        return false;
+    
+    if (compileMode == CompileFunction)
+        dfg.predictArgumentTypes();
+
+    performRedundantPhiElimination(dfg);
+    performPredictionPropagation(dfg);
+    performFixup(dfg);
+    performCSE(dfg);
+    performVirtualRegisterAllocation(dfg);
+    performCFA(dfg);
+
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("Graph after optimization:\n");
+    dfg.dump();
+#endif
+    
+    JITCompiler dataFlowJIT(dfg);
+    bool result;
+    if (compileMode == CompileFunction) {
+        ASSERT(jitCodeWithArityCheck);
+        
+        result = dataFlowJIT.compileFunction(jitCode, *jitCodeWithArityCheck);
+    } else {
+        ASSERT(compileMode == CompileOther);
+        ASSERT(!jitCodeWithArityCheck);
+        
+        result = dataFlowJIT.compile(jitCode);
+    }
+    
+    return result;
+}
+
+bool tryCompile(JSGlobalData& globalData, CodeBlock* codeBlock, JITCode& jitCode)
+{
+    return compile(CompileOther, globalData, codeBlock, jitCode, 0);
+}
+
+bool tryCompileFunction(JSGlobalData& globalData, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
+{
+    return compile(CompileFunction, globalData, codeBlock, jitCode, &jitCodeWithArityCheck);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/dfg/DFGDriver.h b/dfg/DFGDriver.h
new file mode 100644 (file)
index 0000000..639b13f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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 DFGDriver_h
+#define DFGDriver_h
+
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+class CodeBlock;
+class JITCode;
+class JSGlobalData;
+class MacroAssemblerCodePtr;
+
+namespace DFG {
+
+#if ENABLE(DFG_JIT)
+bool tryCompile(JSGlobalData&, CodeBlock*, JITCode&);
+bool tryCompileFunction(JSGlobalData&, CodeBlock*, JITCode&, MacroAssemblerCodePtr& jitCodeWithArityCheck);
+#else
+inline bool tryCompile(JSGlobalData&, CodeBlock*, JITCode&) { return false; }
+inline bool tryCompileFunction(JSGlobalData&, CodeBlock*, JITCode&, MacroAssemblerCodePtr&) { return false; }
+#endif
+
+} } // namespace JSC::DFG
+
+#endif
+
diff --git a/dfg/DFGEdge.h b/dfg/DFGEdge.h
new file mode 100644 (file)
index 0000000..7b4b5b8
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * 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 DFGEdge_h
+#define DFGEdge_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGCommon.h"
+
+namespace JSC { namespace DFG {
+
+class AdjacencyList;
+
+class Edge {
+public:
+    Edge()
+        : m_encodedWord(makeWord(NoNode, UntypedUse))
+    {
+    }
+    
+    explicit Edge(NodeIndex nodeIndex)
+        : m_encodedWord(makeWord(nodeIndex, UntypedUse))
+    {
+    }
+    
+    Edge(NodeIndex nodeIndex, UseKind useKind)
+        : m_encodedWord(makeWord(nodeIndex, useKind))
+    {
+    }
+    
+    NodeIndex indexUnchecked() const { return m_encodedWord >> shift(); }
+    NodeIndex index() const
+    {
+        ASSERT(isSet());
+        return m_encodedWord >> shift();
+    }
+    void setIndex(NodeIndex nodeIndex)
+    {
+        m_encodedWord = makeWord(nodeIndex, useKind());
+    }
+    
+    UseKind useKind() const
+    {
+        ASSERT(isSet());
+        unsigned masked = m_encodedWord & (((1 << shift()) - 1));
+        ASSERT(masked < LastUseKind);
+        return static_cast<UseKind>(masked);
+    }
+    void setUseKind(UseKind useKind)
+    {
+        ASSERT(isSet());
+        m_encodedWord = makeWord(index(), useKind);
+    }
+    
+    bool isSet() const { return indexUnchecked() != NoNode; }
+    bool operator!() const { return !isSet(); }
+    
+    bool operator==(Edge other) const
+    {
+        return m_encodedWord == other.m_encodedWord;
+    }
+    bool operator!=(Edge other) const
+    {
+        return m_encodedWord != other.m_encodedWord;
+    }
+
+private:
+    friend class AdjacencyList;
+    
+    static uint32_t shift() { return 4; }
+    
+    static int32_t makeWord(NodeIndex nodeIndex, UseKind useKind)
+    {
+        ASSERT(static_cast<uint32_t>(((static_cast<int32_t>(nodeIndex) << shift()) >> shift())) == nodeIndex);
+        ASSERT(useKind >= 0 && useKind < LastUseKind);
+        ASSERT(LastUseKind <= (1 << shift()));
+        return (nodeIndex << shift()) | useKind;
+    }
+    
+    int32_t m_encodedWord;
+};
+
+inline bool operator==(Edge nodeUse, NodeIndex nodeIndex)
+{
+    return nodeUse.indexUnchecked() == nodeIndex;
+}
+inline bool operator==(NodeIndex nodeIndex, Edge nodeUse)
+{
+    return nodeUse.indexUnchecked() == nodeIndex;
+}
+inline bool operator!=(Edge nodeUse, NodeIndex nodeIndex)
+{
+    return nodeUse.indexUnchecked() != nodeIndex;
+}
+inline bool operator!=(NodeIndex nodeIndex, Edge nodeUse)
+{
+    return nodeUse.indexUnchecked() != nodeIndex;
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGEdge_h
+
index 87e44ea6b370cbd6c0e9d52f803ee45ea461b5ea..6af45dd81aed91c3a05299f9f69162cddfd82912 100644 (file)
@@ -36,6 +36,8 @@ namespace JSC { namespace DFG {
 typedef MacroAssembler::FPRegisterID FPRReg;
 #define InvalidFPRReg ((FPRReg)-1)
 
 typedef MacroAssembler::FPRegisterID FPRReg;
 #define InvalidFPRReg ((FPRReg)-1)
 
+#if CPU(X86) || CPU(X86_64)
+
 class FPRInfo {
 public:
     typedef FPRReg RegisterType;
 class FPRInfo {
 public:
     typedef FPRReg RegisterType;
@@ -48,11 +50,15 @@ public:
     static const FPRReg fpRegT3 = X86Registers::xmm3;
     static const FPRReg fpRegT4 = X86Registers::xmm4;
     static const FPRReg fpRegT5 = X86Registers::xmm5;
     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.
+#if CPU(X86_64)
+    // Only X86_64 passes aguments in xmm 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 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
+#endif
+    // On X86 the return will actually be on the x87 stack,
+    // so we'll copy to xmm0 for sanity!
     static const FPRReg returnValueFPR = X86Registers::xmm0; // fpRegT0
 
     // FPRReg mapping is direct, the machine regsiter numbers can
     static const FPRReg returnValueFPR = X86Registers::xmm0; // fpRegT0
 
     // FPRReg mapping is direct, the machine regsiter numbers can
@@ -72,10 +78,10 @@ public:
         return (unsigned)reg;
     }
 
         return (unsigned)reg;
     }
 
-#ifndef NDEBUG
     static const char* debugName(FPRReg reg)
     {
         ASSERT(reg != InvalidFPRReg);
     static const char* debugName(FPRReg reg)
     {
         ASSERT(reg != InvalidFPRReg);
+#if CPU(X86_64)
         ASSERT(reg < 16);
         static const char* nameForRegister[16] = {
             "xmm0", "xmm1", "xmm2", "xmm3",
         ASSERT(reg < 16);
         static const char* nameForRegister[16] = {
             "xmm0", "xmm1", "xmm2", "xmm3",
@@ -83,11 +89,76 @@ public:
             "xmm8", "xmm9", "xmm10", "xmm11",
             "xmm12", "xmm13", "xmm14", "xmm15"
         };
             "xmm8", "xmm9", "xmm10", "xmm11",
             "xmm12", "xmm13", "xmm14", "xmm15"
         };
+#elif CPU(X86)
+        ASSERT(reg < 8);
+        static const char* nameForRegister[8] = {
+            "xmm0", "xmm1", "xmm2", "xmm3",
+            "xmm4", "xmm5", "xmm6", "xmm7"
+        };
+#endif
         return nameForRegister[reg];
     }
         return nameForRegister[reg];
     }
+};
+
 #endif
 #endif
+
+#if CPU(ARM_THUMB2)
+
+class FPRInfo {
+public:
+    typedef FPRReg RegisterType;
+    static const unsigned numberOfRegisters = 6;
+
+    // Temporary registers.
+    // d7 is use by the MacroAssembler as fpTempRegister.
+    static const FPRReg fpRegT0 = ARMRegisters::d0;
+    static const FPRReg fpRegT1 = ARMRegisters::d1;
+    static const FPRReg fpRegT2 = ARMRegisters::d2;
+    static const FPRReg fpRegT3 = ARMRegisters::d3;
+    static const FPRReg fpRegT4 = ARMRegisters::d4;
+    static const FPRReg fpRegT5 = ARMRegisters::d5;
+    // ARMv7 doesn't pass arguments in fp registers. The return
+    // value is also actually in integer registers, for now
+    // we'll return in d0 for simplicity.
+    static const FPRReg returnValueFPR = ARMRegisters::d0; // fpRegT0
+
+    // FPRReg mapping is direct, the machine regsiter numbers can
+    // be used directly as indices into the FPR RegisterBank.
+    COMPILE_ASSERT(ARMRegisters::d0 == 0, d0_is_0);
+    COMPILE_ASSERT(ARMRegisters::d1 == 1, d1_is_1);
+    COMPILE_ASSERT(ARMRegisters::d2 == 2, d2_is_2);
+    COMPILE_ASSERT(ARMRegisters::d3 == 3, d3_is_3);
+    COMPILE_ASSERT(ARMRegisters::d4 == 4, d4_is_4);
+    COMPILE_ASSERT(ARMRegisters::d5 == 5, d5_is_5);
+    static FPRReg toRegister(unsigned index)
+    {
+        return (FPRReg)index;
+    }
+    static unsigned toIndex(FPRReg reg)
+    {
+        return (unsigned)reg;
+    }
+
+    static const char* debugName(FPRReg reg)
+    {
+        ASSERT(reg != InvalidFPRReg);
+        ASSERT(reg < 32);
+        static const char* nameForRegister[32] = {
+            "d0", "d1", "d2", "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"
+        };
+        return nameForRegister[reg];
+    }
 };
 
 };
 
+#endif
+
 typedef RegisterBank<FPRInfo>::iterator fpr_iterator;
 
 } } // namespace JSC::DFG
 typedef RegisterBank<FPRInfo>::iterator fpr_iterator;
 
 } } // namespace JSC::DFG
diff --git a/dfg/DFGFixupPhase.cpp b/dfg/DFGFixupPhase.cpp
new file mode 100644 (file)
index 0000000..242fdf8
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DFGFixupPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGGraph.h"
+#include "DFGInsertionSet.h"
+#include "DFGPhase.h"
+
+namespace JSC { namespace DFG {
+
+class FixupPhase : public Phase {
+public:
+    FixupPhase(Graph& graph)
+        : Phase(graph, "fixup")
+    {
+    }
+    
+    void run()
+    {
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex)
+            fixupBlock(m_graph.m_blocks[blockIndex].get());
+    }
+
+private:
+    void fixupBlock(BasicBlock* block)
+    {
+        for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
+            m_compileIndex = block->at(m_indexInBlock);
+            fixupNode(m_graph[m_compileIndex]);
+        }
+        m_insertionSet.execute(*block);
+    }
+    
+    void fixupNode(Node& node)
+    {
+        if (!node.shouldGenerate())
+            return;
+        
+        NodeType op = node.op();
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("   %s @%u: ", Graph::opName(op), m_compileIndex);
+#endif
+        
+        switch (op) {
+        case GetById: {
+            if (!isInt32Prediction(m_graph[m_compileIndex].prediction()))
+                break;
+            if (codeBlock()->identifier(node.identifierNumber()) != globalData().propertyNames->length)
+                break;
+            bool isArray = isArrayPrediction(m_graph[node.child1()].prediction());
+            bool isString = isStringPrediction(m_graph[node.child1()].prediction());
+            bool isInt8Array = m_graph[node.child1()].shouldSpeculateInt8Array();
+            bool isInt16Array = m_graph[node.child1()].shouldSpeculateInt16Array();
+            bool isInt32Array = m_graph[node.child1()].shouldSpeculateInt32Array();
+            bool isUint8Array = m_graph[node.child1()].shouldSpeculateUint8Array();
+            bool isUint8ClampedArray = m_graph[node.child1()].shouldSpeculateUint8ClampedArray();
+            bool isUint16Array = m_graph[node.child1()].shouldSpeculateUint16Array();
+            bool isUint32Array = m_graph[node.child1()].shouldSpeculateUint32Array();
+            bool isFloat32Array = m_graph[node.child1()].shouldSpeculateFloat32Array();
+            bool isFloat64Array = m_graph[node.child1()].shouldSpeculateFloat64Array();
+            if (!isArray && !isString && !isInt8Array && !isInt16Array && !isInt32Array && !isUint8Array && !isUint8ClampedArray && !isUint16Array && !isUint32Array && !isFloat32Array && !isFloat64Array)
+                break;
+            
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+            dataLog("  @%u -> %s", m_compileIndex, isArray ? "GetArrayLength" : "GetStringLength");
+#endif
+            if (isArray)
+                node.setOp(GetArrayLength);
+            else if (isString)
+                node.setOp(GetStringLength);
+            else if (isInt8Array)
+                node.setOp(GetInt8ArrayLength);
+            else if (isInt16Array)
+                node.setOp(GetInt16ArrayLength);
+            else if (isInt32Array)
+                node.setOp(GetInt32ArrayLength);
+            else if (isUint8Array)
+                node.setOp(GetUint8ArrayLength);
+            else if (isUint8ClampedArray)
+                node.setOp(GetUint8ClampedArrayLength);
+            else if (isUint16Array)
+                node.setOp(GetUint16ArrayLength);
+            else if (isUint32Array)
+                node.setOp(GetUint32ArrayLength);
+            else if (isFloat32Array)
+                node.setOp(GetFloat32ArrayLength);
+            else if (isFloat64Array)
+                node.setOp(GetFloat64ArrayLength);
+            else
+                ASSERT_NOT_REACHED();
+            // No longer MustGenerate
+            ASSERT(node.flags() & NodeMustGenerate);
+            node.clearFlags(NodeMustGenerate);
+            m_graph.deref(m_compileIndex);
+            break;
+        }
+        case GetIndexedPropertyStorage: {
+            PredictedType basePrediction = m_graph[node.child2()].prediction();
+            if (!(basePrediction & PredictInt32) && basePrediction) {
+                node.setOpAndDefaultFlags(Nop);
+                m_graph.clearAndDerefChild1(node);
+                m_graph.clearAndDerefChild2(node);
+                m_graph.clearAndDerefChild3(node);
+                node.setRefCount(0);
+            }
+            break;
+        }
+        case GetByVal:
+        case StringCharAt:
+        case StringCharCodeAt: {
+            if (!!node.child3() && m_graph[node.child3()].op() == Nop)
+                node.children.child3() = Edge();
+            break;
+        }
+            
+        case ValueToInt32: {
+            if (m_graph[node.child1()].shouldSpeculateNumber()) {
+                node.clearFlags(NodeMustGenerate);
+                m_graph.deref(m_compileIndex);
+            }
+            break;
+        }
+            
+        case BitAnd:
+        case BitOr:
+        case BitXor:
+        case BitRShift:
+        case BitLShift:
+        case BitURShift: {
+            fixIntEdge(node.children.child1());
+            fixIntEdge(node.children.child2());
+            break;
+        }
+            
+        case CompareEq:
+        case CompareLess:
+        case CompareLessEq:
+        case CompareGreater:
+        case CompareGreaterEq:
+        case CompareStrictEq: {
+            if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]))
+                break;
+            if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()]))
+                break;
+            fixDoubleEdge(0);
+            fixDoubleEdge(1);
+            break;
+        }
+            
+        case LogicalNot: {
+            if (m_graph[node.child1()].shouldSpeculateInteger())
+                break;
+            if (!m_graph[node.child1()].shouldSpeculateNumber())
+                break;
+            fixDoubleEdge(0);
+            break;
+        }
+            
+        case Branch: {
+            if (!m_graph[node.child1()].shouldSpeculateInteger()
+                && m_graph[node.child1()].shouldSpeculateNumber())
+                fixDoubleEdge(0);
+
+            Node& myNode = m_graph[m_compileIndex]; // reload because the graph may have changed
+            Edge logicalNotEdge = myNode.child1();
+            Node& logicalNot = m_graph[logicalNotEdge];
+            if (logicalNot.op() == LogicalNot
+                && logicalNot.adjustedRefCount() == 1) {
+                Edge newChildEdge = logicalNot.child1();
+                if (m_graph[newChildEdge].hasBooleanResult()) {
+                    m_graph.ref(newChildEdge);
+                    m_graph.deref(logicalNotEdge);
+                    myNode.children.setChild1(newChildEdge);
+                    
+                    BlockIndex toBeTaken = myNode.notTakenBlockIndex();
+                    BlockIndex toBeNotTaken = myNode.takenBlockIndex();
+                    myNode.setTakenBlockIndex(toBeTaken);
+                    myNode.setNotTakenBlockIndex(toBeNotTaken);
+                }
+            }
+            break;
+        }
+            
+        case SetLocal: {
+            if (m_graph.isCaptured(node.local()))
+                break;
+            if (!node.variableAccessData()->shouldUseDoubleFormat())
+                break;
+            fixDoubleEdge(0);
+            break;
+        }
+            
+        case ArithAdd:
+        case ValueAdd: {
+            if (m_graph.addShouldSpeculateInteger(node))
+                break;
+            if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()]))
+                break;
+            fixDoubleEdge(0);
+            fixDoubleEdge(1);
+            break;
+        }
+            
+        case ArithSub: {
+            if (m_graph.addShouldSpeculateInteger(node)
+                && node.canSpeculateInteger())
+                break;
+            fixDoubleEdge(0);
+            fixDoubleEdge(1);
+            break;
+        }
+            
+        case ArithNegate: {
+            if (m_graph.negateShouldSpeculateInteger(node))
+                break;
+            fixDoubleEdge(0);
+            break;
+        }
+            
+        case ArithMin:
+        case ArithMax:
+        case ArithMul:
+        case ArithMod: {
+            if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])
+                && node.canSpeculateInteger())
+                break;
+            fixDoubleEdge(0);
+            fixDoubleEdge(1);
+            break;
+        }
+            
+        case ArithDiv: {
+            if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])
+                && node.canSpeculateInteger()) {
+                if (isX86())
+                    break;
+                fixDoubleEdge(0);
+                fixDoubleEdge(1);
+                
+                Node& oldDivision = m_graph[m_compileIndex];
+                
+                Node newDivision = oldDivision;
+                newDivision.setRefCount(2);
+                newDivision.predict(PredictDouble);
+                NodeIndex newDivisionIndex = m_graph.size();
+                
+                oldDivision.setOp(DoubleAsInt32);
+                oldDivision.children.initialize(Edge(newDivisionIndex, DoubleUse), Edge(), Edge());
+                
+                m_graph.append(newDivision);
+                m_insertionSet.append(m_indexInBlock, newDivisionIndex);
+                
+                break;
+            }
+            fixDoubleEdge(0);
+            fixDoubleEdge(1);
+            break;
+        }
+            
+        case ArithAbs: {
+            if (m_graph[node.child1()].shouldSpeculateInteger()
+                && node.canSpeculateInteger())
+                break;
+            fixDoubleEdge(0);
+            break;
+        }
+            
+        case ArithSqrt: {
+            fixDoubleEdge(0);
+            break;
+        }
+            
+        case PutByVal: {
+            if (!m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction())
+                break;
+            if (!m_graph[node.child2()].shouldSpeculateInteger())
+                break;
+            if (isActionableIntMutableArrayPrediction(m_graph[node.child1()].prediction())) {
+                if (m_graph[node.child3()].isConstant())
+                    break;
+                if (m_graph[node.child3()].shouldSpeculateInteger())
+                    break;
+                fixDoubleEdge(2);
+                break;
+            }
+            if (isActionableFloatMutableArrayPrediction(m_graph[node.child1()].prediction())) {
+                fixDoubleEdge(2);
+                break;
+            }
+            break;
+        }
+            
+        default:
+            break;
+        }
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        if (!(node.flags() & NodeHasVarArgs)) {
+            dataLog("new children: ");
+            node.dumpChildren(WTF::dataFile());
+        }
+        dataLog("\n");
+#endif
+    }
+    
+    void fixIntEdge(Edge& edge)
+    {
+        Node& node = m_graph[edge];
+        if (node.op() != ValueToInt32)
+            return;
+        
+        if (!m_graph[node.child1()].shouldSpeculateInteger())
+            return;
+        
+        Edge oldEdge = edge;
+        Edge newEdge = node.child1();
+        
+        m_graph.ref(newEdge);
+        m_graph.deref(oldEdge);
+        
+        edge = newEdge;
+    }
+    
+    void fixDoubleEdge(unsigned childIndex)
+    {
+        Node& source = m_graph[m_compileIndex];
+        Edge& edge = source.children.child(childIndex);
+        
+        if (!m_graph[edge].shouldSpeculateInteger()) {
+            edge.setUseKind(DoubleUse);
+            return;
+        }
+        
+        NodeIndex resultIndex = (NodeIndex)m_graph.size();
+        
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("(replacing @%u->@%u with @%u->@%u) ",
+                m_compileIndex, edge.index(), m_compileIndex, resultIndex);
+#endif
+        
+        // Fix the edge up here because it's a reference that will be clobbered by
+        // the append() below.
+        NodeIndex oldIndex = edge.index();
+        edge = Edge(resultIndex, DoubleUse);
+
+        m_graph.append(Node(Int32ToDouble, source.codeOrigin, oldIndex));
+        m_insertionSet.append(m_indexInBlock, resultIndex);
+        
+        Node& int32ToDouble = m_graph[resultIndex];
+        int32ToDouble.predict(PredictDouble);
+        int32ToDouble.ref();
+    }
+    
+    unsigned m_indexInBlock;
+    NodeIndex m_compileIndex;
+    InsertionSet<NodeIndex> m_insertionSet;
+};
+    
+void performFixup(Graph& graph)
+{
+    runPhase<FixupPhase>(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/dfg/DFGFixupPhase.h b/dfg/DFGFixupPhase.h
new file mode 100644 (file)
index 0000000..1ba85eb
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGFixupPhase_h
+#define DFGFixupPhase_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// Fix portions of the graph that are inefficient given the predictions that
+// we have. This should run after prediction propagation but before CSE.
+
+void performFixup(Graph&);
+
+} } // namespace JSC::DFG::Phase
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGFixupPhase_h
index f4e9f76f711d8e99cc824547634cf7704639a5b9..4a250328f18f50a570d2b84c6b411f8a513c87bc 100644 (file)
@@ -36,12 +36,289 @@ namespace JSC { namespace DFG {
 typedef MacroAssembler::RegisterID GPRReg;
 #define InvalidGPRReg ((GPRReg)-1)
 
 typedef MacroAssembler::RegisterID GPRReg;
 #define InvalidGPRReg ((GPRReg)-1)
 
+#if USE(JSVALUE64)
+class JSValueRegs {
+public:
+    JSValueRegs()
+        : m_gpr(InvalidGPRReg)
+    {
+    }
+    
+    explicit JSValueRegs(GPRReg gpr)
+        : m_gpr(gpr)
+    {
+    }
+    
+    bool operator!() const { return m_gpr == InvalidGPRReg; }
+    
+    GPRReg gpr() const { return m_gpr; }
+    
+private:
+    GPRReg m_gpr;
+};
+
+class JSValueSource {
+public:
+    JSValueSource()
+        : m_offset(notAddress())
+        , m_base(InvalidGPRReg)
+    {
+    }
+    
+    JSValueSource(JSValueRegs regs)
+        : m_offset(notAddress())
+        , m_base(regs.gpr())
+    {
+    }
+    
+    explicit JSValueSource(GPRReg gpr)
+        : m_offset(notAddress())
+        , m_base(gpr)
+    {
+    }
+    
+    JSValueSource(MacroAssembler::Address address)
+        : m_offset(address.offset)
+        , m_base(address.base)
+    {
+        ASSERT(m_offset != notAddress());
+        ASSERT(m_base != InvalidGPRReg);
+    }
+    
+    static JSValueSource unboxedCell(GPRReg payloadGPR)
+    {
+        return JSValueSource(payloadGPR);
+    }
+    
+    bool operator!() const { return m_base == InvalidGPRReg; }
+    
+    bool isAddress() const { return m_offset != notAddress(); }
+    
+    int32_t offset() const
+    {
+        ASSERT(isAddress());
+        return m_offset;
+    }
+    
+    GPRReg base() const
+    {
+        ASSERT(isAddress());
+        return m_base;
+    }
+    
+    GPRReg gpr() const
+    {
+        ASSERT(!isAddress());
+        return m_base;
+    }
+    
+    MacroAssembler::Address asAddress() const { return MacroAssembler::Address(base(), offset()); }
+    
+private:
+    static inline int32_t notAddress() { return 0x80000000; }     
+          
+    int32_t m_offset;
+    GPRReg m_base;
+};
+#endif
+
+#if USE(JSVALUE32_64)
+class JSValueRegs {
+public:
+    JSValueRegs()
+        : m_tagGPR(static_cast<int8_t>(InvalidGPRReg))
+        , m_payloadGPR(static_cast<int8_t>(InvalidGPRReg))
+    {
+    }
+    
+    JSValueRegs(GPRReg tagGPR, GPRReg payloadGPR)
+        : m_tagGPR(tagGPR)
+        , m_payloadGPR(payloadGPR)
+    {
+        ASSERT((static_cast<GPRReg>(m_tagGPR) == InvalidGPRReg) == (static_cast<GPRReg>(payloadGPR) == InvalidGPRReg));
+    }
+    
+    bool operator!() const { return static_cast<GPRReg>(m_tagGPR) == InvalidGPRReg; }
+    
+    GPRReg tagGPR() const { return static_cast<GPRReg>(m_tagGPR); }
+    GPRReg payloadGPR() const { return static_cast<GPRReg>(m_payloadGPR); }
+
+private:
+    int8_t m_tagGPR;
+    int8_t m_payloadGPR;
+};
+
+class JSValueSource {
+public:
+    JSValueSource()
+        : m_offset(notAddress())
+        , m_baseOrTag(static_cast<int8_t>(InvalidGPRReg))
+        , m_payload(static_cast<int8_t>(InvalidGPRReg))
+        , m_tagType(0)
+    {
+    }
+    
+    JSValueSource(JSValueRegs regs)
+        : m_offset(notAddress())
+        , m_baseOrTag(regs.tagGPR())
+        , m_payload(regs.payloadGPR())
+        , m_tagType(0)
+    {
+    }
+    
+    JSValueSource(GPRReg tagGPR, GPRReg payloadGPR)
+        : m_offset(notAddress())
+        , m_baseOrTag(static_cast<int8_t>(tagGPR))
+        , m_payload(static_cast<int8_t>(payloadGPR))
+        , m_tagType(0)
+    {
+    }
+    
+    JSValueSource(MacroAssembler::Address address)
+        : m_offset(address.offset)
+        , m_baseOrTag(static_cast<int8_t>(address.base))
+        , m_payload(static_cast<int8_t>(InvalidGPRReg))
+        , m_tagType(0)
+    {
+        ASSERT(m_offset != notAddress());
+        ASSERT(static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg);
+    }
+    
+    static JSValueSource unboxedCell(GPRReg payloadGPR)
+    {
+        JSValueSource result;
+        result.m_offset = notAddress();
+        result.m_baseOrTag = static_cast<int8_t>(InvalidGPRReg);
+        result.m_payload = static_cast<int8_t>(payloadGPR);
+        result.m_tagType = static_cast<int8_t>(JSValue::CellTag);
+        return result;
+    }
+    
+    bool operator!() const { return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg && static_cast<GPRReg>(m_payload) == InvalidGPRReg; }
+    
+    bool isAddress() const
+    {
+        ASSERT(!!*this);
+        return m_offset != notAddress();
+    }
+    
+    int32_t offset() const
+    {
+        ASSERT(isAddress());
+        return m_offset;
+    }
+    
+    GPRReg base() const
+    {
+        ASSERT(isAddress());
+        return static_cast<GPRReg>(m_baseOrTag);
+    }
+    
+    GPRReg tagGPR() const
+    {
+        ASSERT(!isAddress() && m_baseOrTag != InvalidGPRReg);
+        return static_cast<GPRReg>(m_baseOrTag);
+    }
+    
+    GPRReg payloadGPR() const
+    {
+        ASSERT(!isAddress());
+        return static_cast<GPRReg>(m_payload);
+    }
+    
+    bool hasKnownTag() const
+    {
+        ASSERT(!!*this);
+        ASSERT(!isAddress());
+        return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg;
+    }
+    
+    uint32_t tag() const
+    {
+        return static_cast<int32_t>(m_tagType);
+    }
+    
+    MacroAssembler::Address asAddress(unsigned additionalOffset = 0) const { return MacroAssembler::Address(base(), offset() + additionalOffset); }
+    
+private:
+    static inline int32_t notAddress() { return 0x80000000; }     
+          
+    int32_t m_offset;
+    int8_t m_baseOrTag;
+    int8_t m_payload; 
+    int8_t m_tagType; // Contains the low bits of the tag.
+};
+#endif
+
+#if CPU(X86)
+#define NUMBER_OF_ARGUMENT_REGISTERS 0
+
+class GPRInfo {
+public:
+    typedef GPRReg RegisterType;
+    static const unsigned numberOfRegisters = 5;
+
+    // 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::esi;
+    // These registers match the baseline JIT.
+    static const GPRReg cachedResultRegister = regT0;
+    static const GPRReg cachedResultRegister2 = regT1;
+    static const GPRReg callFrameRegister = X86Registers::edi;
+    // These constants provide the names for the general purpose argument & return value registers.
+    static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2
+    static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
+    static const GPRReg returnValueGPR = X86Registers::eax; // regT0
+    static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
+    static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
+
+    static GPRReg toRegister(unsigned index)
+    {
+        ASSERT(index < numberOfRegisters);
+        static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4 };
+        return registerForIndex[index];
+    }
+
+    static unsigned toIndex(GPRReg reg)
+    {
+        ASSERT(reg != InvalidGPRReg);
+        ASSERT(reg < 8);
+        static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, InvalidIndex };
+        unsigned result = indexForRegister[reg];
+        ASSERT(result != InvalidIndex);
+        return result;
+    }
+
+    static const char* debugName(GPRReg reg)
+    {
+        ASSERT(reg != InvalidGPRReg);
+        ASSERT(reg < 8);
+        static const char* nameForRegister[8] = {
+            "eax", "ecx", "edx", "ebx",
+            "esp", "ebp", "esi", "edi",
+        };
+        return nameForRegister[reg];
+    }
+private:
+
+    static const unsigned InvalidIndex = 0xffffffff;
+};
+
+#endif
+
+#if CPU(X86_64)
+#define NUMBER_OF_ARGUMENT_REGISTERS 6
+
 class GPRInfo {
 public:
     typedef GPRReg RegisterType;
     static const unsigned numberOfRegisters = 9;
 
 class GPRInfo {
 public:
     typedef GPRReg RegisterType;
     static const unsigned numberOfRegisters = 9;
 
-    // These registers match the old JIT.
+    // These registers match the baseline JIT.
+    static const GPRReg cachedResultRegister = X86Registers::eax;
     static const GPRReg timeoutCheckRegister = X86Registers::r12;
     static const GPRReg callFrameRegister = X86Registers::r13;
     static const GPRReg tagTypeNumberRegister = X86Registers::r14;
     static const GPRReg timeoutCheckRegister = X86Registers::r12;
     static const GPRReg callFrameRegister = X86Registers::r13;
     static const GPRReg tagTypeNumberRegister = X86Registers::r14;
@@ -61,8 +338,11 @@ public:
     static const GPRReg argumentGPR1 = X86Registers::esi; // regT5
     static const GPRReg argumentGPR2 = X86Registers::edx; // regT1
     static const GPRReg argumentGPR3 = X86Registers::ecx; // regT2
     static const GPRReg argumentGPR1 = X86Registers::esi; // regT5
     static const GPRReg argumentGPR2 = X86Registers::edx; // regT1
     static const GPRReg argumentGPR3 = X86Registers::ecx; // regT2
+    static const GPRReg argumentGPR4 = X86Registers::r8;  // regT6
+    static const GPRReg argumentGPR5 = X86Registers::r9;  // regT7
     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
     static const GPRReg returnValueGPR = X86Registers::eax; // regT0
     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
+    static const GPRReg nonPreservedNonReturnGPR = X86Registers::esi;
 
     static GPRReg toRegister(unsigned index)
     {
 
     static GPRReg toRegister(unsigned index)
     {
@@ -81,7 +361,6 @@ public:
         return result;
     }
 
         return result;
     }
 
-#ifndef NDEBUG
     static const char* debugName(GPRReg reg)
     {
         ASSERT(reg != InvalidGPRReg);
     static const char* debugName(GPRReg reg)
     {
         ASSERT(reg != InvalidGPRReg);
@@ -94,12 +373,83 @@ public:
         };
         return nameForRegister[reg];
     }
         };
         return nameForRegister[reg];
     }
+private:
+
+    static const unsigned InvalidIndex = 0xffffffff;
+};
+
 #endif
 #endif
+
+#if CPU(ARM_THUMB2)
+#define NUMBER_OF_ARGUMENT_REGISTERS 4
+
+class GPRInfo {
+public:
+    typedef GPRReg RegisterType;
+    static const unsigned numberOfRegisters = 8;
+
+    // Temporary registers.
+    static const GPRReg regT0 = ARMRegisters::r0;
+    static const GPRReg regT1 = ARMRegisters::r1;
+    static const GPRReg regT2 = ARMRegisters::r2;
+    static const GPRReg regT3 = ARMRegisters::r4;
+    static const GPRReg regT4 = ARMRegisters::r8;
+    static const GPRReg regT5 = ARMRegisters::r9;
+    static const GPRReg regT6 = ARMRegisters::r10;
+    static const GPRReg regT7 = ARMRegisters::r11;
+    // These registers match the baseline JIT.
+    static const GPRReg cachedResultRegister = regT0;
+    static const GPRReg cachedResultRegister2 = regT1;
+    static const GPRReg callFrameRegister = ARMRegisters::r5;
+    // These constants provide the names for the general purpose argument & return value registers.
+    static const GPRReg argumentGPR0 = ARMRegisters::r0; // regT0
+    static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1
+    static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2
+    // FIXME: r3 is currently used be the MacroAssembler as a temporary - it seems
+    // This could threoretically be a problem if theis is used in code generation
+    // between the arguments being set up, and the call being made. That said,
+    // any change introducing a problem here is likely to be immediately apparent!
+    static const GPRReg argumentGPR3 = ARMRegisters::r3; // FIXME!
+    static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
+    static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
+    static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r2;
+
+    static GPRReg toRegister(unsigned index)
+    {
+        ASSERT(index < numberOfRegisters);
+        static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7 };
+        return registerForIndex[index];
+    }
+
+    static unsigned toIndex(GPRReg reg)
+    {
+        ASSERT(reg != InvalidGPRReg);
+        ASSERT(reg < 16);
+        static const unsigned indexForRegister[16] = { 0, 1, 2, InvalidIndex, 3, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
+        unsigned result = indexForRegister[reg];
+        ASSERT(result != InvalidIndex);
+        return result;
+    }
+
+    static const char* debugName(GPRReg reg)
+    {
+        ASSERT(reg != InvalidGPRReg);
+        ASSERT(reg < 16);
+        static const char* nameForRegister[16] = {
+            "r0", "r1", "r2", "r3",
+            "r4", "r5", "r6", "r7",
+            "r8", "r9", "r10", "r11",
+            "r12", "r13", "r14", "r15"
+        };
+        return nameForRegister[reg];
+    }
 private:
 
     static const unsigned InvalidIndex = 0xffffffff;
 };
 
 private:
 
     static const unsigned InvalidIndex = 0xffffffff;
 };
 
+#endif
+
 typedef RegisterBank<GPRInfo>::iterator gpr_iterator;
 
 } } // namespace JSC::DFG
 typedef RegisterBank<GPRInfo>::iterator gpr_iterator;
 
 } } // namespace JSC::DFG
index 968ea20eba6df95862efe48563b0715b42473d70..125a5a4f9ecff703d298f4d57bec50b66f2f1a87 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (C) 2011 Apple Inc. All rights reserved.
  *
 /*
  * Copyright (C) 2011 Apple Inc. All rights reserved.
  *
 
 #if ENABLE(DFG_JIT)
 
 
 #if ENABLE(DFG_JIT)
 
+#include "DataFormat.h"
 #include <dfg/DFGJITCompiler.h>
 
 namespace JSC { namespace DFG {
 
 #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.
 // === GenerationInfo ===
 //
 // This class is used to track the current status of a live values during code generation.
@@ -76,6 +61,7 @@ public:
         m_registerFormat = DataFormatNone;
         m_spillFormat = DataFormatNone;
         m_canFill = true;
         m_registerFormat = DataFormatNone;
         m_spillFormat = DataFormatNone;
         m_canFill = true;
+        ASSERT(m_useCount);
     }
     void initInteger(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
     {
     }
     void initInteger(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
     {
@@ -85,7 +71,9 @@ public:
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.gpr = gpr;
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.gpr = gpr;
+        ASSERT(m_useCount);
     }
     }
+#if USE(JSVALUE64)
     void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS)
     {
         ASSERT(format & DataFormatJS);
     void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS)
     {
         ASSERT(format & DataFormatJS);
@@ -96,7 +84,23 @@ public:
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.gpr = gpr;
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.gpr = gpr;
+        ASSERT(m_useCount);
+    }
+#elif USE(JSVALUE32_64)
+    void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg tagGPR, GPRReg payloadGPR, DataFormat format = DataFormatJS)
+    {
+        ASSERT(format & DataFormatJS);
+
+        m_nodeIndex = nodeIndex;
+        m_useCount = useCount;
+        m_registerFormat = format;
+        m_spillFormat = DataFormatNone;
+        m_canFill = false;
+        u.v.tagGPR = tagGPR;
+        u.v.payloadGPR = payloadGPR;
+        ASSERT(m_useCount);
     }
     }
+#endif
     void initCell(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
     {
         m_nodeIndex = nodeIndex;
     void initCell(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
     {
         m_nodeIndex = nodeIndex;
@@ -105,15 +109,38 @@ public:
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.gpr = gpr;
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.gpr = gpr;
+        ASSERT(m_useCount);
+    }
+    void initBoolean(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
+    {
+        m_nodeIndex = nodeIndex;
+        m_useCount = useCount;
+        m_registerFormat = DataFormatBoolean;
+        m_spillFormat = DataFormatNone;
+        m_canFill = false;
+        u.gpr = gpr;
+        ASSERT(m_useCount);
     }
     void initDouble(NodeIndex nodeIndex, uint32_t useCount, FPRReg fpr)
     {
     }
     void initDouble(NodeIndex nodeIndex, uint32_t useCount, FPRReg fpr)
     {
+        ASSERT(fpr != InvalidFPRReg);
         m_nodeIndex = nodeIndex;
         m_useCount = useCount;
         m_registerFormat = DataFormatDouble;
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.fpr = fpr;
         m_nodeIndex = nodeIndex;
         m_useCount = useCount;
         m_registerFormat = DataFormatDouble;
         m_spillFormat = DataFormatNone;
         m_canFill = false;
         u.fpr = fpr;
+        ASSERT(m_useCount);
+    }
+    void initStorage(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
+    {
+        m_nodeIndex = nodeIndex;
+        m_useCount = useCount;
+        m_registerFormat = DataFormatStorage;
+        m_spillFormat = DataFormatNone;
+        m_canFill = false;
+        u.gpr = gpr;
+        ASSERT(m_useCount);
     }
 
     // Get the index of the node that produced this value.
     }
 
     // Get the index of the node that produced this value.
@@ -124,6 +151,7 @@ public:
     // associated machine registers may be freed.
     bool use()
     {
     // associated machine registers may be freed.
     bool use()
     {
+        ASSERT(m_useCount);
         return !--m_useCount;
     }
 
         return !--m_useCount;
     }
 
@@ -140,10 +168,51 @@ public:
     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; }
     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; }
+    
+    bool isJSFormat(DataFormat expectedFormat)
+    {
+        return JSC::isJSFormat(registerFormat(), expectedFormat) || JSC::isJSFormat(spillFormat(), expectedFormat);
+    }
+    
+    bool isJSInteger()
+    {
+        return isJSFormat(DataFormatJSInteger);
+    }
+    
+    bool isJSDouble()
+    {
+        return isJSFormat(DataFormatJSDouble);
+    }
+    
+    bool isJSCell()
+    {
+        return isJSFormat(DataFormatJSCell);
+    }
+    
+    bool isJSBoolean()
+    {
+        return isJSFormat(DataFormatJSBoolean);
+    }
+    
+    bool isUnknownJS()
+    {
+        return spillFormat() == DataFormatNone
+            ? registerFormat() == DataFormatJS || registerFormat() == DataFormatNone
+            : spillFormat() == DataFormatJS;
+    }
 
     // Get the machine resister currently holding the value.
 
     // Get the machine resister currently holding the value.
+#if USE(JSVALUE64)
     GPRReg gpr() { ASSERT(m_registerFormat && m_registerFormat != DataFormatDouble); return u.gpr; }
     FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble); return u.fpr; }
     GPRReg gpr() { ASSERT(m_registerFormat && m_registerFormat != DataFormatDouble); return u.gpr; }
     FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble); return u.fpr; }
+    JSValueRegs jsValueRegs() { ASSERT(m_registerFormat & DataFormatJS); return JSValueRegs(u.gpr); }
+#elif USE(JSVALUE32_64)
+    GPRReg gpr() { ASSERT(!(m_registerFormat & DataFormatJS) && m_registerFormat != DataFormatDouble); return u.gpr; }
+    GPRReg tagGPR() { ASSERT(m_registerFormat & DataFormatJS); return u.v.tagGPR; }
+    GPRReg payloadGPR() { ASSERT(m_registerFormat & DataFormatJS); return u.v.payloadGPR; }
+    FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble || m_registerFormat == DataFormatJSDouble); return u.fpr; }
+    JSValueRegs jsValueRegs() { ASSERT(m_registerFormat & DataFormatJS); return JSValueRegs(u.v.tagGPR, u.v.payloadGPR); }
+#endif
 
     // Check whether a value needs spilling in order to free up any associated machine registers.
     bool needsSpill()
 
     // Check whether a value needs spilling in order to free up any associated machine registers.
     bool needsSpill()
@@ -163,9 +232,6 @@ public:
         ASSERT(m_spillFormat == DataFormatNone);
         // We should only be spilling values that are currently in machine registers.
         ASSERT(m_registerFormat != DataFormatNone);
         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_registerFormat = DataFormatNone;
         m_spillFormat = spillFormat;
@@ -180,39 +246,65 @@ public:
         ASSERT(m_canFill && m_registerFormat != DataFormatNone);
         m_registerFormat = DataFormatNone;
     }
         ASSERT(m_canFill && m_registerFormat != DataFormatNone);
         m_registerFormat = DataFormatNone;
     }
+    
+    void killSpilled()
+    {
+        m_spillFormat = DataFormatNone;
+        m_canFill = false;
+    }
 
     // Record that this value is filled into machine registers,
     // tracking which registers, and what format the value has.
 
     // Record that this value is filled into machine registers,
     // tracking which registers, and what format the value has.
+#if USE(JSVALUE64)
     void fillJSValue(GPRReg gpr, DataFormat format = DataFormatJS)
     {
         ASSERT(format & DataFormatJS);
         m_registerFormat = format;
         u.gpr = gpr;
     }
     void fillJSValue(GPRReg gpr, DataFormat format = DataFormatJS)
     {
         ASSERT(format & DataFormatJS);
         m_registerFormat = format;
         u.gpr = gpr;
     }
+#elif USE(JSVALUE32_64)
+    void fillJSValue(GPRReg tagGPR, GPRReg payloadGPR, DataFormat format = DataFormatJS)
+    {
+        ASSERT(format & DataFormatJS);
+        m_registerFormat = format;
+        u.v.tagGPR = tagGPR; // FIXME: for JSValues with known type (boolean, integer, cell etc.) no tagGPR is needed?
+        u.v.payloadGPR = payloadGPR;
+    }
+    void fillCell(GPRReg gpr)
+    {
+        m_registerFormat = DataFormatCell;
+        u.gpr = gpr;
+    }
+#endif
     void fillInteger(GPRReg gpr)
     {
         m_registerFormat = DataFormatInteger;
         u.gpr = gpr;
     }
     void fillInteger(GPRReg gpr)
     {
         m_registerFormat = DataFormatInteger;
         u.gpr = gpr;
     }
+    void fillBoolean(GPRReg gpr)
+    {
+        m_registerFormat = DataFormatBoolean;
+        u.gpr = gpr;
+    }
     void fillDouble(FPRReg fpr)
     {
     void fillDouble(FPRReg fpr)
     {
+        ASSERT(fpr != InvalidFPRReg);
         m_registerFormat = DataFormatDouble;
         u.fpr = fpr;
     }
         m_registerFormat = DataFormatDouble;
         u.fpr = fpr;
     }
+    void fillStorage(GPRReg gpr)
+    {
+        m_registerFormat = DataFormatStorage;
+        u.gpr = gpr;
+    }
 
 
-#ifndef NDEBUG
     bool alive()
     {
         return m_useCount;
     }
     bool alive()
     {
         return m_useCount;
     }
-#endif
 
 private:
     // The index of the node whose result is stored in this virtual register.
 
 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;
     NodeIndex m_nodeIndex;
     uint32_t m_useCount;
     DataFormat m_registerFormat;
@@ -221,6 +313,12 @@ private:
     union {
         GPRReg gpr;
         FPRReg fpr;
     union {
         GPRReg gpr;
         FPRReg fpr;
+#if USE(JSVALUE32_64)
+        struct {
+            GPRReg tagGPR;
+            GPRReg payloadGPR;
+        } v;
+#endif
     } u;
 };
 
     } u;
 };
 
index b1e69914d41030f49ca72d5f65b617b7222f7aa4..3c99e5d4e321d8c4a8be5b9e8269b9b87c07bc21 100644 (file)
 #include "DFGGraph.h"
 
 #include "CodeBlock.h"
 #include "DFGGraph.h"
 
 #include "CodeBlock.h"
+#include <wtf/BoundsCheckedPointer.h>
 
 #if ENABLE(DFG_JIT)
 
 namespace JSC { namespace DFG {
 
 
 #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 ,
 // Creates an array of stringized names.
 static const char* dfgOpNames[] = {
 #define STRINGIZE_DFG_OP_ENUM(opcode, flags) #opcode ,
@@ -41,17 +40,98 @@ static const char* dfgOpNames[] = {
 #undef STRINGIZE_DFG_OP_ENUM
 };
 
 #undef STRINGIZE_DFG_OP_ENUM
 };
 
-void Graph::dump(NodeIndex nodeIndex, CodeBlock* codeBlock)
+const char *Graph::opName(NodeType op)
+{
+    return dfgOpNames[op];
+}
+
+const char* Graph::nameOfVariableAccessData(VariableAccessData* variableAccessData)
+{
+    // Variables are already numbered. For readability of IR dumps, this returns
+    // an alphabetic name for the variable access data, so that you don't have to
+    // reason about two numbers (variable number and live range number), but instead
+    // a number and a letter.
+    
+    unsigned index = std::numeric_limits<unsigned>::max();
+    for (unsigned i = 0; i < m_variableAccessData.size(); ++i) {
+        if (&m_variableAccessData[i] == variableAccessData) {
+            index = i;
+            break;
+        }
+    }
+    
+    ASSERT(index != std::numeric_limits<unsigned>::max());
+    
+    if (!index)
+        return "A";
+
+    static char buf[10];
+    BoundsCheckedPointer<char> ptr(buf, sizeof(buf));
+    
+    while (index) {
+        *ptr++ = 'A' + (index % 26);
+        index /= 26;
+    }
+    
+    *ptr++ = 0;
+    
+    return buf;
+}
+
+static void printWhiteSpace(unsigned amount)
+{
+    while (amount-- > 0)
+        dataLog(" ");
+}
+
+void Graph::dumpCodeOrigin(NodeIndex prevNodeIndex, NodeIndex nodeIndex)
+{
+    if (prevNodeIndex == NoNode)
+        return;
+    
+    Node& currentNode = at(nodeIndex);
+    Node& previousNode = at(prevNodeIndex);
+    if (previousNode.codeOrigin.inlineCallFrame == currentNode.codeOrigin.inlineCallFrame)
+        return;
+    
+    Vector<CodeOrigin> previousInlineStack = previousNode.codeOrigin.inlineStack();
+    Vector<CodeOrigin> currentInlineStack = currentNode.codeOrigin.inlineStack();
+    unsigned commonSize = std::min(previousInlineStack.size(), currentInlineStack.size());
+    unsigned indexOfDivergence = commonSize;
+    for (unsigned i = 0; i < commonSize; ++i) {
+        if (previousInlineStack[i].inlineCallFrame != currentInlineStack[i].inlineCallFrame) {
+            indexOfDivergence = i;
+            break;
+        }
+    }
+    
+    // Print the pops.
+    for (unsigned i = previousInlineStack.size(); i-- > indexOfDivergence;) {
+        printWhiteSpace(i * 2);
+        dataLog("<-- %p\n", previousInlineStack[i].inlineCallFrame->executable.get());
+    }
+    
+    // Print the pushes.
+    for (unsigned i = indexOfDivergence; i < currentInlineStack.size(); ++i) {
+        printWhiteSpace(i * 2);
+        dataLog("--> %p\n", currentInlineStack[i].inlineCallFrame->executable.get());
+    }
+}
+
+void Graph::dump(NodeIndex nodeIndex)
 {
     Node& node = at(nodeIndex);
 {
     Node& node = at(nodeIndex);
-    NodeType op = node.op;
+    NodeType op = node.op();
 
     unsigned refCount = node.refCount();
 
     unsigned refCount = node.refCount();
-    if (!refCount)
-        return;
+    bool skipped = !refCount;
     bool mustGenerate = node.mustGenerate();
     bool mustGenerate = node.mustGenerate();
-    if (mustGenerate)
+    if (mustGenerate) {
+        ASSERT(refCount);
         --refCount;
         --refCount;
+    }
+    
+    printWhiteSpace((node.codeOrigin.inlineDepth() - 1) * 2);
 
     // Example/explanation of dataflow dump output
     //
 
     // Example/explanation of dataflow dump output
     //
@@ -70,97 +150,216 @@ void Graph::dump(NodeIndex nodeIndex, CodeBlock* codeBlock)
     //         $#   - 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.
     //         $#   - 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());
+    dataLog("% 4d:%s<%c%u:", (int)nodeIndex, skipped ? "  skipped  " : "           ", mustGenerate ? '!' : ' ', refCount);
+    if (node.hasResult() && !skipped && node.hasVirtualRegister())
+        dataLog("%u", node.virtualRegister());
     else
     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;
+        dataLog("-");
+    dataLog(">\t%s(", opName(op));
+    bool hasPrinted = false;
+    if (node.flags() & NodeHasVarArgs) {
+        for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) {
+            if (hasPrinted)
+                dataLog(", ");
+            else
+                hasPrinted = true;
+            dataLog("%s@%u%s",
+                    useKindToString(m_varArgChildren[childIdx].useKind()),
+                    m_varArgChildren[childIdx].index(),
+                    predictionToAbbreviatedString(at(childIdx).prediction()));
+        }
+    } else {
+        if (!!node.child1()) {
+            dataLog("%s@%u%s",
+                    useKindToString(node.child1().useKind()),
+                    node.child1().index(),
+                    predictionToAbbreviatedString(at(node.child1()).prediction()));
+        }
+        if (!!node.child2()) {
+            dataLog(", %s@%u%s",
+                    useKindToString(node.child2().useKind()),
+                    node.child2().index(),
+                    predictionToAbbreviatedString(at(node.child2()).prediction()));
+        }
+        if (!!node.child3()) {
+            dataLog(", %s@%u%s",
+                    useKindToString(node.child3().useKind()),
+                    node.child3().index(),
+                    predictionToAbbreviatedString(at(node.child3()).prediction()));
+        }
+        hasPrinted = !!node.child1();
+    }
 
 
+    if (node.flags()) {
+        dataLog("%s%s", hasPrinted ? ", " : "", nodeFlagsAsString(node.flags()));
+        hasPrinted = true;
+    }
     if (node.hasVarNumber()) {
     if (node.hasVarNumber()) {
-        printf("%svar%u", hasPrinted ? ", " : "", node.varNumber());
+        dataLog("%svar%u", hasPrinted ? ", " : "", node.varNumber());
         hasPrinted = true;
     }
     if (node.hasIdentifier()) {
         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());
+        dataLog("%sid%u{%s}", hasPrinted ? ", " : "", node.identifierNumber(), m_codeBlock->identifier(node.identifierNumber()).ustring().utf8().data());
         hasPrinted = true;
     }
         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);
+    if (node.hasStructureSet()) {
+        for (size_t i = 0; i < node.structureSet().size(); ++i) {
+            dataLog("%sstruct(%p)", hasPrinted ? ", " : "", node.structureSet()[i]);
+            hasPrinted = true;
+        }
+    }
+    if (node.hasStructureTransitionData()) {
+        dataLog("%sstruct(%p -> %p)", hasPrinted ? ", " : "", node.structureTransitionData().previousStructure, node.structureTransitionData().newStructure);
+        hasPrinted = true;
+    }
+    if (node.hasStorageAccessData()) {
+        StorageAccessData& storageAccessData = m_storageAccessData[node.storageAccessDataIndex()];
+        dataLog("%sid%u{%s}", hasPrinted ? ", " : "", storageAccessData.identifierNumber, m_codeBlock->identifier(storageAccessData.identifierNumber).ustring().utf8().data());
+        
+        dataLog(", %lu", static_cast<unsigned long>(storageAccessData.offset));
         hasPrinted = true;
     }
         hasPrinted = true;
     }
-    if (op == Int32Constant) {
-        printf("%s$%u{%d|0x%08x}", hasPrinted ? ", " : "", node.constantNumber(), node.int32Constant(), node.int32Constant());
+    ASSERT(node.hasVariableAccessData() == node.hasLocal());
+    if (node.hasVariableAccessData()) {
+        VariableAccessData* variableAccessData = node.variableAccessData();
+        int operand = variableAccessData->operand();
+        if (operandIsArgument(operand))
+            dataLog("%sarg%u(%s)", hasPrinted ? ", " : "", operandToArgument(operand), nameOfVariableAccessData(variableAccessData));
+        else
+            dataLog("%sr%u(%s)", hasPrinted ? ", " : "", operand, nameOfVariableAccessData(variableAccessData));
         hasPrinted = true;
     }
         hasPrinted = true;
     }
-    if (op == DoubleConstant) {
-        printf("%s$%u{%f})", hasPrinted ? ", " : "", node.constantNumber(), node.numericConstant());
+    if (node.hasConstantBuffer()) {
+        if (hasPrinted)
+            dataLog(", ");
+        dataLog("%u:[", node.startConstant());
+        for (unsigned i = 0; i < node.numConstants(); ++i) {
+            if (i)
+                dataLog(", ");
+            dataLog("%s", m_codeBlock->constantBuffer(node.startConstant())[i].description());
+        }
+        dataLog("]");
         hasPrinted = true;
     }
     if (op == JSConstant) {
         hasPrinted = true;
     }
     if (op == JSConstant) {
-        printf("%s$%u", hasPrinted ? ", " : "", node.constantNumber());
+        dataLog("%s$%u", hasPrinted ? ", " : "", node.constantNumber());
+        JSValue value = valueOfJSConstant(nodeIndex);
+        dataLog(" = %s", value.description());
+        hasPrinted = true;
+    }
+    if (op == WeakJSConstant) {
+        dataLog("%s%p", hasPrinted ? ", " : "", node.weakConstant());
         hasPrinted = true;
     }
     if  (node.isBranch() || node.isJump()) {
         hasPrinted = true;
     }
     if  (node.isBranch() || node.isJump()) {
-        printf("%sT:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.takenBytecodeOffset()));
+        dataLog("%sT:#%u", hasPrinted ? ", " : "", node.takenBlockIndex());
         hasPrinted = true;
     }
     if  (node.isBranch()) {
         hasPrinted = true;
     }
     if  (node.isBranch()) {
-        printf("%sF:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.notTakenBytecodeOffset()));
+        dataLog("%sF:#%u", hasPrinted ? ", " : "", node.notTakenBlockIndex());
         hasPrinted = true;
     }
         hasPrinted = true;
     }
+    (void)hasPrinted;
+    
+    dataLog(")");
 
 
-    printf(")\n");
+    if (!skipped) {
+        if (node.hasVariableAccessData())
+            dataLog("  predicting %s, double ratio %lf%s", predictionToString(node.variableAccessData()->prediction()), node.variableAccessData()->doubleVoteRatio(), node.variableAccessData()->shouldUseDoubleFormat() ? ", forcing double" : "");
+        else if (node.hasHeapPrediction())
+            dataLog("  predicting %s", predictionToString(node.getHeapPrediction()));
+    }
+    
+    dataLog("\n");
 }
 
 }
 
-void Graph::dump(CodeBlock* codeBlock)
+void Graph::dump()
 {
 {
+    NodeIndex lastNodeIndex = NoNode;
     for (size_t b = 0; b < m_blocks.size(); ++b) {
     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);
+        BasicBlock* block = m_blocks[b].get();
+        dataLog("Block #%u (bc#%u): %s%s\n", (int)b, block->bytecodeBegin, block->isReachable ? "" : " (skipped)", block->isOSRTarget ? " (OSR target)" : "");
+        dataLog("  Phi Nodes:\n");
+        for (size_t i = 0; i < block->phis.size(); ++i) {
+            // Dumping the dead Phi nodes is just annoying!
+            if (at(block->phis[i]).refCount())
+                dump(block->phis[i]);
+        }
+        dataLog("  vars before: ");
+        if (block->cfaHasVisited)
+            dumpOperands(block->valuesAtHead, WTF::dataFile());
+        else
+            dataLog("<empty>");
+        dataLog("\n");
+        dataLog("  var links: ");
+        dumpOperands(block->variablesAtHead, WTF::dataFile());
+        dataLog("\n");
+        for (size_t i = 0; i < block->size(); ++i) {
+            dumpCodeOrigin(lastNodeIndex, block->at(i));
+            dump(block->at(i));
+            lastNodeIndex = block->at(i);
+        }
+        dataLog("  vars after: ");
+        if (block->cfaHasVisited)
+            dumpOperands(block->valuesAtTail, WTF::dataFile());
+        else
+            dataLog("<empty>");
+        dataLog("\n");
     }
     }
-    printf("Phi Nodes:\n");
-    for (size_t i = m_blocks.last()->end; i < size(); ++i)
-        dump(i, codeBlock);
 }
 
 }
 
-#endif
+// FIXME: Convert this to be iterative, not recursive.
+#define DO_TO_CHILDREN(node, thingToDo) do {                            \
+        Node& _node = (node);                                           \
+        if (_node.flags() & NodeHasVarArgs) {                           \
+            for (unsigned _childIdx = _node.firstChild();               \
+                 _childIdx < _node.firstChild() + _node.numChildren();  \
+                 _childIdx++)                                           \
+                thingToDo(m_varArgChildren[_childIdx]);                 \
+        } else {                                                        \
+            if (!_node.child1()) {                                      \
+                ASSERT(!_node.child2()                                  \
+                       && !_node.child3());                             \
+                break;                                                  \
+            }                                                           \
+            thingToDo(_node.child1());                                  \
+                                                                        \
+            if (!_node.child2()) {                                      \
+                ASSERT(!_node.child3());                                \
+                break;                                                  \
+            }                                                           \
+            thingToDo(_node.child2());                                  \
+                                                                        \
+            if (!_node.child3())                                        \
+                break;                                                  \
+            thingToDo(_node.child3());                                  \
+        }                                                               \
+    } while (false)
 
 
-// FIXME: Convert this method to be iterative, not recursive.
 void Graph::refChildren(NodeIndex op)
 {
 void Graph::refChildren(NodeIndex op)
 {
-    Node& node = at(op);
+    DO_TO_CHILDREN(at(op), ref);
+}
 
 
-    if (node.child1 == NoNode) {
-        ASSERT(node.child2 == NoNode && node.child3 == NoNode);
-        return;
-    }
-    ref(node.child1);
+void Graph::derefChildren(NodeIndex op)
+{
+    DO_TO_CHILDREN(at(op), deref);
+}
 
 
-    if (node.child2 == NoNode) {
-        ASSERT(node.child3 == NoNode);
-        return;
+void Graph::predictArgumentTypes()
+{
+    ASSERT(m_codeBlock->numParameters() >= 1);
+    for (size_t arg = 0; arg < static_cast<size_t>(m_codeBlock->numParameters()); ++arg) {
+        ValueProfile* profile = m_profiledBlock->valueProfileForArgument(arg);
+        if (!profile)
+            continue;
+        
+        at(m_arguments[arg]).variableAccessData()->predict(profile->computeUpdatedPrediction());
+        
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Argument [%zu] prediction: %s\n", arg, predictionToString(at(m_arguments[arg]).variableAccessData()->prediction()));
+#endif
     }
     }
-    ref(node.child2);
-
-    if (node.child3 == NoNode)
-        return;
-    ref(node.child3);
 }
 
 } } // namespace JSC::DFG
 }
 
 } } // namespace JSC::DFG
index 9fc490cd97aab84df57b17d92c9244b6047ac1e1..0c8ac2dcffdad231e68d79c2192bf9e5908f80bf 100644 (file)
 
 #if ENABLE(DFG_JIT)
 
 
 #if ENABLE(DFG_JIT)
 
-#include <RegisterFile.h>
-#include <dfg/DFGNode.h>
+#include "CodeBlock.h"
+#include "DFGArgumentPosition.h"
+#include "DFGAssemblyHelpers.h"
+#include "DFGBasicBlock.h"
+#include "DFGNode.h"
+#include "MethodOfGettingAValueProfile.h"
+#include "RegisterFile.h"
+#include <wtf/BitVector.h>
+#include <wtf/HashMap.h>
 #include <wtf/Vector.h>
 #include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
 class CodeBlock;
 #include <wtf/Vector.h>
 #include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
 class CodeBlock;
+class ExecState;
 
 namespace DFG {
 
 
 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;
+struct StorageAccessData {
+    size_t offset;
+    unsigned identifierNumber;
+    
+    // NOTE: the offset and identifierNumber do not by themselves
+    // uniquely identify a property. The identifierNumber and a
+    // Structure* do. If those two match, then the offset should
+    // be the same, as well. For any Node that has a StorageAccessData,
+    // it is possible to retrieve the Structure* by looking at the
+    // first child. It should be a CheckStructure, which has the
+    // Structure*.
 };
 
 };
 
-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;
+struct ResolveGlobalData {
+    unsigned identifierNumber;
+    unsigned resolveInfoIndex;
 };
 
 // 
 };
 
 // 
@@ -105,12 +73,23 @@ struct BasicBlock {
 // Nodes that are 'dead' remain in the vector with refCount 0.
 class Graph : public Vector<Node, 64> {
 public:
 // 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)
+    Graph(JSGlobalData& globalData, CodeBlock* codeBlock)
+        : m_globalData(globalData)
+        , m_codeBlock(codeBlock)
+        , m_profiledBlock(codeBlock->alternative())
     {
     {
+        ASSERT(m_profiledBlock);
     }
     }
-
+    
+    using Vector<Node, 64>::operator[];
+    using Vector<Node, 64>::at;
+    
+    Node& operator[](Edge nodeUse) { return at(nodeUse.index()); }
+    const Node& operator[](Edge nodeUse) const { return at(nodeUse.index()); }
+    
+    Node& at(Edge nodeUse) { return at(nodeUse.index()); }
+    const Node& at(Edge nodeUse) const { return at(nodeUse.index()); }
+    
     // Mark a node as being referenced.
     void ref(NodeIndex nodeIndex)
     {
     // Mark a node as being referenced.
     void ref(NodeIndex nodeIndex)
     {
@@ -119,57 +98,310 @@ public:
         if (node.ref())
             refChildren(nodeIndex);
     }
         if (node.ref())
             refChildren(nodeIndex);
     }
+    void ref(Edge nodeUse)
+    {
+        ref(nodeUse.index());
+    }
+    
+    void deref(NodeIndex nodeIndex)
+    {
+        if (at(nodeIndex).deref())
+            derefChildren(nodeIndex);
+    }
+    void deref(Edge nodeUse)
+    {
+        deref(nodeUse.index());
+    }
+    
+    void clearAndDerefChild1(Node& node)
+    {
+        if (!node.child1())
+            return;
+        deref(node.child1());
+        node.children.child1() = Edge();
+    }
 
 
-#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)
+    void clearAndDerefChild2(Node& node)
     {
     {
-        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);
+        if (!node.child2())
+            return;
+        deref(node.child2());
+        node.children.child2() = Edge();
     }
 
     }
 
-    BasicBlock& blockForBytecodeOffset(unsigned bytecodeBegin)
+    void clearAndDerefChild3(Node& node)
     {
     {
-        return *m_blocks[blockIndexForBytecodeOffset(bytecodeBegin)];
+        if (!node.child3())
+            return;
+        deref(node.child3());
+        node.children.child3() = Edge();
     }
 
     }
 
-    void predict(int operand, PredictedType prediction)
+    // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
+    void dump();
+    void dump(NodeIndex);
+
+    // Dump the code origin of the given node as a diff from the code origin of the
+    // preceding node.
+    void dumpCodeOrigin(NodeIndex, NodeIndex);
+
+    BlockIndex blockIndexForBytecodeOffset(Vector<BlockIndex>& blocks, unsigned bytecodeBegin);
+
+    PredictedType getJSConstantPrediction(Node& node)
+    {
+        return predictionFromValue(node.valueOfJSConstant(m_codeBlock));
+    }
+    
+    bool addShouldSpeculateInteger(Node& add)
+    {
+        ASSERT(add.op() == ValueAdd || add.op() == ArithAdd || add.op() == ArithSub);
+        
+        Node& left = at(add.child1());
+        Node& right = at(add.child2());
+        
+        if (left.hasConstant())
+            return addImmediateShouldSpeculateInteger(add, right, left);
+        if (right.hasConstant())
+            return addImmediateShouldSpeculateInteger(add, left, right);
+        
+        return Node::shouldSpeculateInteger(left, right) && add.canSpeculateInteger();
+    }
+    
+    bool negateShouldSpeculateInteger(Node& negate)
+    {
+        ASSERT(negate.op() == ArithNegate);
+        return at(negate.child1()).shouldSpeculateInteger() && negate.canSpeculateInteger();
+    }
+    
+    bool addShouldSpeculateInteger(NodeIndex nodeIndex)
+    {
+        return addShouldSpeculateInteger(at(nodeIndex));
+    }
+    
+    // Helper methods to check nodes for constants.
+    bool isConstant(NodeIndex nodeIndex)
+    {
+        return at(nodeIndex).hasConstant();
+    }
+    bool isJSConstant(NodeIndex nodeIndex)
+    {
+        return at(nodeIndex).hasConstant();
+    }
+    bool isInt32Constant(NodeIndex nodeIndex)
+    {
+        return at(nodeIndex).isInt32Constant(m_codeBlock);
+    }
+    bool isDoubleConstant(NodeIndex nodeIndex)
+    {
+        return at(nodeIndex).isDoubleConstant(m_codeBlock);
+    }
+    bool isNumberConstant(NodeIndex nodeIndex)
     {
     {
-        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;
-            
+        return at(nodeIndex).isNumberConstant(m_codeBlock);
     }
     }
+    bool isBooleanConstant(NodeIndex nodeIndex)
+    {
+        return at(nodeIndex).isBooleanConstant(m_codeBlock);
+    }
+    bool isFunctionConstant(NodeIndex nodeIndex)
+    {
+        if (!isJSConstant(nodeIndex))
+            return false;
+        if (!getJSFunction(valueOfJSConstant(nodeIndex)))
+            return false;
+        return true;
+    }
+    // Helper methods get constant values from nodes.
+    JSValue valueOfJSConstant(NodeIndex nodeIndex)
+    {
+        return at(nodeIndex).valueOfJSConstant(m_codeBlock);
+    }
+    int32_t valueOfInt32Constant(NodeIndex nodeIndex)
+    {
+        return valueOfJSConstant(nodeIndex).asInt32();
+    }
+    double valueOfNumberConstant(NodeIndex nodeIndex)
+    {
+        return valueOfJSConstant(nodeIndex).asNumber();
+    }
+    bool valueOfBooleanConstant(NodeIndex nodeIndex)
+    {
+        return valueOfJSConstant(nodeIndex).asBoolean();
+    }
+    JSFunction* valueOfFunctionConstant(NodeIndex nodeIndex)
+    {
+        JSCell* function = getJSFunction(valueOfJSConstant(nodeIndex));
+        ASSERT(function);
+        return jsCast<JSFunction*>(function);
+    }
+
+    static const char *opName(NodeType);
+    
+    // This is O(n), and should only be used for verbose dumps.
+    const char* nameOfVariableAccessData(VariableAccessData*);
 
 
-    PredictedType getPrediction(int operand)
+    void predictArgumentTypes();
+    
+    StructureSet* addStructureSet(const StructureSet& structureSet)
+    {
+        ASSERT(structureSet.size());
+        m_structureSet.append(structureSet);
+        return &m_structureSet.last();
+    }
+    
+    StructureTransitionData* addStructureTransitionData(const StructureTransitionData& structureTransitionData)
+    {
+        m_structureTransitionData.append(structureTransitionData);
+        return &m_structureTransitionData.last();
+    }
+    
+    CodeBlock* baselineCodeBlockFor(const CodeOrigin& codeOrigin)
+    {
+        return baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, m_profiledBlock);
+    }
+    
+    ValueProfile* valueProfileFor(NodeIndex nodeIndex)
+    {
+        if (nodeIndex == NoNode)
+            return 0;
+        
+        Node& node = at(nodeIndex);
+        CodeBlock* profiledBlock = baselineCodeBlockFor(node.codeOrigin);
+        
+        if (node.hasLocal()) {
+            if (!operandIsArgument(node.local()))
+                return 0;
+            int argument = operandToArgument(node.local());
+            if (node.variableAccessData() != at(m_arguments[argument]).variableAccessData())
+                return 0;
+            return profiledBlock->valueProfileForArgument(argument);
+        }
+        
+        if (node.hasHeapPrediction())
+            return profiledBlock->valueProfileForBytecodeOffset(node.codeOrigin.bytecodeIndexForValueProfile());
+        
+        return 0;
+    }
+    
+    MethodOfGettingAValueProfile methodOfGettingAValueProfileFor(NodeIndex nodeIndex)
     {
     {
-        if (operandIsArgument(operand)) {
-            unsigned argument = operand + m_argumentPredictions.size() + RegisterFile::CallFrameHeaderSize;
-            return m_argumentPredictions[argument].m_value;
+        if (nodeIndex == NoNode)
+            return MethodOfGettingAValueProfile();
+        
+        Node& node = at(nodeIndex);
+        CodeBlock* profiledBlock = baselineCodeBlockFor(node.codeOrigin);
+        
+        if (node.op() == GetLocal) {
+            return MethodOfGettingAValueProfile::fromLazyOperand(
+                profiledBlock,
+                LazyOperandValueProfileKey(
+                    node.codeOrigin.bytecodeIndex, node.local()));
         }
         }
-        if ((unsigned)operand < m_variablePredictions.size())
-            return m_variablePredictions[operand].m_value;
-        return PredictNone;
+        
+        return MethodOfGettingAValueProfile(valueProfileFor(nodeIndex));
+    }
+    
+    bool needsActivation() const
+    {
+#if DFG_ENABLE(ALL_VARIABLES_CAPTURED)
+        return true;
+#else
+        return m_codeBlock->needsFullScopeChain() && m_codeBlock->codeType() != GlobalCode;
+#endif
+    }
+    
+    // Pass an argument index. Currently it's ignored, but that's somewhat
+    // of a bug.
+    bool argumentIsCaptured(int) const
+    {
+        return needsActivation();
+    }
+    bool localIsCaptured(int operand) const
+    {
+#if DFG_ENABLE(ALL_VARIABLES_CAPTURED)
+        return operand < m_codeBlock->m_numVars;
+#else
+        return operand < m_codeBlock->m_numCapturedVars;
+#endif
+    }
+    
+    bool isCaptured(int operand) const
+    {
+        if (operandIsArgument(operand))
+            return argumentIsCaptured(operandToArgument(operand));
+        return localIsCaptured(operand);
+    }
+    bool isCaptured(VirtualRegister virtualRegister) const
+    {
+        return isCaptured(static_cast<int>(virtualRegister));
     }
     }
+    
+    JSGlobalData& m_globalData;
+    CodeBlock* m_codeBlock;
+    CodeBlock* m_profiledBlock;
 
     Vector< OwnPtr<BasicBlock> , 8> m_blocks;
 
     Vector< OwnPtr<BasicBlock> , 8> m_blocks;
+    Vector<Edge, 16> m_varArgChildren;
+    Vector<StorageAccessData> m_storageAccessData;
+    Vector<ResolveGlobalData> m_resolveGlobalData;
+    Vector<NodeIndex, 8> m_arguments;
+    SegmentedVector<VariableAccessData, 16> m_variableAccessData;
+    SegmentedVector<ArgumentPosition, 8> m_argumentPositions;
+    SegmentedVector<StructureSet, 16> m_structureSet;
+    SegmentedVector<StructureTransitionData, 8> m_structureTransitionData;
+    BitVector m_preservedVars;
+    unsigned m_localVars;
+    unsigned m_parameterSlots;
 private:
 private:
-
+    
+    bool addImmediateShouldSpeculateInteger(Node& add, Node& variable, Node& immediate)
+    {
+        ASSERT(immediate.hasConstant());
+        
+        JSValue immediateValue = immediate.valueOfJSConstant(m_codeBlock);
+        if (!immediateValue.isNumber())
+            return false;
+        
+        if (!variable.shouldSpeculateInteger())
+            return false;
+        
+        if (immediateValue.isInt32())
+            return add.canSpeculateInteger();
+        
+        double doubleImmediate = immediateValue.asDouble();
+        const double twoToThe48 = 281474976710656.0;
+        if (doubleImmediate < -twoToThe48 || doubleImmediate > twoToThe48)
+            return false;
+        
+        return nodeCanTruncateInteger(add.arithNodeFlags());
+    }
+    
     // 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);
     // 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);
+    void derefChildren(NodeIndex);
+};
+
+class GetBytecodeBeginForBlock {
+public:
+    GetBytecodeBeginForBlock(Graph& graph)
+        : m_graph(graph)
+    {
+    }
+    
+    unsigned operator()(BlockIndex* blockIndex) const
+    {
+        return m_graph.m_blocks[*blockIndex]->bytecodeBegin;
+    }
 
 
-    Vector<PredictionSlot, 16> m_argumentPredictions;
-    Vector<PredictionSlot, 16> m_variablePredictions;
+private:
+    Graph& m_graph;
 };
 
 };
 
+inline BlockIndex Graph::blockIndexForBytecodeOffset(Vector<BlockIndex>& linkingTargets, unsigned bytecodeBegin)
+{
+    return *WTF::binarySearchWithFunctor<BlockIndex, unsigned>(linkingTargets.begin(), linkingTargets.size(), bytecodeBegin, WTF::KeyMustBePresentInArray, GetBytecodeBeginForBlock(*this));
+}
+
 } } // namespace JSC::DFG
 
 #endif
 } } // namespace JSC::DFG
 
 #endif
diff --git a/dfg/DFGInsertionSet.h b/dfg/DFGInsertionSet.h
new file mode 100644 (file)
index 0000000..82a6a6f
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGInsertionSet_h
+#define DFGInsectionSet_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include <wtf/Vector.h>
+
+namespace JSC { namespace DFG {
+
+template<typename ElementType>
+class Insertion {
+public:
+    Insertion() { }
+    
+    Insertion(size_t index, const ElementType& element)
+        : m_index(index)
+        , m_element(element)
+    {
+    }
+    
+    size_t index() const { return m_index; }
+    const ElementType& element() const { return m_element; }
+private:
+    size_t m_index;
+    ElementType m_element;
+};
+
+template<typename ElementType>
+class InsertionSet {
+public:
+    InsertionSet() { }
+    
+    void append(const Insertion<ElementType>& insertion)
+    {
+        ASSERT(!m_insertions.size() || m_insertions.last().index() <= insertion.index());
+        m_insertions.append(insertion);
+    }
+    
+    void append(size_t index, const ElementType& element)
+    {
+        append(Insertion<ElementType>(index, element));
+    }
+    
+    template<typename CollectionType>
+    void execute(CollectionType& collection)
+    {
+        if (!m_insertions.size())
+            return;
+        collection.grow(collection.size() + m_insertions.size());
+        size_t lastIndex = collection.size();
+        for (size_t indexInInsertions = m_insertions.size(); indexInInsertions--;) {
+            Insertion<ElementType>& insertion = m_insertions[indexInInsertions];
+            size_t firstIndex = insertion.index() + indexInInsertions;
+            size_t indexOffset = indexInInsertions + 1;
+            for (size_t i = lastIndex; i-- > firstIndex;)
+                collection[i] = collection[i - indexOffset];
+            collection[firstIndex] = insertion.element();
+            lastIndex = firstIndex;
+        }
+        m_insertions.resize(0);
+    }
+private:
+    Vector<Insertion<ElementType>, 8> m_insertions;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGInsertionSet_h
+
diff --git a/dfg/DFGJITCodeGenerator.cpp b/dfg/DFGJITCodeGenerator.cpp
deleted file mode 100644 (file)
index 781edbb..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 3c0998d..0000000
+++ /dev/null
@@ -1,957 +0,0 @@
-/*
- * 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
-
index 9e946d22a45b7fef179746de58c1c75c570c0469..56e0d4e1893d0f406349f7f243ec182920563a33 100644 (file)
 #if ENABLE(DFG_JIT)
 
 #include "CodeBlock.h"
 #if ENABLE(DFG_JIT)
 
 #include "CodeBlock.h"
-#include "DFGJITCodeGenerator.h"
-#include "DFGNonSpeculativeJIT.h"
+#include "DFGOSRExitCompiler.h"
 #include "DFGOperations.h"
 #include "DFGRegisterBank.h"
 #include "DFGSpeculativeJIT.h"
 #include "DFGOperations.h"
 #include "DFGRegisterBank.h"
 #include "DFGSpeculativeJIT.h"
+#include "DFGThunks.h"
 #include "JSGlobalData.h"
 #include "LinkBuffer.h"
 
 namespace JSC { namespace DFG {
 
 #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)
+void JITCompiler::linkOSRExits()
 {
 {
-    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);
+    for (unsigned i = 0; i < codeBlock()->numberOfOSRExits(); ++i) {
+        OSRExit& exit = codeBlock()->osrExit(i);
+        exit.m_check.initialJump().link(this);
+        jitAssertHasValidCallFrame();
+        store32(TrustedImm32(i), &globalData()->osrExitIndex);
+        exit.m_check.switchToLateJump(patchableJump());
     }
 }
 
     }
 }
 
-// This method used to fill an integer value to a GPR when linking speculative -> non-speculative.
-void JITCompiler::fillInt32ToInteger(NodeIndex nodeIndex, GPRReg gpr)
+void JITCompiler::compileEntry()
 {
 {
-    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 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.
+    // 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);
+    emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
 }
 
 }
 
-// This method used to fill a JSValue to a GPR when linking speculative -> non-speculative.
-void JITCompiler::fillToJS(NodeIndex nodeIndex, GPRReg gpr)
+void JITCompiler::compileBody(SpeculativeJIT& speculative)
 {
 {
-    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;
-    }
+    // We generate the speculative code path, followed by OSR exit code to return
+    // to the old JIT code if speculations fail.
 
 
-    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());
-    }
+#if DFG_ENABLE(JIT_BREAK_ON_EVERY_FUNCTION)
+    // Handy debug tool!
+    breakpoint();
+#endif
+    
+    addPtr(TrustedImm32(1), AbsoluteAddress(codeBlock()->addressOfSpeculativeSuccessCounter()));
 
 
-    // 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));
-    }
+    bool compiledSpeculative = speculative.compile();
+    ASSERT_UNUSED(compiledSpeculative, compiledSpeculative);
 
 
-    // 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;
+    linkOSRExits();
 
 
-        VirtualRegister virtualRegister = graph()[nodeIndex].virtualRegister();
+    // Iterate over the m_calls vector, checking for jumps to link.
+    bool didLinkExceptionCheck = false;
+    for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
+        Jump& exceptionCheck = m_exceptionChecks[i].m_exceptionCheck;
+        if (exceptionCheck.isSet()) {
+            exceptionCheck.link(this);
+            didLinkExceptionCheck = true;
+        }
+    }
 
 
-        moveDoubleToPtr(FPRInfo::toRegister(index), GPRInfo::regT0);
-        subPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
-        storePtr(GPRInfo::regT0, addressFor(virtualRegister));
+    // If any exception checks were linked, generate code to lookup a handler.
+    if (didLinkExceptionCheck) {
+        // lookupExceptionHandler is passed two arguments, exec (the CallFrame*), and
+        // the index into the CodeBlock's callReturnIndexVector corresponding to the
+        // call that threw the exception (this was set in nonPreservedNonReturnGPR, when
+        // the exception check was planted).
+        move(GPRInfo::nonPreservedNonReturnGPR, GPRInfo::argumentGPR1);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+#if CPU(X86)
+        // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
+        poke(GPRInfo::argumentGPR0);
+        poke(GPRInfo::argumentGPR1, 1);
+#endif
+        m_calls.append(CallLinkRecord(call(), lookupExceptionHandler));
+        // lookupExceptionHandler leaves the handler CallFrame* in the returnValueGPR,
+        // and the address of the handler in returnValueGPR2.
+        jump(GPRInfo::returnValueGPR2);
     }
     }
+}
 
 
-    // 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;
+void JITCompiler::link(LinkBuffer& linkBuffer)
+{
+    // Link the code, populate data in CodeBlock data structures.
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("JIT code for %p start at [%p, %p). Size = %zu.\n", m_codeBlock, linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize(), linkBuffer.debugSize());
+#endif
 
 
-        fillNumericToDouble(nodeIndex, FPRInfo::toRegister(index), GPRInfo::regT0);
-    }
+    // 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);
 
 
-    // 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?
+    if (m_codeBlock->needsCallReturnIndices()) {
+        m_codeBlock->callReturnIndexVector().reserveCapacity(m_exceptionChecks.size());
+        for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
+            unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_exceptionChecks[i].m_call);
+            CodeOrigin codeOrigin = m_exceptionChecks[i].m_codeOrigin;
+            while (codeOrigin.inlineCallFrame)
+                codeOrigin = codeOrigin.inlineCallFrame->caller;
+            unsigned exceptionInfo = codeOrigin.bytecodeIndex;
+            m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
         }
     }
 
         }
     }
 
-    // Jump into the non-speculative path.
-    jump(entry.m_entry);
+    Vector<CodeOriginAtCallReturnOffset>& codeOrigins = m_codeBlock->codeOrigins();
+    codeOrigins.resize(m_exceptionChecks.size());
+    
+    for (unsigned i = 0; i < m_exceptionChecks.size(); ++i) {
+        CallExceptionRecord& record = m_exceptionChecks[i];
+        unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_exceptionChecks[i].m_call);
+        codeOrigins[i].codeOrigin = record.m_codeOrigin;
+        codeOrigins[i].callReturnOffset = returnAddressOffset;
+        record.m_token.assertCodeOriginIndex(i);
+    }
+    
+    m_codeBlock->setNumberOfStructureStubInfos(m_propertyAccesses.size());
+    for (unsigned i = 0; i < m_propertyAccesses.size(); ++i) {
+        StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
+        CodeLocationCall callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_functionCall);
+        info.codeOrigin = m_propertyAccesses[i].m_codeOrigin;
+        info.callReturnLocation = callReturnLocation;
+        info.patch.dfg.deltaCheckImmToCall = differenceBetweenCodePtr(linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCheckImmToCall), callReturnLocation);
+        info.patch.dfg.deltaCallToStructCheck = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToStructCheck));
+#if USE(JSVALUE64)
+        info.patch.dfg.deltaCallToLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToLoadOrStore));
+#else
+        info.patch.dfg.deltaCallToTagLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToTagLoadOrStore));
+        info.patch.dfg.deltaCallToPayloadLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToPayloadLoadOrStore));
+#endif
+        info.patch.dfg.deltaCallToSlowCase = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToSlowCase));
+        info.patch.dfg.deltaCallToDone = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToDone));
+        info.patch.dfg.baseGPR = m_propertyAccesses[i].m_baseGPR;
+#if USE(JSVALUE64)
+        info.patch.dfg.valueGPR = m_propertyAccesses[i].m_valueGPR;
+#else
+        info.patch.dfg.valueTagGPR = m_propertyAccesses[i].m_valueTagGPR;
+        info.patch.dfg.valueGPR = m_propertyAccesses[i].m_valueGPR;
+#endif
+        info.patch.dfg.scratchGPR = m_propertyAccesses[i].m_scratchGPR;
+        info.patch.dfg.registersFlushed = m_propertyAccesses[i].m_registerMode == PropertyAccessRecord::RegistersFlushed;
+    }
+    
+    m_codeBlock->setNumberOfCallLinkInfos(m_jsCalls.size());
+    for (unsigned i = 0; i < m_jsCalls.size(); ++i) {
+        CallLinkInfo& info = m_codeBlock->callLinkInfo(i);
+        info.callType = m_jsCalls[i].m_callType;
+        info.isDFG = true;
+        info.callReturnLocation = CodeLocationLabel(linkBuffer.locationOf(m_jsCalls[i].m_slowCall));
+        info.hotPathBegin = linkBuffer.locationOf(m_jsCalls[i].m_targetToCheck);
+        info.hotPathOther = linkBuffer.locationOfNearCall(m_jsCalls[i].m_fastCall);
+    }
+    
+    MacroAssemblerCodeRef osrExitThunk = globalData()->getCTIStub(osrExitGenerationThunkGenerator);
+    CodeLocationLabel target = CodeLocationLabel(osrExitThunk.code());
+    for (unsigned i = 0; i < codeBlock()->numberOfOSRExits(); ++i) {
+        OSRExit& exit = codeBlock()->osrExit(i);
+        linkBuffer.link(exit.m_check.lateJump(), target);
+        exit.m_check.correctLateJump(linkBuffer);
+    }
+    
+    codeBlock()->shrinkWeakReferencesToFit();
+    codeBlock()->shrinkWeakReferenceTransitionsToFit();
 }
 
 }
 
-void JITCompiler::linkSpeculationChecks(SpeculativeJIT& speculative, NonSpeculativeJIT& nonSpeculative)
+bool JITCompiler::compile(JITCode& entry)
 {
 {
-    // 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;
-    }
+    compileEntry();
+    SpeculativeJIT speculative(*this);
+    compileBody(speculative);
+
+    // Create OSR entry trampolines if necessary.
+    speculative.createOSREntries();
 
 
-    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56289
-    ASSERT(!(checksIter != checksEnd));
-    ASSERT(!(entriesIter != entriesEnd));
+    LinkBuffer linkBuffer(*m_globalData, this, m_codeBlock, JITCompilationCanFail);
+    if (linkBuffer.didFailToAllocate())
+        return false;
+    link(linkBuffer);
+    speculative.linkOSREntries(linkBuffer);
+
+    entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT);
+    return true;
 }
 
 }
 
-void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck)
+bool 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.
+    compileEntry();
 
 
+    // === Function header code generation ===
     // This is the main entry point, without performing an arity 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);
     // 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
     // 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);
+    addPtr(TrustedImm32(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();
 
 
     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();
+    // === Function body code generation ===
     SpeculativeJIT speculative(*this);
     SpeculativeJIT speculative(*this);
-#if !DFG_DEBUG_LOCAL_DISBALE_SPECULATIVE
-    bool compiledSpeculative = speculative.compile();
-#else
-    bool compiledSpeculative = false;
-#endif
+    compileBody(speculative);
 
 
-    // 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 ===
+    // === Function footer code generation ===
+    //
+    // Generate code to perform the slow register file check (if the fast one in
+    // the function header fails), and generate the entry point with arity check.
     //
     //
-    // 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*));
     // 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*));
+
+    CallBeginToken token = beginCall();
     Call callRegisterFileCheck = call();
     Call callRegisterFileCheck = call();
+    notifyCall(callRegisterFileCheck, CodeOrigin(0), token);
     jump(fromRegisterFileCheck);
     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();
     // 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);
+    compileEntry();
+
+    load32(AssemblyHelpers::payloadFor((VirtualRegister)RegisterFile::ArgumentCount), GPRInfo::regT1);
+    branch32(AboveOrEqual, GPRInfo::regT1, TrustedImm32(m_codeBlock->numParameters())).linkTo(fromArityCheck, this);
     move(stackPointerRegister, GPRInfo::argumentGPR0);
     poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
     move(stackPointerRegister, GPRInfo::argumentGPR0);
     poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+    token = beginCall();
     Call callArityCheck = call();
     Call callArityCheck = call();
+    notifyCall(callArityCheck, CodeOrigin(0), token);
     move(GPRInfo::regT0, GPRInfo::callFrameRegister);
     jump(fromArityCheck);
     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));
-            }
-        }
-    }
-
+    
+    // Create OSR entry trampolines if necessary.
+    speculative.createOSREntries();
+
+
+    // === Link ===
+    LinkBuffer linkBuffer(*m_globalData, this, m_codeBlock, JITCompilationCanFail);
+    if (linkBuffer.didFailToAllocate())
+        return false;
+    link(linkBuffer);
+    speculative.linkOSREntries(linkBuffer);
+    
     // 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);
     // 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)));
+    entry = JITCode(linkBuffer.finalizeCode(), JITCode::DFGJIT);
+    return true;
 }
 }
-#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
 
 
 } } // namespace JSC::DFG
 
-#endif
+#endif // ENABLE(DFG_JIT)
index 7ed9a2fe4044f22b28468bfc9a0188e4783c7324..01a1e7246ae9be3ebc4f029c66d513e84cb83670 100644 (file)
 
 #if ENABLE(DFG_JIT)
 
 
 #if ENABLE(DFG_JIT)
 
+#include <assembler/LinkBuffer.h>
 #include <assembler/MacroAssembler.h>
 #include <bytecode/CodeBlock.h>
 #include <assembler/MacroAssembler.h>
 #include <bytecode/CodeBlock.h>
+#include <dfg/DFGCCallHelpers.h>
+#include <dfg/DFGFPRInfo.h>
+#include <dfg/DFGGPRInfo.h>
 #include <dfg/DFGGraph.h>
 #include <dfg/DFGRegisterBank.h>
 #include <jit/JITCode.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;
 namespace JSC {
 
 class AbstractSamplingCounter;
@@ -46,41 +47,134 @@ class JSGlobalData;
 namespace DFG {
 
 class JITCodeGenerator;
 namespace DFG {
 
 class JITCodeGenerator;
-class NonSpeculativeJIT;
+class NodeToRegisterMap;
 class SpeculativeJIT;
 class SpeculationRecovery;
 
 struct EntryLocation;
 class SpeculativeJIT;
 class SpeculationRecovery;
 
 struct EntryLocation;
-struct SpeculationCheck;
+struct OSRExit;
 
 
-// === CallRecord ===
+// === CallLinkRecord ===
 //
 //
-// 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)
+// A record of a call out from JIT code that needs linking to a helper function.
+// Every CallLinkRecord contains a reference to the call instruction & the function
+// that it needs to be linked to.
+struct CallLinkRecord {
+    CallLinkRecord(MacroAssembler::Call call, FunctionPtr function)
         : m_call(call)
         , m_function(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)
+    MacroAssembler::Call m_call;
+    FunctionPtr m_function;
+};
+
+class CallBeginToken {
+public:
+    CallBeginToken()
+#if !ASSERT_DISABLED
+        : m_codeOriginIndex(UINT_MAX)
+#endif
+    {
+    }
+    
+    explicit CallBeginToken(unsigned codeOriginIndex)
+#if !ASSERT_DISABLED
+        : m_codeOriginIndex(codeOriginIndex)
+#endif
+    {
+        UNUSED_PARAM(codeOriginIndex);
+    }
+    
+    void assertCodeOriginIndex(unsigned codeOriginIndex) const
+    {
+        ASSERT_UNUSED(codeOriginIndex, codeOriginIndex < UINT_MAX);
+        ASSERT_UNUSED(codeOriginIndex, codeOriginIndex == m_codeOriginIndex);
+    }
+
+private:
+#if !ASSERT_DISABLED
+    unsigned m_codeOriginIndex;
+#endif
+};
+
+// === CallExceptionRecord ===
+//
+// A record of a call out from JIT code that might throw an exception.
+// Calls that might throw an exception also record the Jump taken on exception
+// (unset if not present) and code origin used to recover handler/source info.
+struct CallExceptionRecord {
+    CallExceptionRecord(MacroAssembler::Call call, CodeOrigin codeOrigin, CallBeginToken token)
+        : m_call(call)
+        , m_codeOrigin(codeOrigin)
+        , m_token(token)
+    {
+    }
+
+    CallExceptionRecord(MacroAssembler::Call call, MacroAssembler::Jump exceptionCheck, CodeOrigin codeOrigin, CallBeginToken token)
         : m_call(call)
         : m_call(call)
-        , m_function(function)
         , m_exceptionCheck(exceptionCheck)
         , m_exceptionCheck(exceptionCheck)
-        , m_exceptionInfo(exceptionInfo)
+        , m_codeOrigin(codeOrigin)
+        , m_token(token)
     {
     }
 
     MacroAssembler::Call m_call;
     {
     }
 
     MacroAssembler::Call m_call;
-    FunctionPtr m_function;
     MacroAssembler::Jump m_exceptionCheck;
     MacroAssembler::Jump m_exceptionCheck;
-    ExceptionInfo m_exceptionInfo;
+    CodeOrigin m_codeOrigin;
+    CallBeginToken m_token;
+};
+
+struct PropertyAccessRecord {
+    enum RegisterMode { RegistersFlushed, RegistersInUse };
+    
+#if USE(JSVALUE64)
+    PropertyAccessRecord(CodeOrigin codeOrigin, MacroAssembler::DataLabelPtr deltaCheckImmToCall, MacroAssembler::Call functionCall, MacroAssembler::PatchableJump deltaCallToStructCheck, MacroAssembler::DataLabelCompact deltaCallToLoadOrStore, MacroAssembler::Label deltaCallToSlowCase, MacroAssembler::Label deltaCallToDone, int8_t baseGPR, int8_t valueGPR, int8_t scratchGPR, RegisterMode registerMode = RegistersInUse)
+#elif USE(JSVALUE32_64)
+    PropertyAccessRecord(CodeOrigin codeOrigin, MacroAssembler::DataLabelPtr deltaCheckImmToCall, MacroAssembler::Call functionCall, MacroAssembler::PatchableJump deltaCallToStructCheck, MacroAssembler::DataLabelCompact deltaCallToTagLoadOrStore, MacroAssembler::DataLabelCompact deltaCallToPayloadLoadOrStore, MacroAssembler::Label deltaCallToSlowCase, MacroAssembler::Label deltaCallToDone, int8_t baseGPR, int8_t valueTagGPR, int8_t valueGPR, int8_t scratchGPR, RegisterMode registerMode = RegistersInUse)
+#endif
+        : m_codeOrigin(codeOrigin)
+        , m_deltaCheckImmToCall(deltaCheckImmToCall)
+        , m_functionCall(functionCall)
+        , m_deltaCallToStructCheck(deltaCallToStructCheck)
+#if USE(JSVALUE64)
+        , m_deltaCallToLoadOrStore(deltaCallToLoadOrStore)
+#elif USE(JSVALUE32_64)
+        , m_deltaCallToTagLoadOrStore(deltaCallToTagLoadOrStore)
+        , m_deltaCallToPayloadLoadOrStore(deltaCallToPayloadLoadOrStore)
+#endif
+        , m_deltaCallToSlowCase(deltaCallToSlowCase)
+        , m_deltaCallToDone(deltaCallToDone)
+        , m_baseGPR(baseGPR)
+#if USE(JSVALUE32_64)
+        , m_valueTagGPR(valueTagGPR)
+#endif
+        , m_valueGPR(valueGPR)
+        , m_scratchGPR(scratchGPR)
+        , m_registerMode(registerMode)
+    {
+    }
+
+    CodeOrigin m_codeOrigin;
+    MacroAssembler::DataLabelPtr m_deltaCheckImmToCall;
+    MacroAssembler::Call m_functionCall;
+    MacroAssembler::PatchableJump m_deltaCallToStructCheck;
+#if USE(JSVALUE64)
+    MacroAssembler::DataLabelCompact m_deltaCallToLoadOrStore;
+#elif USE(JSVALUE32_64)
+    MacroAssembler::DataLabelCompact m_deltaCallToTagLoadOrStore;
+    MacroAssembler::DataLabelCompact m_deltaCallToPayloadLoadOrStore;
+#endif
+    MacroAssembler::Label m_deltaCallToSlowCase;
+    MacroAssembler::Label m_deltaCallToDone;
+    int8_t m_baseGPR;
+#if USE(JSVALUE32_64)
+    int8_t m_valueTagGPR;
+#endif
+    int8_t m_valueGPR;
+    int8_t m_scratchGPR;
+    RegisterMode m_registerMode;
 };
 
 // === JITCompiler ===
 };
 
 // === JITCompiler ===
@@ -91,166 +185,167 @@ struct CallRecord {
 // 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).
 // 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 {
+class JITCompiler : public CCallHelpers {
 public:
 public:
-    JITCompiler(JSGlobalData* globalData, Graph& dfg, CodeBlock* codeBlock)
-        : m_globalData(globalData)
+    JITCompiler(Graph& dfg)
+        : CCallHelpers(&dfg.m_globalData, dfg.m_codeBlock)
         , m_graph(dfg)
         , m_graph(dfg)
-        , m_codeBlock(codeBlock)
+        , m_currentCodeOriginIndex(0)
     {
     }
 
     {
     }
 
-    void compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck);
+    bool compile(JITCode& entry);
+    bool compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck);
 
     // Accessors for properties.
     Graph& graph() { return m_graph; }
 
     // 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)
+    
+    // Get a token for beginning a call, and set the current code origin index in
+    // the call frame.
+    CallBeginToken beginCall()
     {
     {
-        pop(reg);
+        unsigned codeOriginIndex = m_currentCodeOriginIndex++;
+        store32(TrustedImm32(codeOriginIndex), tagFor(static_cast<VirtualRegister>(RegisterFile::ArgumentCount)));
+        return CallBeginToken(codeOriginIndex);
     }
 
     }
 
-    void restoreReturnAddressBeforeReturn(GPRReg reg)
+    // Notify the JIT of a call that does not require linking.
+    void notifyCall(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
     {
     {
-        push(reg);
+        m_exceptionChecks.append(CallExceptionRecord(functionCall, codeOrigin, token));
     }
 
     }
 
-    void restoreReturnAddressBeforeReturn(Address address)
+    // Add a call out from JIT code, without an exception check.
+    Call appendCall(const FunctionPtr& function)
     {
     {
-        push(address);
+        Call functionCall = call();
+        m_calls.append(CallLinkRecord(functionCall, function));
+        return functionCall;
     }
 
     }
 
-    void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, GPRReg to)
+    // Add a call out from JIT code, with an exception check.
+    void addExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
     {
     {
-        loadPtr(Address(GPRInfo::callFrameRegister, entry * sizeof(Register)), to);
+        move(TrustedImm32(m_exceptionChecks.size()), GPRInfo::nonPreservedNonReturnGPR);
+        m_exceptionChecks.append(CallExceptionRecord(functionCall, emitExceptionCheck(), codeOrigin, token));
     }
     }
-    void emitPutToCallFrameHeader(GPRReg from, RegisterFile::CallFrameHeaderEntry entry)
+    
+    // Add a call out from JIT code, with a fast exception check that tests if the return value is zero.
+    void addFastExceptionCheck(Call functionCall, CodeOrigin codeOrigin, CallBeginToken token)
     {
     {
-        storePtr(from, Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
+        move(TrustedImm32(m_exceptionChecks.size()), GPRInfo::nonPreservedNonReturnGPR);
+        Jump exceptionCheck = branchTestPtr(Zero, GPRInfo::returnValueGPR);
+        m_exceptionChecks.append(CallExceptionRecord(functionCall, exceptionCheck, codeOrigin, token));
     }
     }
-
-    void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry)
+    
+    // Helper methods to get predictions
+    PredictedType getPrediction(Node& node) { return node.prediction(); }
+    PredictedType getPrediction(NodeIndex nodeIndex) { return getPrediction(graph()[nodeIndex]); }
+    PredictedType getPrediction(Edge nodeUse) { return getPrediction(nodeUse.index()); }
+
+#if USE(JSVALUE32_64)
+    void* addressOfDoubleConstant(NodeIndex nodeIndex)
     {
     {
-        storePtr(TrustedImmPtr(value), Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
+        ASSERT(m_graph.isNumberConstant(nodeIndex));
+        unsigned constantIndex = graph()[nodeIndex].constantNumber();
+        return &(codeBlock()->constantRegister(FirstConstantRegisterIndex + constantIndex));
     }
 #endif
 
     }
 #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)
+    void addPropertyAccess(const PropertyAccessRecord& record)
     {
     {
-        Call functionCall = call();
-        Jump exceptionCheck = branchTestPtr(NonZero, AbsoluteAddress(&globalData()->exception));
-        m_calls.append(CallRecord(functionCall, function, exceptionCheck, exceptionInfo));
+        m_propertyAccesses.append(record);
     }
 
     }
 
-    // Helper methods to check nodes for constants.
-    bool isConstant(NodeIndex nodeIndex)
-    {
-        return graph()[nodeIndex].isConstant();
-    }
-    bool isInt32Constant(NodeIndex nodeIndex)
+    void addJSCall(Call fastCall, Call slowCall, DataLabelPtr targetToCheck, CallLinkInfo::CallType callType, CodeOrigin codeOrigin)
     {
     {
-        return graph()[nodeIndex].op == Int32Constant;
+        m_jsCalls.append(JSCallRecord(fastCall, slowCall, targetToCheck, callType, codeOrigin));
     }
     }
-    bool isDoubleConstant(NodeIndex nodeIndex)
+    
+    void addWeakReference(JSCell* target)
     {
     {
-        return graph()[nodeIndex].op == DoubleConstant;
+        m_codeBlock->appendWeakReference(target);
     }
     }
-    bool isJSConstant(NodeIndex nodeIndex)
+    
+    void addWeakReferenceTransition(JSCell* codeOrigin, JSCell* from, JSCell* to)
     {
     {
-        return graph()[nodeIndex].op == JSConstant;
+        m_codeBlock->appendWeakReferenceTransition(codeOrigin, from, to);
     }
     }
-
-    // Helper methods get constant values from nodes.
-    int32_t valueOfInt32Constant(NodeIndex nodeIndex)
+    
+    template<typename T>
+    Jump branchWeakPtr(RelationalCondition cond, T left, JSCell* weakPtr)
     {
     {
-        ASSERT(isInt32Constant(nodeIndex));
-        return graph()[nodeIndex].int32Constant();
+        Jump result = branchPtr(cond, left, TrustedImmPtr(weakPtr));
+        addWeakReference(weakPtr);
+        return result;
     }
     }
-    double valueOfDoubleConstant(NodeIndex nodeIndex)
+    
+    void noticeOSREntry(BasicBlock& basicBlock, JITCompiler::Label blockHead, LinkBuffer& linkBuffer)
     {
     {
-        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);
+#if DFG_ENABLE(OSR_ENTRY)
+        OSREntryData* entry = codeBlock()->appendDFGOSREntryData(basicBlock.bytecodeBegin, linkBuffer.offsetOf(blockHead));
+        
+        entry->m_expectedValues = basicBlock.valuesAtHead;
+        
+        // Fix the expected values: in our protocol, a dead variable will have an expected
+        // value of (None, []). But the old JIT may stash some values there. So we really
+        // need (Top, TOP).
+        for (size_t argument = 0; argument < basicBlock.variablesAtHead.numberOfArguments(); ++argument) {
+            NodeIndex nodeIndex = basicBlock.variablesAtHead.argument(argument);
+            if (nodeIndex == NoNode || !m_graph[nodeIndex].shouldGenerate())
+                entry->m_expectedValues.argument(argument).makeTop();
+        }
+        for (size_t local = 0; local < basicBlock.variablesAtHead.numberOfLocals(); ++local) {
+            NodeIndex nodeIndex = basicBlock.variablesAtHead.local(local);
+            if (nodeIndex == NoNode || !m_graph[nodeIndex].shouldGenerate())
+                entry->m_expectedValues.local(local).makeTop();
+            else if (m_graph[nodeIndex].variableAccessData()->shouldUseDoubleFormat())
+                entry->m_localsForcedDouble.set(local);
+        }
 #else
 #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);
+        UNUSED_PARAM(basicBlock);
+        UNUSED_PARAM(blockHead);
+        UNUSED_PARAM(linkBuffer);
 #endif
 #endif
+    }
 
 private:
 
 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;
-
+    // Internal implementation to compile.
+    void compileEntry();
+    void compileBody(SpeculativeJIT&);
+    void link(LinkBuffer&);
+
+    void exitSpeculativeWithOSR(const OSRExit&, SpeculationRecovery*);
+    void linkOSRExits();
+    
     // The dataflow graph currently being generated.
     Graph& m_graph;
 
     // 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 of calls out from JIT code, including exception handler information.
-    Vector<CallRecord> m_calls;
+    // Count of the number of CallRecords with exception handlers.
+    Vector<CallLinkRecord> m_calls;
+    Vector<CallExceptionRecord> m_exceptionChecks;
+    
+    struct JSCallRecord {
+        JSCallRecord(Call fastCall, Call slowCall, DataLabelPtr targetToCheck, CallLinkInfo::CallType callType, CodeOrigin codeOrigin)
+            : m_fastCall(fastCall)
+            , m_slowCall(slowCall)
+            , m_targetToCheck(targetToCheck)
+            , m_callType(callType)
+            , m_codeOrigin(codeOrigin)
+        {
+        }
+        
+        Call m_fastCall;
+        Call m_slowCall;
+        DataLabelPtr m_targetToCheck;
+        CallLinkInfo::CallType m_callType;
+        CodeOrigin m_codeOrigin;
+    };
+    
+    Vector<PropertyAccessRecord, 4> m_propertyAccesses;
+    Vector<JSCallRecord, 4> m_jsCalls;
+    unsigned m_currentCodeOriginIndex;
 };
 
 } } // namespace JSC::DFG
 };
 
 } } // namespace JSC::DFG
index 903be461cc9afbd1e635553cf3c71365ee2ae628..f79a93a69cf7b08014b8b81e329aa72bab5a4373 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef DFGNode_h
 #define DFGNode_h
 
 #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
-
+#include <wtf/Platform.h>
 
 #if ENABLE(DFG_JIT)
 
 
 #if ENABLE(DFG_JIT)
 
-#include <wtf/Vector.h>
+#include "CodeBlock.h"
+#include "CodeOrigin.h"
+#include "DFGAdjacencyList.h"
+#include "DFGCommon.h"
+#include "DFGNodeFlags.h"
+#include "DFGNodeType.h"
+#include "DFGVariableAccessData.h"
+#include "JSValue.h"
+#include "Operands.h"
+#include "PredictedType.h"
+#include "ValueProfile.h"
 
 namespace JSC { namespace DFG {
 
 
 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
+struct StructureTransitionData {
+    Structure* previousStructure;
+    Structure* newStructure;
+    
+    StructureTransitionData() { }
+    
+    StructureTransitionData(Structure* previousStructure, Structure* newStructure)
+        : previousStructure(previousStructure)
+        , newStructure(newStructure)
+    {
+    }
 };
 
 // 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 {
 };
 
 // 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;
+    explicit OpInfo(int32_t value) : m_value(static_cast<uintptr_t>(value)) { }
+    explicit OpInfo(uint32_t value) : m_value(static_cast<uintptr_t>(value)) { }
+#if OS(DARWIN) || USE(JSVALUE64)
+    explicit OpInfo(size_t value) : m_value(static_cast<uintptr_t>(value)) { }
+#endif
+    explicit OpInfo(void* value) : m_value(reinterpret_cast<uintptr_t>(value)) { }
+    uintptr_t m_value;
 };
 
 // === Node ===
 //
 // Node represents a single operation in the data flow graph.
 struct Node {
 };
 
 // === Node ===
 //
 // Node represents a single operation in the data flow graph.
 struct Node {
+    enum VarArgTag { VarArg };
+
     // Construct a node with up to 3 children, no immediate value.
     // 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)
+    Node(NodeType op, CodeOrigin codeOrigin, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
+        : codeOrigin(codeOrigin)
+        , children(AdjacencyList::Fixed, child1, child2, child3)
         , m_virtualRegister(InvalidVirtualRegister)
         , m_refCount(0)
         , m_virtualRegister(InvalidVirtualRegister)
         , m_refCount(0)
+        , m_prediction(PredictNone)
     {
     {
+        setOpAndDefaultFlags(op);
+        ASSERT(!(m_flags & NodeHasVarArgs));
     }
 
     // Construct a node with up to 3 children and an immediate value.
     }
 
     // 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)
+    Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
+        : codeOrigin(codeOrigin)
+        , children(AdjacencyList::Fixed, child1, child2, child3)
         , m_virtualRegister(InvalidVirtualRegister)
         , m_refCount(0)
         , m_opInfo(imm.m_value)
         , m_virtualRegister(InvalidVirtualRegister)
         , m_refCount(0)
         , m_opInfo(imm.m_value)
+        , m_prediction(PredictNone)
     {
     {
+        setOpAndDefaultFlags(op);
+        ASSERT(!(m_flags & NodeHasVarArgs));
     }
 
     // Construct a node with up to 3 children and two immediate values.
     }
 
     // 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)
+    Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
+        : codeOrigin(codeOrigin)
+        , children(AdjacencyList::Fixed, child1, child2, child3)
+        , m_virtualRegister(InvalidVirtualRegister)
+        , m_refCount(0)
+        , m_opInfo(imm1.m_value)
+        , m_opInfo2(safeCast<unsigned>(imm2.m_value))
+        , m_prediction(PredictNone)
+    {
+        setOpAndDefaultFlags(op);
+        ASSERT(!(m_flags & NodeHasVarArgs));
+    }
+    
+    // Construct a node with a variable number of children and two immediate values.
+    Node(VarArgTag, NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
+        : codeOrigin(codeOrigin)
+        , children(AdjacencyList::Variable, firstChild, numChildren)
         , m_virtualRegister(InvalidVirtualRegister)
         , m_refCount(0)
         , m_opInfo(imm1.m_value)
         , m_virtualRegister(InvalidVirtualRegister)
         , m_refCount(0)
         , m_opInfo(imm1.m_value)
+        , m_opInfo2(safeCast<unsigned>(imm2.m_value))
+        , m_prediction(PredictNone)
+    {
+        setOpAndDefaultFlags(op);
+        ASSERT(m_flags & NodeHasVarArgs);
+    }
+    
+    NodeType op() const { return static_cast<NodeType>(m_op); }
+    NodeFlags flags() const { return m_flags; }
+    
+    void setOp(NodeType op)
+    {
+        m_op = op;
+    }
+    
+    void setFlags(NodeFlags flags)
+    {
+        m_flags = flags;
+    }
+    
+    bool mergeFlags(NodeFlags flags)
+    {
+        NodeFlags newFlags = m_flags | flags;
+        if (newFlags == m_flags)
+            return false;
+        m_flags = newFlags;
+        return true;
+    }
+    
+    bool filterFlags(NodeFlags flags)
+    {
+        NodeFlags newFlags = m_flags & flags;
+        if (newFlags == m_flags)
+            return false;
+        m_flags = newFlags;
+        return true;
+    }
+    
+    bool clearFlags(NodeFlags flags)
+    {
+        return filterFlags(~flags);
+    }
+    
+    void setOpAndDefaultFlags(NodeType op)
     {
     {
-        m_constantValue.opInfo2 = imm2.m_value;
+        m_op = op;
+        m_flags = defaultFlags(op);
     }
 
     bool mustGenerate()
     {
     }
 
     bool mustGenerate()
     {
-        return op & NodeMustGenerate;
+        return m_flags & NodeMustGenerate;
     }
 
     bool isConstant()
     {
     }
 
     bool isConstant()
     {
-        return op & NodeIsConstant;
+        return op() == JSConstant;
+    }
+    
+    bool isWeakConstant()
+    {
+        return op() == WeakJSConstant;
+    }
+    
+    bool hasConstant()
+    {
+        return isConstant() || isWeakConstant();
     }
 
     unsigned constantNumber()
     }
 
     unsigned constantNumber()
@@ -228,21 +196,88 @@ struct Node {
         ASSERT(isConstant());
         return m_opInfo;
     }
         ASSERT(isConstant());
         return m_opInfo;
     }
+    
+    JSCell* weakConstant()
+    {
+        return bitwise_cast<JSCell*>(m_opInfo);
+    }
+    
+    JSValue valueOfJSConstant(CodeBlock* codeBlock)
+    {
+        if (op() == WeakJSConstant)
+            return JSValue(weakConstant());
+        return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
+    }
 
 
+    bool isInt32Constant(CodeBlock* codeBlock)
+    {
+        return isConstant() && valueOfJSConstant(codeBlock).isInt32();
+    }
+    
+    bool isDoubleConstant(CodeBlock* codeBlock)
+    {
+        bool result = isConstant() && valueOfJSConstant(codeBlock).isDouble();
+        if (result)
+            ASSERT(!isInt32Constant(codeBlock));
+        return result;
+    }
+    
+    bool isNumberConstant(CodeBlock* codeBlock)
+    {
+        bool result = isConstant() && valueOfJSConstant(codeBlock).isNumber();
+        ASSERT(result == (isInt32Constant(codeBlock) || isDoubleConstant(codeBlock)));
+        return result;
+    }
+    
+    bool isBooleanConstant(CodeBlock* codeBlock)
+    {
+        return isConstant() && valueOfJSConstant(codeBlock).isBoolean();
+    }
+    
+    bool hasVariableAccessData()
+    {
+        switch (op()) {
+        case GetLocal:
+        case SetLocal:
+        case Phi:
+        case SetArgument:
+        case Flush:
+            return true;
+        default:
+            return false;
+        }
+    }
+    
     bool hasLocal()
     {
     bool hasLocal()
     {
-        return op == GetLocal || op == SetLocal;
+        return hasVariableAccessData();
     }
     }
-
+    
+    VariableAccessData* variableAccessData()
+    {
+        ASSERT(hasVariableAccessData());
+        return reinterpret_cast<VariableAccessData*>(m_opInfo)->find();
+    }
+    
     VirtualRegister local()
     {
     VirtualRegister local()
     {
-        ASSERT(hasLocal());
-        return (VirtualRegister)m_opInfo;
+        return variableAccessData()->local();
     }
     }
-
+    
     bool hasIdentifier()
     {
     bool hasIdentifier()
     {
-        return op == GetById || op == PutById || op == PutByIdDirect;
+        switch (op()) {
+        case GetById:
+        case GetByIdFlush:
+        case PutById:
+        case PutByIdDirect:
+        case Resolve:
+        case ResolveBase:
+        case ResolveBaseStrictPut:
+            return true;
+        default:
+            return false;
+        }
     }
 
     unsigned identifierNumber()
     }
 
     unsigned identifierNumber()
@@ -250,10 +285,75 @@ struct Node {
         ASSERT(hasIdentifier());
         return m_opInfo;
     }
         ASSERT(hasIdentifier());
         return m_opInfo;
     }
+    
+    unsigned resolveGlobalDataIndex()
+    {
+        ASSERT(op() == ResolveGlobal);
+        return m_opInfo;
+    }
 
 
+    bool hasArithNodeFlags()
+    {
+        switch (op()) {
+        case UInt32ToNumber:
+        case ArithAdd:
+        case ArithSub:
+        case ArithNegate:
+        case ArithMul:
+        case ArithAbs:
+        case ArithMin:
+        case ArithMax:
+        case ArithMod:
+        case ArithDiv:
+        case ValueAdd:
+            return true;
+        default:
+            return false;
+        }
+    }
+    
+    // This corrects the arithmetic node flags, so that irrelevant bits are
+    // ignored. In particular, anything other than ArithMul does not need
+    // to know if it can speculate on negative zero.
+    NodeFlags arithNodeFlags()
+    {
+        NodeFlags result = m_flags;
+        if (op() == ArithMul || op() == ArithDiv || op() == ArithMod)
+            return result;
+        return result & ~NodeNeedsNegZero;
+    }
+    
+    bool hasConstantBuffer()
+    {
+        return op() == NewArrayBuffer;
+    }
+    
+    unsigned startConstant()
+    {
+        ASSERT(hasConstantBuffer());
+        return m_opInfo;
+    }
+    
+    unsigned numConstants()
+    {
+        ASSERT(hasConstantBuffer());
+        return m_opInfo2;
+    }
+    
+    bool hasRegexpIndex()
+    {
+        return op() == NewRegexp;
+    }
+    
+    unsigned regexpIndex()
+    {
+        ASSERT(hasRegexpIndex());
+        return m_opInfo;
+    }
+    
     bool hasVarNumber()
     {
     bool hasVarNumber()
     {
-        return op == GetGlobalVar || op == PutGlobalVar;
+        return op() == GetGlobalVar || op() == PutGlobalVar || op() == GetScopedVar || op() == PutScopedVar;
     }
 
     unsigned varNumber()
     }
 
     unsigned varNumber()
@@ -262,85 +362,212 @@ struct Node {
         return m_opInfo;
     }
 
         return m_opInfo;
     }
 
+    bool hasScopeChainDepth()
+    {
+        return op() == GetScopeChain;
+    }
+    
+    unsigned scopeChainDepth()
+    {
+        ASSERT(hasScopeChainDepth());
+        return m_opInfo;
+    }
+
     bool hasResult()
     {
     bool hasResult()
     {
-        return op & NodeResultMask;
+        return m_flags & NodeResultMask;
     }
 
     bool hasInt32Result()
     {
     }
 
     bool hasInt32Result()
     {
-        return (op & NodeResultMask) == NodeResultInt32;
+        return (m_flags & NodeResultMask) == NodeResultInt32;
     }
     }
-
-    bool hasDoubleResult()
+    
+    bool hasNumberResult()
     {
     {
-        return (op & NodeResultMask) == NodeResultDouble;
+        return (m_flags & NodeResultMask) == NodeResultNumber;
     }
     }
-
+    
     bool hasJSResult()
     {
     bool hasJSResult()
     {
-        return (op & NodeResultMask) == NodeResultJS;
+        return (m_flags & NodeResultMask) == NodeResultJS;
     }
     }
-
-    // Check for integers or doubles.
-    bool hasNumericResult()
+    
+    bool hasBooleanResult()
     {
     {
-        // This check will need updating if more result types are added.
-        ASSERT((hasInt32Result() || hasDoubleResult()) == !hasJSResult());
-        return !hasJSResult();
+        return (m_flags & NodeResultMask) == NodeResultBoolean;
     }
 
     }
 
-    int32_t int32Constant()
+    bool isJump()
     {
     {
-        ASSERT(op == Int32Constant);
-        return m_constantValue.asInt32;
+        return op() == Jump;
     }
 
     }
 
-    void setInt32Constant(int32_t value)
+    bool isBranch()
     {
     {
-        ASSERT(op == Int32Constant);
-        m_constantValue.asInt32 = value;
+        return op() == Branch;
     }
 
     }
 
-    double numericConstant()
+    bool isTerminal()
     {
     {
-        ASSERT(op == DoubleConstant);
-        return m_constantValue.asDouble;
+        switch (op()) {
+        case Jump:
+        case Branch:
+        case Return:
+        case Throw:
+        case ThrowReferenceError:
+            return true;
+        default:
+            return false;
+        }
     }
 
     }
 
-    void setDoubleConstant(double value)
+    unsigned takenBytecodeOffsetDuringParsing()
     {
     {
-        ASSERT(op == DoubleConstant);
-        m_constantValue.asDouble = value;
+        ASSERT(isBranch() || isJump());
+        return m_opInfo;
     }
 
     }
 
-    bool isJump()
+    unsigned notTakenBytecodeOffsetDuringParsing()
     {
     {
-        return op & NodeIsJump;
+        ASSERT(isBranch());
+        return m_opInfo2;
     }
     }
-
-    bool isBranch()
+    
+    void setTakenBlockIndex(BlockIndex blockIndex)
     {
     {
-        return op & NodeIsBranch;
+        ASSERT(isBranch() || isJump());
+        m_opInfo = blockIndex;
     }
     }
-
-    bool isTerminal()
+    
+    void setNotTakenBlockIndex(BlockIndex blockIndex)
     {
     {
-        return op & NodeIsTerminal;
+        ASSERT(isBranch());
+        m_opInfo2 = blockIndex;
     }
     }
-
-    unsigned takenBytecodeOffset()
+    
+    BlockIndex takenBlockIndex()
     {
         ASSERT(isBranch() || isJump());
         return m_opInfo;
     }
     {
         ASSERT(isBranch() || isJump());
         return m_opInfo;
     }
-
-    unsigned notTakenBytecodeOffset()
+    
+    BlockIndex notTakenBlockIndex()
     {
         ASSERT(isBranch());
     {
         ASSERT(isBranch());
-        return m_constantValue.opInfo2;
+        return m_opInfo2;
+    }
+    
+    bool hasHeapPrediction()
+    {
+        switch (op()) {
+        case GetById:
+        case GetByIdFlush:
+        case GetByVal:
+        case Call:
+        case Construct:
+        case GetByOffset:
+        case GetScopedVar:
+        case Resolve:
+        case ResolveBase:
+        case ResolveBaseStrictPut:
+        case ResolveGlobal:
+        case ArrayPop:
+        case ArrayPush:
+        case RegExpExec:
+        case RegExpTest:
+        case GetGlobalVar:
+            return true;
+        default:
+            return false;
+        }
+    }
+    
+    PredictedType getHeapPrediction()
+    {
+        ASSERT(hasHeapPrediction());
+        return static_cast<PredictedType>(m_opInfo2);
+    }
+    
+    bool predictHeap(PredictedType prediction)
+    {
+        ASSERT(hasHeapPrediction());
+        
+        return mergePrediction(m_opInfo2, prediction);
+    }
+    
+    bool hasFunctionCheckData()
+    {
+        return op() == CheckFunction;
     }
 
     }
 
+    JSFunction* function()
+    {
+        ASSERT(hasFunctionCheckData());
+        return reinterpret_cast<JSFunction*>(m_opInfo);
+    }
+
+    bool hasStructureTransitionData()
+    {
+        return op() == PutStructure;
+    }
+    
+    StructureTransitionData& structureTransitionData()
+    {
+        ASSERT(hasStructureTransitionData());
+        return *reinterpret_cast<StructureTransitionData*>(m_opInfo);
+    }
+    
+    bool hasStructureSet()
+    {
+        return op() == CheckStructure;
+    }
+    
+    StructureSet& structureSet()
+    {
+        ASSERT(hasStructureSet());
+        return *reinterpret_cast<StructureSet*>(m_opInfo);
+    }
+    
+    bool hasStorageAccessData()
+    {
+        return op() == GetByOffset || op() == PutByOffset;
+    }
+    
+    unsigned storageAccessDataIndex()
+    {
+        ASSERT(hasStorageAccessData());
+        return m_opInfo;
+    }
+    
+    bool hasFunctionDeclIndex()
+    {
+        return op() == NewFunction
+            || op() == NewFunctionNoCheck;
+    }
+    
+    unsigned functionDeclIndex()
+    {
+        ASSERT(hasFunctionDeclIndex());
+        return m_opInfo;
+    }
+    
+    bool hasFunctionExprIndex()
+    {
+        return op() == NewFunctionExpression;
+    }
+    
+    unsigned functionExprIndex()
+    {
+        ASSERT(hasFunctionExprIndex());
+        return m_opInfo;
+    }
+    
+    bool hasVirtualRegister()
+    {
+        return m_virtualRegister != InvalidVirtualRegister;
+    }
+    
     VirtualRegister virtualRegister()
     {
         ASSERT(hasResult());
     VirtualRegister virtualRegister()
     {
         ASSERT(hasResult());
@@ -357,7 +584,7 @@ struct Node {
 
     bool shouldGenerate()
     {
 
     bool shouldGenerate()
     {
-        return m_refCount && op != Phi;
+        return m_refCount;
     }
 
     unsigned refCount()
     }
 
     unsigned refCount()
@@ -375,27 +602,220 @@ struct Node {
     {
         return mustGenerate() ? m_refCount - 1 : m_refCount;
     }
     {
         return mustGenerate() ? m_refCount - 1 : m_refCount;
     }
+    
+    void setRefCount(unsigned refCount)
+    {
+        m_refCount = refCount;
+    }
+    
+    // Derefs the node and returns true if the ref count reached zero.
+    // In general you don't want to use this directly; use Graph::deref
+    // instead.
+    bool deref()
+    {
+        ASSERT(m_refCount);
+        return !--m_refCount;
+    }
+    
+    Edge child1()
+    {
+        ASSERT(!(m_flags & NodeHasVarArgs));
+        return children.child1();
+    }
+    
+    // This is useful if you want to do a fast check on the first child
+    // before also doing a check on the opcode. Use this with care and
+    // avoid it if possible.
+    Edge child1Unchecked()
+    {
+        return children.child1Unchecked();
+    }
+
+    Edge child2()
+    {
+        ASSERT(!(m_flags & NodeHasVarArgs));
+        return children.child2();
+    }
+
+    Edge child3()
+    {
+        ASSERT(!(m_flags & NodeHasVarArgs));
+        return children.child3();
+    }
+    
+    unsigned firstChild()
+    {
+        ASSERT(m_flags & NodeHasVarArgs);
+        return children.firstChild();
+    }
+    
+    unsigned numChildren()
+    {
+        ASSERT(m_flags & NodeHasVarArgs);
+        return children.numChildren();
+    }
+    
+    PredictedType prediction()
+    {
+        return m_prediction;
+    }
+    
+    bool predict(PredictedType prediction)
+    {
+        return mergePrediction(m_prediction, prediction);
+    }
+    
+    bool shouldSpeculateInteger()
+    {
+        return isInt32Prediction(prediction());
+    }
+    
+    bool shouldSpeculateDouble()
+    {
+        return isDoublePrediction(prediction());
+    }
+    
+    bool shouldSpeculateNumber()
+    {
+        return isNumberPrediction(prediction());
+    }
+    
+    bool shouldSpeculateBoolean()
+    {
+        return isBooleanPrediction(prediction());
+    }
+    
+    bool shouldSpeculateFinalObject()
+    {
+        return isFinalObjectPrediction(prediction());
+    }
+    
+    bool shouldSpeculateFinalObjectOrOther()
+    {
+        return isFinalObjectOrOtherPrediction(prediction());
+    }
+    
+    bool shouldSpeculateArray()
+    {
+        return isArrayPrediction(prediction());
+    }
+    
+    bool shouldSpeculateInt8Array()
+    {
+        return isInt8ArrayPrediction(prediction());
+    }
+    
+    bool shouldSpeculateInt16Array()
+    {
+        return isInt16ArrayPrediction(prediction());
+    }
+    
+    bool shouldSpeculateInt32Array()
+    {
+        return isInt32ArrayPrediction(prediction());
+    }
+    
+    bool shouldSpeculateUint8Array()
+    {
+        return isUint8ArrayPrediction(prediction());
+    }
+
+    bool shouldSpeculateUint8ClampedArray()
+    {
+        return isUint8ClampedArrayPrediction(prediction());
+    }
+    
+    bool shouldSpeculateUint16Array()
+    {
+        return isUint16ArrayPrediction(prediction());
+    }
+    
+    bool shouldSpeculateUint32Array()
+    {
+        return isUint32ArrayPrediction(prediction());
+    }
+    
+    bool shouldSpeculateFloat32Array()
+    {
+        return isFloat32ArrayPrediction(prediction());
+    }
+    
+    bool shouldSpeculateFloat64Array()
+    {
+        return isFloat64ArrayPrediction(prediction());
+    }
+    
+    bool shouldSpeculateArrayOrOther()
+    {
+        return isArrayOrOtherPrediction(prediction());
+    }
+    
+    bool shouldSpeculateObject()
+    {
+        return isObjectPrediction(prediction());
+    }
+    
+    bool shouldSpeculateCell()
+    {
+        return isCellPrediction(prediction());
+    }
+    
+    static bool shouldSpeculateInteger(Node& op1, Node& op2)
+    {
+        return op1.shouldSpeculateInteger() && op2.shouldSpeculateInteger();
+    }
+    
+    static bool shouldSpeculateNumber(Node& op1, Node& op2)
+    {
+        return op1.shouldSpeculateNumber() && op2.shouldSpeculateNumber();
+    }
+    
+    static bool shouldSpeculateFinalObject(Node& op1, Node& op2)
+    {
+        return op1.shouldSpeculateFinalObject() && op2.shouldSpeculateFinalObject();
+    }
 
 
-    // This enum value describes the type of the node.
-    NodeType op;
+    static bool shouldSpeculateArray(Node& op1, Node& op2)
+    {
+        return op1.shouldSpeculateArray() && op2.shouldSpeculateArray();
+    }
+    
+    bool canSpeculateInteger()
+    {
+        return nodeCanSpeculateInteger(arithNodeFlags());
+    }
+    
+    void dumpChildren(FILE* out)
+    {
+        if (!child1())
+            return;
+        fprintf(out, "@%u", child1().index());
+        if (!child2())
+            return;
+        fprintf(out, ", @%u", child2().index());
+        if (!child3())
+            return;
+        fprintf(out, ", @%u", child3().index());
+    }
+    
     // Used to look up exception handling information (currently implemented as a bytecode index).
     // 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;
+    CodeOrigin codeOrigin;
+    // References to up to 3 children, or links to a variable length set of children.
+    AdjacencyList children;
 
 private:
 
 private:
+    uint16_t m_op; // real type is NodeType
+    NodeFlags m_flags;
     // 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;
     // 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;
+    // Immediate values, accesses type-checked via accessors above. The first one is
+    // big enough to store a pointer.
+    uintptr_t m_opInfo;
+    unsigned m_opInfo2;
+    // The prediction ascribed to this node after propagation.
+    PredictedType m_prediction;
 };
 
 } } // namespace JSC::DFG
 };
 
 } } // namespace JSC::DFG
diff --git a/dfg/DFGNodeFlags.cpp b/dfg/DFGNodeFlags.cpp
new file mode 100644 (file)
index 0000000..54e6b69
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DFGNodeFlags.h"
+
+#if ENABLE(DFG_JIT)
+
+#include <wtf/BoundsCheckedPointer.h>
+
+namespace JSC { namespace DFG {
+
+const char* nodeFlagsAsString(NodeFlags flags)
+{
+    if (!flags)
+        return "<empty>";
+
+    static const int size = 128;
+    static char description[size];
+    BoundsCheckedPointer<char> ptr(description, size);
+    
+    bool hasPrinted = false;
+    
+    if (flags & NodeResultMask) {
+        switch (flags & NodeResultMask) {
+        case NodeResultJS:
+            ptr.strcat("ResultJS");
+            break;
+        case NodeResultNumber:
+            ptr.strcat("ResultNumber");
+            break;
+        case NodeResultInt32:
+            ptr.strcat("ResultInt32");
+            break;
+        case NodeResultBoolean:
+            ptr.strcat("ResultBoolean");
+            break;
+        case NodeResultStorage:
+            ptr.strcat("ResultStorage");
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+            break;
+        }
+        hasPrinted = true;
+    }
+    
+    if (flags & NodeMustGenerate) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("MustGenerate");
+        hasPrinted = true;
+    }
+    
+    if (flags & NodeHasVarArgs) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("HasVarArgs");
+        hasPrinted = true;
+    }
+    
+    if (flags & NodeClobbersWorld) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("ClobbersWorld");
+        hasPrinted = true;
+    }
+    
+    if (flags & NodeMightClobber) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("MightClobber");
+        hasPrinted = true;
+    }
+    
+    if (flags & NodeUsedAsNumber) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("UsedAsNum");
+        hasPrinted = true;
+    }
+    
+    if (flags & NodeNeedsNegZero) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("NeedsNegZero");
+        hasPrinted = true;
+    }
+    
+    if (flags & NodeMayOverflow) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("MayOverflow");
+        hasPrinted = true;
+    }
+    
+    if (flags & NodeMayNegZero) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("MayNegZero");
+        hasPrinted = true;
+    }
+    
+    if (flags & NodeUsedAsInt) {
+        if (hasPrinted)
+            ptr.strcat("|");
+        ptr.strcat("UsedAsInt");
+        hasPrinted = true;
+    }
+    
+    *ptr++ = 0;
+    
+    return description;
+}
+
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/dfg/DFGNodeFlags.h b/dfg/DFGNodeFlags.h
new file mode 100644 (file)
index 0000000..16d7665
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGNodeFlags_h
+#define DFGNodeFlags_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include <wtf/StdLibExtras.h>
+
+namespace JSC { namespace DFG {
+
+// 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 NodeResultMask              0xF
+#define NodeResultJS                0x1
+#define NodeResultNumber            0x2
+#define NodeResultInt32             0x3
+#define NodeResultBoolean           0x4
+#define NodeResultStorage           0x5
+                                
+#define NodeMustGenerate           0x10 // set on nodes that have side effects, and may not trivially be removed by DCE.
+#define NodeHasVarArgs             0x20
+#define NodeClobbersWorld          0x40
+#define NodeMightClobber           0x80
+                                
+#define NodeBehaviorMask          0x300
+#define NodeMayOverflow           0x100
+#define NodeMayNegZero            0x200
+                                
+#define NodeBackPropMask         0x1C00
+#define NodeUseBottom             0x000
+#define NodeUsedAsNumber          0x400 // The result of this computation may be used in a context that observes fractional results.
+#define NodeNeedsNegZero          0x800 // The result of this computation may be used in a context that observes -0.
+#define NodeUsedAsValue           (NodeUsedAsNumber | NodeNeedsNegZero)
+#define NodeUsedAsInt            0x1000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values.
+
+typedef uint16_t NodeFlags;
+
+static inline bool nodeUsedAsNumber(NodeFlags flags)
+{
+    return !!(flags & NodeUsedAsNumber);
+}
+
+static inline bool nodeCanTruncateInteger(NodeFlags flags)
+{
+    return !nodeUsedAsNumber(flags);
+}
+
+static inline bool nodeCanIgnoreNegativeZero(NodeFlags flags)
+{
+    return !(flags & NodeNeedsNegZero);
+}
+
+static inline bool nodeMayOverflow(NodeFlags flags)
+{
+    return !!(flags & NodeMayOverflow);
+}
+
+static inline bool nodeCanSpeculateInteger(NodeFlags flags)
+{
+    if (flags & NodeMayOverflow)
+        return !nodeUsedAsNumber(flags);
+    
+    if (flags & NodeMayNegZero)
+        return nodeCanIgnoreNegativeZero(flags);
+    
+    return true;
+}
+
+const char* nodeFlagsAsString(NodeFlags);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGNodeFlags_h
+
diff --git a/dfg/DFGNodeType.h b/dfg/DFGNodeType.h
new file mode 100644 (file)
index 0000000..8a3828c
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGNodeType_h
+#define DFGNodeType_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGNodeFlags.h"
+
+namespace JSC { namespace DFG {
+
+// This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
+#define FOR_EACH_DFG_OP(macro) \
+    /* A constant in the CodeBlock's constant pool. */\
+    macro(JSConstant, NodeResultJS) \
+    \
+    /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\
+    /* code block. */\
+    macro(WeakJSConstant, NodeResultJS) \
+    \
+    /* Nodes for handling functions (both as call and as construct). */\
+    macro(ConvertThis, NodeResultJS) \
+    macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
+    macro(GetCallee, NodeResultJS) \
+    \
+    /* Nodes for local variable access. */\
+    macro(GetLocal, NodeResultJS) \
+    macro(SetLocal, 0) \
+    macro(Phantom, NodeMustGenerate) \
+    macro(Nop, 0) \
+    macro(Phi, 0) \
+    macro(Flush, NodeMustGenerate) \
+    \
+    /* Marker for arguments being set. */\
+    macro(SetArgument, 0) \
+    \
+    /* Hint that inlining begins here. No code is generated for this node. It's only */\
+    /* used for copying OSR data into inline frame data, to support reification of */\
+    /* call frames of inlined functions. */\
+    macro(InlineStart, 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(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
+    /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
+    macro(UInt32ToNumber, NodeResultNumber) \
+    \
+    /* Used to cast known integers to doubles, so as to separate the double form */\
+    /* of the value from the integer form. */\
+    macro(Int32ToDouble, NodeResultNumber) \
+    /* Used to speculate that a double value is actually an integer. */\
+    macro(DoubleAsInt32, NodeResultInt32) \
+    /* Used to record places where we must check if a value is a number. */\
+    macro(CheckNumber, NodeMustGenerate) \
+    \
+    /* Nodes for arithmetic operations. */\
+    macro(ArithAdd, NodeResultNumber | NodeMustGenerate) \
+    macro(ArithSub, NodeResultNumber | NodeMustGenerate) \
+    macro(ArithNegate, NodeResultNumber | NodeMustGenerate) \
+    macro(ArithMul, NodeResultNumber | NodeMustGenerate) \
+    macro(ArithDiv, NodeResultNumber | NodeMustGenerate) \
+    macro(ArithMod, NodeResultNumber | NodeMustGenerate) \
+    macro(ArithAbs, NodeResultNumber | NodeMustGenerate) \
+    macro(ArithMin, NodeResultNumber | NodeMustGenerate) \
+    macro(ArithMax, NodeResultNumber | NodeMustGenerate) \
+    macro(ArithSqrt, NodeResultNumber | NodeMustGenerate) \
+    \
+    /* Add of values may either be arithmetic, or result in string concatenation. */\
+    macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
+    \
+    /* 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 | NodeMightClobber) \
+    macro(PutByVal, NodeMustGenerate | NodeClobbersWorld) \
+    macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld) \
+    macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
+    macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
+    macro(CheckStructure, NodeMustGenerate) \
+    macro(PutStructure, NodeMustGenerate | NodeClobbersWorld) \
+    macro(GetPropertyStorage, NodeResultStorage) \
+    macro(GetIndexedPropertyStorage, NodeMustGenerate | NodeResultStorage) \
+    macro(GetByOffset, NodeResultJS) \
+    macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \
+    macro(GetArrayLength, NodeResultInt32) \
+    macro(GetStringLength, NodeResultInt32) \
+    macro(GetInt8ArrayLength, NodeResultInt32) \
+    macro(GetInt16ArrayLength, NodeResultInt32) \
+    macro(GetInt32ArrayLength, NodeResultInt32) \
+    macro(GetUint8ArrayLength, NodeResultInt32) \
+    macro(GetUint8ClampedArrayLength, NodeResultInt32) \
+    macro(GetUint16ArrayLength, NodeResultInt32) \
+    macro(GetUint32ArrayLength, NodeResultInt32) \
+    macro(GetFloat32ArrayLength, NodeResultInt32) \
+    macro(GetFloat64ArrayLength, NodeResultInt32) \
+    macro(GetScopeChain, NodeResultJS) \
+    macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \
+    macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \
+    macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
+    macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \
+    macro(CheckFunction, NodeMustGenerate) \
+    \
+    /* Optimizations for array mutation. */\
+    macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    \
+    /* Optimizations for regular expression matching. */\
+    macro(RegExpExec, NodeResultJS | NodeMustGenerate) \
+    macro(RegExpTest, NodeResultJS | NodeMustGenerate) \
+    \
+    /* Optimizations for string access */ \
+    macro(StringCharCodeAt, NodeResultInt32) \
+    macro(StringCharAt, NodeResultJS) \
+    \
+    /* Nodes for comparison operations. */\
+    macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
+    macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
+    macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
+    macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
+    macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
+    macro(CompareStrictEq, NodeResultBoolean) \
+    \
+    /* Calls. */\
+    macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
+    macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
+    \
+    /* Allocations. */\
+    macro(NewObject, NodeResultJS) \
+    macro(NewArray, NodeResultJS | NodeHasVarArgs) \
+    macro(NewArrayBuffer, NodeResultJS) \
+    macro(NewRegexp, NodeResultJS) \
+    \
+    /* Resolve nodes. */\
+    macro(Resolve, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(ResolveBase, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(ResolveBaseStrictPut, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(ResolveGlobal, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    \
+    /* Nodes for misc operations. */\
+    macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \
+    macro(CheckHasInstance, NodeMustGenerate) \
+    macro(InstanceOf, NodeResultBoolean) \
+    macro(IsUndefined, NodeResultBoolean) \
+    macro(IsBoolean, NodeResultBoolean) \
+    macro(IsNumber, NodeResultBoolean) \
+    macro(IsString, NodeResultBoolean) \
+    macro(IsObject, NodeResultBoolean) \
+    macro(IsFunction, NodeResultBoolean) \
+    macro(LogicalNot, NodeResultBoolean | NodeMightClobber) \
+    macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
+    macro(StrCat, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
+    \
+    /* Nodes used for activations. Activation support works by having it anchored at */\
+    /* epilgoues via TearOffActivation, and all CreateActivation nodes kept alive by */\
+    /* being threaded with each other. */\
+    macro(CreateActivation, NodeResultJS) \
+    macro(TearOffActivation, NodeMustGenerate) \
+    \
+    /* Nodes for creating functions. */\
+    macro(NewFunctionNoCheck, NodeResultJS) \
+    macro(NewFunction, NodeResultJS) \
+    macro(NewFunctionExpression, NodeResultJS) \
+    \
+    /* Block terminals. */\
+    macro(Jump, NodeMustGenerate) \
+    macro(Branch, NodeMustGenerate) \
+    macro(Return, NodeMustGenerate) \
+    macro(Throw, NodeMustGenerate) \
+    macro(ThrowReferenceError, NodeMustGenerate) \
+    \
+    /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\
+    /* this point, but execution does continue in the basic block - just in a */\
+    /* different compiler. */\
+    macro(ForceOSRExit, NodeMustGenerate)
+
+// 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 NodeType {
+#define DFG_OP_ENUM(opcode, flags) opcode,
+    FOR_EACH_DFG_OP(DFG_OP_ENUM)
+#undef DFG_OP_ENUM
+    LastNodeType
+};
+
+// Specifies the default flags for each node.
+inline NodeFlags defaultFlags(NodeType op)
+{
+    switch (op) {
+#define DFG_OP_ENUM(opcode, flags) case opcode: return flags;
+    FOR_EACH_DFG_OP(DFG_OP_ENUM)
+#undef DFG_OP_ENUM
+    default:
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGNodeType_h
+
diff --git a/dfg/DFGNonSpeculativeJIT.cpp b/dfg/DFGNonSpeculativeJIT.cpp
deleted file mode 100644 (file)
index 7c50715..0000000
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index e213671..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * 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/DFGOSREntry.cpp b/dfg/DFGOSREntry.cpp
new file mode 100644 (file)
index 0000000..21c76c6
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * 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 "DFGOSREntry.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "CallFrame.h"
+#include "CodeBlock.h"
+#include "DFGNode.h"
+#include "JIT.h"
+
+namespace JSC { namespace DFG {
+
+void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIndex)
+{
+#if DFG_ENABLE(OSR_ENTRY)
+    ASSERT(codeBlock->getJITType() == JITCode::DFGJIT);
+    ASSERT(codeBlock->alternative());
+    ASSERT(codeBlock->alternative()->getJITType() == JITCode::BaselineJIT);
+    ASSERT(!codeBlock->jitCodeMap());
+    ASSERT(codeBlock->numberOfDFGOSREntries());
+
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("OSR in %p(%p) from bc#%u\n", codeBlock, codeBlock->alternative(), bytecodeIndex);
+#endif
+    
+    JSGlobalData* globalData = &exec->globalData();
+    OSREntryData* entry = codeBlock->dfgOSREntryDataForBytecodeIndex(bytecodeIndex);
+    
+    ASSERT(entry->m_bytecodeIndex == bytecodeIndex);
+    
+    // The code below checks if it is safe to perform OSR entry. It may find
+    // that it is unsafe to do so, for any number of reasons, which are documented
+    // below. If the code decides not to OSR then it returns 0, and it's the caller's
+    // responsibility to patch up the state in such a way as to ensure that it's
+    // both safe and efficient to continue executing baseline code for now. This
+    // should almost certainly include calling either codeBlock->optimizeAfterWarmUp()
+    // or codeBlock->dontOptimizeAnytimeSoon().
+    
+    // 1) Verify predictions. If the predictions are inconsistent with the actual
+    //    values, then OSR entry is not possible at this time. It's tempting to
+    //    assume that we could somehow avoid this case. We can certainly avoid it
+    //    for first-time loop OSR - that is, OSR into a CodeBlock that we have just
+    //    compiled. Then we are almost guaranteed that all of the predictions will
+    //    check out. It would be pretty easy to make that a hard guarantee. But
+    //    then there would still be the case where two call frames with the same
+    //    baseline CodeBlock are on the stack at the same time. The top one
+    //    triggers compilation and OSR. In that case, we may no longer have
+    //    accurate value profiles for the one deeper in the stack. Hence, when we
+    //    pop into the CodeBlock that is deeper on the stack, we might OSR and
+    //    realize that the predictions are wrong. Probably, in most cases, this is
+    //    just an anomaly in the sense that the older CodeBlock simply went off
+    //    into a less-likely path. So, the wisest course of action is to simply not
+    //    OSR at this time.
+    
+    for (size_t argument = 0; argument < entry->m_expectedValues.numberOfArguments(); ++argument) {
+        if (argument >= exec->argumentCountIncludingThis()) {
+#if ENABLE(JIT_VERBOSE_OSR)
+            dataLog("    OSR failed because argument %zu was not passed, expected ", argument);
+            entry->m_expectedValues.argument(argument).dump(WTF::dataFile());
+            dataLog(".\n");
+#endif
+            return 0;
+        }
+        
+        JSValue value;
+        if (!argument)
+            value = exec->hostThisValue();
+        else
+            value = exec->argument(argument - 1);
+        
+        if (!entry->m_expectedValues.argument(argument).validate(value)) {
+#if ENABLE(JIT_VERBOSE_OSR)
+            dataLog("    OSR failed because argument %zu is %s, expected ", argument, value.description());
+            entry->m_expectedValues.argument(argument).dump(WTF::dataFile());
+            dataLog(".\n");
+#endif
+            return 0;
+        }
+    }
+    
+    for (size_t local = 0; local < entry->m_expectedValues.numberOfLocals(); ++local) {
+        if (entry->m_localsForcedDouble.get(local)) {
+            if (!exec->registers()[local].jsValue().isNumber()) {
+#if ENABLE(JIT_VERBOSE_OSR)
+                dataLog("    OSR failed because variable %zu is %s, expected number.\n", local, exec->registers()[local].jsValue().description());
+#endif
+                return 0;
+            }
+            continue;
+        }
+        if (!entry->m_expectedValues.local(local).validate(exec->registers()[local].jsValue())) {
+#if ENABLE(JIT_VERBOSE_OSR)
+            dataLog("    OSR failed because variable %zu is %s, expected ", local, exec->registers()[local].jsValue().description());
+            entry->m_expectedValues.local(local).dump(WTF::dataFile());
+            dataLog(".\n");
+#endif
+            return 0;
+        }
+    }
+
+    // 2) Check the stack height. The DFG JIT may require a taller stack than the
+    //    baseline JIT, in some cases. If we can't grow the stack, then don't do
+    //    OSR right now. That's the only option we have unless we want basic block
+    //    boundaries to start throwing RangeErrors. Although that would be possible,
+    //    it seems silly: you'd be diverting the program to error handling when it
+    //    would have otherwise just kept running albeit less quickly.
+    
+    if (!globalData->interpreter->registerFile().grow(&exec->registers()[codeBlock->m_numCalleeRegisters])) {
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("    OSR failed because stack growth failed.\n");
+#endif
+        return 0;
+    }
+    
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("    OSR should succeed.\n");
+#endif
+    
+    // 3) Perform data format conversions.
+    for (size_t local = 0; local < entry->m_expectedValues.numberOfLocals(); ++local) {
+        if (entry->m_localsForcedDouble.get(local))
+            *bitwise_cast<double*>(exec->registers() + local) = exec->registers()[local].jsValue().asNumber();
+    }
+    
+    // 4) Fix the call frame.
+    
+    exec->setCodeBlock(codeBlock);
+    
+    // 5) Find and return the destination machine code address.
+    
+    void* result = codeBlock->getJITCode().executableAddressAtOffset(entry->m_machineCodeOffset);
+    
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("    OSR returning machine code address %p.\n", result);
+#endif
+    
+    return result;
+#else // DFG_ENABLE(OSR_ENTRY)
+    UNUSED_PARAM(exec);
+    UNUSED_PARAM(codeBlock);
+    UNUSED_PARAM(bytecodeIndex);
+    return 0;
+#endif
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
diff --git a/dfg/DFGOSREntry.h b/dfg/DFGOSREntry.h
new file mode 100644 (file)
index 0000000..a5c264c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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 DFGOSREntry_h
+#define DFGOSREntry_h
+
+#include "DFGAbstractValue.h"
+#include "Operands.h"
+#include <wtf/BitVector.h>
+
+namespace JSC {
+
+class ExecState;
+class CodeBlock;
+
+namespace DFG {
+
+#if ENABLE(DFG_JIT)
+struct OSREntryData {
+    unsigned m_bytecodeIndex;
+    unsigned m_machineCodeOffset;
+    Operands<AbstractValue> m_expectedValues;
+    BitVector m_localsForcedDouble;
+};
+
+inline unsigned getOSREntryDataBytecodeIndex(OSREntryData* osrEntryData)
+{
+    return osrEntryData->m_bytecodeIndex;
+}
+
+void* prepareOSREntry(ExecState*, CodeBlock*, unsigned bytecodeIndex);
+#else
+inline void* prepareOSREntry(ExecState*, CodeBlock*, unsigned) { return 0; }
+#endif
+
+} } // namespace JSC::DFG
+
+#endif // DFGOSREntry_h
+
diff --git a/dfg/DFGOSRExit.cpp b/dfg/DFGOSRExit.cpp
new file mode 100644 (file)
index 0000000..844be2a
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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 "DFGOSRExit.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAssemblyHelpers.h"
+#include "DFGSpeculativeJIT.h"
+
+namespace JSC { namespace DFG {
+
+static unsigned computeNumVariablesForCodeOrigin(
+    CodeBlock* codeBlock, const CodeOrigin& codeOrigin)
+{
+    if (!codeOrigin.inlineCallFrame)
+        return codeBlock->m_numCalleeRegisters;
+    return
+        codeOrigin.inlineCallFrame->stackOffset +
+        baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame)->m_numCalleeRegisters;
+}
+
+OSRExit::OSRExit(ExitKind kind, JSValueSource jsValueSource, MethodOfGettingAValueProfile valueProfile, MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex)
+    : m_jsValueSource(jsValueSource)
+    , m_valueProfile(valueProfile)
+    , m_check(check)
+    , m_nodeIndex(jit->m_compileIndex)
+    , m_codeOrigin(jit->m_codeOriginForOSR)
+    , m_codeOriginForExitProfile(m_codeOrigin)
+    , m_recoveryIndex(recoveryIndex)
+    , m_kind(kind)
+    , m_count(0)
+    , m_arguments(jit->m_arguments.size())
+    , m_variables(computeNumVariablesForCodeOrigin(jit->m_jit.graph().m_profiledBlock, jit->m_codeOriginForOSR))
+    , m_lastSetOperand(jit->m_lastSetOperand)
+{
+    ASSERT(m_codeOrigin.isSet());
+    for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
+        m_arguments[argument] = jit->computeValueRecoveryFor(jit->m_arguments[argument]);
+    for (unsigned variable = 0; variable < m_variables.size(); ++variable)
+        m_variables[variable] = jit->computeValueRecoveryFor(jit->m_variables[variable]);
+}
+
+void OSRExit::dump(FILE* out) const
+{
+    for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
+        m_arguments[argument].dump(out);
+    fprintf(out, " : ");
+    for (unsigned variable = 0; variable < m_variables.size(); ++variable)
+        m_variables[variable].dump(out);
+}
+
+bool OSRExit::considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock)
+{
+    if (static_cast<double>(m_count) / dfgCodeBlock->speculativeFailCounter() <= Options::osrExitProminenceForFrequentExitSite)
+        return false;
+    
+    return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOriginForExitProfile, profiledCodeBlock)->addFrequentExitSite(FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind));
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
diff --git a/dfg/DFGOSRExit.h b/dfg/DFGOSRExit.h
new file mode 100644 (file)
index 0000000..841fddd
--- /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. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED 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 DFGOSRExit_h
+#define DFGOSRExit_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeOrigin.h"
+#include "DFGCommon.h"
+#include "DFGCorrectableJumpPoint.h"
+#include "DFGExitProfile.h"
+#include "DFGGPRInfo.h"
+#include "MacroAssembler.h"
+#include "MethodOfGettingAValueProfile.h"
+#include "Operands.h"
+#include "ValueProfile.h"
+#include "ValueRecovery.h"
+#include <wtf/Vector.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,
+    BooleanSpeculationCheck
+};
+
+// === 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;
+};
+
+// === OSRExit ===
+//
+// This structure describes how to exit the speculative path by
+// going into baseline code.
+struct OSRExit {
+    OSRExit(ExitKind, JSValueSource, MethodOfGettingAValueProfile, MacroAssembler::Jump, SpeculativeJIT*, unsigned recoveryIndex = 0);
+    
+    MacroAssemblerCodeRef m_code;
+    
+    JSValueSource m_jsValueSource;
+    MethodOfGettingAValueProfile m_valueProfile;
+    
+    CorrectableJumpPoint m_check;
+    NodeIndex m_nodeIndex;
+    CodeOrigin m_codeOrigin;
+    CodeOrigin m_codeOriginForExitProfile;
+    
+    unsigned m_recoveryIndex;
+    
+    ExitKind m_kind;
+    uint32_t m_count;
+    
+    // Convenient way of iterating over ValueRecoveries while being
+    // generic over argument versus variable.
+    int numberOfRecoveries() const { return m_arguments.size() + m_variables.size(); }
+    const ValueRecovery& valueRecovery(int index) const
+    {
+        if (index < (int)m_arguments.size())
+            return m_arguments[index];
+        return m_variables[index - m_arguments.size()];
+    }
+    ValueRecovery& valueRecoveryForOperand(int operand)
+    {
+        if (operandIsArgument(operand))
+            return m_arguments[operandToArgument(operand)];
+        return m_variables[operand];
+    }
+    bool isArgument(int index) const { return index < (int)m_arguments.size(); }
+    bool isVariable(int index) const { return !isArgument(index); }
+    int argumentForIndex(int index) const
+    {
+        return index;
+    }
+    int variableForIndex(int index) const
+    {
+        return index - m_arguments.size();
+    }
+    int operandForIndex(int index) const
+    {
+        if (index < (int)m_arguments.size())
+            return operandToArgument(index);
+        return index - m_arguments.size();
+    }
+    
+    bool considerAddingAsFrequentExitSite(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock)
+    {
+        if (!m_count || !exitKindIsCountable(m_kind))
+            return false;
+        return considerAddingAsFrequentExitSiteSlow(dfgCodeBlock, profiledCodeBlock);
+    }
+    
+    void dump(FILE* out) const;
+    
+    Vector<ValueRecovery, 0> m_arguments;
+    Vector<ValueRecovery, 0> m_variables;
+    int m_lastSetOperand;
+
+private:
+    bool considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock);
+};
+
+#if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE)
+struct SpeculationFailureDebugInfo {
+    CodeBlock* codeBlock;
+    NodeIndex nodeIndex;
+};
+#endif
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGOSRExit_h
+
diff --git a/dfg/DFGOSRExitCompiler.cpp b/dfg/DFGOSRExitCompiler.cpp
new file mode 100644 (file)
index 0000000..a63f671
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * 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 "DFGOSRExitCompiler.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "CallFrame.h"
+#include "LinkBuffer.h"
+#include "RepatchBuffer.h"
+
+namespace JSC { namespace DFG {
+
+extern "C" {
+
+void compileOSRExit(ExecState* exec)
+{
+    CodeBlock* codeBlock = exec->codeBlock();
+    
+    ASSERT(codeBlock);
+    ASSERT(codeBlock->getJITType() == JITCode::DFGJIT);
+    
+    JSGlobalData* globalData = &exec->globalData();
+    
+    uint32_t exitIndex = globalData->osrExitIndex;
+    OSRExit& exit = codeBlock->osrExit(exitIndex);
+    
+    // Make sure all code on our inline stack is JIT compiled. This is necessary since
+    // we may opt to inline a code block even before it had ever been compiled by the
+    // JIT, but our OSR exit infrastructure currently only works if the target of the
+    // OSR exit is JIT code. This could be changed since there is nothing particularly
+    // hard about doing an OSR exit into the interpreter, but for now this seems to make
+    // sense in that if we're OSR exiting from inlined code of a DFG code block, then
+    // probably it's a good sign that the thing we're exiting into is hot. Even more
+    // interestingly, since the code was inlined, it may never otherwise get JIT
+    // compiled since the act of inlining it may ensure that it otherwise never runs.
+    for (CodeOrigin codeOrigin = exit.m_codeOrigin; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) {
+        static_cast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())
+            ->baselineCodeBlockFor(codeOrigin.inlineCallFrame->isCall ? CodeForCall : CodeForConstruct)
+            ->jitCompile(*globalData);
+    }
+    
+    SpeculationRecovery* recovery = 0;
+    if (exit.m_recoveryIndex)
+        recovery = &codeBlock->speculationRecovery(exit.m_recoveryIndex - 1);
+
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("Generating OSR exit #%u (bc#%u, @%u, %s) for code block %p.\n", exitIndex, exit.m_codeOrigin.bytecodeIndex, exit.m_nodeIndex, exitKindToString(exit.m_kind), codeBlock);
+#endif
+
+    {
+        AssemblyHelpers jit(globalData, codeBlock);
+        OSRExitCompiler exitCompiler(jit);
+
+        jit.jitAssertHasValidCallFrame();
+        exitCompiler.compileExit(exit, recovery);
+        
+        LinkBuffer patchBuffer(*globalData, &jit, codeBlock);
+        exit.m_code = patchBuffer.finalizeCode();
+
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("OSR exit code at [%p, %p).\n", patchBuffer.debugAddress(), static_cast<char*>(patchBuffer.debugAddress()) + patchBuffer.debugSize());
+#endif
+    }
+    
+    {
+        RepatchBuffer repatchBuffer(codeBlock);
+        repatchBuffer.relink(exit.m_check.codeLocationForRepatch(codeBlock), CodeLocationLabel(exit.m_code.code()));
+    }
+    
+    globalData->osrExitJumpDestination = exit.m_code.code().executableAddress();
+}
+
+} // extern "C"
+
+void OSRExitCompiler::handleExitCounts(const OSRExit& exit)
+{
+    m_jit.add32(AssemblyHelpers::TrustedImm32(1), AssemblyHelpers::AbsoluteAddress(&exit.m_count));
+    
+    m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.codeBlock()), GPRInfo::regT0);
+    
+    AssemblyHelpers::JumpList tooFewFails;
+    
+    if (exit.m_kind == InadequateCoverage) {
+        // Proceed based on the assumption that we can profitably optimize this code once
+        // it has executed enough times.
+        
+        m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfForcedOSRExitCounter()), GPRInfo::regT2);
+        m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1);
+        m_jit.add32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2);
+        m_jit.add32(AssemblyHelpers::TrustedImm32(-1), GPRInfo::regT1);
+        m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfForcedOSRExitCounter()));
+        m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()));
+        
+        tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(Options::forcedOSRExitCountForReoptimization)));
+    } else {
+        // Proceed based on the assumption that we can handle these exits so long as they
+        // don't get too frequent.
+        
+        m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()), GPRInfo::regT2);
+        m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1);
+        m_jit.add32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2);
+        m_jit.add32(AssemblyHelpers::TrustedImm32(-1), GPRInfo::regT1);
+        m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()));
+        m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()));
+    
+        m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0);
+    
+        tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(m_jit.codeBlock()->largeFailCountThreshold())));
+        m_jit.mul32(AssemblyHelpers::TrustedImm32(Options::desiredSpeculativeSuccessFailRatio), GPRInfo::regT2, GPRInfo::regT2);
+    
+        tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1));
+    }
+
+    // Reoptimize as soon as possible.
+    m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter()));
+    m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold()));
+    AssemblyHelpers::Jump doneAdjusting = m_jit.jump();
+    
+    tooFewFails.link(&m_jit);
+    
+    // Adjust the execution counter such that the target is to only optimize after a while.
+    int32_t targetValue =
+        ExecutionCounter::applyMemoryUsageHeuristicsAndConvertToInt(
+            m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp(),
+            m_jit.baselineCodeBlock());
+    m_jit.store32(AssemblyHelpers::TrustedImm32(-targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter()));
+    m_jit.store32(AssemblyHelpers::TrustedImm32(targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold()));
+    m_jit.store32(AssemblyHelpers::TrustedImm32(ExecutionCounter::formattedTotalCount(targetValue)), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionTotalCount()));
+    
+    doneAdjusting.link(&m_jit);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
diff --git a/dfg/DFGOSRExitCompiler.h b/dfg/DFGOSRExitCompiler.h
new file mode 100644 (file)
index 0000000..5236449
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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 DFGOSRExitCompiler_h
+#define DFGOSRExitCompiler_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAssemblyHelpers.h"
+#include "DFGOSRExit.h"
+#include "DFGOperations.h"
+
+namespace JSC {
+
+class ExecState;
+
+namespace DFG {
+
+class OSRExitCompiler {
+public:
+    OSRExitCompiler(AssemblyHelpers& jit)
+        : m_jit(jit)
+    {
+    }
+    
+    void compileExit(const OSRExit&, SpeculationRecovery*);
+
+private:
+#if !ASSERT_DISABLED
+    static unsigned badIndex() { return static_cast<unsigned>(-1); };
+#endif
+    
+    void initializePoisoned(unsigned size)
+    {
+#if ASSERT_DISABLED
+        m_poisonScratchIndices.resize(size);
+#else
+        m_poisonScratchIndices.fill(badIndex(), size);
+#endif
+    }
+    
+    unsigned poisonIndex(unsigned index)
+    {
+        unsigned result = m_poisonScratchIndices[index];
+        ASSERT(result != badIndex());
+        return result;
+    }
+    
+    void handleExitCounts(const OSRExit&);
+    
+    AssemblyHelpers& m_jit;
+    Vector<unsigned> m_poisonScratchIndices;
+};
+
+extern "C" {
+void DFG_OPERATION compileOSRExit(ExecState*);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGOSRExitCompiler_h
diff --git a/dfg/DFGOSRExitCompiler32_64.cpp b/dfg/DFGOSRExitCompiler32_64.cpp
new file mode 100644 (file)
index 0000000..d16422a
--- /dev/null
@@ -0,0 +1,639 @@
+/*
+ * 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 "DFGOSRExitCompiler.h"
+
+#if ENABLE(DFG_JIT) && USE(JSVALUE32_64)
+
+#include "DFGOperations.h"
+
+namespace JSC { namespace DFG {
+
+void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* recovery)
+{
+    // 1) Pro-forma stuff.
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("OSR exit for Node @%d (", (int)exit.m_nodeIndex);
+    for (CodeOrigin codeOrigin = exit.m_codeOrigin; ; codeOrigin = codeOrigin.inlineCallFrame->caller) {
+        dataLog("bc#%u", codeOrigin.bytecodeIndex);
+        if (!codeOrigin.inlineCallFrame)
+            break;
+        dataLog(" -> %p ", codeOrigin.inlineCallFrame->executable.get());
+    }
+    dataLog(") at JIT offset 0x%x  ", m_jit.debugOffset());
+    exit.dump(WTF::dataFile());
+#endif
+#if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE)
+    SpeculationFailureDebugInfo* debugInfo = new SpeculationFailureDebugInfo;
+    debugInfo->codeBlock = m_jit.codeBlock();
+    debugInfo->nodeIndex = exit.m_nodeIndex;
+    
+    m_jit.debugCall(debugOperationPrintSpeculationFailure, debugInfo);
+#endif
+    
+#if DFG_ENABLE(JIT_BREAK_ON_SPECULATION_FAILURE)
+    m_jit.breakpoint();
+#endif
+    
+#if DFG_ENABLE(SUCCESS_STATS)
+    static SamplingCounter counter("SpeculationFailure");
+    m_jit.emitCount(counter);
+#endif
+
+    // 2) Perform speculation recovery. This only comes into play when an operation
+    //    starts mutating state before verifying the speculation it has already made.
+    
+    if (recovery) {
+        switch (recovery->type()) {
+        case SpeculativeAdd:
+            m_jit.sub32(recovery->src(), recovery->dest());
+            break;
+            
+        case BooleanSpeculationCheck:
+            break;
+            
+        default:
+            break;
+        }
+    }
+
+    // 3) Refine some value profile, if appropriate.
+    
+    if (!!exit.m_jsValueSource && !!exit.m_valueProfile) {
+        EncodedJSValue* bucket = exit.m_valueProfile.getSpecFailBucket(0);
+        
+        if (exit.m_jsValueSource.isAddress()) {
+            // Save a register so we can use it.
+            GPRReg scratch = GPRInfo::regT0;
+            if (scratch == exit.m_jsValueSource.base())
+                scratch = GPRInfo::regT1;
+            ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(sizeof(uint32_t));
+            EncodedJSValue* scratchDataBuffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer());
+            m_jit.store32(scratch, scratchDataBuffer);
+            m_jit.load32(exit.m_jsValueSource.asAddress(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), scratch);
+            m_jit.store32(scratch, &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag);
+            m_jit.load32(exit.m_jsValueSource.asAddress(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), scratch);
+            m_jit.store32(scratch, &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.payload);
+            m_jit.load32(scratchDataBuffer, scratch);
+        } else if (exit.m_jsValueSource.hasKnownTag()) {
+            m_jit.store32(AssemblyHelpers::TrustedImm32(exit.m_jsValueSource.tag()), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag);
+            m_jit.store32(exit.m_jsValueSource.payloadGPR(), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.payload);
+        } else {
+            m_jit.store32(exit.m_jsValueSource.tagGPR(), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag);
+            m_jit.store32(exit.m_jsValueSource.payloadGPR(), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.payload);
+        }
+    }
+    
+    // 4) Figure out how many scratch slots we'll need. We need one for every GPR/FPR
+    //    whose destination is now occupied by a DFG virtual register, and we need
+    //    one for every displaced virtual register if there are more than
+    //    GPRInfo::numberOfRegisters of them. Also see if there are any constants,
+    //    any undefined slots, any FPR slots, and any unboxed ints.
+            
+    Vector<bool> poisonedVirtualRegisters(exit.m_variables.size());
+    for (unsigned i = 0; i < poisonedVirtualRegisters.size(); ++i)
+        poisonedVirtualRegisters[i] = false;
+
+    unsigned numberOfPoisonedVirtualRegisters = 0;
+    unsigned numberOfDisplacedVirtualRegisters = 0;
+    
+    // Booleans for fast checks. We expect that most OSR exits do not have to rebox
+    // Int32s, have no FPRs, and have no constants. If there are constants, we
+    // expect most of them to be jsUndefined(); if that's true then we handle that
+    // specially to minimize code size and execution time.
+    bool haveUnboxedInt32InRegisterFile = false;
+    bool haveUnboxedCellInRegisterFile = false;
+    bool haveUnboxedBooleanInRegisterFile = false;
+    bool haveUInt32s = false;
+    bool haveFPRs = false;
+    bool haveConstants = false;
+    bool haveUndefined = false;
+    
+    for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+        const ValueRecovery& recovery = exit.valueRecovery(index);
+        switch (recovery.technique()) {
+        case DisplacedInRegisterFile:
+        case Int32DisplacedInRegisterFile:
+        case CellDisplacedInRegisterFile:
+        case BooleanDisplacedInRegisterFile:
+            numberOfDisplacedVirtualRegisters++;
+            ASSERT((int)recovery.virtualRegister() >= 0);
+            
+            // See if we might like to store to this virtual register before doing
+            // virtual register shuffling. If so, we say that the virtual register
+            // is poisoned: it cannot be stored to until after displaced virtual
+            // registers are handled. We track poisoned virtual register carefully
+            // to ensure this happens efficiently. Note that we expect this case
+            // to be rare, so the handling of it is optimized for the cases in
+            // which it does not happen.
+            if (recovery.virtualRegister() < (int)exit.m_variables.size()) {
+                switch (exit.m_variables[recovery.virtualRegister()].technique()) {
+                case InGPR:
+                case UnboxedInt32InGPR:
+                case UnboxedBooleanInGPR:
+                case UInt32InGPR:
+                case InPair:
+                case InFPR:
+                    if (!poisonedVirtualRegisters[recovery.virtualRegister()]) {
+                        poisonedVirtualRegisters[recovery.virtualRegister()] = true;
+                        numberOfPoisonedVirtualRegisters++;
+                    }
+                    break;
+                default:
+                    break;
+                }
+            }
+            break;
+            
+        case UInt32InGPR:
+            haveUInt32s = true;
+            break;
+
+        case AlreadyInRegisterFileAsUnboxedInt32:
+            haveUnboxedInt32InRegisterFile = true;
+            break;
+            
+        case AlreadyInRegisterFileAsUnboxedCell:
+            haveUnboxedCellInRegisterFile = true;
+            break;
+            
+        case AlreadyInRegisterFileAsUnboxedBoolean:
+            haveUnboxedBooleanInRegisterFile = true;
+            break;
+            
+        case InFPR:
+            haveFPRs = true;
+            break;
+            
+        case Constant:
+            haveConstants = true;
+            if (recovery.constant().isUndefined())
+                haveUndefined = true;
+            break;
+            
+        default:
+            break;
+        }
+    }
+    
+    unsigned scratchBufferLengthBeforeUInt32s = numberOfPoisonedVirtualRegisters + ((numberOfDisplacedVirtualRegisters * 2) <= GPRInfo::numberOfRegisters ? 0 : numberOfDisplacedVirtualRegisters);
+    ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(sizeof(EncodedJSValue) * (scratchBufferLengthBeforeUInt32s + (haveUInt32s ? 2 : 0)));
+    EncodedJSValue* scratchDataBuffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
+
+    // From here on, the code assumes that it is profitable to maximize the distance
+    // between when something is computed and when it is stored.
+    
+    // 5) Perform all reboxing of integers and cells, except for those in registers.
+
+    if (haveUnboxedInt32InRegisterFile || haveUnboxedCellInRegisterFile || haveUnboxedBooleanInRegisterFile) {
+        for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+            const ValueRecovery& recovery = exit.valueRecovery(index);
+            switch (recovery.technique()) {
+            case AlreadyInRegisterFileAsUnboxedInt32:
+                m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), AssemblyHelpers::tagFor(static_cast<VirtualRegister>(exit.operandForIndex(index))));
+                break;
+
+            case AlreadyInRegisterFileAsUnboxedCell:
+                m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor(static_cast<VirtualRegister>(exit.operandForIndex(index))));
+                break;
+
+            case AlreadyInRegisterFileAsUnboxedBoolean:
+                m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::BooleanTag), AssemblyHelpers::tagFor(static_cast<VirtualRegister>(exit.operandForIndex(index))));
+                break;
+
+            default:
+                break;
+            }
+        }
+    }
+
+    // 6) Dump all non-poisoned GPRs. For poisoned GPRs, save them into the scratch storage.
+    //    Note that GPRs do not have a fast change (like haveFPRs) because we expect that
+    //    most OSR failure points will have at least one GPR that needs to be dumped.
+    
+    initializePoisoned(exit.m_variables.size());
+    unsigned currentPoisonIndex = 0;
+    
+    for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+        const ValueRecovery& recovery = exit.valueRecovery(index);
+        int operand = exit.operandForIndex(index);
+        switch (recovery.technique()) {
+        case InGPR:
+        case UnboxedInt32InGPR:
+        case UnboxedBooleanInGPR:
+            if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
+                m_jit.store32(recovery.gpr(), reinterpret_cast<char*>(scratchDataBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+                m_poisonScratchIndices[exit.variableForIndex(index)] = currentPoisonIndex;
+                currentPoisonIndex++;
+            } else {
+                uint32_t tag = JSValue::EmptyValueTag;
+                if (recovery.technique() == InGPR)
+                    tag = JSValue::CellTag;
+                else if (recovery.technique() == UnboxedInt32InGPR)
+                    tag = JSValue::Int32Tag;
+                else
+                    tag = JSValue::BooleanTag;
+                m_jit.store32(AssemblyHelpers::TrustedImm32(tag), AssemblyHelpers::tagFor((VirtualRegister)operand));
+                m_jit.store32(recovery.gpr(), AssemblyHelpers::payloadFor((VirtualRegister)operand));
+            }
+            break;
+        case InPair:
+            if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
+                m_jit.store32(recovery.tagGPR(), reinterpret_cast<char*>(scratchDataBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+                m_jit.store32(recovery.payloadGPR(), reinterpret_cast<char*>(scratchDataBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+                m_poisonScratchIndices[exit.variableForIndex(index)] = currentPoisonIndex;
+                currentPoisonIndex++;
+            } else {
+                m_jit.store32(recovery.tagGPR(), AssemblyHelpers::tagFor((VirtualRegister)operand));
+                m_jit.store32(recovery.payloadGPR(), AssemblyHelpers::payloadFor((VirtualRegister)operand));
+            }
+            break;
+        case UInt32InGPR: {
+            EncodedJSValue* myScratch = scratchDataBuffer + scratchBufferLengthBeforeUInt32s;
+            
+            GPRReg addressGPR = GPRInfo::regT0;
+            if (addressGPR == recovery.gpr())
+                addressGPR = GPRInfo::regT1;
+            
+            m_jit.storePtr(addressGPR, myScratch);
+            m_jit.move(AssemblyHelpers::TrustedImmPtr(myScratch + 1), addressGPR);
+            m_jit.storeDouble(FPRInfo::fpRegT0, addressGPR);
+            
+            AssemblyHelpers::Jump positive = m_jit.branch32(AssemblyHelpers::GreaterThanOrEqual, recovery.gpr(), AssemblyHelpers::TrustedImm32(0));
+            
+            m_jit.convertInt32ToDouble(recovery.gpr(), FPRInfo::fpRegT0);
+            m_jit.addDouble(AssemblyHelpers::AbsoluteAddress(&AssemblyHelpers::twoToThe32), FPRInfo::fpRegT0);
+            if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
+                m_jit.move(AssemblyHelpers::TrustedImmPtr(scratchDataBuffer + currentPoisonIndex), addressGPR);
+                m_jit.storeDouble(FPRInfo::fpRegT0, addressGPR);
+            } else
+                m_jit.storeDouble(FPRInfo::fpRegT0, AssemblyHelpers::addressFor((VirtualRegister)operand));
+            
+            AssemblyHelpers::Jump done = m_jit.jump();
+            
+            positive.link(&m_jit);
+            
+            if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
+                m_jit.store32(recovery.gpr(), reinterpret_cast<char*>(scratchDataBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+                m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), reinterpret_cast<char*>(scratchDataBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+            } else {
+                m_jit.store32(recovery.gpr(), AssemblyHelpers::payloadFor((VirtualRegister)operand));
+                m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), AssemblyHelpers::tagFor((VirtualRegister)operand));
+            }
+            
+            done.link(&m_jit);
+            
+            m_jit.move(AssemblyHelpers::TrustedImmPtr(myScratch + 1), addressGPR);
+            m_jit.loadDouble(addressGPR, FPRInfo::fpRegT0);
+            m_jit.loadPtr(myScratch, addressGPR);
+                              
+            if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
+                m_poisonScratchIndices[exit.variableForIndex(index)] = currentPoisonIndex;
+                currentPoisonIndex++;
+            }
+            break;
+        }
+        default:
+            break;
+        }
+    }
+    
+    // 7) Dump all doubles into the register file, or to the scratch storage if the
+    //    destination virtual register is poisoned.
+    if (haveFPRs) {
+        for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+            const ValueRecovery& recovery = exit.valueRecovery(index);
+            if (recovery.technique() != InFPR)
+                continue;
+            if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
+                m_jit.storeDouble(recovery.fpr(), scratchDataBuffer + currentPoisonIndex);
+                m_poisonScratchIndices[exit.variableForIndex(index)] = currentPoisonIndex;
+                currentPoisonIndex++;
+            } else
+                m_jit.storeDouble(recovery.fpr(), AssemblyHelpers::addressFor((VirtualRegister)exit.operandForIndex(index)));
+        }
+    }
+    
+    // At this point all GPRs are available for scratch use.
+    
+    ASSERT(currentPoisonIndex == numberOfPoisonedVirtualRegisters);
+    
+    // 8) Reshuffle displaced virtual registers. Optimize for the case that
+    //    the number of displaced virtual registers is not more than the number
+    //    of available physical registers.
+    
+    if (numberOfDisplacedVirtualRegisters) {
+        if (numberOfDisplacedVirtualRegisters * 2 <= GPRInfo::numberOfRegisters) {
+            // So far this appears to be the case that triggers all the time, but
+            // that is far from guaranteed.
+        
+            unsigned displacementIndex = 0;
+            for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+                const ValueRecovery& recovery = exit.valueRecovery(index);
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                    m_jit.load32(AssemblyHelpers::tagFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                    break;
+                case Int32DisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                    m_jit.move(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), GPRInfo::toRegister(displacementIndex++));
+                    break;
+                case CellDisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                    m_jit.move(AssemblyHelpers::TrustedImm32(JSValue::CellTag), GPRInfo::toRegister(displacementIndex++));
+                    break;
+                case BooleanDisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                    m_jit.move(AssemblyHelpers::TrustedImm32(JSValue::BooleanTag), GPRInfo::toRegister(displacementIndex++));
+                    break;
+                default:
+                    break;
+                }
+            }
+        
+            displacementIndex = 0;
+            for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+                const ValueRecovery& recovery = exit.valueRecovery(index);
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                case Int32DisplacedInRegisterFile:
+                case CellDisplacedInRegisterFile:
+                case BooleanDisplacedInRegisterFile:
+                    m_jit.store32(GPRInfo::toRegister(displacementIndex++), AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                    m_jit.store32(GPRInfo::toRegister(displacementIndex++), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+                    break;
+                default:
+                    break;
+                }
+            }
+        } else {
+            // FIXME: This should use the shuffling algorithm that we use
+            // for speculative->non-speculative jumps, if we ever discover that
+            // some hot code with lots of live values that get displaced and
+            // spilled really enjoys frequently failing speculation.
+        
+            // For now this code is engineered to be correct but probably not
+            // super. In particular, it correctly handles cases where for example
+            // the displacements are a permutation of the destination values, like
+            //
+            // 1 -> 2
+            // 2 -> 1
+            //
+            // It accomplishes this by simply lifting all of the virtual registers
+            // from their old (DFG JIT) locations and dropping them in a scratch
+            // location in memory, and then transferring from that scratch location
+            // to their new (old JIT) locations.
+        
+            unsigned scratchIndex = numberOfPoisonedVirtualRegisters;
+            for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+                const ValueRecovery& recovery = exit.valueRecovery(index);
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::regT0);
+                    m_jit.load32(AssemblyHelpers::tagFor(recovery.virtualRegister()), GPRInfo::regT1);
+                    m_jit.store32(GPRInfo::regT0, reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+                    m_jit.store32(GPRInfo::regT1, reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+                    scratchIndex++;
+                    break;
+                case Int32DisplacedInRegisterFile:
+                case CellDisplacedInRegisterFile:
+                case BooleanDisplacedInRegisterFile:
+                    m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::regT0);
+                    m_jit.store32(GPRInfo::regT0, reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+                    break;
+                default:
+                    break;
+                }
+            }
+        
+            scratchIndex = numberOfPoisonedVirtualRegisters;
+            for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+                const ValueRecovery& recovery = exit.valueRecovery(index);
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                    m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                    m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag), GPRInfo::regT1);
+                    m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                    m_jit.store32(GPRInfo::regT1, AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+                    scratchIndex++;
+                    break;
+                case Int32DisplacedInRegisterFile:
+                    m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                    m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+                    m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                    break;
+                case CellDisplacedInRegisterFile:
+                    m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                    m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+                    m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                    break;
+                case BooleanDisplacedInRegisterFile:
+                    m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                    m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::BooleanTag), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+                    m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                    break;
+                default:
+                    break;
+                }
+            }
+        
+            ASSERT(scratchIndex == numberOfPoisonedVirtualRegisters + numberOfDisplacedVirtualRegisters);
+        }
+    }
+    
+    // 9) Dump all poisoned virtual registers.
+    
+    if (numberOfPoisonedVirtualRegisters) {
+        for (int virtualRegister = 0; virtualRegister < (int)exit.m_variables.size(); ++virtualRegister) {
+            if (!poisonedVirtualRegisters[virtualRegister])
+                continue;
+            
+            const ValueRecovery& recovery = exit.m_variables[virtualRegister];
+            switch (recovery.technique()) {
+            case InGPR:
+            case UnboxedInt32InGPR:
+            case UnboxedBooleanInGPR: {
+                m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)virtualRegister));
+                uint32_t tag = JSValue::EmptyValueTag;
+                if (recovery.technique() == InGPR)
+                    tag = JSValue::CellTag;
+                else if (recovery.technique() == UnboxedInt32InGPR)
+                    tag = JSValue::Int32Tag;
+                else
+                    tag = JSValue::BooleanTag;
+                m_jit.store32(AssemblyHelpers::TrustedImm32(tag), AssemblyHelpers::tagFor((VirtualRegister)virtualRegister));
+                break;
+            }
+
+            case InFPR:
+            case InPair:
+            case UInt32InGPR:
+                m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+                m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag), GPRInfo::regT1);
+                m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)virtualRegister));
+                m_jit.store32(GPRInfo::regT1, AssemblyHelpers::tagFor((VirtualRegister)virtualRegister));
+                break;
+                
+            default:
+                break;
+            }
+        }
+    }
+    
+    // 10) Dump all constants. Optimize for Undefined, since that's a constant we see
+    //     often.
+
+    if (haveConstants) {
+        if (haveUndefined) {
+            m_jit.move(AssemblyHelpers::TrustedImm32(jsUndefined().payload()), GPRInfo::regT0);
+            m_jit.move(AssemblyHelpers::TrustedImm32(jsUndefined().tag()), GPRInfo::regT1);
+        }
+        
+        for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+            const ValueRecovery& recovery = exit.valueRecovery(index);
+            if (recovery.technique() != Constant)
+                continue;
+            if (recovery.constant().isUndefined()) {
+                m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                m_jit.store32(GPRInfo::regT1, AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+            } else {
+                m_jit.store32(AssemblyHelpers::TrustedImm32(recovery.constant().payload()), AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
+                m_jit.store32(AssemblyHelpers::TrustedImm32(recovery.constant().tag()), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
+            }
+        }
+    }
+    
+    // 11) Adjust the old JIT's execute counter. Since we are exiting OSR, we know
+    //     that all new calls into this code will go to the new JIT, so the execute
+    //     counter only affects call frames that performed OSR exit and call frames
+    //     that were still executing the old JIT at the time of another call frame's
+    //     OSR exit. We want to ensure that the following is true:
+    //
+    //     (a) Code the performs an OSR exit gets a chance to reenter optimized
+    //         code eventually, since optimized code is faster. But we don't
+    //         want to do such reentery too aggressively (see (c) below).
+    //
+    //     (b) If there is code on the call stack that is still running the old
+    //         JIT's code and has never OSR'd, then it should get a chance to
+    //         perform OSR entry despite the fact that we've exited.
+    //
+    //     (c) Code the performs an OSR exit should not immediately retry OSR
+    //         entry, since both forms of OSR are expensive. OSR entry is
+    //         particularly expensive.
+    //
+    //     (d) Frequent OSR failures, even those that do not result in the code
+    //         running in a hot loop, result in recompilation getting triggered.
+    //
+    //     To ensure (c), we'd like to set the execute counter to
+    //     counterValueForOptimizeAfterWarmUp(). This seems like it would endanger
+    //     (a) and (b), since then every OSR exit would delay the opportunity for
+    //     every call frame to perform OSR entry. Essentially, if OSR exit happens
+    //     frequently and the function has few loops, then the counter will never
+    //     become non-negative and OSR entry will never be triggered. OSR entry
+    //     will only happen if a loop gets hot in the old JIT, which does a pretty
+    //     good job of ensuring (a) and (b). But that doesn't take care of (d),
+    //     since each speculation failure would reset the execute counter.
+    //     So we check here if the number of speculation failures is significantly
+    //     larger than the number of successes (we want 90% success rate), and if
+    //     there have been a large enough number of failures. If so, we set the
+    //     counter to 0; otherwise we set the counter to
+    //     counterValueForOptimizeAfterWarmUp().
+    
+    handleExitCounts(exit);
+    
+    // 12) Load the result of the last bytecode operation into regT0.
+    
+    if (exit.m_lastSetOperand != std::numeric_limits<int>::max()) {
+        m_jit.load32(AssemblyHelpers::payloadFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
+        m_jit.load32(AssemblyHelpers::tagFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister2);
+    }
+    
+    // 13) Fix call frame (s).
+    
+    ASSERT(m_jit.baselineCodeBlock()->getJITType() == JITCode::BaselineJIT);
+    m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)RegisterFile::CodeBlock));
+    
+    for (CodeOrigin codeOrigin = exit.m_codeOrigin; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) {
+        InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame;
+        CodeBlock* baselineCodeBlock = m_jit.baselineCodeBlockFor(codeOrigin);
+        CodeBlock* baselineCodeBlockForCaller = m_jit.baselineCodeBlockFor(inlineCallFrame->caller);
+        Vector<BytecodeAndMachineOffset>& decodedCodeMap = m_jit.decodedCodeMapFor(baselineCodeBlockForCaller);
+        unsigned returnBytecodeIndex = inlineCallFrame->caller.bytecodeIndex + OPCODE_LENGTH(op_call);
+        BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned, BytecodeAndMachineOffset::getBytecodeIndex>(decodedCodeMap.begin(), decodedCodeMap.size(), returnBytecodeIndex);
+        
+        ASSERT(mapping);
+        ASSERT(mapping->m_bytecodeIndex == returnBytecodeIndex);
+        
+        void* jumpTarget = baselineCodeBlockForCaller->getJITCode().executableAddressAtOffset(mapping->m_machineCodeOffset);
+
+        GPRReg callerFrameGPR;
+        if (inlineCallFrame->caller.inlineCallFrame) {
+            m_jit.add32(AssemblyHelpers::TrustedImm32(inlineCallFrame->caller.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT3);
+            callerFrameGPR = GPRInfo::regT3;
+        } else
+            callerFrameGPR = GPRInfo::callFrameRegister;
+        
+        m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CodeBlock)));
+        m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ScopeChain)));
+        m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee->scope()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ScopeChain)));
+        m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CallerFrame)));
+        m_jit.storePtr(callerFrameGPR, AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CallerFrame)));
+        m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ReturnPC)));
+        m_jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ArgumentCount)));
+        m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee)));
+        m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee.get()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee)));
+    }
+    
+    if (exit.m_codeOrigin.inlineCallFrame)
+        m_jit.addPtr(AssemblyHelpers::TrustedImm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister);
+
+    // 14) Jump into the corresponding baseline JIT code.
+    
+    CodeBlock* baselineCodeBlock = m_jit.baselineCodeBlockFor(exit.m_codeOrigin);
+    Vector<BytecodeAndMachineOffset>& decodedCodeMap = m_jit.decodedCodeMapFor(baselineCodeBlock);
+    
+    BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned, BytecodeAndMachineOffset::getBytecodeIndex>(decodedCodeMap.begin(), decodedCodeMap.size(), exit.m_codeOrigin.bytecodeIndex);
+    
+    ASSERT(mapping);
+    ASSERT(mapping->m_bytecodeIndex == exit.m_codeOrigin.bytecodeIndex);
+    
+    void* jumpTarget = baselineCodeBlock->getJITCode().executableAddressAtOffset(mapping->m_machineCodeOffset);
+    
+    ASSERT(GPRInfo::regT2 != GPRInfo::cachedResultRegister && GPRInfo::regT2 != GPRInfo::cachedResultRegister2);
+    
+    m_jit.move(AssemblyHelpers::TrustedImmPtr(jumpTarget), GPRInfo::regT2);
+    m_jit.jump(GPRInfo::regT2);
+
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("   -> %p\n", jumpTarget);
+#endif
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT) && USE(JSVALUE32_64)
diff --git a/dfg/DFGOSRExitCompiler64.cpp b/dfg/DFGOSRExitCompiler64.cpp
new file mode 100644 (file)
index 0000000..6f116e4
--- /dev/null
@@ -0,0 +1,613 @@
+/*
+ * 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 "DFGOSRExitCompiler.h"
+
+#if ENABLE(DFG_JIT) && USE(JSVALUE64)
+
+#include "DFGOperations.h"
+
+namespace JSC { namespace DFG {
+
+void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* recovery)
+{
+    // 1) Pro-forma stuff.
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("OSR exit for Node @%d (", (int)exit.m_nodeIndex);
+    for (CodeOrigin codeOrigin = exit.m_codeOrigin; ; codeOrigin = codeOrigin.inlineCallFrame->caller) {
+        dataLog("bc#%u", codeOrigin.bytecodeIndex);
+        if (!codeOrigin.inlineCallFrame)
+            break;
+        dataLog(" -> %p ", codeOrigin.inlineCallFrame->executable.get());
+    }
+    dataLog(")  ");
+    exit.dump(WTF::dataFile());
+#endif
+#if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE)
+    SpeculationFailureDebugInfo* debugInfo = new SpeculationFailureDebugInfo;
+    debugInfo->codeBlock = m_jit.codeBlock();
+    debugInfo->nodeIndex = exit.m_nodeIndex;
+    
+    m_jit.debugCall(debugOperationPrintSpeculationFailure, debugInfo);
+#endif
+    
+#if DFG_ENABLE(JIT_BREAK_ON_SPECULATION_FAILURE)
+    m_jit.breakpoint();
+#endif
+    
+#if DFG_ENABLE(SUCCESS_STATS)
+    static SamplingCounter counter("SpeculationFailure");
+    m_jit.emitCount(counter);
+#endif
+    
+    // 2) Perform speculation recovery. This only comes into play when an operation
+    //    starts mutating state before verifying the speculation it has already made.
+    
+    GPRReg alreadyBoxed = InvalidGPRReg;
+    
+    if (recovery) {
+        switch (recovery->type()) {
+        case SpeculativeAdd:
+            m_jit.sub32(recovery->src(), recovery->dest());
+            m_jit.orPtr(GPRInfo::tagTypeNumberRegister, recovery->dest());
+            alreadyBoxed = recovery->dest();
+            break;
+            
+        case BooleanSpeculationCheck:
+            m_jit.xorPtr(AssemblyHelpers::TrustedImm32(static_cast<int32_t>(ValueFalse)), recovery->dest());
+            break;
+            
+        default:
+            break;
+        }
+    }
+
+    // 3) Refine some value profile, if appropriate.
+    
+    if (!!exit.m_jsValueSource && !!exit.m_valueProfile) {
+        EncodedJSValue* bucket = exit.m_valueProfile.getSpecFailBucket(0);
+        
+#if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE)
+        dataLog("  (have exit profile, bucket %p)  ", bucket);
+#endif
+            
+        if (exit.m_jsValueSource.isAddress()) {
+            // We can't be sure that we have a spare register. So use the tagTypeNumberRegister,
+            // since we know how to restore it.
+            m_jit.loadPtr(AssemblyHelpers::Address(exit.m_jsValueSource.asAddress()), GPRInfo::tagTypeNumberRegister);
+            m_jit.storePtr(GPRInfo::tagTypeNumberRegister, bucket);
+            m_jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(TagTypeNumber)), GPRInfo::tagTypeNumberRegister);
+        } else
+            m_jit.storePtr(exit.m_jsValueSource.gpr(), bucket);
+    }
+
+    // 4) Figure out how many scratch slots we'll need. We need one for every GPR/FPR
+    //    whose destination is now occupied by a DFG virtual register, and we need
+    //    one for every displaced virtual register if there are more than
+    //    GPRInfo::numberOfRegisters of them. Also see if there are any constants,
+    //    any undefined slots, any FPR slots, and any unboxed ints.
+            
+    Vector<bool> poisonedVirtualRegisters(exit.m_variables.size());
+    for (unsigned i = 0; i < poisonedVirtualRegisters.size(); ++i)
+        poisonedVirtualRegisters[i] = false;
+
+    unsigned numberOfPoisonedVirtualRegisters = 0;
+    unsigned numberOfDisplacedVirtualRegisters = 0;
+    
+    // Booleans for fast checks. We expect that most OSR exits do not have to rebox
+    // Int32s, have no FPRs, and have no constants. If there are constants, we
+    // expect most of them to be jsUndefined(); if that's true then we handle that
+    // specially to minimize code size and execution time.
+    bool haveUnboxedInt32s = false;
+    bool haveUnboxedDoubles = false;
+    bool haveFPRs = false;
+    bool haveConstants = false;
+    bool haveUndefined = false;
+    bool haveUInt32s = false;
+    
+    for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+        const ValueRecovery& recovery = exit.valueRecovery(index);
+        switch (recovery.technique()) {
+        case Int32DisplacedInRegisterFile:
+        case DoubleDisplacedInRegisterFile:
+        case DisplacedInRegisterFile:
+            numberOfDisplacedVirtualRegisters++;
+            ASSERT((int)recovery.virtualRegister() >= 0);
+            
+            // See if we might like to store to this virtual register before doing
+            // virtual register shuffling. If so, we say that the virtual register
+            // is poisoned: it cannot be stored to until after displaced virtual
+            // registers are handled. We track poisoned virtual register carefully
+            // to ensure this happens efficiently. Note that we expect this case
+            // to be rare, so the handling of it is optimized for the cases in
+            // which it does not happen.
+            if (recovery.virtualRegister() < (int)exit.m_variables.size()) {
+                switch (exit.m_variables[recovery.virtualRegister()].technique()) {
+                case InGPR:
+                case UnboxedInt32InGPR:
+                case UInt32InGPR:
+                case InFPR:
+                    if (!poisonedVirtualRegisters[recovery.virtualRegister()]) {
+                        poisonedVirtualRegisters[recovery.virtualRegister()] = true;
+                        numberOfPoisonedVirtualRegisters++;
+                    }
+                    break;
+                default:
+                    break;
+                }
+            }
+            break;
+            
+        case UnboxedInt32InGPR:
+        case AlreadyInRegisterFileAsUnboxedInt32:
+            haveUnboxedInt32s = true;
+            break;
+            
+        case AlreadyInRegisterFileAsUnboxedDouble:
+            haveUnboxedDoubles = true;
+            break;
+            
+        case UInt32InGPR:
+            haveUInt32s = true;
+            break;
+            
+        case InFPR:
+            haveFPRs = true;
+            break;
+            
+        case Constant:
+            haveConstants = true;
+            if (recovery.constant().isUndefined())
+                haveUndefined = true;
+            break;
+            
+        default:
+            break;
+        }
+    }
+    
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("  ");
+    if (numberOfPoisonedVirtualRegisters)
+        dataLog("Poisoned=%u ", numberOfPoisonedVirtualRegisters);
+    if (numberOfDisplacedVirtualRegisters)
+        dataLog("Displaced=%u ", numberOfDisplacedVirtualRegisters);
+    if (haveUnboxedInt32s)
+        dataLog("UnboxedInt32 ");
+    if (haveUnboxedDoubles)
+        dataLog("UnboxedDoubles ");
+    if (haveUInt32s)
+        dataLog("UInt32 ");
+    if (haveFPRs)
+        dataLog("FPR ");
+    if (haveConstants)
+        dataLog("Constants ");
+    if (haveUndefined)
+        dataLog("Undefined ");
+    dataLog(" ");
+#endif
+    
+    ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(sizeof(EncodedJSValue) * std::max(haveUInt32s ? 2u : 0u, numberOfPoisonedVirtualRegisters + (numberOfDisplacedVirtualRegisters <= GPRInfo::numberOfRegisters ? 0 : numberOfDisplacedVirtualRegisters)));
+    EncodedJSValue* scratchDataBuffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
+
+    // From here on, the code assumes that it is profitable to maximize the distance
+    // between when something is computed and when it is stored.
+    
+    // 5) Perform all reboxing of integers.
+    
+    if (haveUnboxedInt32s || haveUInt32s) {
+        for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+            const ValueRecovery& recovery = exit.valueRecovery(index);
+            switch (recovery.technique()) {
+            case UnboxedInt32InGPR:
+                if (recovery.gpr() != alreadyBoxed)
+                    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, recovery.gpr());
+                break;
+                
+            case AlreadyInRegisterFileAsUnboxedInt32:
+                m_jit.store32(AssemblyHelpers::TrustedImm32(static_cast<uint32_t>(TagTypeNumber >> 32)), AssemblyHelpers::tagFor(static_cast<VirtualRegister>(exit.operandForIndex(index))));
+                break;
+                
+            case UInt32InGPR: {
+                // This occurs when the speculative JIT left an unsigned 32-bit integer
+                // in a GPR. If it's positive, we can just box the int. Otherwise we
+                // need to turn it into a boxed double.
+                
+                // We don't try to be clever with register allocation here; we assume
+                // that the program is using FPRs and we don't try to figure out which
+                // ones it is using. Instead just temporarily save fpRegT0 and then
+                // restore it. This makes sense because this path is not cheap to begin
+                // with, and should happen very rarely.
+                
+                GPRReg addressGPR = GPRInfo::regT0;
+                if (addressGPR == recovery.gpr())
+                    addressGPR = GPRInfo::regT1;
+                
+                m_jit.storePtr(addressGPR, scratchDataBuffer);
+                m_jit.move(AssemblyHelpers::TrustedImmPtr(scratchDataBuffer + 1), addressGPR);
+                m_jit.storeDouble(FPRInfo::fpRegT0, addressGPR);
+                
+                AssemblyHelpers::Jump positive = m_jit.branch32(AssemblyHelpers::GreaterThanOrEqual, recovery.gpr(), AssemblyHelpers::TrustedImm32(0));
+
+                m_jit.convertInt32ToDouble(recovery.gpr(), FPRInfo::fpRegT0);
+                m_jit.addDouble(AssemblyHelpers::AbsoluteAddress(&AssemblyHelpers::twoToThe32), FPRInfo::fpRegT0);
+                m_jit.boxDouble(FPRInfo::fpRegT0, recovery.gpr());
+                
+                AssemblyHelpers::Jump done = m_jit.jump();
+                
+                positive.link(&m_jit);
+                
+                m_jit.orPtr(GPRInfo::tagTypeNumberRegister, recovery.gpr());
+                
+                done.link(&m_jit);
+                
+                m_jit.loadDouble(addressGPR, FPRInfo::fpRegT0);
+                m_jit.loadPtr(scratchDataBuffer, addressGPR);
+                break;
+            }
+                
+            default:
+                break;
+            }
+        }
+    }
+    
+    // 6) Dump all non-poisoned GPRs. For poisoned GPRs, save them into the scratch storage.
+    //    Note that GPRs do not have a fast change (like haveFPRs) because we expect that
+    //    most OSR failure points will have at least one GPR that needs to be dumped.
+    
+    initializePoisoned(exit.m_variables.size());
+    unsigned currentPoisonIndex = 0;
+    
+    for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+        const ValueRecovery& recovery = exit.valueRecovery(index);
+        int operand = exit.operandForIndex(index);
+        switch (recovery.technique()) {
+        case InGPR:
+        case UnboxedInt32InGPR:
+        case UInt32InGPR:
+            if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
+                m_jit.storePtr(recovery.gpr(), scratchDataBuffer + currentPoisonIndex);
+                m_poisonScratchIndices[exit.variableForIndex(index)] = currentPoisonIndex;
+                currentPoisonIndex++;
+            } else
+                m_jit.storePtr(recovery.gpr(), AssemblyHelpers::addressFor((VirtualRegister)operand));
+            break;
+        default:
+            break;
+        }
+    }
+    
+    // At this point all GPRs are available for scratch use.
+    
+    if (haveFPRs) {
+        // 7) Box all doubles (relies on there being more GPRs than FPRs)
+        
+        for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+            const ValueRecovery& recovery = exit.valueRecovery(index);
+            if (recovery.technique() != InFPR)
+                continue;
+            FPRReg fpr = recovery.fpr();
+            GPRReg gpr = GPRInfo::toRegister(FPRInfo::toIndex(fpr));
+            m_jit.boxDouble(fpr, gpr);
+        }
+        
+        // 8) Dump all doubles into the register file, or to the scratch storage if
+        //    the destination virtual register is poisoned.
+        
+        for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+            const ValueRecovery& recovery = exit.valueRecovery(index);
+            if (recovery.technique() != InFPR)
+                continue;
+            GPRReg gpr = GPRInfo::toRegister(FPRInfo::toIndex(recovery.fpr()));
+            if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
+                m_jit.storePtr(gpr, scratchDataBuffer + currentPoisonIndex);
+                m_poisonScratchIndices[exit.variableForIndex(index)] = currentPoisonIndex;
+                currentPoisonIndex++;
+            } else
+                m_jit.storePtr(gpr, AssemblyHelpers::addressFor((VirtualRegister)exit.operandForIndex(index)));
+        }
+    }
+    
+    // At this point all GPRs and FPRs are available for scratch use.
+    
+    // 9) Box all unboxed doubles in the register file.
+    if (haveUnboxedDoubles) {
+        for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+            const ValueRecovery& recovery = exit.valueRecovery(index);
+            if (recovery.technique() != AlreadyInRegisterFileAsUnboxedDouble)
+                continue;
+            m_jit.loadDouble(AssemblyHelpers::addressFor((VirtualRegister)exit.operandForIndex(index)), FPRInfo::fpRegT0);
+            m_jit.boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0);
+            m_jit.storePtr(GPRInfo::regT0, AssemblyHelpers::addressFor((VirtualRegister)exit.operandForIndex(index)));
+        }
+    }
+    
+    ASSERT(currentPoisonIndex == numberOfPoisonedVirtualRegisters);
+    
+    // 10) Reshuffle displaced virtual registers. Optimize for the case that
+    //    the number of displaced virtual registers is not more than the number
+    //    of available physical registers.
+    
+    if (numberOfDisplacedVirtualRegisters) {
+        if (numberOfDisplacedVirtualRegisters <= GPRInfo::numberOfRegisters) {
+            // So far this appears to be the case that triggers all the time, but
+            // that is far from guaranteed.
+        
+            unsigned displacementIndex = 0;
+            for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+                const ValueRecovery& recovery = exit.valueRecovery(index);
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                    m_jit.loadPtr(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::toRegister(displacementIndex++));
+                    break;
+                    
+                case Int32DisplacedInRegisterFile: {
+                    GPRReg gpr = GPRInfo::toRegister(displacementIndex++);
+                    m_jit.load32(AssemblyHelpers::addressFor(recovery.virtualRegister()), gpr);
+                    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
+                    break;
+                }
+                    
+                case DoubleDisplacedInRegisterFile: {
+                    GPRReg gpr = GPRInfo::toRegister(displacementIndex++);
+                    m_jit.loadPtr(AssemblyHelpers::addressFor(recovery.virtualRegister()), gpr);
+                    m_jit.subPtr(GPRInfo::tagTypeNumberRegister, gpr);
+                    break;
+                }
+                    
+                default:
+                    break;
+                }
+            }
+        
+            displacementIndex = 0;
+            for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+                const ValueRecovery& recovery = exit.valueRecovery(index);
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                case Int32DisplacedInRegisterFile:
+                case DoubleDisplacedInRegisterFile:
+                    m_jit.storePtr(GPRInfo::toRegister(displacementIndex++), AssemblyHelpers::addressFor((VirtualRegister)exit.operandForIndex(index)));
+                    break;
+                    
+                default:
+                    break;
+                }
+            }
+        } else {
+            // FIXME: This should use the shuffling algorithm that we use
+            // for speculative->non-speculative jumps, if we ever discover that
+            // some hot code with lots of live values that get displaced and
+            // spilled really enjoys frequently failing speculation.
+        
+            // For now this code is engineered to be correct but probably not
+            // super. In particular, it correctly handles cases where for example
+            // the displacements are a permutation of the destination values, like
+            //
+            // 1 -> 2
+            // 2 -> 1
+            //
+            // It accomplishes this by simply lifting all of the virtual registers
+            // from their old (DFG JIT) locations and dropping them in a scratch
+            // location in memory, and then transferring from that scratch location
+            // to their new (old JIT) locations.
+        
+            unsigned scratchIndex = numberOfPoisonedVirtualRegisters;
+            for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+                const ValueRecovery& recovery = exit.valueRecovery(index);
+                
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                    m_jit.loadPtr(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0);
+                    m_jit.storePtr(GPRInfo::regT0, scratchDataBuffer + scratchIndex++);
+                    break;
+                    
+                case Int32DisplacedInRegisterFile: {
+                    m_jit.load32(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0);
+                    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
+                    m_jit.storePtr(GPRInfo::regT0, scratchDataBuffer + scratchIndex++);
+                    break;
+                }
+                    
+                case DoubleDisplacedInRegisterFile: {
+                    m_jit.loadPtr(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0);
+                    m_jit.subPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
+                    m_jit.storePtr(GPRInfo::regT0, scratchDataBuffer + scratchIndex++);
+                    break;
+                }
+                    
+                default:
+                    break;
+                }
+            }
+        
+            scratchIndex = numberOfPoisonedVirtualRegisters;
+            for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+                const ValueRecovery& recovery = exit.valueRecovery(index);
+                switch (recovery.technique()) {
+                case DisplacedInRegisterFile:
+                case Int32DisplacedInRegisterFile:
+                case DoubleDisplacedInRegisterFile:
+                    m_jit.loadPtr(scratchDataBuffer + scratchIndex++, GPRInfo::regT0);
+                    m_jit.storePtr(GPRInfo::regT0, AssemblyHelpers::addressFor((VirtualRegister)exit.operandForIndex(index)));
+                    break;
+                    
+                default:
+                    break;
+                }
+            }
+        
+            ASSERT(scratchIndex == numberOfPoisonedVirtualRegisters + numberOfDisplacedVirtualRegisters);
+        }
+    }
+    
+    // 11) Dump all poisoned virtual registers.
+    
+    if (numberOfPoisonedVirtualRegisters) {
+        for (int virtualRegister = 0; virtualRegister < (int)exit.m_variables.size(); ++virtualRegister) {
+            if (!poisonedVirtualRegisters[virtualRegister])
+                continue;
+            
+            const ValueRecovery& recovery = exit.m_variables[virtualRegister];
+            switch (recovery.technique()) {
+            case InGPR:
+            case UnboxedInt32InGPR:
+            case UInt32InGPR:
+            case InFPR:
+                m_jit.loadPtr(scratchDataBuffer + poisonIndex(virtualRegister), GPRInfo::regT0);
+                m_jit.storePtr(GPRInfo::regT0, AssemblyHelpers::addressFor((VirtualRegister)virtualRegister));
+                break;
+                
+            default:
+                break;
+            }
+        }
+    }
+    
+    // 12) Dump all constants. Optimize for Undefined, since that's a constant we see
+    //     often.
+
+    if (haveConstants) {
+        if (haveUndefined)
+            m_jit.move(AssemblyHelpers::TrustedImmPtr(JSValue::encode(jsUndefined())), GPRInfo::regT0);
+        
+        for (int index = 0; index < exit.numberOfRecoveries(); ++index) {
+            const ValueRecovery& recovery = exit.valueRecovery(index);
+            if (recovery.technique() != Constant)
+                continue;
+            if (recovery.constant().isUndefined())
+                m_jit.storePtr(GPRInfo::regT0, AssemblyHelpers::addressFor((VirtualRegister)exit.operandForIndex(index)));
+            else
+                m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(JSValue::encode(recovery.constant())), AssemblyHelpers::addressFor((VirtualRegister)exit.operandForIndex(index)));
+        }
+    }
+    
+    // 13) Adjust the old JIT's execute counter. Since we are exiting OSR, we know
+    //     that all new calls into this code will go to the new JIT, so the execute
+    //     counter only affects call frames that performed OSR exit and call frames
+    //     that were still executing the old JIT at the time of another call frame's
+    //     OSR exit. We want to ensure that the following is true:
+    //
+    //     (a) Code the performs an OSR exit gets a chance to reenter optimized
+    //         code eventually, since optimized code is faster. But we don't
+    //         want to do such reentery too aggressively (see (c) below).
+    //
+    //     (b) If there is code on the call stack that is still running the old
+    //         JIT's code and has never OSR'd, then it should get a chance to
+    //         perform OSR entry despite the fact that we've exited.
+    //
+    //     (c) Code the performs an OSR exit should not immediately retry OSR
+    //         entry, since both forms of OSR are expensive. OSR entry is
+    //         particularly expensive.
+    //
+    //     (d) Frequent OSR failures, even those that do not result in the code
+    //         running in a hot loop, result in recompilation getting triggered.
+    //
+    //     To ensure (c), we'd like to set the execute counter to
+    //     counterValueForOptimizeAfterWarmUp(). This seems like it would endanger
+    //     (a) and (b), since then every OSR exit would delay the opportunity for
+    //     every call frame to perform OSR entry. Essentially, if OSR exit happens
+    //     frequently and the function has few loops, then the counter will never
+    //     become non-negative and OSR entry will never be triggered. OSR entry
+    //     will only happen if a loop gets hot in the old JIT, which does a pretty
+    //     good job of ensuring (a) and (b). But that doesn't take care of (d),
+    //     since each speculation failure would reset the execute counter.
+    //     So we check here if the number of speculation failures is significantly
+    //     larger than the number of successes (we want 90% success rate), and if
+    //     there have been a large enough number of failures. If so, we set the
+    //     counter to 0; otherwise we set the counter to
+    //     counterValueForOptimizeAfterWarmUp().
+    
+    handleExitCounts(exit);
+    
+    // 14) Load the result of the last bytecode operation into regT0.
+    
+    if (exit.m_lastSetOperand != std::numeric_limits<int>::max())
+        m_jit.loadPtr(AssemblyHelpers::addressFor((VirtualRegister)exit.m_lastSetOperand), GPRInfo::cachedResultRegister);
+    
+    // 15) Fix call frame(s).
+    
+    ASSERT(m_jit.baselineCodeBlock()->getJITType() == JITCode::BaselineJIT);
+    m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), AssemblyHelpers::addressFor((VirtualRegister)RegisterFile::CodeBlock));
+    
+    for (CodeOrigin codeOrigin = exit.m_codeOrigin; codeOrigin.inlineCallFrame; codeOrigin = codeOrigin.inlineCallFrame->caller) {
+        InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame;
+        CodeBlock* baselineCodeBlock = m_jit.baselineCodeBlockFor(codeOrigin);
+        CodeBlock* baselineCodeBlockForCaller = m_jit.baselineCodeBlockFor(inlineCallFrame->caller);
+        Vector<BytecodeAndMachineOffset>& decodedCodeMap = m_jit.decodedCodeMapFor(baselineCodeBlockForCaller);
+        unsigned returnBytecodeIndex = inlineCallFrame->caller.bytecodeIndex + OPCODE_LENGTH(op_call);
+        BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned, BytecodeAndMachineOffset::getBytecodeIndex>(decodedCodeMap.begin(), decodedCodeMap.size(), returnBytecodeIndex);
+        
+        ASSERT(mapping);
+        ASSERT(mapping->m_bytecodeIndex == returnBytecodeIndex);
+        
+        void* jumpTarget = baselineCodeBlockForCaller->getJITCode().executableAddressAtOffset(mapping->m_machineCodeOffset);
+
+        GPRReg callerFrameGPR;
+        if (inlineCallFrame->caller.inlineCallFrame) {
+            m_jit.addPtr(AssemblyHelpers::TrustedImm32(inlineCallFrame->caller.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister, GPRInfo::regT3);
+            callerFrameGPR = GPRInfo::regT3;
+        } else
+            callerFrameGPR = GPRInfo::callFrameRegister;
+        
+        m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CodeBlock)));
+        m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee->scope()), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ScopeChain)));
+        m_jit.storePtr(callerFrameGPR, AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::CallerFrame)));
+        m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ReturnPC)));
+        m_jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::ArgumentCount)));
+        m_jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->callee.get()), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + RegisterFile::Callee)));
+    }
+    
+    if (exit.m_codeOrigin.inlineCallFrame)
+        m_jit.addPtr(AssemblyHelpers::TrustedImm32(exit.m_codeOrigin.inlineCallFrame->stackOffset * sizeof(EncodedJSValue)), GPRInfo::callFrameRegister);
+    
+    // 16) Jump into the corresponding baseline JIT code.
+    
+    CodeBlock* baselineCodeBlock = m_jit.baselineCodeBlockFor(exit.m_codeOrigin);
+    Vector<BytecodeAndMachineOffset>& decodedCodeMap = m_jit.decodedCodeMapFor(baselineCodeBlock);
+    
+    BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned, BytecodeAndMachineOffset::getBytecodeIndex>(decodedCodeMap.begin(), decodedCodeMap.size(), exit.m_codeOrigin.bytecodeIndex);
+    
+    ASSERT(mapping);
+    ASSERT(mapping->m_bytecodeIndex == exit.m_codeOrigin.bytecodeIndex);
+    
+    void* jumpTarget = baselineCodeBlock->getJITCode().executableAddressAtOffset(mapping->m_machineCodeOffset);
+    
+    ASSERT(GPRInfo::regT1 != GPRInfo::cachedResultRegister);
+    
+    m_jit.move(AssemblyHelpers::TrustedImmPtr(jumpTarget), GPRInfo::regT1);
+    
+    m_jit.jump(GPRInfo::regT1);
+
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("-> %p\n", jumpTarget);
+#endif
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT) && USE(JSVALUE64)
index a310d229602c17ef8f36bb664c5775ebf5721de6..25172d00f7d3a8c6bf59a4f81275c165b100ca86 100644 (file)
 #include "config.h"
 #include "DFGOperations.h"
 
 #include "config.h"
 #include "DFGOperations.h"
 
-#if ENABLE(DFG_JIT)
-
 #include "CodeBlock.h"
 #include "CodeBlock.h"
+#include "DFGOSRExit.h"
+#include "DFGRepatch.h"
+#include "HostCallReturnValue.h"
+#include "GetterSetter.h"
+#include <wtf/InlineASM.h>
 #include "Interpreter.h"
 #include "Interpreter.h"
-#include "JSByteArray.h"
+#include "JITExceptions.h"
+#include "JSActivation.h"
 #include "JSGlobalData.h"
 #include "JSGlobalData.h"
+#include "JSStaticScopeObject.h"
 #include "Operations.h"
 
 #include "Operations.h"
 
+#if ENABLE(DFG_JIT)
+
+#if CPU(X86_64)
+
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, register) \
+    asm( \
+    ".globl " SYMBOL_STRING(function) "\n" \
+    HIDE_SYMBOL(function) "\n" \
+    SYMBOL_STRING(function) ":" "\n" \
+        "mov (%rsp), %" STRINGIZE(register) "\n" \
+        "jmp " SYMBOL_STRING_RELOCATION(function##WithReturnAddress) "\n" \
+    );
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function)    FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rsi)
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function)  FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)  FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, r8)
+
+#elif CPU(X86)
+
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, offset) \
+    asm( \
+    ".text" "\n" \
+    ".globl " SYMBOL_STRING(function) "\n" \
+    HIDE_SYMBOL(function) "\n" \
+    SYMBOL_STRING(function) ":" "\n" \
+        "mov (%esp), %eax\n" \
+        "mov %eax, " STRINGIZE(offset) "(%esp)\n" \
+        "jmp " SYMBOL_STRING_RELOCATION(function##WithReturnAddress) "\n" \
+    );
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function)    FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 8)
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function)  FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 16)
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)  FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 20)
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 24)
+
+#elif COMPILER(GCC) && CPU(ARM_THUMB2)
+
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
+    asm ( \
+    ".text" "\n" \
+    ".align 2" "\n" \
+    ".globl " SYMBOL_STRING(function) "\n" \
+    HIDE_SYMBOL(function) "\n" \
+    ".thumb" "\n" \
+    ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
+    SYMBOL_STRING(function) ":" "\n" \
+        "mov a2, lr" "\n" \
+        "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+    );
+
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
+    asm ( \
+    ".text" "\n" \
+    ".align 2" "\n" \
+    ".globl " SYMBOL_STRING(function) "\n" \
+    HIDE_SYMBOL(function) "\n" \
+    ".thumb" "\n" \
+    ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
+    SYMBOL_STRING(function) ":" "\n" \
+        "mov a4, lr" "\n" \
+        "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+    );
+
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
+    asm ( \
+    ".text" "\n" \
+    ".align 2" "\n" \
+    ".globl " SYMBOL_STRING(function) "\n" \
+    HIDE_SYMBOL(function) "\n" \
+    ".thumb" "\n" \
+    ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
+    SYMBOL_STRING(function) ":" "\n" \
+        "str lr, [sp, #0]" "\n" \
+        "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+    );
+
+#define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
+    asm ( \
+    ".text" "\n" \
+    ".align 2" "\n" \
+    ".globl " SYMBOL_STRING(function) "\n" \
+    HIDE_SYMBOL(function) "\n" \
+    ".thumb" "\n" \
+    ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
+    SYMBOL_STRING(function) ":" "\n" \
+        "str lr, [sp, #4]" "\n" \
+        "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
+    );
+
+#endif
+
+#define P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
+void* DFG_OPERATION function##WithReturnAddress(ExecState*, ReturnAddressPtr); \
+FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function)
+
+#define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
+EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, JSCell*, Identifier*, ReturnAddressPtr); \
+FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function)
+
+#define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
+EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr); \
+FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)
+
+#define V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
+void DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, JSCell*, Identifier*, ReturnAddressPtr); \
+FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function)
+
 namespace JSC { namespace DFG {
 
 namespace JSC { namespace DFG {
 
-EncodedJSValue operationConvertThis(ExecState* exec, EncodedJSValue encodedOp)
+template<bool strict>
+static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value)
+{
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+    
+    if (isJSArray(baseValue)) {
+        JSArray* array = asArray(baseValue);
+        if (array->canSetIndex(index)) {
+            array->setIndex(globalData, index, value);
+            return;
+        }
+
+        JSArray::putByIndex(array, exec, index, value, strict);
+        return;
+    }
+
+    baseValue.putByIndex(exec, index, value, strict);
+}
+
+template<bool strict>
+ALWAYS_INLINE static void DFG_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
 {
 {
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+
+    JSValue baseValue = JSValue::decode(encodedBase);
+    JSValue property = JSValue::decode(encodedProperty);
+    JSValue value = JSValue::decode(encodedValue);
+
+    if (LIKELY(property.isUInt32())) {
+        putByVal<strict>(exec, baseValue, property.asUInt32(), value);
+        return;
+    }
+
+    if (property.isDouble()) {
+        double propertyAsDouble = property.asDouble();
+        uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
+        if (propertyAsDouble == propertyAsUInt32) {
+            putByVal<strict>(exec, baseValue, propertyAsUInt32, value);
+            return;
+        }
+    }
+
+
+    // Don't put to an object if toString throws an exception.
+    Identifier ident(exec, property.toString(exec)->value(exec));
+    if (!globalData->exception) {
+        PutPropertySlot slot(strict);
+        baseValue.put(exec, ident, value, slot);
+    }
+}
+
+extern "C" {
+
+EncodedJSValue DFG_OPERATION operationConvertThis(ExecState* exec, EncodedJSValue encodedOp)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+
     return JSValue::encode(JSValue::decode(encodedOp).toThisObject(exec));
 }
 
     return JSValue::encode(JSValue::decode(encodedOp).toThisObject(exec));
 }
 
-EncodedJSValue operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+inline JSCell* createThis(ExecState* exec, JSCell* prototype, JSFunction* constructor)
 {
 {
+#if !ASSERT_DISABLED
+    ConstructData constructData;
+    ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
+#endif
+    
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+
+    Structure* structure;
+    if (prototype->isObject())
+        structure = asObject(prototype)->inheritorID(globalData);
+    else
+        structure = constructor->scope()->globalObject->emptyObjectStructure();
+    
+    return constructEmptyObject(exec, structure);
+}
+
+JSCell* DFG_OPERATION operationCreateThis(ExecState* exec, JSCell* prototype)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+
+    return createThis(exec, prototype, jsCast<JSFunction*>(exec->callee()));
+}
+
+JSCell* DFG_OPERATION operationCreateThisInlined(ExecState* exec, JSCell* prototype, JSCell* constructor)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    return createThis(exec, prototype, jsCast<JSFunction*>(constructor));
+}
+
+JSCell* DFG_OPERATION operationNewObject(ExecState* exec)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    return constructEmptyObject(exec);
+}
+
+EncodedJSValue DFG_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
     JSValue op1 = JSValue::decode(encodedOp1);
     JSValue op2 = JSValue::decode(encodedOp2);
+    
+    return JSValue::encode(jsAdd(exec, op1, op2));
+}
 
 
-    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));
-    }
+EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
     
     
-    double number1;
-    double number2;
-    if (op1.getNumber(number1) && op2.getNumber(number2))
-        return JSValue::encode(jsNumber(number1 + number2));
+    JSValue op1 = JSValue::decode(encodedOp1);
+    JSValue op2 = JSValue::decode(encodedOp2);
+    
+    ASSERT(!op1.isNumber() || !op2.isNumber());
+    
+    if (op1.isString() && !op2.isObject())
+        return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
 
     return JSValue::encode(jsAddSlowCase(exec, op1, op2));
 }
 
 
     return JSValue::encode(jsAddSlowCase(exec, op1, op2));
 }
 
-EncodedJSValue operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
+static inline EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
+{
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+    
+    // FIXME: the JIT used to handle these in compiled code!
+    if (isJSArray(base) && asArray(base)->canGetIndex(index))
+        return JSValue::encode(asArray(base)->getIndex(index));
+
+    // FIXME: the JITstub used to relink this to an optimized form!
+    if (isJSString(base) && asString(base)->canGetIndex(index))
+        return JSValue::encode(asString(base)->getIndex(exec, index));
+
+    return JSValue::encode(JSValue(base).get(exec, index));
+}
+
+EncodedJSValue DFG_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
 {
 {
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
     JSValue baseValue = JSValue::decode(encodedBase);
     JSValue property = JSValue::decode(encodedProperty);
 
     JSValue baseValue = JSValue::decode(encodedBase);
     JSValue property = JSValue::decode(encodedProperty);
 
@@ -71,175 +308,913 @@ EncodedJSValue operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, En
         JSCell* base = baseValue.asCell();
 
         if (property.isUInt32()) {
         JSCell* base = baseValue.asCell();
 
         if (property.isUInt32()) {
-            JSGlobalData* globalData = &exec->globalData();
-            uint32_t i = property.asUInt32();
+            return getByVal(exec, base, property.asUInt32());
+        } else if (property.isDouble()) {
+            double propertyAsDouble = property.asDouble();
+            uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
+            if (propertyAsUInt32 == propertyAsDouble)
+                return getByVal(exec, base, propertyAsUInt32);
+        } else if (property.isString()) {
+            if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
+                return JSValue::encode(result);
+        }
+    }
 
 
-            // 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));
+    Identifier ident(exec, property.toString(exec)->value(exec));
+    return JSValue::encode(baseValue.get(exec, ident));
+}
 
 
-            // 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));
+EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue property = JSValue::decode(encodedProperty);
 
 
-            // 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));
+    if (property.isUInt32())
+        return getByVal(exec, base, property.asUInt32());
+    if (property.isDouble()) {
+        double propertyAsDouble = property.asDouble();
+        uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
+        if (propertyAsUInt32 == propertyAsDouble)
+            return getByVal(exec, base, propertyAsUInt32);
+    } else if (property.isString()) {
+        if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
+            return JSValue::encode(result);
+    }
 
 
-            return JSValue::encode(baseValue.get(exec, i));
-        }
+    Identifier ident(exec, property.toString(exec)->value(exec));
+    return JSValue::encode(JSValue(base).get(exec, ident));
+}
 
 
-        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));
-        }
-    }
+EncodedJSValue DFG_OPERATION operationGetById(ExecState* exec, EncodedJSValue base, Identifier* propertyName)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue baseValue = JSValue::decode(base);
+    PropertySlot slot(baseValue);
+    return JSValue::encode(baseValue.get(exec, *propertyName, slot));
+}
 
 
-    Identifier ident(exec, property.toString(exec));
-    return JSValue::encode(baseValue.get(exec, ident));
+J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdBuildList);
+EncodedJSValue DFG_OPERATION operationGetByIdBuildListWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue baseValue = JSValue::decode(base);
+    PropertySlot slot(baseValue);
+    JSValue result = baseValue.get(exec, *propertyName, slot);
+
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    dfgBuildGetByIDList(exec, baseValue, *propertyName, slot, stubInfo);
+
+    return JSValue::encode(result);
 }
 
 }
 
-EncodedJSValue operationGetById(ExecState* exec, EncodedJSValue encodedBase, Identifier* identifier)
+J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdProtoBuildList);
+EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildListWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
 {
 {
-    JSValue baseValue = JSValue::decode(encodedBase);
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue baseValue = JSValue::decode(base);
     PropertySlot slot(baseValue);
     PropertySlot slot(baseValue);
-    return JSValue::encode(baseValue.get(exec, *identifier, slot));
+    JSValue result = baseValue.get(exec, *propertyName, slot);
+
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    dfgBuildGetByIDProtoList(exec, baseValue, *propertyName, slot, stubInfo);
+
+    return JSValue::encode(result);
 }
 
 }
 
-template<bool strict>
-ALWAYS_INLINE static void operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdOptimize);
+EncodedJSValue DFG_OPERATION operationGetByIdOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
 {
     JSGlobalData* globalData = &exec->globalData();
 {
     JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue baseValue = JSValue::decode(base);
+    PropertySlot slot(baseValue);
+    JSValue result = baseValue.get(exec, *propertyName, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    if (stubInfo.seen)
+        dfgRepatchGetByID(exec, baseValue, *propertyName, slot, stubInfo);
+    else
+        stubInfo.seen = true;
 
 
-    JSValue baseValue = JSValue::decode(encodedBase);
-    JSValue property = JSValue::decode(encodedProperty);
-    JSValue value = JSValue::decode(encodedValue);
+    return JSValue::encode(result);
+}
 
 
-    if (LIKELY(property.isUInt32())) {
-        uint32_t i = property.asUInt32();
+EncodedJSValue DFG_OPERATION operationCallCustomGetter(ExecState* exec, JSCell* base, PropertySlot::GetValueFunc function, Identifier* ident)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    return JSValue::encode(function(exec, asObject(base), *ident));
+}
 
 
-        if (isJSArray(globalData, baseValue)) {
-            JSArray* jsArray = asArray(baseValue);
-            if (jsArray->canSetIndex(i)) {
-                jsArray->setIndex(*globalData, i, value);
-                return;
-            }
+EncodedJSValue DFG_OPERATION operationCallGetter(ExecState* exec, JSCell* base, JSCell* value)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    GetterSetter* getterSetter = asGetterSetter(value);
+    JSObject* getter = getterSetter->getter();
+    if (!getter)
+        return JSValue::encode(jsUndefined());
+    CallData callData;
+    CallType callType = getter->methodTable()->getCallData(getter, callData);
+    return JSValue::encode(call(exec, getter, callType, callData, asObject(base), ArgList()));
+}
 
 
-            jsArray->JSArray::put(exec, i, value);
-            return;
-        }
+void DFG_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue);
+}
 
 
-        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;
-            }
-        }
+void DFG_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
+}
+
+void DFG_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    operationPutByValInternal<true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
+}
+
+void DFG_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    operationPutByValInternal<false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
+}
+
+void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    if (index >= 0) {
+        // We should only get here if index is outside the existing vector.
+        ASSERT(!array->canSetIndex(index));
+        JSArray::putByIndex(array, exec, index, JSValue::decode(encodedValue), true);
+        return;
+    }
+    
+    PutPropertySlot slot(true);
+    array->methodTable()->put(
+        array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
+}
 
 
-        baseValue.put(exec, i, value);
+void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    if (index >= 0) {
+        // We should only get here if index is outside the existing vector.
+        ASSERT(!array->canSetIndex(index));
+        JSArray::putByIndex(array, exec, index, JSValue::decode(encodedValue), false);
         return;
     }
         return;
     }
+    
+    PutPropertySlot slot(false);
+    array->methodTable()->put(
+        array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
+}
 
 
-    // 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);
+EncodedJSValue DFG_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    array->push(exec, JSValue::decode(encodedValue));
+    return JSValue::encode(jsNumber(array->length()));
+}
+
+EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState* exec, JSCell* base, JSCell* argument)
+{
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+    
+    if (!base->inherits(&RegExpObject::s_info))
+        return throwVMTypeError(exec);
+
+    ASSERT(argument->isString() || argument->isObject());
+    JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec);
+    return JSValue::encode(asRegExpObject(base)->exec(exec, input));
+}
+        
+size_t DFG_OPERATION operationRegExpTest(ExecState* exec, JSCell* base, JSCell* argument)
+{
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+
+    if (!base->inherits(&RegExpObject::s_info)) {
+        throwTypeError(exec);
+        return false;
     }
     }
+
+    ASSERT(argument->isString() || argument->isObject());
+    JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec);
+    return asRegExpObject(base)->test(exec, input);
+}
+        
+EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    return JSValue::encode(array->pop(exec));
+}
+        
+void DFG_OPERATION operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    PutPropertySlot slot(true);
+    base->methodTable()->put(base, exec, *propertyName, JSValue::decode(encodedValue), slot);
 }
 
 }
 
-void operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+void DFG_OPERATION operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
 {
 {
-    operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue);
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    PutPropertySlot slot(false);
+    base->methodTable()->put(base, exec, *propertyName, JSValue::decode(encodedValue), slot);
 }
 
 }
 
-void operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+void DFG_OPERATION operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
 {
 {
-    operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    PutPropertySlot slot(true);
+    ASSERT(base->isObject());
+    asObject(base)->putDirect(exec->globalData(), *propertyName, JSValue::decode(encodedValue), slot);
+}
+
+void DFG_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    PutPropertySlot slot(false);
+    ASSERT(base->isObject());
+    asObject(base)->putDirect(exec->globalData(), *propertyName, JSValue::decode(encodedValue), slot);
+}
+
+V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdStrictOptimize);
+void DFG_OPERATION operationPutByIdStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue value = JSValue::decode(encodedValue);
+    JSValue baseValue(base);
+    PutPropertySlot slot(true);
+    
+    baseValue.put(exec, *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    if (stubInfo.seen)
+        dfgRepatchPutByID(exec, baseValue, *propertyName, slot, stubInfo, NotDirect);
+    else
+        stubInfo.seen = true;
+}
+
+V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdNonStrictOptimize);
+void DFG_OPERATION operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue value = JSValue::decode(encodedValue);
+    JSValue baseValue(base);
+    PutPropertySlot slot(false);
+    
+    baseValue.put(exec, *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    if (stubInfo.seen)
+        dfgRepatchPutByID(exec, baseValue, *propertyName, slot, stubInfo, NotDirect);
+    else
+        stubInfo.seen = true;
+}
+
+V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectStrictOptimize);
+void DFG_OPERATION operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue value = JSValue::decode(encodedValue);
+    PutPropertySlot slot(true);
+    
+    ASSERT(base->isObject());
+    asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    if (stubInfo.seen)
+        dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct);
+    else
+        stubInfo.seen = true;
+}
+
+V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectNonStrictOptimize);
+void DFG_OPERATION operationPutByIdDirectNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue value = JSValue::decode(encodedValue);
+    PutPropertySlot slot(false);
+    
+    ASSERT(base->isObject());
+    asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    if (stubInfo.seen)
+        dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct);
+    else
+        stubInfo.seen = true;
 }
 
 }
 
-void operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdStrictBuildList);
+void DFG_OPERATION operationPutByIdStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
 {
 {
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue value = JSValue::decode(encodedValue);
+    JSValue baseValue(base);
     PutPropertySlot slot(true);
     PutPropertySlot slot(true);
-    JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot);
+    
+    baseValue.put(exec, *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    dfgBuildPutByIdList(exec, baseValue, *propertyName, slot, stubInfo, NotDirect);
 }
 
 }
 
-void operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdNonStrictBuildList);
+void DFG_OPERATION operationPutByIdNonStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
 {
 {
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue value = JSValue::decode(encodedValue);
+    JSValue baseValue(base);
     PutPropertySlot slot(false);
     PutPropertySlot slot(false);
-    JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot);
+    
+    baseValue.put(exec, *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    dfgBuildPutByIdList(exec, baseValue, *propertyName, slot, stubInfo, NotDirect);
 }
 
 }
 
-void operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectStrictBuildList);
+void DFG_OPERATION operationPutByIdDirectStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
 {
 {
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue value = JSValue::decode(encodedValue);
     PutPropertySlot slot(true);
     PutPropertySlot slot(true);
-    JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot);
+    
+    ASSERT(base->isObject());
+    asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    dfgBuildPutByIdList(exec, base, *propertyName, slot, stubInfo, Direct);
 }
 
 }
 
-void operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectNonStrictBuildList);
+void DFG_OPERATION operationPutByIdDirectNonStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
 {
 {
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue value = JSValue::decode(encodedValue);
     PutPropertySlot slot(false);
     PutPropertySlot slot(false);
-    JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot);
+    
+    ASSERT(base->isObject());
+    asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    dfgBuildPutByIdList(exec, base, *propertyName, slot, stubInfo, Direct);
 }
 
 }
 
-bool operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+size_t DFG_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
 {
-    return jsLess(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    return jsLess<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
 }
 
 }
 
-bool operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+size_t DFG_OPERATION operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
 {
-    return jsLessEq(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    return jsLessEq<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
 }
 
 }
 
-bool operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+size_t DFG_OPERATION operationCompareGreater(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
 {
-    return JSValue::equal(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    return jsLess<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
 }
 
 }
 
-bool operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+size_t DFG_OPERATION operationCompareGreaterEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
 {
-    return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    return jsLessEq<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
 }
 
 }
 
-DFGHandler lookupExceptionHandler(ExecState* exec, ReturnAddressPtr faultLocation)
+size_t DFG_OPERATION operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
 {
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    return JSValue::equalSlowCaseInline(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+}
+
+size_t DFG_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue op1 = JSValue::decode(encodedOp1);
+    JSValue op2 = JSValue::decode(encodedOp2);
+    
+    ASSERT(op1.isCell());
+    ASSERT(op2.isCell());
+    
+    return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
+}
+
+size_t DFG_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+
+    JSValue src1 = JSValue::decode(encodedOp1);
+    JSValue src2 = JSValue::decode(encodedOp2);
+    
+    return JSValue::strictEqual(exec, src1, src2);
+}
+
+static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
+{
+    ExecState* exec = execCallee->callerFrame();
+    JSGlobalData* globalData = &exec->globalData();
+
+    execCallee->setScopeChain(exec->scopeChain());
+    execCallee->setCodeBlock(0);
+    execCallee->clearReturnPC();
+
+    if (kind == CodeForCall) {
+        CallData callData;
+        CallType callType = getCallData(callee, callData);
+    
+        ASSERT(callType != CallTypeJS);
+    
+        if (callType == CallTypeHost) {
+            NativeCallFrameTracer tracer(globalData, execCallee);
+            execCallee->setCallee(asObject(callee));
+            globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
+            if (globalData->exception)
+                return 0;
+
+            return reinterpret_cast<void*>(getHostCallReturnValue);
+        }
+    
+        ASSERT(callType == CallTypeNone);
+        exec->globalData().exception = createNotAFunctionError(exec, callee);
+        return 0;
+    }
+
+    ASSERT(kind == CodeForConstruct);
+    
+    ConstructData constructData;
+    ConstructType constructType = getConstructData(callee, constructData);
+    
+    ASSERT(constructType != ConstructTypeJS);
+    
+    if (constructType == ConstructTypeHost) {
+        NativeCallFrameTracer tracer(globalData, execCallee);
+        execCallee->setCallee(asObject(callee));
+        globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
+        if (globalData->exception)
+            return 0;
+
+        return reinterpret_cast<void*>(getHostCallReturnValue);
+    }
+    
+    ASSERT(constructType == ConstructTypeNone);
+    exec->globalData().exception = createNotAConstructorError(exec, callee);
+    return 0;
+}
+
+inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, CodeSpecializationKind kind)
+{
+    ExecState* exec = execCallee->callerFrame();
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue calleeAsValue = execCallee->calleeAsValue();
+    JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
+    if (!calleeAsFunctionCell)
+        return handleHostCall(execCallee, calleeAsValue, kind);
+
+    JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
+    execCallee->setScopeChain(callee->scopeUnchecked());
+    ExecutableBase* executable = callee->executable();
+
+    MacroAssemblerCodePtr codePtr;
+    CodeBlock* codeBlock = 0;
+    if (executable->isHostFunction())
+        codePtr = executable->generatedJITCodeFor(kind).addressForCall();
+    else {
+        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
+        JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
+        if (error) {
+            globalData->exception = createStackOverflowError(exec);
+            return 0;
+        }
+        codeBlock = &functionExecutable->generatedBytecodeFor(kind);
+        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
+            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
+        else
+            codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
+    }
+    CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress);
+    if (!callLinkInfo.seenOnce())
+        callLinkInfo.setSeen();
+    else
+        dfgLinkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
+    return codePtr.executableAddress();
+}
+
+P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(operationLinkCall);
+void* DFG_OPERATION operationLinkCallWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
+{
+    return linkFor(execCallee, returnAddress, CodeForCall);
+}
+
+P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(operationLinkConstruct);
+void* DFG_OPERATION operationLinkConstructWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
+{
+    return linkFor(execCallee, returnAddress, CodeForConstruct);
+}
+
+inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
+{
+    ExecState* exec = execCallee->callerFrame();
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+
+    JSValue calleeAsValue = execCallee->calleeAsValue();
+    JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
+    if (UNLIKELY(!calleeAsFunctionCell))
+        return handleHostCall(execCallee, calleeAsValue, kind);
+    
+    JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
+    execCallee->setScopeChain(function->scopeUnchecked());
+    ExecutableBase* executable = function->executable();
+    if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
+        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
+        JSObject* error = functionExecutable->compileFor(execCallee, function->scope(), kind);
+        if (error) {
+            exec->globalData().exception = error;
+            return 0;
+        }
+    }
+    return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress();
+}
+
+void* DFG_OPERATION operationVirtualCall(ExecState* execCallee)
+{    
+    return virtualFor(execCallee, CodeForCall);
+}
+
+void* DFG_OPERATION operationVirtualConstruct(ExecState* execCallee)
+{
+    return virtualFor(execCallee, CodeForConstruct);
+}
+
+EncodedJSValue DFG_OPERATION operationResolve(ExecState* exec, Identifier* propertyName)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    ScopeChainNode* scopeChain = exec->scopeChain();
+    ScopeChainIterator iter = scopeChain->begin();
+    ScopeChainIterator end = scopeChain->end();
+    ASSERT(iter != end);
+
+    do {
+        JSObject* record = iter->get();
+        PropertySlot slot(record);
+        if (record->getPropertySlot(exec, *propertyName, slot))
+            return JSValue::encode(slot.getValue(exec, *propertyName));
+    } while (++iter != end);
+
+    return throwVMError(exec, createUndefinedVariableError(exec, *propertyName));
+}
+
+EncodedJSValue DFG_OPERATION operationResolveBase(ExecState* exec, Identifier* propertyName)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    return JSValue::encode(resolveBase(exec, *propertyName, exec->scopeChain(), false));
+}
+
+EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState* exec, Identifier* propertyName)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSValue base = resolveBase(exec, *propertyName, exec->scopeChain(), true);
+    if (!base)
+        throwError(exec, createErrorForInvalidGlobalAssignment(exec, propertyName->ustring()));
+    return JSValue::encode(base);
+}
+
+EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState* exec, GlobalResolveInfo* resolveInfo, Identifier* propertyName)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+
+    PropertySlot slot(globalObject);
+    if (globalObject->getPropertySlot(exec, *propertyName, slot)) {
+        JSValue result = slot.getValue(exec, *propertyName);
+
+        if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
+            resolveInfo->structure.set(exec->globalData(), exec->codeBlock()->ownerExecutable(), globalObject->structure());
+            resolveInfo->offset = slot.cachedOffset();
+        }
+
+        return JSValue::encode(result);
+    }
+
+    return throwVMError(exec, createUndefinedVariableError(exec, *propertyName));
+}
+
+EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
+}
+
+EncodedJSValue DFG_OPERATION operationStrCat(ExecState* exec, void* buffer, size_t size)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+
+    return JSValue::encode(jsString(exec, static_cast<Register*>(buffer), size));
+}
+
+EncodedJSValue DFG_OPERATION operationNewArray(ExecState* exec, void* buffer, size_t size)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+
+    return JSValue::encode(constructArray(exec, static_cast<JSValue*>(buffer), size));
+}
+
+EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState* exec, size_t start, size_t size)
+{
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+    return JSValue::encode(constructArray(exec, exec->codeBlock()->constantBuffer(start), size));
+}
+
+EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr)
+{
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+    RegExp* regexp = static_cast<RegExp*>(regexpPtr);
+    if (!regexp->isValid()) {
+        throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
+        return JSValue::encode(jsUndefined());
+    }
+    
+    return JSValue::encode(RegExpObject::create(exec->globalData(), exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regexp));
+}
+
+JSCell* DFG_OPERATION operationCreateActivation(ExecState* exec)
+{
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+    JSActivation* activation = JSActivation::create(
+        globalData, exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable()));
+    exec->setScopeChain(exec->scopeChain()->push(activation));
+    return activation;
+}
+
+void DFG_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activation)
+{
+    ASSERT(activation);
+    ASSERT(activation->inherits(&JSActivation::s_info));
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+    jsCast<JSActivation*>(activation)->tearOff(exec->globalData());
+}
+
+JSCell* DFG_OPERATION operationNewFunction(ExecState* exec, JSCell* functionExecutable)
+{
+    ASSERT(functionExecutable->inherits(&FunctionExecutable::s_info));
+    JSGlobalData& globalData = exec->globalData();
+    NativeCallFrameTracer tracer(&globalData, exec);
+    return static_cast<FunctionExecutable*>(functionExecutable)->make(exec, exec->scopeChain());
+}
+
+JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState* exec, JSCell* functionExecutableAsCell)
+{
+    ASSERT(functionExecutableAsCell->inherits(&FunctionExecutable::s_info));
+    FunctionExecutable* functionExecutable =
+        static_cast<FunctionExecutable*>(functionExecutableAsCell);
+    JSFunction *function = functionExecutable->make(exec, exec->scopeChain());
+    if (!functionExecutable->name().isNull()) {
+        JSStaticScopeObject* functionScopeObject =
+            JSStaticScopeObject::create(
+                exec, functionExecutable->name(), function, ReadOnly | DontDelete);
+        function->setScope(exec->globalData(), function->scope()->push(functionScopeObject));
+    }
+    return function;
+}
+
+size_t DFG_OPERATION operationIsObject(EncodedJSValue value)
+{
+    return jsIsObjectType(JSValue::decode(value));
+}
+
+size_t DFG_OPERATION operationIsFunction(EncodedJSValue value)
+{
+    return jsIsFunctionType(JSValue::decode(value));
+}
+
+double DFG_OPERATION operationFModOnInts(int32_t a, int32_t b)
+{
+    return fmod(a, b);
+}
+
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState* exec, uint32_t callIndex)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+
     JSValue exceptionValue = exec->exception();
     ASSERT(exceptionValue);
     JSValue exceptionValue = exec->exception();
     ASSERT(exceptionValue);
+    
+    unsigned vPCIndex = exec->codeBlock()->bytecodeOffsetForCallAtIndex(callIndex);
+    ExceptionHandler handler = genericThrow(globalData, exec, exceptionValue, vPCIndex);
+    ASSERT(handler.catchRoutine);
+    return dfgHandlerEncoded(handler.callFrame, handler.catchRoutine);
+}
 
 
-    unsigned vPCIndex = exec->codeBlock()->bytecodeOffset(faultLocation);
-    HandlerInfo* handler = exec->globalData().interpreter->throwException(exec, exceptionValue, vPCIndex);
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState* exec, StructureStubInfo* stubInfo)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
 
 
-    void* catchRoutine = handler ? handler->nativeCode.executableAddress() : (void*)ctiOpThrowNotCaught;
-    ASSERT(catchRoutine);
-    return DFGHandler(exec, catchRoutine);
+    JSValue exceptionValue = exec->exception();
+    ASSERT(exceptionValue);
+    
+    CodeOrigin codeOrigin = stubInfo->codeOrigin;
+    while (codeOrigin.inlineCallFrame)
+        codeOrigin = codeOrigin.inlineCallFrame->caller;
+    
+    ExceptionHandler handler = genericThrow(globalData, exec, exceptionValue, codeOrigin.bytecodeIndex);
+    ASSERT(handler.catchRoutine);
+    return dfgHandlerEncoded(handler.callFrame, handler.catchRoutine);
 }
 
 }
 
-double dfgConvertJSValueToNumber(ExecState* exec, EncodedJSValue value)
+double DFG_OPERATION dfgConvertJSValueToNumber(ExecState* exec, EncodedJSValue value)
 {
 {
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
     return JSValue::decode(value).toNumber(exec);
 }
 
     return JSValue::decode(value).toNumber(exec);
 }
 
-int32_t dfgConvertJSValueToInt32(ExecState* exec, EncodedJSValue value)
+size_t DFG_OPERATION dfgConvertJSValueToInt32(ExecState* exec, EncodedJSValue value)
 {
 {
-    return JSValue::decode(value).toInt32(exec);
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    // toInt32/toUInt32 return the same value; we want the value zero extended to fill the register.
+    return JSValue::decode(value).toUInt32(exec);
 }
 
 }
 
-bool dfgConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
+size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
 {
 {
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
     return JSValue::decode(encodedOp).toBoolean(exec);
 }
 
     return JSValue::decode(encodedOp).toBoolean(exec);
 }
 
+#if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE)
+void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+    
+    SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
+    CodeBlock* codeBlock = debugInfo->codeBlock;
+    CodeBlock* alternative = codeBlock->alternative();
+    dataLog("Speculation failure in %p at @%u with executeCounter = %d, "
+            "reoptimizationRetryCounter = %u, optimizationDelayCounter = %u, "
+            "success/fail %u/(%u+%u)\n",
+            codeBlock,
+            debugInfo->nodeIndex,
+            alternative ? alternative->jitExecuteCounter() : 0,
+            alternative ? alternative->reoptimizationRetryCounter() : 0,
+            alternative ? alternative->optimizationDelayCounter() : 0,
+            codeBlock->speculativeSuccessCounter(),
+            codeBlock->speculativeFailCounter(),
+            codeBlock->forcedOSRExitCounter());
+}
+#endif
+
+} // extern "C"
 } } // namespace JSC::DFG
 
 #endif
 } } // namespace JSC::DFG
 
 #endif
+
+#if COMPILER(GCC)
+
+namespace JSC {
+
+#if CPU(X86_64)
+asm (
+".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
+SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+    "mov -40(%r13), %r13\n"
+    "mov %r13, %rdi\n"
+    "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+);
+#elif CPU(X86)
+asm (
+".text" "\n" \
+".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
+SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+    "mov -40(%edi), %edi\n"
+    "mov %edi, 4(%esp)\n"
+    "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+);
+#elif CPU(ARM_THUMB2)
+asm (
+".text" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
+HIDE_SYMBOL(getHostCallReturnValue) "\n"
+".thumb" "\n"
+".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
+SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
+    "ldr r5, [r5, #-40]" "\n"
+    "mov r0, r5" "\n"
+    "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
+);
+#endif
+
+extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState* exec)
+{
+    if (!exec)
+        return JSValue::encode(JSValue());
+    return JSValue::encode(exec->globalData().hostCallReturnValue);
+}
+
+} // namespace JSC
+
+#endif // COMPILER(GCC)
+
index d4c7c0feb96dba155a52d208b1c5df71d082f562..5da754a26f732a2de927be161f3f99a9c26b2a18 100644 (file)
 
 #if ENABLE(DFG_JIT)
 
 
 #if ENABLE(DFG_JIT)
 
-#include <dfg/DFGJITCompiler.h>
+#include "DFGJITCompiler.h"
+#include "PutKind.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
-class Identifier;
+struct GlobalResolveInfo;
 
 namespace DFG {
 
 
 namespace DFG {
 
+extern "C" {
+
+#if CALLING_CONVENTION_IS_STDCALL
+#define DFG_OPERATION CDECL
+#else
+#define DFG_OPERATION
+#endif
+
 // These typedefs provide typechecking when generating calls out to helper routines;
 // this helps prevent calling a helper routine with the wrong arguments!
 // 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);
+/*
+    Key:
+    V: void
+    J: JSValue
+    P: pointer (void*)
+    C: JSCell*
+    A: JSArray*
+    S: size_t
+    Z: int32_t
+    D: double
+    I: Identifier*
+    G: GlobalResolveInfo*
+*/
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EA)(ExecState*, JSArray*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECI)(ExecState*, JSCell*, Identifier*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EGI)(ExecState*, GlobalResolveInfo*, Identifier*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EI)(ExecState*, Identifier*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJ)(ExecState*, EncodedJSValue);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJA)(ExecState*, EncodedJSValue, JSArray*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJI)(ExecState*, EncodedJSValue, Identifier*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJP)(ExecState*, EncodedJSValue, void*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EP)(ExecState*, void*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPP)(ExecState*, void*, void*);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPS)(ExecState*, void*, size_t);
+typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ESS)(ExecState*, size_t, size_t);
+typedef JSCell* DFG_OPERATION (*C_DFGOperation_E)(ExecState*);
+typedef JSCell* DFG_OPERATION (*C_DFGOperation_EC)(ExecState*, JSCell*);
+typedef JSCell* DFG_OPERATION (*C_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*);
+typedef double DFG_OPERATION (*D_DFGOperation_DD)(double, double);
+typedef double DFG_OPERATION (*D_DFGOperation_ZZ)(int32_t, int32_t);
+typedef double DFG_OPERATION (*D_DFGOperation_EJ)(ExecState*, EncodedJSValue);
+typedef int32_t DFG_OPERATION (*Z_DFGOperation_D)(double);
+typedef size_t DFG_OPERATION (*S_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*);
+typedef size_t DFG_OPERATION (*S_DFGOperation_EJ)(ExecState*, EncodedJSValue);
+typedef size_t DFG_OPERATION (*S_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
+typedef size_t DFG_OPERATION (*S_DFGOperation_J)(EncodedJSValue);
+typedef void DFG_OPERATION (*V_DFGOperation_EAZJ)(ExecState*, JSArray*, int32_t, EncodedJSValue);
+typedef void DFG_OPERATION (*V_DFGOperation_ECJJ)(ExecState*, JSCell*, EncodedJSValue, EncodedJSValue);
+typedef void DFG_OPERATION (*V_DFGOperation_EJCI)(ExecState*, EncodedJSValue, JSCell*, Identifier*);
+typedef void DFG_OPERATION (*V_DFGOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
+typedef void DFG_OPERATION (*V_DFGOperation_EJPP)(ExecState*, EncodedJSValue, EncodedJSValue, void*);
+typedef void DFG_OPERATION (*V_DFGOperation_EPZJ)(ExecState*, void*, int32_t, EncodedJSValue);
+typedef void DFG_OPERATION (V_DFGOperation_EC)(ExecState*, JSCell*);
+typedef void* DFG_OPERATION (*P_DFGOperation_E)(ExecState*);
 
 // These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
 
 // 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);
+JSCell* DFG_OPERATION operationNewObject(ExecState*);
+JSCell* DFG_OPERATION operationCreateThis(ExecState*, JSCell* encodedOp1);
+JSCell* DFG_OPERATION operationCreateThisInlined(ExecState*, JSCell* encodedOp1, JSCell* constructor);
+EncodedJSValue DFG_OPERATION operationConvertThis(ExecState*, EncodedJSValue encodedOp1);
+EncodedJSValue DFG_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+EncodedJSValue DFG_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty);
+EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty);
+EncodedJSValue DFG_OPERATION operationGetById(ExecState*, EncodedJSValue, Identifier*);
+EncodedJSValue DFG_OPERATION operationGetByIdBuildList(ExecState*, EncodedJSValue, Identifier*);
+EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildList(ExecState*, EncodedJSValue, Identifier*);
+EncodedJSValue DFG_OPERATION operationGetByIdOptimize(ExecState*, EncodedJSValue, Identifier*);
+EncodedJSValue DFG_OPERATION operationCallCustomGetter(ExecState*, JSCell*, PropertySlot::GetValueFunc, Identifier*);
+EncodedJSValue DFG_OPERATION operationCallGetter(ExecState*, JSCell*, JSCell*);
+EncodedJSValue DFG_OPERATION operationResolve(ExecState*, Identifier*);
+EncodedJSValue DFG_OPERATION operationResolveBase(ExecState*, Identifier*);
+EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState*, Identifier*);
+EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState*, GlobalResolveInfo*, Identifier*);
+EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState*, EncodedJSValue);
+EncodedJSValue DFG_OPERATION operationStrCat(ExecState*, void*, size_t);
+EncodedJSValue DFG_OPERATION operationNewArray(ExecState*, void*, size_t);
+EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState*, size_t, size_t);
+EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState*, void*);
+void DFG_OPERATION operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
+void DFG_OPERATION operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
+void DFG_OPERATION operationPutByValCellStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
+void DFG_OPERATION operationPutByValCellNonStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
+void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue);
+void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue);
+EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*);
+EncodedJSValue DFG_OPERATION operationArrayPop(ExecState*, JSArray*);
+EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState*, JSCell*, JSCell*);
+void DFG_OPERATION operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+void DFG_OPERATION operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+void DFG_OPERATION operationPutByIdDirectStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+void DFG_OPERATION operationPutByIdDirectNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+void DFG_OPERATION operationPutByIdStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+void DFG_OPERATION operationPutByIdNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+void DFG_OPERATION operationPutByIdDirectStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+void DFG_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+void DFG_OPERATION operationPutByIdStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+void DFG_OPERATION operationPutByIdNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+void DFG_OPERATION operationPutByIdDirectStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+void DFG_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*);
+// These comparisons return a boolean within a size_t such that the value is zero extended to fill the register.
+size_t DFG_OPERATION operationRegExpTest(ExecState*, JSCell*, JSCell*);
+size_t DFG_OPERATION operationCompareLess(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+size_t DFG_OPERATION operationCompareLessEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+size_t DFG_OPERATION operationCompareGreater(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+size_t DFG_OPERATION operationCompareGreaterEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+size_t DFG_OPERATION operationCompareEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+size_t DFG_OPERATION operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+size_t DFG_OPERATION operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+void* DFG_OPERATION operationVirtualCall(ExecState*);
+void* DFG_OPERATION operationLinkCall(ExecState*);
+void* DFG_OPERATION operationVirtualConstruct(ExecState*);
+void* DFG_OPERATION operationLinkConstruct(ExecState*);
+JSCell* DFG_OPERATION operationCreateActivation(ExecState*);
+void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*);
+JSCell* DFG_OPERATION operationNewFunction(ExecState*, JSCell*);
+JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState*, JSCell*);
+double DFG_OPERATION operationFModOnInts(int32_t, int32_t);
+size_t DFG_OPERATION operationIsObject(EncodedJSValue);
+size_t DFG_OPERATION operationIsFunction(EncodedJSValue);
 
 // 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.
 
 // 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.
+
+// According to C++ rules, a type used for the return signature of function with C linkage (i.e.
+// 'extern "C"') needs to be POD; hence putting any constructors into it could cause either compiler
+// warnings, or worse, a change in the ABI used to return these types.
 struct DFGHandler {
 struct DFGHandler {
-    DFGHandler(ExecState* exec, void* handler)
-        : exec(exec)
-        , handler(handler)
-    {
-    }
-
-    ExecState* exec;
-    void* handler;
+    union Union {
+        struct Struct {
+            ExecState* exec;
+            void* handler;
+        } s;
+        uint64_t encoded;
+    } u;
 };
 };
-DFGHandler lookupExceptionHandler(ExecState*, ReturnAddressPtr faultLocation);
+
+inline DFGHandler createDFGHandler(ExecState* exec, void* handler)
+{
+    DFGHandler result;
+    result.u.s.exec = exec;
+    result.u.s.handler = handler;
+    return result;
+}
+
+#if CPU(X86_64)
+typedef DFGHandler DFGHandlerEncoded;
+inline DFGHandlerEncoded dfgHandlerEncoded(ExecState* exec, void* handler)
+{
+    return createDFGHandler(exec, handler);
+}
+#else
+typedef uint64_t DFGHandlerEncoded;
+inline DFGHandlerEncoded dfgHandlerEncoded(ExecState* exec, void* handler)
+{
+    COMPILE_ASSERT(sizeof(DFGHandler::Union) == sizeof(uint64_t), DFGHandler_Union_is_64bit);
+    return createDFGHandler(exec, handler).u.encoded;
+}
+#endif
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState*, uint32_t);
+DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState*, StructureStubInfo*);
 
 // These operations implement the implicitly called ToInt32, ToNumber, and ToBoolean conversions from ES5.
 
 // 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);
+double DFG_OPERATION dfgConvertJSValueToNumber(ExecState*, EncodedJSValue);
+// This conversion returns an int32_t within a size_t such that the value is zero extended to fill the register.
+size_t DFG_OPERATION dfgConvertJSValueToInt32(ExecState*, EncodedJSValue);
+size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState*, EncodedJSValue);
+
+#if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE)
+void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void*);
+#endif
 
 
+} // extern "C"
 } } // namespace JSC::DFG
 
 #endif
 } } // namespace JSC::DFG
 
 #endif
diff --git a/dfg/DFGPhase.cpp b/dfg/DFGPhase.cpp
new file mode 100644 (file)
index 0000000..bae12b1
--- /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. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED 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 "DFGPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+void Phase::beginPhase()
+{
+    dataLog("Beginning DFG phase %s.\n", m_name);
+    dataLog("Graph before %s:\n", m_name);
+    m_graph.dump();
+}
+
+void Phase::endPhase()
+{
+}
+#endif
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
diff --git a/dfg/DFGPhase.h b/dfg/DFGPhase.h
new file mode 100644 (file)
index 0000000..1d344c0
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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 DFGPhase_h
+#define DFGPhase_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGCommon.h"
+#include "DFGGraph.h"
+
+namespace JSC { namespace DFG {
+
+class Phase {
+public:
+    Phase(Graph& graph, const char* name)
+        : m_graph(graph)
+        , m_name(name)
+    {
+        beginPhase();
+    }
+    
+    ~Phase()
+    {
+        endPhase();
+    }
+    
+    // Each phase must have a run() method.
+    
+protected:
+    // Things you need to have a DFG compiler phase.
+    Graph& m_graph;
+    
+    JSGlobalData& globalData() { return m_graph.m_globalData; }
+    CodeBlock* codeBlock() { return m_graph.m_codeBlock; }
+    CodeBlock* profiledBlock() { return m_graph.m_profiledBlock; }
+    
+    const char* m_name;
+    
+private:
+    // Call these hooks when starting and finishing.
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+    void beginPhase();
+    void endPhase();
+#else // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+    void beginPhase() { }
+    void endPhase() { }
+#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+};
+
+template<typename PhaseType>
+void runPhase(Graph& graph)
+{
+    PhaseType phase(graph);
+    phase.run();
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGPhase_h
+
diff --git a/dfg/DFGPredictionPropagationPhase.cpp b/dfg/DFGPredictionPropagationPhase.cpp
new file mode 100644 (file)
index 0000000..5317460
--- /dev/null
@@ -0,0 +1,843 @@
+/*
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DFGPredictionPropagationPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGGraph.h"
+#include "DFGPhase.h"
+
+namespace JSC { namespace DFG {
+
+class PredictionPropagationPhase : public Phase {
+public:
+    PredictionPropagationPhase(Graph& graph)
+        : Phase(graph, "prediction propagation")
+    {
+    }
+    
+    void run()
+    {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        m_count = 0;
+#endif
+        // 1) propagate predictions
+
+        do {
+            m_changed = false;
+            
+            // Forward propagation is near-optimal for both topologically-sorted and
+            // DFS-sorted code.
+            propagateForward();
+            if (!m_changed)
+                break;
+            
+            // Backward propagation reduces the likelihood that pathological code will
+            // cause slowness. Loops (especially nested ones) resemble backward flow.
+            // This pass captures two cases: (1) it detects if the forward fixpoint
+            // found a sound solution and (2) short-circuits backward flow.
+            m_changed = false;
+            propagateBackward();
+        } while (m_changed);
+        
+        // 2) repropagate predictions while doing double voting.
+
+        do {
+            m_changed = false;
+            doRoundOfDoubleVoting();
+            propagateForward();
+            if (!m_changed)
+                break;
+            
+            m_changed = false;
+            doRoundOfDoubleVoting();
+            propagateBackward();
+        } while (m_changed);
+    }
+    
+private:
+    bool setPrediction(PredictedType prediction)
+    {
+        ASSERT(m_graph[m_compileIndex].hasResult());
+        
+        // setPrediction() is used when we know that there is no way that we can change
+        // our minds about what the prediction is going to be. There is no semantic
+        // difference between setPrediction() and mergePrediction() other than the
+        // increased checking to validate this property.
+        ASSERT(m_graph[m_compileIndex].prediction() == PredictNone || m_graph[m_compileIndex].prediction() == prediction);
+        
+        return m_graph[m_compileIndex].predict(prediction);
+    }
+    
+    bool mergePrediction(PredictedType prediction)
+    {
+        ASSERT(m_graph[m_compileIndex].hasResult());
+        
+        return m_graph[m_compileIndex].predict(prediction);
+    }
+    
+    bool isNotNegZero(NodeIndex nodeIndex)
+    {
+        if (!m_graph.isNumberConstant(nodeIndex))
+            return false;
+        double value = m_graph.valueOfNumberConstant(nodeIndex);
+        return !value && 1.0 / value < 0.0;
+    }
+    
+    bool isNotZero(NodeIndex nodeIndex)
+    {
+        if (!m_graph.isNumberConstant(nodeIndex))
+            return false;
+        return !!m_graph.valueOfNumberConstant(nodeIndex);
+    }
+    
+    void propagate(Node& node)
+    {
+        if (!node.shouldGenerate())
+            return;
+        
+        NodeType op = node.op();
+        NodeFlags flags = node.flags() & NodeBackPropMask;
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("   %s @%u: %s ", Graph::opName(op), m_compileIndex, nodeFlagsAsString(flags));
+#endif
+        
+        bool changed = false;
+        
+        switch (op) {
+        case JSConstant:
+        case WeakJSConstant: {
+            changed |= setPrediction(predictionFromValue(m_graph.valueOfJSConstant(m_compileIndex)));
+            break;
+        }
+            
+        case GetLocal: {
+            VariableAccessData* variableAccessData = node.variableAccessData();
+            PredictedType prediction = variableAccessData->prediction();
+            if (prediction)
+                changed |= mergePrediction(prediction);
+            
+            changed |= variableAccessData->mergeFlags(flags);
+            break;
+        }
+            
+        case SetLocal: {
+            VariableAccessData* variableAccessData = node.variableAccessData();
+            changed |= variableAccessData->predict(m_graph[node.child1()].prediction());
+            changed |= m_graph[node.child1()].mergeFlags(variableAccessData->flags());
+            break;
+        }
+            
+        case Flush: {
+            // Make sure that the analysis knows that flushed locals escape.
+            VariableAccessData* variableAccessData = node.variableAccessData();
+            changed |= variableAccessData->mergeFlags(NodeUsedAsValue);
+            break;
+        }
+            
+        case BitAnd:
+        case BitOr:
+        case BitXor:
+        case BitRShift:
+        case BitLShift:
+        case BitURShift: {
+            changed |= setPrediction(PredictInt32);
+            flags |= NodeUsedAsInt;
+            flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero);
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            changed |= m_graph[node.child2()].mergeFlags(flags);
+            break;
+        }
+            
+        case ValueToInt32: {
+            changed |= setPrediction(PredictInt32);
+            flags |= NodeUsedAsInt;
+            flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero);
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            break;
+        }
+            
+        case ArrayPop: {
+            changed |= mergePrediction(node.getHeapPrediction());
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+
+        case ArrayPush: {
+            changed |= mergePrediction(node.getHeapPrediction());
+            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
+            changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsValue);
+            break;
+        }
+
+        case RegExpExec:
+        case RegExpTest: {
+            changed |= mergePrediction(node.getHeapPrediction());
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+
+        case StringCharCodeAt: {
+            changed |= mergePrediction(PredictInt32);
+            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
+            changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+            break;
+        }
+
+        case ArithMod: {
+            PredictedType left = m_graph[node.child1()].prediction();
+            PredictedType right = m_graph[node.child2()].prediction();
+            
+            if (left && right) {
+                if (isInt32Prediction(mergePredictions(left, right))
+                    && nodeCanSpeculateInteger(node.arithNodeFlags()))
+                    changed |= mergePrediction(PredictInt32);
+                else
+                    changed |= mergePrediction(PredictDouble);
+            }
+            
+            flags |= NodeUsedAsValue;
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            changed |= m_graph[node.child2()].mergeFlags(flags);
+            break;
+        }
+            
+        case UInt32ToNumber: {
+            if (nodeCanSpeculateInteger(node.arithNodeFlags()))
+                changed |= mergePrediction(PredictInt32);
+            else
+                changed |= mergePrediction(PredictNumber);
+            
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            break;
+        }
+
+        case ValueAdd: {
+            PredictedType left = m_graph[node.child1()].prediction();
+            PredictedType right = m_graph[node.child2()].prediction();
+            
+            if (left && right) {
+                if (isNumberPrediction(left) && isNumberPrediction(right)) {
+                    if (m_graph.addShouldSpeculateInteger(node))
+                        changed |= mergePrediction(PredictInt32);
+                    else
+                        changed |= mergePrediction(PredictDouble);
+                } else if (!(left & PredictNumber) || !(right & PredictNumber)) {
+                    // left or right is definitely something other than a number.
+                    changed |= mergePrediction(PredictString);
+                } else
+                    changed |= mergePrediction(PredictString | PredictInt32 | PredictDouble);
+            }
+            
+            if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
+                flags &= ~NodeNeedsNegZero;
+            
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            changed |= m_graph[node.child2()].mergeFlags(flags);
+            break;
+        }
+            
+        case ArithAdd: {
+            PredictedType left = m_graph[node.child1()].prediction();
+            PredictedType right = m_graph[node.child2()].prediction();
+            
+            if (left && right) {
+                if (m_graph.addShouldSpeculateInteger(node))
+                    changed |= mergePrediction(PredictInt32);
+                else
+                    changed |= mergePrediction(PredictDouble);
+            }
+            
+            if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index()))
+                flags &= ~NodeNeedsNegZero;
+            
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            changed |= m_graph[node.child2()].mergeFlags(flags);
+            break;
+        }
+            
+        case ArithSub: {
+            PredictedType left = m_graph[node.child1()].prediction();
+            PredictedType right = m_graph[node.child2()].prediction();
+            
+            if (left && right) {
+                if (m_graph.addShouldSpeculateInteger(node))
+                    changed |= mergePrediction(PredictInt32);
+                else
+                    changed |= mergePrediction(PredictDouble);
+            }
+
+            if (isNotZero(node.child1().index()) || isNotZero(node.child2().index()))
+                flags &= ~NodeNeedsNegZero;
+            
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            changed |= m_graph[node.child2()].mergeFlags(flags);
+            break;
+        }
+            
+        case ArithNegate:
+            if (m_graph[node.child1()].prediction()) {
+                if (m_graph.negateShouldSpeculateInteger(node))
+                    changed |= mergePrediction(PredictInt32);
+                else
+                    changed |= mergePrediction(PredictDouble);
+            }
+
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            break;
+            
+        case ArithMin:
+        case ArithMax: {
+            PredictedType left = m_graph[node.child1()].prediction();
+            PredictedType right = m_graph[node.child2()].prediction();
+            
+            if (left && right) {
+                if (isInt32Prediction(mergePredictions(left, right))
+                    && nodeCanSpeculateInteger(node.arithNodeFlags()))
+                    changed |= mergePrediction(PredictInt32);
+                else
+                    changed |= mergePrediction(PredictDouble);
+            }
+
+            flags |= NodeUsedAsNumber;
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            changed |= m_graph[node.child2()].mergeFlags(flags);
+            break;
+        }
+            
+        case ArithMul:
+        case ArithDiv: {
+            PredictedType left = m_graph[node.child1()].prediction();
+            PredictedType right = m_graph[node.child2()].prediction();
+            
+            if (left && right) {
+                if (isInt32Prediction(mergePredictions(left, right))
+                    && nodeCanSpeculateInteger(node.arithNodeFlags()))
+                    changed |= mergePrediction(PredictInt32);
+                else
+                    changed |= mergePrediction(PredictDouble);
+            }
+
+            // As soon as a multiply happens, we can easily end up in the part
+            // of the double domain where the point at which you do truncation
+            // can change the outcome. So, ArithMul always checks for overflow
+            // no matter what, and always forces its inputs to check as well.
+            
+            flags |= NodeUsedAsNumber | NodeNeedsNegZero;
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            changed |= m_graph[node.child2()].mergeFlags(flags);
+            break;
+        }
+            
+        case ArithSqrt: {
+            changed |= setPrediction(PredictDouble);
+            changed |= m_graph[node.child1()].mergeFlags(flags | NodeUsedAsValue);
+            break;
+        }
+            
+        case ArithAbs: {
+            PredictedType child = m_graph[node.child1()].prediction();
+            if (nodeCanSpeculateInteger(node.arithNodeFlags()))
+                changed |= mergePrediction(child);
+            else
+                changed |= setPrediction(PredictDouble);
+
+            flags &= ~NodeNeedsNegZero;
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            break;
+        }
+            
+        case LogicalNot:
+        case CompareLess:
+        case CompareLessEq:
+        case CompareGreater:
+        case CompareGreaterEq:
+        case CompareEq:
+        case CompareStrictEq:
+        case InstanceOf:
+        case IsUndefined:
+        case IsBoolean:
+        case IsNumber:
+        case IsString:
+        case IsObject:
+        case IsFunction: {
+            changed |= setPrediction(PredictBoolean);
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+            
+        case GetById: {
+            changed |= mergePrediction(node.getHeapPrediction());
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+            
+        case GetByIdFlush:
+            changed |= mergePrediction(node.getHeapPrediction());
+            changed |= mergeDefaultFlags(node);
+            break;
+            
+        case GetByVal: {
+            if (m_graph[node.child1()].shouldSpeculateFloat32Array()
+                || m_graph[node.child1()].shouldSpeculateFloat64Array())
+                changed |= mergePrediction(PredictDouble);
+            else
+                changed |= mergePrediction(node.getHeapPrediction());
+
+            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
+            changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+            break;
+        }
+            
+        case GetPropertyStorage: 
+        case GetIndexedPropertyStorage: {
+            changed |= setPrediction(PredictOther);
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+
+        case GetByOffset: {
+            changed |= mergePrediction(node.getHeapPrediction());
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+            
+        case Call:
+        case Construct: {
+            changed |= mergePrediction(node.getHeapPrediction());
+            for (unsigned childIdx = node.firstChild();
+                 childIdx < node.firstChild() + node.numChildren();
+                 ++childIdx) {
+                Edge edge = m_graph.m_varArgChildren[childIdx];
+                changed |= m_graph[edge].mergeFlags(NodeUsedAsValue);
+            }
+            break;
+        }
+            
+        case ConvertThis: {
+            PredictedType prediction = m_graph[node.child1()].prediction();
+            if (prediction) {
+                if (prediction & ~PredictObjectMask) {
+                    prediction &= PredictObjectMask;
+                    prediction = mergePredictions(prediction, PredictObjectOther);
+                }
+                changed |= mergePrediction(prediction);
+            }
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+            
+        case GetGlobalVar: {
+            changed |= mergePrediction(node.getHeapPrediction());
+            break;
+        }
+            
+        case PutGlobalVar: {
+            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
+            break;
+        }
+            
+        case GetScopedVar:
+        case Resolve:
+        case ResolveBase:
+        case ResolveBaseStrictPut:
+        case ResolveGlobal: {
+            PredictedType prediction = node.getHeapPrediction();
+            changed |= mergePrediction(prediction);
+            break;
+        }
+            
+        case GetScopeChain: {
+            changed |= setPrediction(PredictCellOther);
+            break;
+        }
+            
+        case GetCallee: {
+            changed |= setPrediction(PredictFunction);
+            break;
+        }
+            
+        case CreateThis:
+        case NewObject: {
+            changed |= setPrediction(PredictFinalObject);
+            changed |= mergeDefaultFlags(node);
+            break;
+        }
+            
+        case NewArray: {
+            changed |= setPrediction(PredictArray);
+            for (unsigned childIdx = node.firstChild();
+                 childIdx < node.firstChild() + node.numChildren();
+                 ++childIdx) {
+                Edge edge = m_graph.m_varArgChildren[childIdx];
+                changed |= m_graph[edge].mergeFlags(NodeUsedAsValue);
+            }
+            break;
+        }
+            
+        case NewArrayBuffer: {
+            changed |= setPrediction(PredictArray);
+            break;
+        }
+            
+        case NewRegexp: {
+            changed |= setPrediction(PredictObjectOther);
+            break;
+        }
+        
+        case StringCharAt: {
+            changed |= setPrediction(PredictString);
+            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
+            changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+            break;
+        }
+            
+        case StrCat: {
+            changed |= setPrediction(PredictString);
+            for (unsigned childIdx = node.firstChild();
+                 childIdx < node.firstChild() + node.numChildren();
+                 ++childIdx)
+                changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsNumber);
+            break;
+        }
+            
+        case ToPrimitive: {
+            PredictedType child = m_graph[node.child1()].prediction();
+            if (child) {
+                if (isObjectPrediction(child)) {
+                    // I'd love to fold this case into the case below, but I can't, because
+                    // removing PredictObjectMask from something that only has an object
+                    // prediction and nothing else means we have an ill-formed PredictedType
+                    // (strong predict-none). This should be killed once we remove all traces
+                    // of static (aka weak) predictions.
+                    changed |= mergePrediction(PredictString);
+                } else if (child & PredictObjectMask) {
+                    // Objects get turned into strings. So if the input has hints of objectness,
+                    // the output will have hinsts of stringiness.
+                    changed |= mergePrediction(
+                        mergePredictions(child & ~PredictObjectMask, PredictString));
+                } else
+                    changed |= mergePrediction(child);
+            }
+            changed |= m_graph[node.child1()].mergeFlags(flags);
+            break;
+        }
+            
+        case CreateActivation: {
+            changed |= setPrediction(PredictObjectOther);
+            break;
+        }
+            
+        case NewFunction:
+        case NewFunctionNoCheck:
+        case NewFunctionExpression: {
+            changed |= setPrediction(PredictFunction);
+            break;
+        }
+            
+        case PutByValAlias:
+        case GetArrayLength:
+        case GetInt8ArrayLength:
+        case GetInt16ArrayLength:
+        case GetInt32ArrayLength:
+        case GetUint8ArrayLength:
+        case GetUint8ClampedArrayLength:
+        case GetUint16ArrayLength:
+        case GetUint32ArrayLength:
+        case GetFloat32ArrayLength:
+        case GetFloat64ArrayLength:
+        case GetStringLength:
+        case Int32ToDouble:
+        case DoubleAsInt32: {
+            // This node should never be visible at this stage of compilation. It is
+            // inserted by fixup(), which follows this phase.
+            ASSERT_NOT_REACHED();
+            break;
+        }
+        
+        case PutByVal:
+            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
+            changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
+            changed |= m_graph[node.child3()].mergeFlags(NodeUsedAsValue);
+            break;
+
+        case PutScopedVar:
+        case Return:
+        case Throw:
+            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
+            break;
+
+        case PutById:
+        case PutByIdDirect:
+            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
+            changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsValue);
+            break;
+
+        case PutByOffset:
+            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
+            changed |= m_graph[node.child3()].mergeFlags(NodeUsedAsValue);
+            break;
+            
+        case Phi:
+            break;
+
+#ifndef NDEBUG
+        // These get ignored because they don't return anything.
+        case DFG::Jump:
+        case Branch:
+        case Breakpoint:
+        case CheckHasInstance:
+        case ThrowReferenceError:
+        case ForceOSRExit:
+        case SetArgument:
+        case CheckStructure:
+        case CheckFunction:
+        case PutStructure:
+        case TearOffActivation:
+        case CheckNumber:
+            changed |= mergeDefaultFlags(node);
+            break;
+            
+        // These gets ignored because it doesn't do anything.
+        case Phantom:
+        case InlineStart:
+        case Nop:
+            break;
+            
+        case LastNodeType:
+            ASSERT_NOT_REACHED();
+            break;
+#else
+        default:
+            changed |= mergeDefaultFlags(node);
+            break;
+#endif
+        }
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("%s\n", predictionToString(m_graph[m_compileIndex].prediction()));
+#endif
+        
+        m_changed |= changed;
+    }
+        
+    bool mergeDefaultFlags(Node& node)
+    {
+        bool changed = false;
+        if (node.flags() & NodeHasVarArgs) {
+            for (unsigned childIdx = node.firstChild();
+                 childIdx < node.firstChild() + node.numChildren();
+                 childIdx++)
+                changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsValue);
+        } else {
+            if (!node.child1())
+                return changed;
+            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue);
+            if (!node.child2())
+                return changed;
+            changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsValue);
+            if (!node.child3())
+                return changed;
+            changed |= m_graph[node.child3()].mergeFlags(NodeUsedAsValue);
+        }
+        return changed;
+    }
+    
+    void propagateForward()
+    {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("Propagating predictions forward [%u]\n", ++m_count);
+#endif
+        for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex)
+            propagate(m_graph[m_compileIndex]);
+    }
+    
+    void propagateBackward()
+    {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("Propagating predictions backward [%u]\n", ++m_count);
+#endif
+        for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;)
+            propagate(m_graph[m_compileIndex]);
+    }
+    
+    void vote(Edge nodeUse, VariableAccessData::Ballot ballot)
+    {
+        switch (m_graph[nodeUse].op()) {
+        case ValueToInt32:
+        case UInt32ToNumber:
+            nodeUse = m_graph[nodeUse].child1();
+            break;
+        default:
+            break;
+        }
+        
+        if (m_graph[nodeUse].op() == GetLocal)
+            m_graph[nodeUse].variableAccessData()->vote(ballot);
+    }
+    
+    void vote(Node& node, VariableAccessData::Ballot ballot)
+    {
+        if (node.flags() & NodeHasVarArgs) {
+            for (unsigned childIdx = node.firstChild();
+                 childIdx < node.firstChild() + node.numChildren();
+                 childIdx++)
+                vote(m_graph.m_varArgChildren[childIdx], ballot);
+            return;
+        }
+        
+        if (!node.child1())
+            return;
+        vote(node.child1(), ballot);
+        if (!node.child2())
+            return;
+        vote(node.child2(), ballot);
+        if (!node.child3())
+            return;
+        vote(node.child3(), ballot);
+    }
+    
+    void doRoundOfDoubleVoting()
+    {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        dataLog("Voting on double uses of locals [%u]\n", m_count);
+#endif
+        for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i)
+            m_graph.m_variableAccessData[i].find()->clearVotes();
+        for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex) {
+            Node& node = m_graph[m_compileIndex];
+            switch (node.op()) {
+            case ValueAdd:
+            case ArithAdd:
+            case ArithSub: {
+                PredictedType left = m_graph[node.child1()].prediction();
+                PredictedType right = m_graph[node.child2()].prediction();
+                
+                VariableAccessData::Ballot ballot;
+                
+                if (isNumberPrediction(left) && isNumberPrediction(right)
+                    && !m_graph.addShouldSpeculateInteger(node))
+                    ballot = VariableAccessData::VoteDouble;
+                else
+                    ballot = VariableAccessData::VoteValue;
+                
+                vote(node.child1(), ballot);
+                vote(node.child2(), ballot);
+                break;
+            }
+                
+            case ArithMul:
+            case ArithMin:
+            case ArithMax:
+            case ArithMod:
+            case ArithDiv: {
+                PredictedType left = m_graph[node.child1()].prediction();
+                PredictedType right = m_graph[node.child2()].prediction();
+                
+                VariableAccessData::Ballot ballot;
+                
+                if (isNumberPrediction(left) && isNumberPrediction(right)
+                    && !(Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child1()])
+                         && node.canSpeculateInteger()))
+                    ballot = VariableAccessData::VoteDouble;
+                else
+                    ballot = VariableAccessData::VoteValue;
+                
+                vote(node.child1(), ballot);
+                vote(node.child2(), ballot);
+                break;
+            }
+                
+            case ArithAbs:
+                VariableAccessData::Ballot ballot;
+                if (!(m_graph[node.child1()].shouldSpeculateInteger()
+                      && node.canSpeculateInteger()))
+                    ballot = VariableAccessData::VoteDouble;
+                else
+                    ballot = VariableAccessData::VoteValue;
+                
+                vote(node.child1(), ballot);
+                break;
+                
+            case ArithSqrt:
+                vote(node.child1(), VariableAccessData::VoteDouble);
+                break;
+                
+            case SetLocal: {
+                PredictedType prediction = m_graph[node.child1()].prediction();
+                if (isDoublePrediction(prediction))
+                    node.variableAccessData()->vote(VariableAccessData::VoteDouble);
+                else if (!isNumberPrediction(prediction) || isInt32Prediction(prediction))
+                    node.variableAccessData()->vote(VariableAccessData::VoteValue);
+                break;
+            }
+                
+            default:
+                vote(node, VariableAccessData::VoteValue);
+                break;
+            }
+        }
+        for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
+            VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
+            if (!variableAccessData->isRoot())
+                continue;
+            if (operandIsArgument(variableAccessData->local())
+                || m_graph.isCaptured(variableAccessData->local()))
+                continue;
+            m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat();
+        }
+        for (unsigned i = 0; i < m_graph.m_argumentPositions.size(); ++i)
+            m_changed |= m_graph.m_argumentPositions[i].mergeArgumentAwareness();
+        for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
+            VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
+            if (!variableAccessData->isRoot())
+                continue;
+            if (operandIsArgument(variableAccessData->local())
+                || m_graph.isCaptured(variableAccessData->local()))
+                continue;
+            m_changed |= variableAccessData->makePredictionForDoubleFormat();
+        }
+    }
+    
+    NodeIndex m_compileIndex;
+    bool m_changed;
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+    unsigned m_count;
+#endif
+};
+    
+void performPredictionPropagation(Graph& graph)
+{
+    runPhase<PredictionPropagationPhase>(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/dfg/DFGPredictionPropagationPhase.h b/dfg/DFGPredictionPropagationPhase.h
new file mode 100644 (file)
index 0000000..fe12713
--- /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. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED 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 DFGPredictionPropagationPhase_h
+#define DFGPredictionPropagationPhase_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// Propagate predictions gathered at heap load sites by the value profiler, and
+// from slow path executions, to generate a prediction for each node in the graph.
+// This is a crucial phase of compilation, since before running this phase, we
+// have no idea what types any node (or most variables) could possibly have, unless
+// that node is either a heap load, a call, a GetLocal for an argument, or an
+// arithmetic op that had definitely taken slow path. Most nodes (even most
+// arithmetic nodes) do not qualify for any of these categories. But after running
+// this phase, we'll have full information for the expected type of each node.
+
+void performPredictionPropagation(Graph&);
+
+} } // namespace JSC::DFG::Phase
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGPredictionPropagationPhase_h
diff --git a/dfg/DFGRedundantPhiEliminationPhase.cpp b/dfg/DFGRedundantPhiEliminationPhase.cpp
new file mode 100644 (file)
index 0000000..b16a72a
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this 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 "DFGRedundantPhiEliminationPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGGraph.h"
+
+namespace JSC { namespace DFG {
+
+class RedundantPhiEliminationPhase : public Phase {
+public:
+    RedundantPhiEliminationPhase(Graph& graph)
+        : Phase(graph, "redundant phi elimination")
+    {
+    }
+    
+    void run()
+    {
+        bool changed = false;
+        do {
+            changed = fixupPhis();
+        } while (changed);
+
+        updateBlockVariableInformation();
+
+        // Update the Phi references from non-Phi nodes, e.g., the GetLocals.
+        for (NodeIndex index = 0; index < m_graph.size(); ++index) {
+            Node& node = m_graph[index];
+
+            if (!node.shouldGenerate())
+                continue;
+
+            switch (node.op()) {
+            case GetLocal:
+                replacePhiChild(node, 0);
+                break;
+            default:
+                break;
+            }
+        }
+
+    }
+
+private:
+    NodeIndex getRedundantReplacement(NodeIndex phi)
+    {
+        NodeIndex child1 = m_graph[phi].child1().indexUnchecked();
+        NodeIndex candidate = child1 == phi ? NoNode : child1;
+
+        NodeIndex child2 = m_graph[phi].child2().indexUnchecked();
+        if (candidate != NoNode) {
+            if (child2 != NoNode && child2 != candidate && child2 != phi)
+                return NoNode;
+        } else if (child2 != phi)
+            candidate = child2;
+
+        NodeIndex child3 = m_graph[phi].child3().indexUnchecked();
+        if (candidate != NoNode) {
+            if (child3 != NoNode && child3 != candidate && child3 != phi)
+                return NoNode;
+        } else if (child3 != phi)
+            candidate = child3;
+        
+        return candidate;
+    }
+
+    bool replacePhiChild(Node& node, unsigned childIndex)
+    {
+        ASSERT(childIndex < 3);
+
+        bool replaced = false;
+        NodeIndex child = node.children.child(childIndex).indexUnchecked();
+        if (child != NoNode && m_graph[child].op() == Phi) {
+            NodeIndex childReplacement = getRedundantReplacement(child);
+            if (childReplacement != NoNode) {
+                node.children.child(childIndex).setIndex(childReplacement);
+                replaced = true;
+                if (node.refCount()) {
+                    m_graph[childReplacement].ref();
+                    m_graph.deref(child);
+                }
+            }
+        }
+        return replaced;
+    }
+
+    bool fixupPhis()
+    {
+        bool changed = false;
+
+        for (BlockIndex block = 0; block < m_graph.m_blocks.size(); ++block) {
+            Vector<NodeIndex>& phis = m_graph.m_blocks[block]->phis;
+
+            for (size_t i = 0; i < phis.size(); ++i) {
+                NodeIndex phi = phis[i];
+                Node& phiNode = m_graph[phi];
+
+                changed |= (replacePhiChild(phiNode, 0) && phiNode.refCount());
+                changed |= (replacePhiChild(phiNode, 1) && phiNode.refCount());
+                changed |= (replacePhiChild(phiNode, 2) && phiNode.refCount());
+            }
+        }
+
+        return changed;
+    }
+
+    void updateBlockVariableInformation()
+    {
+        // Redundant Phi nodes are eliminated, we need to update
+        // the variable information if it references them.
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
+            BasicBlock* basicBlock = m_graph.m_blocks[blockIndex].get();
+
+            for (size_t arg = 0; arg < basicBlock->variablesAtHead.numberOfArguments(); ++arg) {
+                NodeIndex nodeIndex = basicBlock->variablesAtHead.argument(arg);
+                if (nodeIndex != NoNode && m_graph[nodeIndex].op() == Phi && !m_graph[nodeIndex].refCount()) {
+                    NodeIndex replacement = getRedundantReplacement(nodeIndex);
+                    if (replacement != NoNode) {
+                        // This argument must be unused in this block.
+                        ASSERT(basicBlock->variablesAtTail.argument(arg) == nodeIndex);
+                        basicBlock->variablesAtHead.argument(arg) = replacement;
+                        basicBlock->variablesAtTail.argument(arg) = replacement;
+                    }
+                }
+            }
+
+            for (size_t local = 0; local < basicBlock->variablesAtHead.numberOfLocals(); ++local) {
+                NodeIndex nodeIndex = basicBlock->variablesAtHead.local(local);
+                if (nodeIndex != NoNode && m_graph[nodeIndex].op() == Phi && !m_graph[nodeIndex].refCount()) {
+                    NodeIndex replacement = getRedundantReplacement(nodeIndex);
+                    if (replacement != NoNode) {
+                        // This local variable must be unused in this block.
+                        ASSERT(basicBlock->variablesAtTail.local(local) == nodeIndex);
+                        basicBlock->variablesAtHead.local(local) = replacement;
+                        basicBlock->variablesAtTail.local(local) = replacement;
+                    }
+                }
+            }
+        }
+    }
+
+};
+
+void performRedundantPhiElimination(Graph& graph)
+{
+    runPhase<RedundantPhiEliminationPhase>(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
diff --git a/dfg/DFGRedundantPhiEliminationPhase.h b/dfg/DFGRedundantPhiEliminationPhase.h
new file mode 100644 (file)
index 0000000..202ab44
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this 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 DFGRedundantPhiEliminationPhase_h
+#define DFGRedundantPhiEliminationPhase_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGPhase.h"
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// We inserted many can-be-redundant Phi nodes when building the graph.
+// This phase will just remove them.
+
+void performRedundantPhiElimination(Graph&);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGRedundantPhiEliminationPhase_h
+
index f4fdd50a7197a7a14d7edf9b16e32ebde9147d93..85dc246f290d1bfd882dbab31a861f9ac4e5c48a 100644 (file)
@@ -28,7 +28,7 @@
 
 #if ENABLE(DFG_JIT)
 
 
 #if ENABLE(DFG_JIT)
 
-#include <dfg/DFGNode.h>
+#include <dfg/DFGCommon.h>
 
 namespace JSC { namespace DFG {
 
 
 namespace JSC { namespace DFG {
 
@@ -79,6 +79,26 @@ public:
     {
     }
 
     {
     }
 
+    // Attempt to allocate a register - this function finds an unlocked
+    // register, locks it, and returns it. If none can be found, this
+    // returns -1 (InvalidGPRReg or InvalidFPRReg).
+    RegID tryAllocate()
+    {
+        VirtualRegister ignored;
+        
+        for (uint32_t i = m_lastAllocated + 1; i < NUM_REGS; ++i) {
+            if (!m_data[i].lockCount && m_data[i].name == InvalidVirtualRegister)
+                return allocateInternal(i, ignored);
+        }
+        // Loop over the remaining entries.
+        for (uint32_t i = 0; i <= m_lastAllocated; ++i) {
+            if (!m_data[i].lockCount && m_data[i].name == InvalidVirtualRegister)
+                return allocateInternal(i, ignored);
+        }
+        
+        return (RegID)-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
     // 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
@@ -139,6 +159,19 @@ public:
         return allocateInternal(currentLowest, spillMe);
     }
 
         return allocateInternal(currentLowest, spillMe);
     }
 
+    // Allocates the given register, even if this will force a spill.
+    VirtualRegister allocateSpecific(RegID reg)
+    {
+        unsigned index = BankInfo::toIndex(reg);
+
+        ++m_data[index].lockCount;
+        VirtualRegister name = nameAtIndex(index);
+        if (name != InvalidVirtualRegister)
+            releaseAtIndex(index);
+        
+        return name;
+    }
+
     // 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)
     // 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)
@@ -199,11 +232,11 @@ public:
         // For each register, print the VirtualRegister 'name'.
         for (uint32_t i =0; i < NUM_REGS; ++i) {
             if (m_data[i].name != InvalidVirtualRegister)
         // 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);
+                dataLog("[%02d]", m_data[i].name);
             else
             else
-                fprintf(stderr, "[--]");
+                dataLog("[--]");
         }
         }
-        fprintf(stderr, "\n");
+        dataLog("\n");
     }
 #endif
 
     }
 #endif
 
diff --git a/dfg/DFGRepatch.cpp b/dfg/DFGRepatch.cpp
new file mode 100644 (file)
index 0000000..7945381
--- /dev/null
@@ -0,0 +1,917 @@
+/*
+ * 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 "DFGRepatch.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGCCallHelpers.h"
+#include "DFGSpeculativeJIT.h"
+#include "LinkBuffer.h"
+#include "Operations.h"
+#include "PolymorphicPutByIdList.h"
+#include "RepatchBuffer.h"
+
+namespace JSC { namespace DFG {
+
+static void dfgRepatchCall(CodeBlock* codeblock, CodeLocationCall call, FunctionPtr newCalleeFunction)
+{
+    RepatchBuffer repatchBuffer(codeblock);
+    repatchBuffer.relink(call, newCalleeFunction);
+}
+
+static void dfgRepatchByIdSelfAccess(CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure, size_t offset, const FunctionPtr &slowPathFunction, bool compact)
+{
+    RepatchBuffer repatchBuffer(codeBlock);
+
+    // Only optimize once!
+    repatchBuffer.relink(stubInfo.callReturnLocation, slowPathFunction);
+
+    // Patch the structure check & the offset of the load.
+    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(intptr_t)stubInfo.patch.dfg.deltaCheckImmToCall), structure);
+#if USE(JSVALUE64)
+    if (compact)
+        repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToLoadOrStore), sizeof(JSValue) * offset);
+    else
+        repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToLoadOrStore), sizeof(JSValue) * offset);
+#elif USE(JSVALUE32_64)
+    if (compact) {
+        repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToTagLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+        repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToPayloadLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+    } else {
+        repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToTagLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+        repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToPayloadLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+    }
+#endif
+}
+
+static void emitRestoreScratch(MacroAssembler& stubJit, bool needToRestoreScratch, GPRReg scratchGPR, MacroAssembler::Jump& success, MacroAssembler::Jump& fail, MacroAssembler::JumpList failureCases)
+{
+    if (needToRestoreScratch) {
+        stubJit.pop(scratchGPR);
+        
+        success = stubJit.jump();
+        
+        // link failure cases here, so we can pop scratchGPR, and then jump back.
+        failureCases.link(&stubJit);
+        
+        stubJit.pop(scratchGPR);
+        
+        fail = stubJit.jump();
+        return;
+    }
+    
+    success = stubJit.jump();
+}
+
+static void linkRestoreScratch(LinkBuffer& patchBuffer, bool needToRestoreScratch, MacroAssembler::Jump success, MacroAssembler::Jump fail, MacroAssembler::JumpList failureCases, CodeLocationLabel successLabel, CodeLocationLabel slowCaseBegin)
+{
+    patchBuffer.link(success, successLabel);
+        
+    if (needToRestoreScratch) {
+        patchBuffer.link(fail, slowCaseBegin);
+        return;
+    }
+    
+    // link failure cases directly back to normal path
+    patchBuffer.link(failureCases, slowCaseBegin);
+}
+
+static void linkRestoreScratch(LinkBuffer& patchBuffer, bool needToRestoreScratch, StructureStubInfo& stubInfo, MacroAssembler::Jump success, MacroAssembler::Jump fail, MacroAssembler::JumpList failureCases)
+{
+    linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase));
+}
+
+static void generateProtoChainAccessStub(ExecState* exec, StructureStubInfo& stubInfo, StructureChain* chain, size_t count, size_t offset, Structure* structure, CodeLocationLabel successLabel, CodeLocationLabel slowCaseLabel, MacroAssemblerCodeRef& stubRoutine)
+{
+    JSGlobalData* globalData = &exec->globalData();
+
+    MacroAssembler stubJit;
+        
+    GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.dfg.baseGPR);
+#if USE(JSVALUE32_64)
+    GPRReg resultTagGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueTagGPR);
+#endif
+    GPRReg resultGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueGPR);
+    GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.patch.dfg.scratchGPR);
+    bool needToRestoreScratch = false;
+    
+    if (scratchGPR == InvalidGPRReg) {
+        scratchGPR = SpeculativeJIT::selectScratchGPR(baseGPR, resultGPR);
+        stubJit.push(scratchGPR);
+        needToRestoreScratch = true;
+    }
+    
+    MacroAssembler::JumpList failureCases;
+    
+    failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(structure)));
+    
+    Structure* currStructure = structure;
+    WriteBarrier<Structure>* it = chain->head();
+    JSObject* protoObject = 0;
+    for (unsigned i = 0; i < count; ++i, ++it) {
+        protoObject = asObject(currStructure->prototypeForLookup(exec));
+        stubJit.move(MacroAssembler::TrustedImmPtr(protoObject), scratchGPR);
+        failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(scratchGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(protoObject->structure())));
+        currStructure = it->get();
+    }
+    
+    stubJit.loadPtr(protoObject->addressOfPropertyStorage(), resultGPR);
+#if USE(JSVALUE64)
+    stubJit.loadPtr(MacroAssembler::Address(resultGPR, offset * sizeof(WriteBarrier<Unknown>)), resultGPR);
+#elif USE(JSVALUE32_64)
+    stubJit.load32(MacroAssembler::Address(resultGPR, offset * sizeof(WriteBarrier<Unknown>) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
+    stubJit.load32(MacroAssembler::Address(resultGPR, offset * sizeof(WriteBarrier<Unknown>) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultGPR);
+#endif
+
+    MacroAssembler::Jump success, fail;
+    
+    emitRestoreScratch(stubJit, needToRestoreScratch, scratchGPR, success, fail, failureCases);
+    
+    LinkBuffer patchBuffer(*globalData, &stubJit, exec->codeBlock());
+    
+    linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, successLabel, slowCaseLabel);
+    
+    stubRoutine = patchBuffer.finalizeCode();
+}
+
+static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+    // FIXME: Write a test that proves we need to check for recursion here just
+    // like the interpreter does, then add a check for recursion.
+
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSGlobalData* globalData = &exec->globalData();
+    
+    if (isJSArray(baseValue) && propertyName == exec->propertyNames().length) {
+        GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.dfg.baseGPR);
+#if USE(JSVALUE32_64)
+        GPRReg resultTagGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueTagGPR);
+#endif
+        GPRReg resultGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueGPR);
+        GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.patch.dfg.scratchGPR);
+        bool needToRestoreScratch = false;
+        
+        MacroAssembler stubJit;
+        
+        if (scratchGPR == InvalidGPRReg) {
+            scratchGPR = SpeculativeJIT::selectScratchGPR(baseGPR, resultGPR);
+            stubJit.push(scratchGPR);
+            needToRestoreScratch = true;
+        }
+        
+        MacroAssembler::JumpList failureCases;
+        
+        failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        
+        stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), scratchGPR);
+        stubJit.load32(MacroAssembler::Address(scratchGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), scratchGPR);
+        failureCases.append(stubJit.branch32(MacroAssembler::LessThan, scratchGPR, MacroAssembler::TrustedImm32(0)));
+
+#if USE(JSVALUE64)
+        stubJit.orPtr(GPRInfo::tagTypeNumberRegister, scratchGPR, resultGPR);
+#elif USE(JSVALUE32_64)
+        stubJit.move(scratchGPR, resultGPR);
+        stubJit.move(JITCompiler::TrustedImm32(0xffffffff), resultTagGPR); // JSValue::Int32Tag
+#endif
+
+        MacroAssembler::Jump success, fail;
+        
+        emitRestoreScratch(stubJit, needToRestoreScratch, scratchGPR, success, fail, failureCases);
+        
+        LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock);
+        
+        linkRestoreScratch(patchBuffer, needToRestoreScratch, stubInfo, success, fail, failureCases);
+        
+        stubInfo.stubRoutine = patchBuffer.finalizeCode();
+        
+        RepatchBuffer repatchBuffer(codeBlock);
+        repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code()));
+        repatchBuffer.relink(stubInfo.callReturnLocation, operationGetById);
+        
+        return true;
+    }
+    
+    // FIXME: should support length access for String.
+
+    // FIXME: Cache property access for immediates.
+    if (!baseValue.isCell())
+        return false;
+    JSCell* baseCell = baseValue.asCell();
+    Structure* structure = baseCell->structure();
+    if (!slot.isCacheable())
+        return false;
+    if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching())
+        return false;
+
+    // Optimize self access.
+    if (slot.slotBase() == baseValue) {
+        if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset)) {
+            dfgRepatchCall(codeBlock, stubInfo.callReturnLocation, operationGetByIdBuildList);
+            return true;
+        }
+
+        dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetByIdBuildList, true);
+        stubInfo.initGetByIdSelf(*globalData, codeBlock->ownerExecutable(), structure);
+        return true;
+    }
+    
+    if (structure->isDictionary())
+        return false;
+    
+    // FIXME: optimize getters and setters
+    if (slot.cachedPropertyType() != PropertySlot::Value)
+        return false;
+    
+    size_t offset = slot.cachedOffset();
+    size_t count = normalizePrototypeChain(exec, baseValue, slot.slotBase(), propertyName, offset);
+    if (!count)
+        return false;
+
+    StructureChain* prototypeChain = structure->prototypeChain(exec);
+    
+    ASSERT(slot.slotBase().isObject());
+    
+    generateProtoChainAccessStub(exec, stubInfo, prototypeChain, count, offset, structure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase), stubInfo.stubRoutine);
+    
+    RepatchBuffer repatchBuffer(codeBlock);
+    repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code()));
+    repatchBuffer.relink(stubInfo.callReturnLocation, operationGetByIdProtoBuildList);
+    
+    stubInfo.initGetByIdChain(*globalData, codeBlock->ownerExecutable(), structure, prototypeChain);
+    return true;
+}
+
+void dfgRepatchGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+    bool cached = tryCacheGetByID(exec, baseValue, propertyName, slot, stubInfo);
+    if (!cached)
+        dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
+}
+
+static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identifier& ident, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+    if (!baseValue.isCell()
+        || !slot.isCacheable()
+        || baseValue.asCell()->structure()->isUncacheableDictionary()
+        || slot.slotBase() != baseValue)
+        return false;
+    
+    if (!stubInfo.patch.dfg.registersFlushed) {
+        // We cannot do as much inline caching if the registers were not flushed prior to this GetById. In particular,
+        // non-Value cached properties require planting calls, which requires registers to have been flushed. Thus,
+        // if registers were not flushed, don't do non-Value caching.
+        if (slot.cachedPropertyType() != PropertySlot::Value)
+            return false;
+    }
+    
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSCell* baseCell = baseValue.asCell();
+    Structure* structure = baseCell->structure();
+    JSGlobalData* globalData = &exec->globalData();
+    
+    ASSERT(slot.slotBase().isObject());
+    
+    PolymorphicAccessStructureList* polymorphicStructureList;
+    int listIndex;
+    
+    if (stubInfo.accessType == access_unset) {
+        ASSERT(!stubInfo.stubRoutine);
+        polymorphicStructureList = new PolymorphicAccessStructureList();
+        stubInfo.initGetByIdSelfList(polymorphicStructureList, 0);
+        listIndex = 0;
+    } else if (stubInfo.accessType == access_get_by_id_self) {
+        ASSERT(!stubInfo.stubRoutine);
+        polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), MacroAssemblerCodeRef::createSelfManagedCodeRef(stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase)), stubInfo.u.getByIdSelf.baseObjectStructure.get(), true);
+        stubInfo.initGetByIdSelfList(polymorphicStructureList, 1);
+        listIndex = 1;
+    } else {
+        polymorphicStructureList = stubInfo.u.getByIdSelfList.structureList;
+        listIndex = stubInfo.u.getByIdSelfList.listSize;
+    }
+    
+    if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
+        stubInfo.u.getByIdSelfList.listSize++;
+        
+        GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.dfg.baseGPR);
+#if USE(JSVALUE32_64)
+        GPRReg resultTagGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueTagGPR);
+#endif
+        GPRReg resultGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueGPR);
+        GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.patch.dfg.scratchGPR);
+        
+        CCallHelpers stubJit(globalData, codeBlock);
+        
+        MacroAssembler::Jump wrongStruct = stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(structure));
+        
+        // The strategy we use for stubs is as follows:
+        // 1) Call DFG helper that calls the getter.
+        // 2) Check if there was an exception, and if there was, call yet another
+        //    helper.
+        
+        bool isDirect = false;
+        MacroAssembler::Call operationCall;
+        MacroAssembler::Call handlerCall;
+        FunctionPtr operationFunction;
+        MacroAssembler::Jump success;
+        
+        if (slot.cachedPropertyType() == PropertySlot::Getter
+            || slot.cachedPropertyType() == PropertySlot::Custom) {
+            if (slot.cachedPropertyType() == PropertySlot::Getter) {
+                ASSERT(baseGPR != scratchGPR);
+                stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
+#if USE(JSVALUE64)
+                stubJit.loadPtr(MacroAssembler::Address(scratchGPR, slot.cachedOffset() * sizeof(JSValue)), scratchGPR);
+#elif USE(JSVALUE32_64)
+                stubJit.load32(MacroAssembler::Address(scratchGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), scratchGPR);
+#endif
+                stubJit.setupArgumentsWithExecState(baseGPR, scratchGPR);
+                operationFunction = operationCallGetter;
+            } else {
+                stubJit.setupArgumentsWithExecState(
+                    baseGPR,
+                    MacroAssembler::TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()),
+                    MacroAssembler::TrustedImmPtr(const_cast<Identifier*>(&ident)));
+                operationFunction = operationCallCustomGetter;
+            }
+            
+            // Need to make sure that whenever this call is made in the future, we remember the
+            // place that we made it from. It just so happens to be the place that we are at
+            // right now!
+            stubJit.store32(
+                MacroAssembler::TrustedImm32(exec->codeOriginIndexForDFG()),
+                CCallHelpers::tagFor(static_cast<VirtualRegister>(RegisterFile::ArgumentCount)));
+            
+            operationCall = stubJit.call();
+#if USE(JSVALUE64)
+            stubJit.move(GPRInfo::returnValueGPR, resultGPR);
+#else
+            stubJit.setupResults(resultGPR, resultTagGPR);
+#endif
+            success = stubJit.emitExceptionCheck(CCallHelpers::InvertedExceptionCheck);
+            
+            stubJit.setupArgumentsWithExecState(
+                MacroAssembler::TrustedImmPtr(&stubInfo));
+            handlerCall = stubJit.call();
+            stubJit.jump(GPRInfo::returnValueGPR2);
+        } else {
+            stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
+#if USE(JSVALUE64)
+            stubJit.loadPtr(MacroAssembler::Address(resultGPR, slot.cachedOffset() * sizeof(JSValue)), resultGPR);
+#elif USE(JSVALUE32_64)
+            stubJit.load32(MacroAssembler::Address(resultGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
+            stubJit.load32(MacroAssembler::Address(resultGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultGPR);
+#endif
+            success = stubJit.jump();
+            isDirect = true;
+        }
+
+        LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock);
+        
+        CodeLocationLabel lastProtoBegin;
+        if (listIndex)
+            lastProtoBegin = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine.code());
+        else
+            lastProtoBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase);
+        ASSERT(!!lastProtoBegin);
+        
+        patchBuffer.link(wrongStruct, lastProtoBegin);
+        patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone));
+        if (!isDirect) {
+            patchBuffer.link(operationCall, operationFunction);
+            patchBuffer.link(handlerCall, lookupExceptionHandlerInStub);
+        }
+        
+        MacroAssemblerCodeRef stubRoutine = patchBuffer.finalizeCode();
+        
+        polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
+        
+        CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck);
+        RepatchBuffer repatchBuffer(codeBlock);
+        repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
+        
+        if (listIndex < (POLYMORPHIC_LIST_CACHE_SIZE - 1))
+            return true;
+    }
+    
+    return false;
+}
+
+void dfgBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+    bool dontChangeCall = tryBuildGetByIDList(exec, baseValue, propertyName, slot, stubInfo);
+    if (!dontChangeCall)
+        dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
+}
+
+static bool tryBuildGetByIDProtoList(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+    if (!baseValue.isCell()
+        || !slot.isCacheable()
+        || baseValue.asCell()->structure()->isDictionary()
+        || baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()
+        || slot.slotBase() == baseValue
+        || slot.cachedPropertyType() != PropertySlot::Value)
+        return false;
+    
+    ASSERT(slot.slotBase().isObject());
+    
+    size_t offset = slot.cachedOffset();
+    size_t count = normalizePrototypeChain(exec, baseValue, slot.slotBase(), propertyName, offset);
+    if (!count)
+        return false;
+
+    Structure* structure = baseValue.asCell()->structure();
+    StructureChain* prototypeChain = structure->prototypeChain(exec);
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSGlobalData* globalData = &exec->globalData();
+    
+    PolymorphicAccessStructureList* polymorphicStructureList;
+    int listIndex = 1;
+    
+    if (stubInfo.accessType == access_get_by_id_chain) {
+        ASSERT(!!stubInfo.stubRoutine);
+        polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), stubInfo.stubRoutine, stubInfo.u.getByIdChain.baseObjectStructure.get(), stubInfo.u.getByIdChain.chain.get(), true);
+        stubInfo.stubRoutine = MacroAssemblerCodeRef();
+        stubInfo.initGetByIdProtoList(polymorphicStructureList, 1);
+    } else {
+        ASSERT(stubInfo.accessType == access_get_by_id_proto_list);
+        polymorphicStructureList = stubInfo.u.getByIdProtoList.structureList;
+        listIndex = stubInfo.u.getByIdProtoList.listSize;
+    }
+    
+    if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
+        stubInfo.u.getByIdProtoList.listSize++;
+        
+        CodeLocationLabel lastProtoBegin = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine.code());
+        ASSERT(!!lastProtoBegin);
+
+        MacroAssemblerCodeRef stubRoutine;
+        
+        generateProtoChainAccessStub(exec, stubInfo, prototypeChain, count, offset, structure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone), lastProtoBegin, stubRoutine);
+        
+        polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, true);
+        
+        CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck);
+        RepatchBuffer repatchBuffer(codeBlock);
+        repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
+        
+        if (listIndex < (POLYMORPHIC_LIST_CACHE_SIZE - 1))
+            return true;
+    }
+    
+    return false;
+}
+
+void dfgBuildGetByIDProtoList(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+    bool dontChangeCall = tryBuildGetByIDProtoList(exec, baseValue, propertyName, slot, stubInfo);
+    if (!dontChangeCall)
+        dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
+}
+
+static V_DFGOperation_EJCI appropriateGenericPutByIdFunction(const PutPropertySlot &slot, PutKind putKind)
+{
+    if (slot.isStrictMode()) {
+        if (putKind == Direct)
+            return operationPutByIdDirectStrict;
+        return operationPutByIdStrict;
+    }
+    if (putKind == Direct)
+        return operationPutByIdDirectNonStrict;
+    return operationPutByIdNonStrict;
+}
+
+static V_DFGOperation_EJCI appropriateListBuildingPutByIdFunction(const PutPropertySlot &slot, PutKind putKind)
+{
+    if (slot.isStrictMode()) {
+        if (putKind == Direct)
+            return operationPutByIdDirectStrictBuildList;
+        return operationPutByIdStrictBuildList;
+    }
+    if (putKind == Direct)
+        return operationPutByIdDirectNonStrictBuildList;
+    return operationPutByIdNonStrictBuildList;
+}
+
+static void testPrototype(MacroAssembler &stubJit, GPRReg scratchGPR, JSValue prototype, MacroAssembler::JumpList& failureCases)
+{
+    if (prototype.isNull())
+        return;
+    
+    ASSERT(prototype.isCell());
+    
+    stubJit.move(MacroAssembler::TrustedImmPtr(prototype.asCell()), scratchGPR);
+    failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(scratchGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(prototype.asCell()->structure())));
+}
+
+static void emitPutReplaceStub(
+    ExecState* exec,
+    JSValue,
+    const Identifier&,
+    const PutPropertySlot& slot,
+    StructureStubInfo& stubInfo,
+    PutKind,
+    Structure* structure,
+    CodeLocationLabel failureLabel,
+    MacroAssemblerCodeRef& stubRoutine)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.dfg.baseGPR);
+#if USE(JSVALUE32_64)
+    GPRReg valueTagGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueTagGPR);
+#endif
+    GPRReg valueGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueGPR);
+    GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.patch.dfg.scratchGPR);
+    bool needToRestoreScratch = false;
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+    GPRReg scratchGPR2;
+    const bool writeBarrierNeeded = true;
+#else
+    const bool writeBarrierNeeded = false;
+#endif
+    
+    MacroAssembler stubJit;
+    
+    if (scratchGPR == InvalidGPRReg && (writeBarrierNeeded || !structure->isUsingInlineStorage())) {
+        scratchGPR = SpeculativeJIT::selectScratchGPR(baseGPR, valueGPR);
+        needToRestoreScratch = true;
+        stubJit.push(scratchGPR);
+    }
+
+    MacroAssembler::Jump badStructure = stubJit.branchPtr(
+        MacroAssembler::NotEqual,
+        MacroAssembler::Address(baseGPR, JSCell::structureOffset()),
+        MacroAssembler::TrustedImmPtr(structure));
+    
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+    scratchGPR2 = SpeculativeJIT::selectScratchGPR(baseGPR, valueGPR, scratchGPR);
+    stubJit.push(scratchGPR2);
+    SpeculativeJIT::writeBarrier(stubJit, baseGPR, scratchGPR, scratchGPR2, WriteBarrierForPropertyAccess);
+    stubJit.pop(scratchGPR2);
+#endif
+    
+#if USE(JSVALUE64)
+    if (structure->isUsingInlineStorage())
+        stubJit.storePtr(valueGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + slot.cachedOffset() * sizeof(JSValue)));
+    else {
+        stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
+        stubJit.storePtr(valueGPR, MacroAssembler::Address(scratchGPR, slot.cachedOffset() * sizeof(JSValue)));
+    }
+#elif USE(JSVALUE32_64)
+    if (structure->isUsingInlineStorage()) {
+        stubJit.store32(valueGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+        stubJit.store32(valueTagGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+    } else {
+        stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
+        stubJit.store32(valueGPR, MacroAssembler::Address(scratchGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+        stubJit.store32(valueTagGPR, MacroAssembler::Address(scratchGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+    }
+#endif
+    
+    MacroAssembler::Jump success;
+    MacroAssembler::Jump failure;
+    
+    if (needToRestoreScratch) {
+        stubJit.pop(scratchGPR);
+        success = stubJit.jump();
+        
+        badStructure.link(&stubJit);
+        stubJit.pop(scratchGPR);
+        failure = stubJit.jump();
+    } else {
+        success = stubJit.jump();
+        failure = badStructure;
+    }
+    
+    LinkBuffer patchBuffer(*globalData, &stubJit, exec->codeBlock());
+    patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone));
+    patchBuffer.link(failure, failureLabel);
+            
+    stubRoutine = patchBuffer.finalizeCode();
+}
+
+static void emitPutTransitionStub(
+    ExecState* exec,
+    JSValue,
+    const Identifier&,
+    const PutPropertySlot& slot,
+    StructureStubInfo& stubInfo,
+    PutKind putKind,
+    Structure* structure,
+    Structure* oldStructure,
+    StructureChain* prototypeChain,
+    CodeLocationLabel failureLabel,
+    MacroAssemblerCodeRef& stubRoutine)
+{
+    JSGlobalData* globalData = &exec->globalData();
+
+    GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.dfg.baseGPR);
+#if USE(JSVALUE32_64)
+    GPRReg valueTagGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueTagGPR);
+#endif
+    GPRReg valueGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueGPR);
+    GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.patch.dfg.scratchGPR);
+    bool needToRestoreScratch = false;
+            
+    ASSERT(scratchGPR != baseGPR);
+            
+    MacroAssembler stubJit;
+            
+    MacroAssembler::JumpList failureCases;
+            
+    if (scratchGPR == InvalidGPRReg) {
+        scratchGPR = SpeculativeJIT::selectScratchGPR(baseGPR, valueGPR);
+        stubJit.push(scratchGPR);
+        needToRestoreScratch = true;
+    }
+    
+    failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(oldStructure)));
+            
+    testPrototype(stubJit, scratchGPR, oldStructure->storedPrototype(), failureCases);
+            
+    if (putKind == NotDirect) {
+        for (WriteBarrier<Structure>* it = prototypeChain->head(); *it; ++it)
+            testPrototype(stubJit, scratchGPR, (*it)->storedPrototype(), failureCases);
+    }
+
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+    // Must always emit this write barrier as the structure transition itself requires it
+    GPRReg scratch2 = SpeculativeJIT::selectScratchGPR(baseGPR, valueGPR, scratchGPR);
+    stubJit.push(scratch2);
+    SpeculativeJIT::writeBarrier(stubJit, baseGPR, scratchGPR, scratch2, WriteBarrierForPropertyAccess);
+    stubJit.pop(scratch2);
+#endif
+
+    stubJit.storePtr(MacroAssembler::TrustedImmPtr(structure), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
+#if USE(JSVALUE64)
+    if (structure->isUsingInlineStorage())
+        stubJit.storePtr(valueGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + slot.cachedOffset() * sizeof(JSValue)));
+    else {
+        stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
+        stubJit.storePtr(valueGPR, MacroAssembler::Address(scratchGPR, slot.cachedOffset() * sizeof(JSValue)));
+    }
+#elif USE(JSVALUE32_64)
+    if (structure->isUsingInlineStorage()) {
+        stubJit.store32(valueGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+        stubJit.store32(valueTagGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+    } else {
+        stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
+        stubJit.store32(valueGPR, MacroAssembler::Address(scratchGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+        stubJit.store32(valueTagGPR, MacroAssembler::Address(scratchGPR, slot.cachedOffset() * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+    }
+#endif
+            
+    MacroAssembler::Jump success;
+    MacroAssembler::Jump failure;
+            
+    if (needToRestoreScratch) {
+        stubJit.pop(scratchGPR);
+        success = stubJit.jump();
+
+        failureCases.link(&stubJit);
+        stubJit.pop(scratchGPR);
+        failure = stubJit.jump();
+    } else
+        success = stubJit.jump();
+            
+    LinkBuffer patchBuffer(*globalData, &stubJit, exec->codeBlock());
+    patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone));
+    if (needToRestoreScratch)
+        patchBuffer.link(failure, failureLabel);
+    else
+        patchBuffer.link(failureCases, failureLabel);
+            
+    stubRoutine = patchBuffer.finalizeCode();
+}
+
+static bool tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier& ident, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
+{
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSGlobalData* globalData = &exec->globalData();
+
+    if (!baseValue.isCell())
+        return false;
+    JSCell* baseCell = baseValue.asCell();
+    Structure* structure = baseCell->structure();
+    Structure* oldStructure = structure->previousID();
+    
+    if (!slot.isCacheable())
+        return false;
+    if (structure->isUncacheableDictionary())
+        return false;
+
+    // Optimize self access.
+    if (slot.base() == baseValue) {
+        if (slot.type() == PutPropertySlot::NewProperty) {
+            if (structure->isDictionary())
+                return false;
+            
+            // skip optimizing the case where we need a realloc
+            if (oldStructure->propertyStorageCapacity() != structure->propertyStorageCapacity())
+                return false;
+            
+            normalizePrototypeChain(exec, baseCell);
+            
+            StructureChain* prototypeChain = structure->prototypeChain(exec);
+            
+            emitPutTransitionStub(
+                exec, baseValue, ident, slot, stubInfo, putKind,
+                structure, oldStructure, prototypeChain,
+                stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase),
+                stubInfo.stubRoutine);
+            
+            RepatchBuffer repatchBuffer(codeBlock);
+            repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code()));
+            repatchBuffer.relink(stubInfo.callReturnLocation, appropriateListBuildingPutByIdFunction(slot, putKind));
+            
+            stubInfo.initPutByIdTransition(*globalData, codeBlock->ownerExecutable(), oldStructure, structure, prototypeChain, putKind == Direct);
+            
+            return true;
+        }
+
+        dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), appropriateListBuildingPutByIdFunction(slot, putKind), false);
+        stubInfo.initPutByIdReplace(*globalData, codeBlock->ownerExecutable(), structure);
+        return true;
+    }
+
+    return false;
+}
+
+void dfgRepatchPutByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
+{
+    bool cached = tryCachePutByID(exec, baseValue, propertyName, slot, stubInfo, putKind);
+    if (!cached)
+        dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, appropriateGenericPutByIdFunction(slot, putKind));
+}
+
+static bool tryBuildPutByIdList(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
+{
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSGlobalData* globalData = &exec->globalData();
+
+    if (!baseValue.isCell())
+        return false;
+    JSCell* baseCell = baseValue.asCell();
+    Structure* structure = baseCell->structure();
+    Structure* oldStructure = structure->previousID();
+    
+    if (!slot.isCacheable())
+        return false;
+    if (structure->isUncacheableDictionary())
+        return false;
+
+    // Optimize self access.
+    if (slot.base() == baseValue) {
+        PolymorphicPutByIdList* list;
+        MacroAssemblerCodeRef stubRoutine;
+        
+        if (slot.type() == PutPropertySlot::NewProperty) {
+            if (structure->isDictionary())
+                return false;
+            
+            // skip optimizing the case where we need a realloc
+            if (oldStructure->propertyStorageCapacity() != structure->propertyStorageCapacity())
+                return false;
+            
+            normalizePrototypeChain(exec, baseCell);
+            
+            StructureChain* prototypeChain = structure->prototypeChain(exec);
+            
+            // We're now committed to creating the stub. Mogrify the meta-data accordingly.
+            list = PolymorphicPutByIdList::from(
+                putKind, stubInfo,
+                stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase));
+            
+            emitPutTransitionStub(
+                exec, baseValue, propertyName, slot, stubInfo, putKind,
+                structure, oldStructure, prototypeChain,
+                CodeLocationLabel(list->currentSlowPathTarget()),
+                stubRoutine);
+            
+            list->addAccess(
+                PutByIdAccess::transition(
+                    *globalData, codeBlock->ownerExecutable(),
+                    oldStructure, structure, prototypeChain,
+                    stubRoutine));
+        } else {
+            // We're now committed to creating the stub. Mogrify the meta-data accordingly.
+            list = PolymorphicPutByIdList::from(
+                putKind, stubInfo,
+                stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase));
+            
+            emitPutReplaceStub(
+                exec, baseValue, propertyName, slot, stubInfo, putKind,
+                structure, CodeLocationLabel(list->currentSlowPathTarget()), stubRoutine);
+            
+            list->addAccess(
+                PutByIdAccess::replace(
+                    *globalData, codeBlock->ownerExecutable(),
+                    structure, stubRoutine));
+        }
+        
+        RepatchBuffer repatchBuffer(codeBlock);
+        repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubRoutine.code()));
+        
+        if (list->isFull())
+            repatchBuffer.relink(stubInfo.callReturnLocation, appropriateGenericPutByIdFunction(slot, putKind));
+        
+        return true;
+    }
+    
+    return false;
+}
+
+void dfgBuildPutByIdList(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
+{
+    bool cached = tryBuildPutByIdList(exec, baseValue, propertyName, slot, stubInfo, putKind);
+    if (!cached)
+        dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, appropriateGenericPutByIdFunction(slot, putKind));
+}
+
+void dfgLinkFor(ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock, JSFunction* callee, MacroAssemblerCodePtr codePtr, CodeSpecializationKind kind)
+{
+    CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
+    
+    RepatchBuffer repatchBuffer(callerCodeBlock);
+    
+    ASSERT(!callLinkInfo.isLinked());
+    callLinkInfo.callee.set(exec->callerFrame()->globalData(), callLinkInfo.hotPathBegin, callerCodeBlock->ownerExecutable(), callee);
+    callLinkInfo.lastSeenCallee.set(exec->callerFrame()->globalData(), callerCodeBlock->ownerExecutable(), callee);
+    repatchBuffer.relink(callLinkInfo.hotPathOther, codePtr);
+    
+    if (calleeCodeBlock)
+        calleeCodeBlock->linkIncomingCall(&callLinkInfo);
+    
+    if (kind == CodeForCall) {
+        repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualCall);
+        return;
+    }
+    ASSERT(kind == CodeForConstruct);
+    repatchBuffer.relink(CodeLocationCall(callLinkInfo.callReturnLocation), operationVirtualConstruct);
+}
+
+void dfgResetGetByID(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo)
+{
+    repatchBuffer.relink(stubInfo.callReturnLocation, operationGetByIdOptimize);
+    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(uintptr_t)stubInfo.patch.dfg.deltaCheckImmToCall), reinterpret_cast<void*>(-1));
+#if USE(JSVALUE64)
+    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToLoadOrStore), 0);
+#else
+    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToTagLoadOrStore), 0);
+    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToPayloadLoadOrStore), 0);
+#endif
+    repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase));
+}
+
+void dfgResetPutByID(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo)
+{
+    V_DFGOperation_EJCI unoptimizedFunction = bitwise_cast<V_DFGOperation_EJCI>(MacroAssembler::readCallTarget(stubInfo.callReturnLocation).executableAddress());
+    V_DFGOperation_EJCI optimizedFunction;
+    if (unoptimizedFunction == operationPutByIdStrict || unoptimizedFunction == operationPutByIdStrictBuildList)
+        optimizedFunction = operationPutByIdStrictOptimize;
+    else if (unoptimizedFunction == operationPutByIdNonStrict || unoptimizedFunction == operationPutByIdNonStrictBuildList)
+        optimizedFunction = operationPutByIdNonStrictOptimize;
+    else if (unoptimizedFunction == operationPutByIdDirectStrict || unoptimizedFunction == operationPutByIdDirectStrictBuildList)
+        optimizedFunction = operationPutByIdDirectStrictOptimize;
+    else {
+        ASSERT(unoptimizedFunction == operationPutByIdDirectNonStrict || unoptimizedFunction == operationPutByIdDirectNonStrictBuildList);
+        optimizedFunction = operationPutByIdDirectNonStrictOptimize;
+    }
+    repatchBuffer.relink(stubInfo.callReturnLocation, optimizedFunction);
+    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(uintptr_t)stubInfo.patch.dfg.deltaCheckImmToCall), reinterpret_cast<void*>(-1));
+#if USE(JSVALUE64)
+    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToLoadOrStore), 0);
+#else
+    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToTagLoadOrStore), 0);
+    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToPayloadLoadOrStore), 0);
+#endif
+    repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase));
+}
+
+} } // namespace JSC::DFG
+
+#endif
diff --git a/dfg/DFGRepatch.h b/dfg/DFGRepatch.h
new file mode 100644 (file)
index 0000000..83d4e97
--- /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. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED 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 DFGRepatch_h
+#define DFGRepatch_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGJITCompiler.h"
+#include "DFGOperations.h"
+
+namespace JSC { namespace DFG {
+
+void dfgRepatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
+void dfgBuildGetByIDList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
+void dfgBuildGetByIDProtoList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
+void dfgRepatchPutByID(ExecState*, JSValue, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
+void dfgBuildPutByIdList(ExecState*, JSValue, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
+void dfgLinkFor(ExecState*, CallLinkInfo&, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr, CodeSpecializationKind);
+void dfgResetGetByID(RepatchBuffer&, StructureStubInfo&);
+void dfgResetPutByID(RepatchBuffer&, StructureStubInfo&);
+
+} } // namespace JSC::DFG
+
+#else // ENABLE(DFG_JIT)
+
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+class RepatchBuffer;
+struct StructureStubInfo;
+
+namespace DFG {
+
+inline NO_RETURN_DUE_TO_ASSERT void dfgResetGetByID(RepatchBuffer&, StructureStubInfo&) { ASSERT_NOT_REACHED(); }
+inline NO_RETURN_DUE_TO_ASSERT void dfgResetPutByID(RepatchBuffer&, StructureStubInfo&) { ASSERT_NOT_REACHED(); }
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+#endif // DFGRepatch_h
index 1e44292cd2397a965f3e593d9d54816b1038dd0e..578f2b147c403b5f414823fc26b3186d6b0439fa 100644 (file)
@@ -28,7 +28,8 @@
 
 #if ENABLE(DFG_JIT)
 
 
 #if ENABLE(DFG_JIT)
 
-#include <dfg/DFGGraph.h>
+#include "DFGGraph.h"
+#include <wtf/BitVector.h>
 #include <wtf/Vector.h>
 
 namespace JSC { namespace DFG {
 #include <wtf/Vector.h>
 
 namespace JSC { namespace DFG {
@@ -42,25 +43,42 @@ namespace JSC { namespace DFG {
 // another node.
 class ScoreBoard {
 public:
 // another node.
 class ScoreBoard {
 public:
-    ScoreBoard(Graph& graph, uint32_t firstTemporary)
+    ScoreBoard(Graph& graph, const BitVector& usedVars)
         : m_graph(graph)
         : m_graph(graph)
-        , m_firstTemporary(firstTemporary)
+        , m_highWatermark(0)
     {
     {
+        m_used.fill(0, usedVars.size());
+        m_free.reserveCapacity(usedVars.size());
+        for (size_t i = usedVars.size(); i-- > 0;) {
+            if (usedVars.get(i)) {
+                m_used[i] = max(); // This is mostly for debugging and sanity.
+                m_highWatermark = std::max(m_highWatermark, static_cast<unsigned>(i) + 1);
+            } else
+                m_free.append(i);
+        }
     }
 
     }
 
-#if DFG_CONSISTENCY_CHECK
     ~ScoreBoard()
     {
     ~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.
+        assertClear();
+    }
+    
+    void assertClear()
+    {
+#if !ASSERT_DISABLED
+        // For every entry in the used list the use count of the virtual register should be zero, or max, due to it being a preserved local.
         for (size_t i = 0; i < m_used.size(); ++i)
         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.
+            ASSERT(!m_used[i] || m_used[i] == max());
+        // For every entry in the free list, the use count should be zero.
         for (size_t i = 0; i < m_free.size(); ++i)
         for (size_t i = 0; i < m_free.size(); ++i)
-            ASSERT(!m_used[i]);
-    }
+            ASSERT(!m_used[m_free[i]]);
+        // There must not be duplicates in the free list.
+        for (size_t i = 0; i < m_free.size(); ++i) {
+            for (size_t j = i + 1; j < m_free.size(); ++j)
+                ASSERT(m_free[i] != m_free[j]);
+        }
 #endif
 #endif
+    }
 
     VirtualRegister allocate()
     {
 
     VirtualRegister allocate()
     {
@@ -71,13 +89,15 @@ public:
             m_free.removeLast();
             // Use count must have hit zero for it to have been added to the free list!
             ASSERT(!m_used[index]);
             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);
+            m_highWatermark = std::max(m_highWatermark, static_cast<unsigned>(index) + 1);
+            return (VirtualRegister)index;
         }
 
         // Allocate a new VirtualRegister, and add a corresponding entry to m_used.
         }
 
         // Allocate a new VirtualRegister, and add a corresponding entry to m_used.
-        size_t next = allocatedCount();
+        size_t next = m_used.size();
         m_used.append(0);
         m_used.append(0);
-        return (VirtualRegister)(m_firstTemporary + next);
+        m_highWatermark = std::max(m_highWatermark, static_cast<unsigned>(next) + 1);
+        return (VirtualRegister)next;
     }
 
     // Increment the usecount for the VirtualRegsiter associated with 'child',
     }
 
     // Increment the usecount for the VirtualRegsiter associated with 'child',
@@ -89,8 +109,12 @@ public:
 
         // Find the virtual register number for this child, increment its use count.
         Node& node = m_graph[child];
 
         // Find the virtual register number for this child, increment its use count.
         Node& node = m_graph[child];
-        uint32_t index = node.virtualRegister() - m_firstTemporary;
+        uint32_t index = node.virtualRegister();
+        ASSERT(m_used[index] != max());
         if (node.refCount() == ++m_used[index]) {
         if (node.refCount() == ++m_used[index]) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+            dataLog(" Freeing virtual register %u.", index);
+#endif
             // 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.
             // 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.
@@ -98,40 +122,51 @@ public:
             m_free.append(index);
         }
     }
             m_free.append(index);
         }
     }
-
-    unsigned allocatedCount()
+    void use(Edge child)
     {
     {
-        // m_used contains an entry for every allocated VirtualRegister.
-        return m_used.size();
+        use(child.indexUnchecked());
     }
 
     }
 
+    unsigned highWatermark()
+    {
+        return m_highWatermark;
+    }
+    
 #ifndef NDEBUG
     void dump()
     {
 #ifndef NDEBUG
     void dump()
     {
-        printf("    USED: [ ");
+        dataLog("    USED: [ ");
         for (unsigned i = 0; i < m_used.size(); ++i) {
         for (unsigned i = 0; i < m_used.size(); ++i) {
-            if (!m_free.contains(i))
-                printf("%d:%d ", m_firstTemporary + i, m_used[i]);
+            if (!m_free.contains(i)) {
+                dataLog("%d:", i);
+                if (m_used[i] == max())
+                    dataLog("local ");
+                else
+                    dataLog("%d ", m_used[i]);
+            }
         }
         }
-        printf("]\n");
+        dataLog("]\n");
 
 
-        printf("    FREE: [ ");
+        dataLog("    FREE: [ ");
         for (unsigned i = 0; i < m_used.size(); ++i) {
         for (unsigned i = 0; i < m_used.size(); ++i) {
-            if (m_free.contains(i)) {
+            if (m_free.contains(i) && m_used[i] != max()) {
                 ASSERT(!m_used[i]);
                 ASSERT(!m_used[i]);
-                printf("%d ", m_firstTemporary + i);
+                dataLog("%d ", i);
             }
         }
             }
         }
-        printf("]\n");
+        dataLog("]\n");
     }
 
 #endif
 
 private:
     }
 
 #endif
 
 private:
+    static uint32_t max() { return std::numeric_limits<uint32_t>::max(); }
+    
     // The graph, so we can get refCounts for nodes, to determine when values are dead.
     Graph& m_graph;
     // 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;
+    
+    // The size of the span of virtual registers that this code block will use.
+    unsigned m_highWatermark;
     
     // 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
     
     // 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
index 71004fe9140a0b80ac80d997f35f6268001de59b..0bcee7510c8164b2dacfa9eaed38c4b8bfe68bba 100644 (file)
 
 #if ENABLE(DFG_JIT)
 
 
 #if ENABLE(DFG_JIT)
 
+#include "LinkBuffer.h"
+
 namespace JSC { namespace DFG {
 
 namespace JSC { namespace DFG {
 
-template<bool strict>
-GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat& returnFormat)
+// On Windows we need to wrap fmod; on other platforms we can call it directly.
+// On ARMv7 we assert that all function pointers have to low bit set (point to thumb code).
+#if CALLING_CONVENTION_IS_STDCALL || CPU(ARM_THUMB2)
+static double DFG_OPERATION fmodAsDFGOperation(double x, double y)
+{
+    return fmod(x, y);
+}
+#else
+#define fmodAsDFGOperation fmod
+#endif
+
+void SpeculativeJIT::clearGenerationInfo()
+{
+    for (unsigned i = 0; i < m_generationInfo.size(); ++i)
+        m_generationInfo[i] = GenerationInfo();
+    m_gprs = RegisterBank<GPRInfo>();
+    m_fprs = RegisterBank<FPRInfo>();
+}
+
+GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex)
 {
     Node& node = m_jit.graph()[nodeIndex];
     VirtualRegister virtualRegister = node.virtualRegister();
     GenerationInfo& info = m_generationInfo[virtualRegister];
 {
     Node& node = m_jit.graph()[nodeIndex];
     VirtualRegister virtualRegister = node.virtualRegister();
     GenerationInfo& info = m_generationInfo[virtualRegister];
-
+    
     switch (info.registerFormat()) {
     case DataFormatNone: {
     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);
-
+        if (info.spillFormat() == DataFormatStorage) {
+            GPRReg gpr = allocate();
             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
             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);
             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;
+            info.fillStorage(gpr);
             return gpr;
         }
             return gpr;
         }
-        // else fall through & handle as DataFormatJSInteger.
-        m_gprs.unlock(gpr);
+        
+        // Must be a cell; fill it as a cell and then return the pointer.
+        return fillSpeculateCell(nodeIndex);
     }
     }
-
-    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;
-        }
-
+        
+    case DataFormatStorage: {
         GPRReg gpr = info.gpr();
         m_gprs.lock(gpr);
         GPRReg gpr = info.gpr();
         m_gprs.lock(gpr);
-        returnFormat = DataFormatJSInteger;
         return gpr;
     }
         return gpr;
     }
-
-    case DataFormatInteger: {
-        GPRReg gpr = info.gpr();
-        m_gprs.lock(gpr);
-        returnFormat = DataFormatInteger;
-        return gpr;
+        
+    default:
+        return fillSpeculateCell(nodeIndex);
     }
     }
+}
 
 
-    case DataFormatDouble:
-    case DataFormatCell:
-    case DataFormatJSDouble:
-    case DataFormatJSCell: {
-        terminateSpeculativeExecution();
-        returnFormat = DataFormatInteger;
-        return allocate();
-    }
+void SpeculativeJIT::useChildren(Node& node)
+{
+    if (node.flags() & NodeHasVarArgs) {
+        for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
+            use(m_jit.graph().m_varArgChildren[childIdx]);
+    } else {
+        Edge child1 = node.child1();
+        if (!child1) {
+            ASSERT(!node.child2() && !node.child3());
+            return;
+        }
+        use(child1);
+        
+        Edge child2 = node.child2();
+        if (!child2) {
+            ASSERT(!node.child3());
+            return;
+        }
+        use(child2);
+        
+        Edge child3 = node.child3();
+        if (!child3)
+            return;
+        use(child3);
     }
     }
+}
 
 
-    ASSERT_NOT_REACHED();
-    return InvalidGPRReg;
+bool SpeculativeJIT::isStrictInt32(NodeIndex nodeIndex)
+{
+    if (isInt32Constant(nodeIndex))
+        return true;
+    
+    Node& node = m_jit.graph()[nodeIndex];
+    GenerationInfo& info = m_generationInfo[node.virtualRegister()];
+    
+    return info.registerFormat() == DataFormatInteger;
 }
 
 }
 
-SpeculationCheck::SpeculationCheck(MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex)
-    : m_check(check)
-    , m_nodeIndex(jit->m_compileIndex)
-    , m_recoveryIndex(recoveryIndex)
+bool SpeculativeJIT::isKnownInteger(NodeIndex nodeIndex)
 {
 {
-    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;
-    }
+    if (isInt32Constant(nodeIndex))
+        return true;
+
+    Node& node = m_jit.graph()[nodeIndex];
+    
+    if (node.hasInt32Result())
+        return true;
+    
+    GenerationInfo& info = m_generationInfo[node.virtualRegister()];
+
+    return info.isJSInteger();
 }
 
 }
 
-GPRReg SpeculativeJIT::fillSpeculateInt(NodeIndex nodeIndex, DataFormat& returnFormat)
+bool SpeculativeJIT::isKnownNumeric(NodeIndex nodeIndex)
 {
 {
-    return fillSpeculateIntInternal<false>(nodeIndex, returnFormat);
+    if (isInt32Constant(nodeIndex) || isNumberConstant(nodeIndex))
+        return true;
+
+    Node& node = m_jit.graph()[nodeIndex];
+    
+    if (node.hasNumberResult())
+        return true;
+    
+    GenerationInfo& info = m_generationInfo[node.virtualRegister()];
+
+    return info.isJSInteger() || info.isJSDouble();
 }
 
 }
 
-GPRReg SpeculativeJIT::fillSpeculateIntStrict(NodeIndex nodeIndex)
+bool SpeculativeJIT::isKnownCell(NodeIndex nodeIndex)
 {
 {
-    DataFormat mustBeDataFormatInteger;
-    GPRReg result = fillSpeculateIntInternal<true>(nodeIndex, mustBeDataFormatInteger);
-    ASSERT(mustBeDataFormatInteger == DataFormatInteger);
-    return result;
+    return m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()].isJSCell();
 }
 
 }
 
-GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
+bool SpeculativeJIT::isKnownNotCell(NodeIndex nodeIndex)
 {
     Node& node = m_jit.graph()[nodeIndex];
     VirtualRegister virtualRegister = node.virtualRegister();
     GenerationInfo& info = m_generationInfo[virtualRegister];
 {
     Node& node = m_jit.graph()[nodeIndex];
     VirtualRegister virtualRegister = node.virtualRegister();
     GenerationInfo& info = m_generationInfo[virtualRegister];
+    if (node.hasConstant() && !valueOfJSConstant(nodeIndex).isCell())
+        return true;
+    return !(info.isJSCell() || info.isUnknownJS());
+}
 
 
-    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);
+bool SpeculativeJIT::isKnownNotInteger(NodeIndex nodeIndex)
+{
+    Node& node = m_jit.graph()[nodeIndex];
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+    
+    return info.isJSDouble() || info.isJSCell() || info.isJSBoolean()
+        || (node.hasConstant() && !valueOfJSConstant(nodeIndex).isInt32());
+}
 
 
-        if (info.spillFormat() != DataFormatJSCell)
-            speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
-        info.fillJSValue(gpr, DataFormatJSCell);
-        return gpr;
-    }
+bool SpeculativeJIT::isKnownNotNumber(NodeIndex nodeIndex)
+{
+    Node& node = m_jit.graph()[nodeIndex];
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+    
+    return (!info.isJSDouble() && !info.isJSInteger() && !info.isUnknownJS())
+        || (node.hasConstant() && !isNumberConstant(nodeIndex));
+}
 
 
-    case DataFormatCell:
-    case DataFormatJSCell: {
-        GPRReg gpr = info.gpr();
-        m_gprs.lock(gpr);
-        return gpr;
+void SpeculativeJIT::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind)
+{
+    UNUSED_PARAM(jit);
+    UNUSED_PARAM(owner);
+    UNUSED_PARAM(scratch1);
+    UNUSED_PARAM(scratch2);
+    UNUSED_PARAM(useKind);
+    ASSERT(owner != scratch1);
+    ASSERT(owner != scratch2);
+    ASSERT(scratch1 != scratch2);
+
+#if ENABLE(WRITE_BARRIER_PROFILING)
+    JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));
+#endif
+    markCellCard(jit, owner, scratch1, scratch2);
+}
+
+void SpeculativeJIT::markCellCard(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2)
+{
+    UNUSED_PARAM(jit);
+    UNUSED_PARAM(owner);
+    UNUSED_PARAM(scratch1);
+    UNUSED_PARAM(scratch2);
+    
+#if ENABLE(GGC)
+    jit.move(owner, scratch1);
+    jit.andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch1);
+    jit.move(owner, scratch2);
+    // consume additional 8 bits as we're using an approximate filter
+    jit.rshift32(TrustedImm32(MarkedBlock::atomShift + 8), scratch2);
+    jit.andPtr(TrustedImm32(MarkedBlock::atomMask >> 8), scratch2);
+    MacroAssembler::Jump filter = jit.branchTest8(MacroAssembler::Zero, MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfMarks()));
+    jit.move(owner, scratch2);
+    jit.rshift32(TrustedImm32(MarkedBlock::cardShift), scratch2);
+    jit.andPtr(TrustedImm32(MarkedBlock::cardMask), scratch2);
+    jit.store8(TrustedImm32(1), MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfCards()));
+    filter.link(&jit);
+#endif
+}
+
+void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
+{
+    UNUSED_PARAM(ownerGPR);
+    UNUSED_PARAM(valueGPR);
+    UNUSED_PARAM(scratch1);
+    UNUSED_PARAM(scratch2);
+    UNUSED_PARAM(useKind);
+
+    if (isKnownNotCell(valueUse.index()))
+        return;
+
+#if ENABLE(WRITE_BARRIER_PROFILING)
+    JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
+#endif
+
+#if ENABLE(GGC)
+    GPRTemporary temp1;
+    GPRTemporary temp2;
+    if (scratch1 == InvalidGPRReg) {
+        GPRTemporary scratchGPR(this);
+        temp1.adopt(scratchGPR);
+        scratch1 = temp1.gpr();
+    }
+    if (scratch2 == InvalidGPRReg) {
+        GPRTemporary scratchGPR(this);
+        temp2.adopt(scratchGPR);
+        scratch2 = temp2.gpr();
+    }
+    
+    JITCompiler::Jump rhsNotCell;
+    bool hadCellCheck = false;
+    if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) {
+        hadCellCheck = true;
+        rhsNotCell = m_jit.branchIfNotCell(valueGPR);
     }
 
     }
 
-    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;
+    markCellCard(m_jit, ownerGPR, scratch1, scratch2);
+
+    if (hadCellCheck)
+        rhsNotCell.link(&m_jit);
+#endif
+}
+
+void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
+{
+    UNUSED_PARAM(ownerGPR);
+    UNUSED_PARAM(value);
+    UNUSED_PARAM(scratch1);
+    UNUSED_PARAM(scratch2);
+    UNUSED_PARAM(useKind);
+    
+    if (Heap::isMarked(value))
+        return;
+
+#if ENABLE(WRITE_BARRIER_PROFILING)
+    JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
+#endif
+
+#if ENABLE(GGC)
+    GPRTemporary temp1;
+    GPRTemporary temp2;
+    if (scratch1 == InvalidGPRReg) {
+        GPRTemporary scratchGPR(this);
+        temp1.adopt(scratchGPR);
+        scratch1 = temp1.gpr();
+    }
+    if (scratch2 == InvalidGPRReg) {
+        GPRTemporary scratchGPR(this);
+        temp2.adopt(scratchGPR);
+        scratch2 = temp2.gpr();
     }
 
     }
 
-    case DataFormatJSInteger:
-    case DataFormatInteger:
-    case DataFormatJSDouble:
-    case DataFormatDouble: {
-        terminateSpeculativeExecution();
-        return allocate();
+    markCellCard(m_jit, ownerGPR, scratch1, scratch2);
+#endif
+}
+
+void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch)
+{
+    UNUSED_PARAM(owner);
+    UNUSED_PARAM(valueGPR);
+    UNUSED_PARAM(scratch);
+    UNUSED_PARAM(useKind);
+
+    if (isKnownNotCell(valueUse.index()))
+        return;
+
+#if ENABLE(WRITE_BARRIER_PROFILING)
+    JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
+#endif
+
+#if ENABLE(GGC)
+    JITCompiler::Jump rhsNotCell;
+    bool hadCellCheck = false;
+    if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) {
+        hadCellCheck = true;
+        rhsNotCell = m_jit.branchIfNotCell(valueGPR);
     }
     }
+    
+    GPRTemporary temp;
+    if (scratch == InvalidGPRReg) {
+        GPRTemporary scratchGPR(this);
+        temp.adopt(scratchGPR);
+        scratch = temp.gpr();
     }
 
     }
 
-    ASSERT_NOT_REACHED();
-    return InvalidGPRReg;
+    uint8_t* cardAddress = Heap::addressOfCardFor(owner);
+    m_jit.move(JITCompiler::TrustedImmPtr(cardAddress), scratch);
+    m_jit.store8(JITCompiler::TrustedImm32(1), JITCompiler::Address(scratch));
+
+    if (hadCellCheck)
+        rhsNotCell.link(&m_jit);
+#endif
 }
 
 }
 
-void SpeculativeJIT::compilePeepHoleBranch(Node& node, JITCompiler::RelationalCondition condition)
+bool SpeculativeJIT::nonSpeculativeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
 {
 {
-    Node& branchNode = m_jit.graph()[m_compileIndex + 1];
-    BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
-    BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock != UINT_MAX) {
+        NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
 
 
-    // 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;
+        ASSERT(node.adjustedRefCount() == 1);
+        
+        nonSpeculativePeepholeBranch(node, branchNodeIndex, cond, helperFunction);
+    
+        m_indexInBlock = branchIndexInBlock;
+        m_compileIndex = branchNodeIndex;
+        
+        return true;
     }
     }
+    
+    nonSpeculativeNonPeepholeCompare(node, cond, helperFunction);
+    
+    return false;
+}
 
 
-    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);
+bool SpeculativeJIT::nonSpeculativeStrictEq(Node& node, bool invert)
+{
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock != UINT_MAX) {
+        NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+
+        ASSERT(node.adjustedRefCount() == 1);
+        
+        nonSpeculativePeepholeStrictEq(node, branchNodeIndex, invert);
+    
+        m_indexInBlock = branchIndexInBlock;
+        m_compileIndex = branchNodeIndex;
+        
+        return true;
     }
     }
+    
+    nonSpeculativeNonPeepholeStrictEq(node, invert);
+    
+    return false;
+}
 
 
-    // Check for fall through, otherwise we need to jump.
-    if (notTaken != (m_block + 1))
-        addBranch(m_jit.jump(), notTaken);
+#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 SpeculativeJIT::compile(Node& node)
+void SpeculativeJIT::dump(const char* label)
 {
 {
-    NodeType op = node.op;
+    if (label)
+        dataLog("<%s>\n", label);
+
+    dataLog("  gprs:\n");
+    m_gprs.dump();
+    dataLog("  fprs:\n");
+    m_fprs.dump();
+    dataLog("  VirtualRegisters:\n");
+    for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
+        GenerationInfo& info = m_generationInfo[i];
+        if (info.alive())
+            dataLog("    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
+        else
+            dataLog("    % 3d:[__][__]", i);
+        if (info.registerFormat() == DataFormatDouble)
+            dataLog(":fpr%d\n", info.fpr());
+        else if (info.registerFormat() != DataFormatNone
+#if USE(JSVALUE32_64)
+            && !(info.registerFormat() & DataFormatJS)
+#endif
+            ) {
+            ASSERT(info.gpr() != InvalidGPRReg);
+            dataLog(":%s\n", GPRInfo::debugName(info.gpr()));
+        } else
+            dataLog("\n");
+    }
+    if (label)
+        dataLog("</%s>\n", label);
+}
+#endif
 
 
-    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());
+#if DFG_ENABLE(CONSISTENCY_CHECK)
+void SpeculativeJIT::checkConsistency()
+{
+    bool failed = false;
 
 
-            // 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);
+    for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+        if (iter.isLocked()) {
+            dataLog("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()) {
+            dataLog("DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName());
+            failed = true;
         }
         }
-        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);
+    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;
             break;
-        }
-        case PredictArray: {
-            SpeculateCellOperand cell(this, node.child1);
-            m_jit.storePtr(cell.gpr(), JITCompiler::addressFor(node.local()));
-            noResult(m_compileIndex);
+        case DataFormatJS:
+        case DataFormatJSInteger:
+        case DataFormatJSDouble:
+        case DataFormatJSCell:
+        case DataFormatJSBoolean:
+#if USE(JSVALUE32_64)
+            break;
+#endif
+        case DataFormatInteger:
+        case DataFormatCell:
+        case DataFormatBoolean:
+        case DataFormatStorage: {
+            GPRReg gpr = info.gpr();
+            ASSERT(gpr != InvalidGPRReg);
+            if (m_gprs.name(gpr) != virtualRegister) {
+                dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr));
+                failed = true;
+            }
             break;
         }
             break;
         }
-
-        default: {
-            JSValueOperand value(this, node.child1);
-            m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
-            noResult(m_compileIndex);
+        case DataFormatDouble: {
+            FPRReg fpr = info.fpr();
+            ASSERT(fpr != InvalidFPRReg);
+            if (m_fprs.name(fpr) != virtualRegister) {
+                dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr));
+                failed = true;
+            }
             break;
         }
         }
             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());
+    for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+        VirtualRegister virtualRegister = iter.name();
+        if (virtualRegister == InvalidVirtualRegister)
+            continue;
 
 
-            integerResult(result.gpr(), m_compileIndex);
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+#if USE(JSVALUE64)
+        if (iter.regID() != info.gpr()) {
+            dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
+            failed = true;
+        }
+#else
+        if (!(info.registerFormat() & DataFormatJS)) {
+            if (iter.regID() != info.gpr()) {
+                dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
+                failed = true;
+            }
         } else {
         } else {
-            SpeculateIntegerOperand op1(this, node.child1);
-            SpeculateIntegerOperand op2(this, node.child2);
-            GPRTemporary result(this, op1, op2);
+            if (iter.regID() != info.tagGPR() && iter.regID() != info.payloadGPR()) {
+                dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
+                failed = true;
+            }
+        }
+#endif
+    }
 
 
-            GPRReg reg1 = op1.gpr();
-            GPRReg reg2 = op2.gpr();
-            bitOp(op, reg1, reg2, result.gpr());
+    for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+        VirtualRegister virtualRegister = iter.name();
+        if (virtualRegister == InvalidVirtualRegister)
+            continue;
 
 
-            integerResult(result.gpr(), m_compileIndex);
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        if (iter.regID() != info.fpr()) {
+            dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
+            failed = true;
         }
         }
-        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());
+    if (failed) {
+        dump();
+        CRASH();
+    }
+}
+#endif
 
 
-            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);
+GPRTemporary::GPRTemporary()
+    : m_jit(0)
+    , m_gpr(InvalidGPRReg)
+{
+}
 
 
-            GPRReg reg1 = op1.gpr();
-            GPRReg reg2 = op2.gpr();
-            shiftOp(op, reg1, reg2, result.gpr());
+GPRTemporary::GPRTemporary(SpeculativeJIT* jit)
+    : m_jit(jit)
+    , m_gpr(InvalidGPRReg)
+{
+    m_gpr = m_jit->allocate();
+}
 
 
-            integerResult(result.gpr(), m_compileIndex);
-        }
-        break;
+GPRTemporary::GPRTemporary(SpeculativeJIT* jit, GPRReg specific)
+    : m_jit(jit)
+    , m_gpr(InvalidGPRReg)
+{
+    m_gpr = m_jit->allocate(specific);
+}
 
 
-    case UInt32ToNumber: {
-        IntegerOperand op1(this, node.child1);
-        GPRTemporary result(this, op1);
+GPRTemporary::GPRTemporary(SpeculativeJIT* 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();
+}
 
 
-        // Test the operand is positive.
-        speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)));
+GPRTemporary::GPRTemporary(SpeculativeJIT* 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();
+}
 
 
-        m_jit.move(op1.gpr(), result.gpr());
-        integerResult(result.gpr(), m_compileIndex, op1.format());
-        break;
-    }
+GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateStrictInt32Operand& 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();
+}
 
 
-    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;
-    }
+GPRTemporary::GPRTemporary(SpeculativeJIT* 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();
+}
 
 
-    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;
-    }
+GPRTemporary::GPRTemporary(SpeculativeJIT* 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();
+}
 
 
-    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;
-    }
+GPRTemporary::GPRTemporary(SpeculativeJIT* 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();
+}
 
 
-    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;
-    }
+GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateBooleanOperand& 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();
+}
 
 
-    case ValueAdd:
-    case ArithAdd: {
-        int32_t imm1;
-        if (isDoubleConstantWithInt32Value(node.child1, imm1)) {
-            SpeculateIntegerOperand op2(this, node.child2);
-            GPRTemporary result(this);
+#if USE(JSVALUE64)
+GPRTemporary::GPRTemporary(SpeculativeJIT* 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();
+}
+#else
+GPRTemporary::GPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1, bool tag)
+    : m_jit(jit)
+    , m_gpr(InvalidGPRReg)
+{
+    if (!op1.isDouble() && m_jit->canReuse(op1.index()))
+        m_gpr = m_jit->reuse(tag ? op1.tagGPR() : op1.payloadGPR());
+    else
+        m_gpr = m_jit->allocate();
+}
+#endif
 
 
-            speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
+GPRTemporary::GPRTemporary(SpeculativeJIT* jit, StorageOperand& 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();
+}
 
 
-            integerResult(result.gpr(), m_compileIndex);
-            break;
-        }
-            
-        int32_t imm2;
-        if (isDoubleConstantWithInt32Value(node.child2, imm2)) {
-            SpeculateIntegerOperand op1(this, node.child1);
-            GPRTemporary result(this);
+void GPRTemporary::adopt(GPRTemporary& other)
+{
+    ASSERT(!m_jit);
+    ASSERT(m_gpr == InvalidGPRReg);
+    ASSERT(other.m_jit);
+    ASSERT(other.m_gpr != InvalidGPRReg);
+    m_jit = other.m_jit;
+    m_gpr = other.m_gpr;
+    other.m_jit = 0;
+    other.m_gpr = InvalidGPRReg;
+}
 
 
-            speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
+FPRTemporary::FPRTemporary(SpeculativeJIT* jit)
+    : m_jit(jit)
+    , m_fpr(InvalidFPRReg)
+{
+    m_fpr = m_jit->fprAllocate();
+}
 
 
-            integerResult(result.gpr(), m_compileIndex);
-            break;
+FPRTemporary::FPRTemporary(SpeculativeJIT* 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(SpeculativeJIT* 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();
+}
+
+FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& 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(SpeculativeJIT* jit, SpeculateDoubleOperand& op1, SpeculateDoubleOperand& 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();
+}
+
+#if USE(JSVALUE32_64)
+FPRTemporary::FPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1)
+    : m_jit(jit)
+    , m_fpr(InvalidFPRReg)
+{
+    if (op1.isDouble() && m_jit->canReuse(op1.index()))
+        m_fpr = m_jit->reuse(op1.fpr());
+    else
+        m_fpr = m_jit->fprAllocate();
+}
+#endif
+
+void ValueSource::dump(FILE* out) const
+{
+    switch (kind()) {
+    case SourceNotSet:
+        fprintf(out, "NotSet");
+        break;
+    case SourceIsDead:
+        fprintf(out, "IsDead");
+        break;
+    case ValueInRegisterFile:
+        fprintf(out, "InRegFile");
+        break;
+    case Int32InRegisterFile:
+        fprintf(out, "Int32");
+        break;
+    case CellInRegisterFile:
+        fprintf(out, "Cell");
+        break;
+    case BooleanInRegisterFile:
+        fprintf(out, "Bool");
+        break;
+    case DoubleInRegisterFile:
+        fprintf(out, "Double");
+        break;
+    case HaveNode:
+        fprintf(out, "Node(%d)", m_nodeIndex);
+        break;
+    }
+}
+
+void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
+{
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+    
+    SpeculateDoubleOperand op1(this, node.child1());
+    SpeculateDoubleOperand op2(this, node.child2());
+    
+    branchDouble(condition, op1.fpr(), op2.fpr(), taken);
+    jump(notTaken);
+}
+
+void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, const ClassInfo* classInfo, PredictionChecker predictionCheck)
+{
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+
+    MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
+    
+    if (taken == (m_block + 1)) {
+        condition = MacroAssembler::NotEqual;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+
+    SpeculateCellOperand op1(this, node.child1());
+    SpeculateCellOperand op2(this, node.child2());
+    
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    
+    if (!predictionCheck(m_state.forNode(node.child1()).m_type))
+        speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
+    if (!predictionCheck(m_state.forNode(node.child2()).m_type))
+        speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
+    
+    branchPtr(condition, op1GPR, op2GPR, taken);
+    jump(notTaken);
+}
+
+void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
+{
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+
+    // 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;
+    }
+
+    if (isInt32Constant(node.child1().index())) {
+        int32_t imm = valueOfInt32Constant(node.child1().index());
+        SpeculateIntegerOperand op2(this, node.child2());
+        branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
+    } else if (isInt32Constant(node.child2().index())) {
+        SpeculateIntegerOperand op1(this, node.child1());
+        int32_t imm = valueOfInt32Constant(node.child2().index());
+        branch32(condition, op1.gpr(), JITCompiler::Imm32(imm), taken);
+    } else {
+        SpeculateIntegerOperand op1(this, node.child1());
+        SpeculateIntegerOperand op2(this, node.child2());
+        branch32(condition, op1.gpr(), op2.gpr(), taken);
+    }
+
+    jump(notTaken);
+}
+
+// Returns true if the compare is fused with a subsequent branch.
+bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
+{
+    // Fused compare & branch.
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock != UINT_MAX) {
+        NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+
+        // 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);
+
+        if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())))
+            compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
+        else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2())))
+            compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
+        else if (node.op() == CompareEq) {
+            if (Node::shouldSpeculateFinalObject(
+                    at(node.child1()), at(node.child2()))) {
+                compilePeepHoleObjectEquality(
+                    node, branchNodeIndex, &JSFinalObject::s_info,
+                    isFinalObjectPrediction);
+            } else if (Node::shouldSpeculateArray(
+                           at(node.child1()), at(node.child2()))) {
+                compilePeepHoleObjectEquality(
+                    node, branchNodeIndex, &JSArray::s_info,
+                    isArrayPrediction);
+            } else if (at(node.child1()).shouldSpeculateFinalObject()
+                       && at(node.child2()).shouldSpeculateFinalObjectOrOther()) {
+                compilePeepHoleObjectToObjectOrOtherEquality(
+                    node.child1(), node.child2(), branchNodeIndex,
+                    &JSFinalObject::s_info, isFinalObjectPrediction);
+            } else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()
+                       && at(node.child2()).shouldSpeculateFinalObject()) {
+                compilePeepHoleObjectToObjectOrOtherEquality(
+                    node.child2(), node.child1(), branchNodeIndex,
+                    &JSFinalObject::s_info, isFinalObjectPrediction);
+            } else if (at(node.child1()).shouldSpeculateArray()
+                       && at(node.child2()).shouldSpeculateArrayOrOther()) {
+                compilePeepHoleObjectToObjectOrOtherEquality(
+                    node.child1(), node.child2(), branchNodeIndex,
+                    &JSArray::s_info, isArrayPrediction);
+            } else if (at(node.child1()).shouldSpeculateArrayOrOther()
+                       && at(node.child2()).shouldSpeculateArray()) {
+                compilePeepHoleObjectToObjectOrOtherEquality(
+                    node.child2(), node.child1(), branchNodeIndex,
+                    &JSArray::s_info, isArrayPrediction);
+            } else {
+                nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
+                return true;
+            }
+        } else {
+            nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
+            return true;
         }
         }
-            
-        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);
+        use(node.child1());
+        use(node.child2());
+        m_indexInBlock = branchIndexInBlock;
+        m_compileIndex = branchNodeIndex;
+        return true;
+    }
+    return false;
+}
+
+void SpeculativeJIT::compileMovHint(Node& node)
+{
+    ASSERT(node.op() == SetLocal);
+    
+    setNodeIndexForOperand(node.child1().index(), node.local());
+    m_lastSetOperand = node.local();
+}
 
 
-        if (gpr1 == gprResult)
-            speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
-        else if (gpr2 == gprResult)
-            speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
+void SpeculativeJIT::compile(BasicBlock& block)
+{
+    ASSERT(m_compileOkay);
+    
+    if (!block.isReachable)
+        return;
+
+    m_blockHeads[m_block] = m_jit.label();
+#if DFG_ENABLE(JIT_BREAK_ON_EVERY_BLOCK)
+    m_jit.breakpoint();
+#endif
+    
+    m_jit.jitAssertHasValidCallFrame();
+
+    ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
+    for (size_t i = 0; i < m_arguments.size(); ++i) {
+        NodeIndex nodeIndex = block.variablesAtHead.argument(i);
+        if (nodeIndex == NoNode || m_jit.graph().argumentIsCaptured(i))
+            m_arguments[i] = ValueSource(ValueInRegisterFile);
+        else
+            m_arguments[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
+    }
+    
+    m_state.reset();
+    m_state.beginBasicBlock(&block);
+    
+    ASSERT(m_variables.size() == block.variablesAtHead.numberOfLocals());
+    for (size_t i = 0; i < m_variables.size(); ++i) {
+        NodeIndex nodeIndex = block.variablesAtHead.local(i);
+        if ((nodeIndex == NoNode || !at(nodeIndex).refCount()) && !m_jit.graph().localIsCaptured(i))
+            m_variables[i] = ValueSource(SourceIsDead);
+        else if (m_jit.graph().localIsCaptured(i))
+            m_variables[i] = ValueSource(ValueInRegisterFile);
+        else if (at(nodeIndex).variableAccessData()->shouldUseDoubleFormat())
+            m_variables[i] = ValueSource(DoubleInRegisterFile);
         else
         else
-            speculationCheck(check);
+            m_variables[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
+    }
+    
+    m_lastSetOperand = std::numeric_limits<int>::max();
+    m_codeOriginForOSR = CodeOrigin();
+    
+    if (DFG_ENABLE_EDGE_CODE_VERIFICATION) {
+        JITCompiler::Jump verificationSucceeded =
+            m_jit.branch32(JITCompiler::Equal, GPRInfo::regT0, TrustedImm32(m_block));
+        m_jit.breakpoint();
+        verificationSucceeded.link(&m_jit);
+    }
 
 
-        integerResult(gprResult, m_compileIndex);
-        break;
+    for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) {
+        m_compileIndex = block[m_indexInBlock];
+        Node& node = at(m_compileIndex);
+        m_codeOriginForOSR = node.codeOrigin;
+        if (!node.shouldGenerate()) {
+#if DFG_ENABLE(DEBUG_VERBOSE)
+            dataLog("SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
+#endif
+            switch (node.op()) {
+            case SetLocal:
+                compileMovHint(node);
+                break;
+
+            case InlineStart: {
+                InlineCallFrame* inlineCallFrame = node.codeOrigin.inlineCallFrame;
+                int argumentCountIncludingThis = inlineCallFrame->arguments.size();
+                for (int i = 0; i < argumentCountIncludingThis; ++i) {
+                    ValueRecovery recovery = computeValueRecoveryFor(m_variables[inlineCallFrame->stackOffset + CallFrame::argumentOffsetIncludingThis(i)]);
+                    // The recovery should refer either to something that has already been
+                    // stored into the register file at the right place, or to a constant,
+                    // since the Arguments code isn't smart enough to handle anything else.
+                    // The exception is the this argument, which we don't really need to be
+                    // able to recover.
+#if DFG_ENABLE(DEBUG_VERBOSE)
+                    dataLog("\nRecovery for argument %d: ", i);
+                    recovery.dump(WTF::dataFile());
+#endif
+                    ASSERT(!i || (recovery.isAlreadyInRegisterFile() || recovery.isConstant()));
+                    inlineCallFrame->arguments[i] = recovery;
+                }
+                break;
+            }
+                
+            default:
+                break;
+            }
+        } else {
+            
+#if DFG_ENABLE(DEBUG_VERBOSE)
+            dataLog("SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
+#endif
+#if DFG_ENABLE(JIT_BREAK_ON_EVERY_NODE)
+            m_jit.breakpoint();
+#endif
+#if DFG_ENABLE(XOR_DEBUG_AID)
+            m_jit.xorPtr(JITCompiler::TrustedImm32(m_compileIndex), GPRInfo::regT0);
+            m_jit.xorPtr(JITCompiler::TrustedImm32(m_compileIndex), GPRInfo::regT0);
+#endif
+            checkConsistency();
+            compile(node);
+            if (!m_compileOkay) {
+                m_compileOkay = true;
+                clearGenerationInfo();
+                return;
+            }
+            
+#if DFG_ENABLE(DEBUG_VERBOSE)
+            if (node.hasResult()) {
+                GenerationInfo& info = m_generationInfo[node.virtualRegister()];
+                dataLog("-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)node.virtualRegister());
+                if (info.registerFormat() != DataFormatNone) {
+                    if (info.registerFormat() == DataFormatDouble)
+                        dataLog(", %s", FPRInfo::debugName(info.fpr()));
+#if USE(JSVALUE32_64)
+                    else if (info.registerFormat() & DataFormatJS)
+                        dataLog(", %s %s", GPRInfo::debugName(info.tagGPR()), GPRInfo::debugName(info.payloadGPR()));
+#endif
+                    else
+                        dataLog(", %s", GPRInfo::debugName(info.gpr()));
+                }
+                dataLog("    ");
+            } else
+                dataLog("    ");
+#endif
+        }
+        
+#if DFG_ENABLE(VERBOSE_VALUE_RECOVERIES)
+        for (size_t i = 0; i < m_arguments.size(); ++i)
+            computeValueRecoveryFor(argumentToOperand(i)).dump(stderr);
+        
+        dataLog(" : ");
+        
+        for (int operand = 0; operand < (int)m_variables.size(); ++operand)
+            computeValueRecoveryFor(operand).dump(stderr);
+#endif
+
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("\n");
+#endif
+        
+        // Make sure that the abstract state is rematerialized for the next node.
+        m_state.execute(m_indexInBlock);
+        
+        if (node.shouldGenerate())
+            checkConsistency();
+    }
+    
+    // Perform the most basic verification that children have been used correctly.
+#if !ASSERT_DISABLED
+    for (unsigned index = 0; index < m_generationInfo.size(); ++index) {
+        GenerationInfo& info = m_generationInfo[index];
+        ASSERT(!info.alive());
+    }
+#endif
+}
+
+// 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);
+    m_codeOriginForOSR = CodeOrigin(0);
+
+    for (size_t i = 0; i < m_arguments.size(); ++i)
+        m_arguments[i] = ValueSource(ValueInRegisterFile);
+    for (size_t i = 0; i < m_variables.size(); ++i)
+        m_variables[i] = ValueSource(ValueInRegisterFile);
+    
+    for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
+        NodeIndex nodeIndex = m_jit.graph().m_arguments[i];
+        Node& node = at(nodeIndex);
+        ASSERT(node.op() == SetArgument);
+        if (!node.shouldGenerate()) {
+            // The argument is dead. We don't do any checks for such arguments.
+            continue;
+        }
+        
+        VariableAccessData* variableAccessData = node.variableAccessData();
+        VirtualRegister virtualRegister = variableAccessData->local();
+        PredictedType predictedType = variableAccessData->prediction();
+
+        JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
+        
+#if USE(JSVALUE64)
+        if (isInt32Prediction(predictedType))
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
+        else if (isArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        } else if (isBooleanPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
+        } else if (isInt8ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
+        } else if (isInt16ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
+        } else if (isInt32ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
+        } else if (isUint8ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
+        } else if (isUint8ClampedArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
+        } else if (isUint16ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
+        } else if (isUint32ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
+        } else if (isFloat32ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
+        } else if (isFloat64ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
+        }
+#else
+        if (isInt32Prediction(predictedType))
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
+        else if (isArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        } else if (isBooleanPrediction(predictedType))
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
+        else if (isInt8ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
+        } else if (isInt16ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
+        } else if (isInt32ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
+        } else if (isUint8ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
+        } else if (isUint8ClampedArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
+        } else if (isUint16ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
+        }  else if (isUint32ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
+        }  else if (isFloat32ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
+        }   else if (isFloat64ArrayPrediction(predictedType)) {
+            GPRTemporary temp(this);
+            m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
+            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
+        } 
+#endif
+    }
+}
+
+bool SpeculativeJIT::compile()
+{
+    checkArgumentTypes();
+
+    if (DFG_ENABLE_EDGE_CODE_VERIFICATION)
+        m_jit.move(TrustedImm32(0), GPRInfo::regT0);
+
+    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]);
+    linkBranches();
+    return true;
+}
+
+void SpeculativeJIT::createOSREntries()
+{
+    for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
+        BasicBlock& block = *m_jit.graph().m_blocks[blockIndex];
+        if (!block.isOSRTarget)
+            continue;
+
+        // Currently we only need to create OSR entry trampolines when using edge code
+        // verification. But in the future, we'll need this for other things as well (like
+        // when we have global reg alloc).
+        // If we don't need OSR entry trampolin
+        if (!DFG_ENABLE_EDGE_CODE_VERIFICATION) {
+            m_osrEntryHeads.append(m_blockHeads[blockIndex]);
+            continue;
+        }
+        
+        m_osrEntryHeads.append(m_jit.label());
+        m_jit.move(TrustedImm32(blockIndex), GPRInfo::regT0);
+        m_jit.jump().linkTo(m_blockHeads[blockIndex], &m_jit);
+    }
+}
+
+void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
+{
+    unsigned osrEntryIndex = 0;
+    for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
+        BasicBlock& block = *m_jit.graph().m_blocks[blockIndex];
+        if (block.isOSRTarget)
+            m_jit.noticeOSREntry(block, m_osrEntryHeads[osrEntryIndex++], linkBuffer);
+    }
+    ASSERT(osrEntryIndex == m_osrEntryHeads.size());
+}
+
+ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
+{
+    switch (valueSource.kind()) {
+    case SourceIsDead:
+        return ValueRecovery::constant(jsUndefined());
+        
+    case ValueInRegisterFile:
+        return ValueRecovery::alreadyInRegisterFile();
+        
+    case Int32InRegisterFile:
+        return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
+
+    case CellInRegisterFile:
+        return ValueRecovery::alreadyInRegisterFileAsUnboxedCell();
+
+    case BooleanInRegisterFile:
+        return ValueRecovery::alreadyInRegisterFileAsUnboxedBoolean();
+        
+    case DoubleInRegisterFile:
+        return ValueRecovery::alreadyInRegisterFileAsUnboxedDouble();
+
+    case HaveNode: {
+        if (isConstant(valueSource.nodeIndex()))
+            return ValueRecovery::constant(valueOfJSConstant(valueSource.nodeIndex()));
+    
+        Node* nodePtr = &at(valueSource.nodeIndex());
+        if (!nodePtr->shouldGenerate()) {
+            // It's legitimately dead. As in, nobody will ever use this node, or operand,
+            // ever. Set it to Undefined to make the GC happy after the OSR.
+            return ValueRecovery::constant(jsUndefined());
+        }
+    
+        GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
+        if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
+            // Try to see if there is an alternate node that would contain the value we want.
+            // There are four possibilities:
+            //
+            // Int32ToDouble: We can use this in place of the original node, but
+            //    we'd rather not; so we use it only if it is the only remaining
+            //    live version.
+            //
+            // ValueToInt32: If the only remaining live version of the value is
+            //    ValueToInt32, then we can use it.
+            //
+            // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
+            //    then the only remaining uses are ones that want a properly formed number
+            //    rather than a UInt32 intermediate.
+            //
+            // The reverse of the above: This node could be a UInt32ToNumber, but its
+            //    alternative is still alive. This means that the only remaining uses of
+            //    the number would be fine with a UInt32 intermediate.
+            //
+            // DoubleAsInt32: Same as UInt32ToNumber.
+            //
+        
+            bool found = false;
+        
+            if (nodePtr->op() == UInt32ToNumber || nodePtr->op() == DoubleAsInt32) {
+                NodeIndex nodeIndex = nodePtr->child1().index();
+                nodePtr = &at(nodeIndex);
+                infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
+                if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
+                    found = true;
+            }
+        
+            if (!found) {
+                NodeIndex int32ToDoubleIndex = NoNode;
+                NodeIndex valueToInt32Index = NoNode;
+                NodeIndex uint32ToNumberIndex = NoNode;
+                NodeIndex doubleAsInt32Index = NoNode;
+            
+                for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
+                    GenerationInfo& info = m_generationInfo[virtualRegister];
+                    if (!info.alive())
+                        continue;
+                    if (info.nodeIndex() == NoNode)
+                        continue;
+                    Node& node = at(info.nodeIndex());
+                    if (node.child1Unchecked() != valueSource.nodeIndex())
+                        continue;
+                    switch (node.op()) {
+                    case Int32ToDouble:
+                        int32ToDoubleIndex = info.nodeIndex();
+                        break;
+                    case ValueToInt32:
+                        valueToInt32Index = info.nodeIndex();
+                        break;
+                    case UInt32ToNumber:
+                        uint32ToNumberIndex = info.nodeIndex();
+                        break;
+                    case DoubleAsInt32:
+                        doubleAsInt32Index = info.nodeIndex();
+                    default:
+                        break;
+                    }
+                }
+            
+                NodeIndex nodeIndexToUse;
+                if (doubleAsInt32Index != NoNode)
+                    nodeIndexToUse = doubleAsInt32Index;
+                else if (int32ToDoubleIndex != NoNode)
+                    nodeIndexToUse = int32ToDoubleIndex;
+                else if (valueToInt32Index != NoNode)
+                    nodeIndexToUse = valueToInt32Index;
+                else if (uint32ToNumberIndex != NoNode)
+                    nodeIndexToUse = uint32ToNumberIndex;
+                else
+                    nodeIndexToUse = NoNode;
+            
+                if (nodeIndexToUse != NoNode) {
+                    nodePtr = &at(nodeIndexToUse);
+                    infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
+                    ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
+                    found = true;
+                }
+            }
+        
+            if (!found)
+                return ValueRecovery::constant(jsUndefined());
+        }
+    
+        ASSERT(infoPtr->alive());
+
+        if (infoPtr->registerFormat() != DataFormatNone) {
+            if (infoPtr->registerFormat() == DataFormatDouble)
+                return ValueRecovery::inFPR(infoPtr->fpr());
+#if USE(JSVALUE32_64)
+            if (infoPtr->registerFormat() & DataFormatJS)
+                return ValueRecovery::inPair(infoPtr->tagGPR(), infoPtr->payloadGPR());
+#endif
+            return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
+        }
+        if (infoPtr->spillFormat() != DataFormatNone)
+            return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()), infoPtr->spillFormat());
+    
+        ASSERT_NOT_REACHED();
+        return ValueRecovery();
+    }
+        
+    default:
+        ASSERT_NOT_REACHED();
+        return ValueRecovery();
+    }
+}
+
+void SpeculativeJIT::compileGetCharCodeAt(Node& node)
+{
+    ASSERT(node.child3() == NoNode);
+    SpeculateCellOperand string(this, node.child1());
+    SpeculateStrictInt32Operand index(this, node.child2());
+    StorageOperand storage(this, node.child3());
+
+    GPRReg stringReg = string.gpr();
+    GPRReg indexReg = index.gpr();
+    GPRReg storageReg = storage.gpr();
+    
+    if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
+        ASSERT(!(at(node.child1()).prediction() & PredictString));
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        noResult(m_compileIndex);
+        return;
+    }
+
+    // unsigned comparison so we can filter out negative indices and indices that are too large
+    speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, indexReg, MacroAssembler::Address(stringReg, JSString::offsetOfLength())));
+
+    GPRTemporary scratch(this);
+    GPRReg scratchReg = scratch.gpr();
+
+    m_jit.loadPtr(MacroAssembler::Address(stringReg, JSString::offsetOfValue()), scratchReg);
+
+    // Load the character into scratchReg
+    JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
+
+    m_jit.load8(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesOne, 0), scratchReg);
+    JITCompiler::Jump cont8Bit = m_jit.jump();
+
+    is16Bit.link(&m_jit);
+
+    m_jit.load16(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesTwo, 0), scratchReg);
+
+    cont8Bit.link(&m_jit);
+
+    integerResult(scratchReg, m_compileIndex);
+}
+
+void SpeculativeJIT::compileGetByValOnString(Node& node)
+{
+    SpeculateCellOperand base(this, node.child1());
+    SpeculateStrictInt32Operand property(this, node.child2());
+    StorageOperand storage(this, node.child3());
+    GPRReg baseReg = base.gpr();
+    GPRReg propertyReg = property.gpr();
+    GPRReg storageReg = storage.gpr();
+
+    if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
+        ASSERT(!(at(node.child1()).prediction() & PredictString));
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        noResult(m_compileIndex);
+        return;
+    }
+
+    // unsigned comparison so we can filter out negative indices and indices that are too large
+    speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSString::offsetOfLength())));
+
+    GPRTemporary scratch(this);
+    GPRReg scratchReg = scratch.gpr();
+
+    m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
+
+    // Load the character into scratchReg
+    JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
+
+    m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, 0), scratchReg);
+    JITCompiler::Jump cont8Bit = m_jit.jump();
+
+    is16Bit.link(&m_jit);
+
+    m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo, 0), scratchReg);
+
+    // We only support ascii characters
+    speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, scratchReg, TrustedImm32(0x100)));
+
+    // 8 bit string values don't need the isASCII check.
+    cont8Bit.link(&m_jit);
+
+    GPRTemporary smallStrings(this);
+    GPRReg smallStringsReg = smallStrings.gpr();
+    m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalData()->smallStrings.singleCharacterStrings()), smallStringsReg);
+    m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, scratchReg, MacroAssembler::ScalePtr, 0), scratchReg);
+    speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
+    cellResult(scratchReg, m_compileIndex);
+}
+
+GeneratedOperandType SpeculativeJIT::checkGeneratedTypeForToInt32(NodeIndex nodeIndex)
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("checkGeneratedTypeForToInt32@%d   ", nodeIndex);
+#endif
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    if (info.registerFormat() == DataFormatNone) {
+        if (node.hasConstant()) {
+            if (isInt32Constant(nodeIndex))
+                return GeneratedOperandInteger;
+
+            if (isNumberConstant(nodeIndex))
+                return GeneratedOperandDouble;
+
+            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            return GeneratedOperandTypeUnknown;
+        }
+
+        if (info.spillFormat() == DataFormatDouble)
+            return GeneratedOperandDouble;
     }
 
     }
 
-    case ArithSub: {
-        int32_t imm2;
-        if (isDoubleConstantWithInt32Value(node.child2, imm2)) {
-            SpeculateIntegerOperand op1(this, node.child1);
+    switch (info.registerFormat()) {
+    case DataFormatBoolean: // This type never occurs.
+    case DataFormatStorage:
+        ASSERT_NOT_REACHED();
+
+    case DataFormatCell:
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        return GeneratedOperandTypeUnknown;
+
+    case DataFormatNone:
+    case DataFormatJSCell:
+    case DataFormatJS:
+    case DataFormatJSBoolean:
+        return GeneratedOperandJSValue;
+
+    case DataFormatJSInteger:
+    case DataFormatInteger:
+        return GeneratedOperandInteger;
+
+    case DataFormatJSDouble:
+    case DataFormatDouble:
+        return GeneratedOperandDouble;
+    }
+
+    ASSERT_NOT_REACHED();
+    return GeneratedOperandTypeUnknown;
+}
+
+void SpeculativeJIT::compileValueToInt32(Node& node)
+{
+    if (at(node.child1()).shouldSpeculateInteger()) {
+        SpeculateIntegerOperand op1(this, node.child1());
+        GPRTemporary result(this, op1);
+        m_jit.move(op1.gpr(), result.gpr());
+        integerResult(result.gpr(), m_compileIndex, op1.format());
+        return;
+    }
+    
+    if (at(node.child1()).shouldSpeculateNumber()) {
+        switch (checkGeneratedTypeForToInt32(node.child1().index())) {
+        case GeneratedOperandInteger: {
+            SpeculateIntegerOperand op1(this, node.child1());
+            GPRTemporary result(this, op1);
+            m_jit.move(op1.gpr(), result.gpr());
+            integerResult(result.gpr(), m_compileIndex, op1.format());
+            return;
+        }
+        case GeneratedOperandDouble: {
             GPRTemporary result(this);
             GPRTemporary result(this);
+            DoubleOperand op1(this, node.child1());
+            FPRReg fpr = op1.fpr();
+            GPRReg gpr = result.gpr();
+            JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
 
 
-            speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
+            silentSpillAllRegisters(gpr);
+            callOperation(toInt32, gpr, fpr);
+            silentFillAllRegisters(gpr);
 
 
-            integerResult(result.gpr(), m_compileIndex);
+            truncatedToInteger.link(&m_jit);
+            integerResult(gpr, m_compileIndex);
+            return;
+        }
+        case GeneratedOperandJSValue: {
+            GPRTemporary result(this);
+#if USE(JSVALUE64)
+            JSValueOperand op1(this, node.child1());
+
+            GPRReg gpr = op1.gpr();
+            GPRReg resultGpr = result.gpr();
+            FPRTemporary tempFpr(this);
+            FPRReg fpr = tempFpr.fpr();
+
+            JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
+
+            speculationCheck(BadType, JSValueRegs(gpr), node.child1().index(), m_jit.branchTestPtr(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
+
+            // First, if we get here we have a double encoded as a JSValue
+            m_jit.move(gpr, resultGpr);
+            unboxDouble(resultGpr, fpr);
+
+            silentSpillAllRegisters(resultGpr);
+            callOperation(toInt32, resultGpr, fpr);
+            silentFillAllRegisters(resultGpr);
+
+            JITCompiler::Jump converted = m_jit.jump();
+
+            isInteger.link(&m_jit);
+            m_jit.zeroExtend32ToPtr(gpr, resultGpr);
+
+            converted.link(&m_jit);
+#else
+            Node& childNode = at(node.child1().index());
+            VirtualRegister virtualRegister = childNode.virtualRegister();
+            GenerationInfo& info = m_generationInfo[virtualRegister];
+
+            JSValueOperand op1(this, node.child1());
+
+            GPRReg payloadGPR = op1.payloadGPR();
+            GPRReg resultGpr = result.gpr();
+
+            if (info.registerFormat() == DataFormatJSInteger)
+                m_jit.move(payloadGPR, resultGpr);
+            else {
+                GPRReg tagGPR = op1.tagGPR();
+                FPRTemporary tempFpr(this);
+                FPRReg fpr = tempFpr.fpr();
+                FPRTemporary scratch(this);
+
+                JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
+
+                speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node.child1().index(), m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
+
+                unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
+
+                silentSpillAllRegisters(resultGpr);
+                callOperation(toInt32, resultGpr, fpr);
+                silentFillAllRegisters(resultGpr);
+
+                JITCompiler::Jump converted = m_jit.jump();
+
+                isInteger.link(&m_jit);
+                m_jit.move(payloadGPR, resultGpr);
+
+                converted.link(&m_jit);
+            }
+#endif
+            integerResult(resultGpr, m_compileIndex);
+            return;
+        }
+        case GeneratedOperandTypeUnknown:
+            ASSERT_NOT_REACHED();
             break;
         }
             break;
         }
+    }
+    
+    if (at(node.child1()).shouldSpeculateBoolean()) {
+        SpeculateBooleanOperand op1(this, node.child1());
+        GPRTemporary result(this, op1);
+        
+        m_jit.and32(JITCompiler::TrustedImm32(1), op1.gpr());
+        
+        integerResult(op1.gpr(), m_compileIndex);
+        return;
+    }
+    
+    // Do it the safe way.
+    nonSpeculativeValueToInt32(node);
+    return;
+}
+
+void SpeculativeJIT::compileUInt32ToNumber(Node& node)
+{
+    if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
+        // We know that this sometimes produces doubles. So produce a double every
+        // time. This at least allows subsequent code to not have weird conditionals.
             
             
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this);
+        IntegerOperand op1(this, node.child1());
+        FPRTemporary result(this);
+            
+        GPRReg inputGPR = op1.gpr();
+        FPRReg outputFPR = result.fpr();
+            
+        m_jit.convertInt32ToDouble(inputGPR, outputFPR);
+            
+        JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
+        m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), outputFPR);
+        positive.link(&m_jit);
+            
+        doubleResult(outputFPR, m_compileIndex);
+        return;
+    }
 
 
-        speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
+    IntegerOperand op1(this, node.child1());
+    GPRTemporary result(this, op1);
 
 
-        integerResult(result.gpr(), m_compileIndex);
-        break;
+    // Test the operand is positive. This is a very special speculation check - we actually
+    // use roll-forward speculation here, where if this fails, we jump to the baseline
+    // instruction that follows us, rather than the one we're executing right now. We have
+    // to do this because by this point, the original values necessary to compile whatever
+    // operation the UInt32ToNumber originated from might be dead.
+    forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)), ValueRecovery::uint32InGPR(op1.gpr()));
+
+    m_jit.move(op1.gpr(), result.gpr());
+    integerResult(result.gpr(), m_compileIndex, op1.format());
+}
+
+void SpeculativeJIT::compileDoubleAsInt32(Node& node)
+{
+    SpeculateDoubleOperand op1(this, node.child1());
+    FPRTemporary scratch(this);
+    GPRTemporary result(this);
+    
+    FPRReg valueFPR = op1.fpr();
+    FPRReg scratchFPR = scratch.fpr();
+    GPRReg resultGPR = result.gpr();
+
+    JITCompiler::JumpList failureCases;
+    m_jit.branchConvertDoubleToInt32(valueFPR, resultGPR, failureCases, scratchFPR);
+    forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, failureCases, ValueRecovery::inFPR(valueFPR));
+
+    integerResult(resultGPR, m_compileIndex);
+}
+
+void SpeculativeJIT::compileInt32ToDouble(Node& node)
+{
+#if USE(JSVALUE64)
+    // On JSVALUE64 we have a way of loading double constants in a more direct manner
+    // than a int->double conversion. On 32_64, unfortunately, we currently don't have
+    // any such mechanism - though we could have it, if we just provisioned some memory
+    // in CodeBlock for the double form of integer constants.
+    if (at(node.child1()).hasConstant()) {
+        ASSERT(isInt32Constant(node.child1().index()));
+        FPRTemporary result(this);
+        GPRTemporary temp(this);
+        m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(node.child1().index())))), temp.gpr());
+        m_jit.movePtrToDouble(temp.gpr(), result.fpr());
+        doubleResult(result.fpr(), m_compileIndex);
+        return;
+    }
+#endif
+    
+    if (isInt32Prediction(m_state.forNode(node.child1()).m_type)) {
+        SpeculateIntegerOperand op1(this, node.child1());
+        FPRTemporary result(this);
+        m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
+        doubleResult(result.fpr(), m_compileIndex);
+        return;
     }
     }
+    
+    JSValueOperand op1(this, node.child1());
+    FPRTemporary result(this);
+    
+#if USE(JSVALUE64)
+    GPRTemporary temp(this);
+
+    GPRReg op1GPR = op1.gpr();
+    GPRReg tempGPR = temp.gpr();
+    FPRReg resultFPR = result.fpr();
+    
+    JITCompiler::Jump isInteger = m_jit.branchPtr(
+        MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
+    
+    speculationCheck(
+        BadType, JSValueRegs(op1GPR), node.child1(),
+        m_jit.branchTestPtr(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
+    
+    m_jit.move(op1GPR, tempGPR);
+    unboxDouble(tempGPR, resultFPR);
+    JITCompiler::Jump done = m_jit.jump();
+    
+    isInteger.link(&m_jit);
+    m_jit.convertInt32ToDouble(op1GPR, resultFPR);
+    done.link(&m_jit);
+#else
+    FPRTemporary temp(this);
+    
+    GPRReg op1TagGPR = op1.tagGPR();
+    GPRReg op1PayloadGPR = op1.payloadGPR();
+    FPRReg tempFPR = temp.fpr();
+    FPRReg resultFPR = result.fpr();
+    
+    JITCompiler::Jump isInteger = m_jit.branch32(
+        MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
+    
+    speculationCheck(
+        BadType, JSValueRegs(op1TagGPR, op1PayloadGPR), node.child1(),
+        m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
+    
+    unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
+    JITCompiler::Jump done = m_jit.jump();
+    
+    isInteger.link(&m_jit);
+    m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR);
+    done.link(&m_jit);
+#endif
+    
+    doubleResult(resultFPR, m_compileIndex);
+}
 
 
-    case ArithMul: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this);
+static double clampDoubleToByte(double d)
+{
+    d += 0.5;
+    if (!(d > 0))
+        d = 0;
+    else if (d > 255)
+        d = 255;
+    return d;
+}
 
 
-        GPRReg reg1 = op1.gpr();
-        GPRReg reg2 = op2.gpr();
-        speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
+static void compileClampIntegerToByte(JITCompiler& jit, GPRReg result)
+{
+    MacroAssembler::Jump inBounds = jit.branch32(MacroAssembler::BelowOrEqual, result, JITCompiler::TrustedImm32(0xff));
+    MacroAssembler::Jump tooBig = jit.branch32(MacroAssembler::GreaterThan, result, JITCompiler::TrustedImm32(0xff));
+    jit.xorPtr(result, result);
+    MacroAssembler::Jump clamped = jit.jump();
+    tooBig.link(&jit);
+    jit.move(JITCompiler::TrustedImm32(255), result);
+    clamped.link(&jit);
+    inBounds.link(&jit);
+}
 
 
-        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);
+static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
+{
+    // Unordered compare so we pick up NaN
+    static const double zero = 0;
+    static const double byteMax = 255;
+    static const double half = 0.5;
+    jit.loadDouble(&zero, scratch);
+    MacroAssembler::Jump tooSmall = jit.branchDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered, source, scratch);
+    jit.loadDouble(&byteMax, scratch);
+    MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
+    
+    jit.loadDouble(&half, scratch);
+    // FIXME: This should probably just use a floating point round!
+    // https://bugs.webkit.org/show_bug.cgi?id=72054
+    jit.addDouble(source, scratch);
+    jit.truncateDoubleToInt32(scratch, result);   
+    MacroAssembler::Jump truncatedInt = jit.jump();
+    
+    tooSmall.link(&jit);
+    jit.xorPtr(result, result);
+    MacroAssembler::Jump zeroed = jit.jump();
+    
+    tooBig.link(&jit);
+    jit.move(JITCompiler::TrustedImm32(255), result);
+    
+    truncatedInt.link(&jit);
+    zeroed.link(&jit);
 
 
-        integerResult(result.gpr(), m_compileIndex);
+}
+
+void SpeculativeJIT::compileGetTypedArrayLength(const TypedArrayDescriptor& descriptor, Node& node, bool needsSpeculationCheck)
+{
+    SpeculateCellOperand base(this, node.child1());
+    GPRTemporary result(this);
+    
+    GPRReg baseGPR = base.gpr();
+    GPRReg resultGPR = result.gpr();
+    
+    if (needsSpeculationCheck)
+        speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+    
+    m_jit.load32(MacroAssembler::Address(baseGPR, descriptor.m_lengthOffset), resultGPR);
+    
+    integerResult(resultGPR, m_compileIndex);
+}
+
+void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness)
+{
+    SpeculateCellOperand base(this, node.child1());
+    SpeculateStrictInt32Operand property(this, node.child2());
+    StorageOperand storage(this, node.child3());
+
+    GPRReg baseReg = base.gpr();
+    GPRReg propertyReg = property.gpr();
+    GPRReg storageReg = storage.gpr();
+
+    GPRTemporary result(this);
+    GPRReg resultReg = result.gpr();
+
+    if (speculationRequirements != NoTypedArrayTypeSpecCheck) {
+        ASSERT_NOT_REACHED();
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        noResult(m_compileIndex);
+        return;
+    }
+
+    MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset));
+    m_jit.xorPtr(resultReg, resultReg);
+    MacroAssembler::Jump outOfBounds = m_jit.jump();
+    inBounds.link(&m_jit);
+    switch (elementSize) {
+    case 1:
+        if (signedness == SignedTypedArray)
+            m_jit.load8Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
+        else
+            m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
+        break;
+    case 2:
+        if (signedness == SignedTypedArray)
+            m_jit.load16Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
+        else
+            m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
+        break;
+    case 4:
+        m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
         break;
         break;
+    default:
+        ASSERT_NOT_REACHED();
     }
     }
+    outOfBounds.link(&m_jit);
+    if (elementSize < 4 || signedness == SignedTypedArray) {
+        integerResult(resultReg, m_compileIndex);
+        return;
+    }
+    
+    ASSERT(elementSize == 4 && signedness == UnsignedTypedArray);
+    if (node.shouldSpeculateInteger()) {
+        forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultReg, TrustedImm32(0)), ValueRecovery::uint32InGPR(resultReg));
+        integerResult(resultReg, m_compileIndex);
+        return;
+    }
+    
+    FPRTemporary fresult(this);
+    m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
+    JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
+    m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
+    positive.link(&m_jit);
+    doubleResult(fresult.fpr(), m_compileIndex);
+}
 
 
-    case ArithDiv: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this, op1, op2);
+void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness, TypedArrayRounding rounding)
+{
+    Edge baseUse = node.child1();
+    Edge valueUse = node.child3();
+    
+    if (speculationRequirements != NoTypedArrayTypeSpecCheck)
+        speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+    GPRTemporary value;
+    GPRReg valueGPR;
+    
+    if (at(valueUse).isConstant()) {
+        JSValue jsValue = valueOfJSConstant(valueUse.index());
+        if (!jsValue.isNumber()) {
+            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            noResult(m_compileIndex);
+            return;
+        }
+        double d = jsValue.asNumber();
+        if (rounding == ClampRounding) {
+            ASSERT(elementSize == 1);
+            d = clampDoubleToByte(d);
+        }
+        GPRTemporary scratch(this);
+        GPRReg scratchReg = scratch.gpr();
+        m_jit.move(Imm32(toInt32(d)), scratchReg);
+        value.adopt(scratch);
+        valueGPR = scratchReg;
+    } else if (at(valueUse).shouldSpeculateInteger()) {
+        SpeculateIntegerOperand valueOp(this, valueUse);
+        GPRTemporary scratch(this);
+        GPRReg scratchReg = scratch.gpr();
+        m_jit.move(valueOp.gpr(), scratchReg);
+        if (rounding == ClampRounding) {
+            ASSERT(elementSize == 1);
+            compileClampIntegerToByte(m_jit, scratchReg);
+        }
+        value.adopt(scratch);
+        valueGPR = scratchReg;
+    } else if (rounding == ClampRounding) {
+        ASSERT(elementSize == 1);
+        SpeculateDoubleOperand valueOp(this, valueUse);
+        GPRTemporary result(this);
+        FPRTemporary floatScratch(this);
+        FPRReg fpr = valueOp.fpr();
+        GPRReg gpr = result.gpr();
+        compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
+        value.adopt(result);
+        valueGPR = gpr;
+    } else {
+        SpeculateDoubleOperand valueOp(this, valueUse);
+        GPRTemporary result(this);
+        FPRReg fpr = valueOp.fpr();
+        GPRReg gpr = result.gpr();
+        MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr);
+        m_jit.xorPtr(gpr, gpr);
+        MacroAssembler::Jump fixed = m_jit.jump();
+        notNaN.link(&m_jit);
+
+        MacroAssembler::Jump done;
+        if (signedness == SignedTypedArray)
+            done = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful);
+        else
+            done = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful);
 
 
-        op1.gpr();
-        op2.gpr();
-        terminateSpeculativeExecution();
+        silentSpillAllRegisters(gpr);
+        callOperation(toInt32, gpr, fpr);
+        silentFillAllRegisters(gpr);
 
 
-        integerResult(result.gpr(), m_compileIndex);
+        done.link(&m_jit);
+        fixed.link(&m_jit);
+        value.adopt(result);
+        valueGPR = gpr;
+    }
+    ASSERT_UNUSED(valueGPR, valueGPR != property);
+    ASSERT(valueGPR != base);
+    GPRTemporary storage(this);
+    GPRReg storageReg = storage.gpr();
+    ASSERT(valueGPR != storageReg);
+    m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);
+    MacroAssembler::Jump outOfBounds;
+    if (speculationRequirements != NoTypedArraySpecCheck)
+        outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
+
+    switch (elementSize) {
+    case 1:
+        m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne));
+        break;
+    case 2:
+        m_jit.store16(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesTwo));
+        break;
+    case 4:
+        m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
         break;
         break;
+    default:
+        ASSERT_NOT_REACHED();
     }
     }
+    if (speculationRequirements != NoTypedArraySpecCheck)
+        outOfBounds.link(&m_jit);
+    noResult(m_compileIndex);
+}
 
 
-    case ArithMod: {
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this, op1, op2);
+void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements)
+{
+    SpeculateCellOperand base(this, node.child1());
+    SpeculateStrictInt32Operand property(this, node.child2());
+    StorageOperand storage(this, node.child3());
+
+    GPRReg baseReg = base.gpr();
+    GPRReg propertyReg = property.gpr();
+    GPRReg storageReg = storage.gpr();
+    
+    if (speculationRequirements != NoTypedArrayTypeSpecCheck) {
+        ASSERT_NOT_REACHED();
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        noResult(m_compileIndex);
+        return;
+    }
 
 
-        op1.gpr();
-        op2.gpr();
-        terminateSpeculativeExecution();
+    FPRTemporary result(this);
+    FPRReg resultReg = result.fpr();
+    ASSERT(speculationRequirements != NoTypedArraySpecCheck);
+    MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset));
+    static const double zero = 0;
+    m_jit.loadDouble(&zero, resultReg);
+    MacroAssembler::Jump outOfBounds = m_jit.jump();
+    inBounds.link(&m_jit);
+    switch (elementSize) {
+    case 4:
+        m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
+        m_jit.convertFloatToDouble(resultReg, resultReg);
+        break;
+    case 8: {
+        m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
+        MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, resultReg, resultReg);
+        static const double NaN = std::numeric_limits<double>::quiet_NaN();
+        m_jit.loadDouble(&NaN, resultReg);
+        notNaN.link(&m_jit);
+        break;
+    }
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    outOfBounds.link(&m_jit);
+    doubleResult(resultReg, m_compileIndex);
+}
 
 
-        integerResult(result.gpr(), m_compileIndex);
+void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements)
+{
+    Edge baseUse = node.child1();
+    Edge valueUse = node.child3();
+    
+    SpeculateDoubleOperand valueOp(this, valueUse);
+    
+    if (speculationRequirements != NoTypedArrayTypeSpecCheck)
+        speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+    
+    GPRTemporary result(this);
+    
+    GPRTemporary storage(this);
+    GPRReg storageReg = storage.gpr();
+    
+    m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);
+    MacroAssembler::Jump outOfBounds;
+    if (speculationRequirements != NoTypedArraySpecCheck)
+        outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
+    
+    switch (elementSize) {
+    case 4: {
+        FPRTemporary scratch(this);
+        m_jit.moveDouble(valueOp.fpr(), scratch.fpr());
+        m_jit.convertDoubleToFloat(valueOp.fpr(), scratch.fpr());
+        m_jit.storeFloat(scratch.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
         break;
     }
         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);
+    case 8:
+        m_jit.storeDouble(valueOp.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesEight));
         break;
         break;
+    default:
+        ASSERT_NOT_REACHED();
     }
     }
+    if (speculationRequirements != NoTypedArraySpecCheck)
+        outOfBounds.link(&m_jit);
+    noResult(m_compileIndex);
+}
 
 
-    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;
-        }
+void SpeculativeJIT::compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchReg)
+{
+    // Check that prototype is an object.
+    m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
+    speculationCheck(BadType, JSValueRegs(), NoNode, m_jit.branchIfNotObject(scratchReg));
+    
+    // Initialize scratchReg with the value being checked.
+    m_jit.move(valueReg, scratchReg);
+    
+    // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
+    MacroAssembler::Label loop(&m_jit);
+    m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
+#if USE(JSVALUE64)
+    m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
+#else
+    m_jit.load32(MacroAssembler::Address(scratchReg, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), scratchReg);
+#endif
+    MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
+#if USE(JSVALUE64)
+    m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
+#else
+    m_jit.branchTest32(MacroAssembler::NonZero, scratchReg).linkTo(loop, &m_jit);
+#endif
+    
+    // No match - result is false.
+#if USE(JSVALUE64)
+    m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
+#else
+    m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
+#endif
+    MacroAssembler::Jump putResult = m_jit.jump();
+    
+    isInstance.link(&m_jit);
+#if USE(JSVALUE64)
+    m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);
+#else
+    m_jit.move(MacroAssembler::TrustedImm32(1), scratchReg);
+#endif
+    
+    putResult.link(&m_jit);
+}
 
 
-        // Normal case, not fused to branch.
-        SpeculateIntegerOperand op1(this, node.child1);
-        SpeculateIntegerOperand op2(this, node.child2);
-        GPRTemporary result(this, op1, op2);
+void SpeculativeJIT::compileInstanceOf(Node& node)
+{
+    if ((!!(at(node.child1()).prediction() & ~PredictCell)
+         && !!(m_state.forNode(node.child1()).m_type & ~PredictCell))
+        || at(node.child1()).adjustedRefCount() == 1) {
+        // It might not be a cell. Speculate less aggressively.
+        // Or: it might only be used once (i.e. by us), so we get zero benefit
+        // from speculating any more aggressively than we absolutely need to.
+        
+        JSValueOperand value(this, node.child1());
+        SpeculateCellOperand prototype(this, node.child3());
+        GPRTemporary scratch(this);
+        
+        GPRReg prototypeReg = prototype.gpr();
+        GPRReg scratchReg = scratch.gpr();
+        
+#if USE(JSVALUE64)
+        GPRReg valueReg = value.gpr();
+        MacroAssembler::Jump isCell = m_jit.branchTestPtr(MacroAssembler::Zero, valueReg, GPRInfo::tagMaskRegister);
+        m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
+#else
+        GPRReg valueTagReg = value.tagGPR();
+        GPRReg valueReg = value.payloadGPR();
+        MacroAssembler::Jump isCell = m_jit.branch32(MacroAssembler::Equal, valueTagReg, TrustedImm32(JSValue::CellTag));
+        m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
+#endif
 
 
-        m_jit.compare32(JITCompiler::LessThan, op1.gpr(), op2.gpr(), result.gpr());
+        MacroAssembler::Jump done = m_jit.jump();
+        
+        isCell.link(&m_jit);
+        
+        compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
+        
+        done.link(&m_jit);
 
 
-        // If we add a DataFormatBool, we should use it here.
-        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
-        jsValueResult(result.gpr(), m_compileIndex);
-        break;
+#if USE(JSVALUE64)
+        jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
+#else
+        booleanResult(scratchReg, m_compileIndex);
+#endif
+        return;
     }
     }
+    
+    SpeculateCellOperand value(this, node.child1());
+    // Base unused since we speculate default InstanceOf behaviour in CheckHasInstance.
+    SpeculateCellOperand prototype(this, node.child3());
+    
+    GPRTemporary scratch(this);
+    
+    GPRReg valueReg = value.gpr();
+    GPRReg prototypeReg = prototype.gpr();
+    GPRReg scratchReg = scratch.gpr();
+    
+    compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
+
+#if USE(JSVALUE64)
+    jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
+#else
+    booleanResult(scratchReg, m_compileIndex);
+#endif
+}
 
 
-    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);
+void SpeculativeJIT::compileSoftModulo(Node& node)
+{
+    // In the fast path, the dividend value could be the final result
+    // (in case of |dividend| < |divisor|), so we speculate it as strict int32.
+    SpeculateStrictInt32Operand op1(this, node.child1());
+#if CPU(X86) || CPU(X86_64)
+    if (isInt32Constant(node.child2().index())) {
+        int32_t divisor = valueOfInt32Constant(node.child2().index());
+        if (divisor) {
+            GPRReg op1Gpr = op1.gpr();
+
+            GPRTemporary eax(this, X86Registers::eax);
+            GPRTemporary edx(this, X86Registers::edx);
+            GPRTemporary scratch(this);
+            GPRReg scratchGPR = scratch.gpr();
+
+            GPRReg op1SaveGPR;
+            if (op1Gpr == X86Registers::eax || op1Gpr == X86Registers::edx) {
+                op1SaveGPR = allocate();
+                ASSERT(op1Gpr != op1SaveGPR);
+                m_jit.move(op1Gpr, op1SaveGPR);
+            } else
+                op1SaveGPR = op1Gpr;
+            ASSERT(op1SaveGPR != X86Registers::eax);
+            ASSERT(op1SaveGPR != X86Registers::edx);
+
+            m_jit.move(op1Gpr, eax.gpr());
+            m_jit.move(TrustedImm32(divisor), scratchGPR);
+            if (divisor == -1)
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, eax.gpr(), TrustedImm32(-2147483647-1)));
+            m_jit.assembler().cdq();
+            m_jit.assembler().idivl_r(scratchGPR);
+            // Check that we're not about to create negative zero.
+            // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
+            JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
+            speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
+            numeratorPositive.link(&m_jit);
+            
+            if (op1SaveGPR != op1Gpr)
+                unlock(op1SaveGPR);
 
 
-            use(node.child1);
-            use(node.child2);
-            ++m_compileIndex;
+            integerResult(edx.gpr(), m_compileIndex);
             return;
         }
             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;
     }
     }
+#endif
 
 
-    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;
+    SpeculateIntegerOperand op2(this, node.child2());
+#if CPU(X86) || CPU(X86_64)
+    GPRTemporary eax(this, X86Registers::eax);
+    GPRTemporary edx(this, X86Registers::edx);
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    
+    GPRReg op2TempGPR;
+    GPRReg temp;
+    GPRReg op1SaveGPR;
+    
+    if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
+        op2TempGPR = allocate();
+        temp = op2TempGPR;
+    } else {
+        op2TempGPR = InvalidGPRReg;
+        if (op1GPR == X86Registers::eax)
+            temp = X86Registers::edx;
+        else
+            temp = X86Registers::eax;
     }
     }
+    
+    if (op1GPR == X86Registers::eax || op1GPR == X86Registers::edx) {
+        op1SaveGPR = allocate();
+        ASSERT(op1GPR != op1SaveGPR);
+        m_jit.move(op1GPR, op1SaveGPR);
+    } else
+        op1SaveGPR = op1GPR;
+    
+    ASSERT(temp != op1GPR);
+    ASSERT(temp != op2GPR);
+    ASSERT(op1SaveGPR != X86Registers::eax);
+    ASSERT(op1SaveGPR != X86Registers::edx);
+    
+    m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
+    
+    JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
+    
+    JITCompiler::Jump done;
+    // FIXME: if the node is not used as number then we can do this more easily.
+    speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
+    speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
+    
+    safeDenominator.link(&m_jit);
+            
+    if (op2TempGPR != InvalidGPRReg) {
+        m_jit.move(op2GPR, op2TempGPR);
+        op2GPR = op2TempGPR;
+    }
+            
+    m_jit.move(op1GPR, eax.gpr());
+    m_jit.assembler().cdq();
+    m_jit.assembler().idivl_r(op2GPR);
+            
+    if (op2TempGPR != InvalidGPRReg)
+        unlock(op2TempGPR);
+
+    // Check that we're not about to create negative zero.
+    // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
+    JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
+    speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
+    numeratorPositive.link(&m_jit);
+    
+    if (op1SaveGPR != op1GPR)
+        unlock(op1SaveGPR);
+            
+    integerResult(edx.gpr(), m_compileIndex);
+#else // CPU(X86) || CPU(X86_64) --> so not X86
+    // Do this the *safest* way possible: call out to a C function that will do the modulo,
+    // and then attempt to convert back.
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    
+    FPRResult result(this);
+    
+    flushRegisters();
+    callOperation(operationFModOnInts, result.fpr(), op1GPR, op2GPR);
+    
+    FPRTemporary scratch(this);
+    GPRTemporary intResult(this);
+    JITCompiler::JumpList failureCases;
+    m_jit.branchConvertDoubleToInt32(result.fpr(), intResult.gpr(), failureCases, scratch.fpr());
+    speculationCheck(Overflow, JSValueRegs(), NoNode, failureCases);
+    
+    integerResult(intResult.gpr(), m_compileIndex);
+#endif // CPU(X86) || CPU(X86_64)
+}
 
 
-    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());
+void SpeculativeJIT::compileAdd(Node& node)
+{
+    if (m_jit.graph().addShouldSpeculateInteger(node)) {
+        if (isNumberConstant(node.child1().index())) {
+            int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
+            SpeculateIntegerOperand op2(this, node.child2());
+            GPRTemporary result(this);
 
 
-        // If we add a DataFormatBool, we should use it here.
-        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
-        jsValueResult(result.gpr(), m_compileIndex);
-        break;
-    }
+            if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+                m_jit.move(op2.gpr(), result.gpr());
+                m_jit.add32(Imm32(imm1), result.gpr());
+            } else
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
 
 
-    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;
+            integerResult(result.gpr(), m_compileIndex);
+            return;
         }
         }
+                
+        if (isNumberConstant(node.child2().index())) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
+            GPRTemporary result(this);
+                
+            if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+                m_jit.move(op1.gpr(), result.gpr());
+                m_jit.add32(Imm32(imm2), result.gpr());
+            } else
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
 
 
-        SpeculateCellOperand base(this, node.child1);
-        SpeculateStrictInt32Operand property(this, node.child2);
-        GPRTemporary storage(this);
+            integerResult(result.gpr(), m_compileIndex);
+            return;
+        }
+                
+        SpeculateIntegerOperand op1(this, node.child1());
+        SpeculateIntegerOperand op2(this, node.child2());
+        GPRTemporary result(this, op1, op2);
 
 
-        GPRReg baseReg = base.gpr();
-        GPRReg propertyReg = property.gpr();
-        GPRReg storageReg = storage.gpr();
+        GPRReg gpr1 = op1.gpr();
+        GPRReg gpr2 = op2.gpr();
+        GPRReg gprResult = result.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);
+        if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+            if (gpr1 == gprResult)
+                m_jit.add32(gpr2, gprResult);
+            else {
+                m_jit.move(gpr2, gprResult);
+                m_jit.add32(gpr1, gprResult);
+            }
+        } else {
+            MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
+                
+            if (gpr1 == gprResult)
+                speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
+            else if (gpr2 == gprResult)
+                speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
+            else
+                speculationCheck(Overflow, JSValueRegs(), NoNode, check);
+        }
 
 
-        // 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;
+        integerResult(gprResult, m_compileIndex);
+        return;
     }
     }
+        
+    if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
+        SpeculateDoubleOperand op1(this, node.child1());
+        SpeculateDoubleOperand op2(this, node.child2());
+        FPRTemporary result(this, op1, op2);
 
 
-    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();
+        FPRReg reg1 = op1.fpr();
+        FPRReg reg2 = op2.fpr();
+        m_jit.addDouble(reg1, reg2, result.fpr());
 
 
-        // 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())));
+        doubleResult(result.fpr(), m_compileIndex);
+        return;
+    }
 
 
-        // Get the array storage.
-        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
+    if (node.op() == ValueAdd) {
+        compileValueAdd(node);
+        return;
+    }
+    
+    // We don't handle this yet. :-(
+    terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+}
 
 
-        // 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)));
+void SpeculativeJIT::compileArithSub(Node& node)
+{
+    if (m_jit.graph().addShouldSpeculateInteger(node)) {
+        if (isNumberConstant(node.child2().index())) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
+            GPRTemporary result(this);
 
 
-        // 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);
+            if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+                m_jit.move(op1.gpr(), result.gpr());
+                m_jit.sub32(Imm32(imm2), result.gpr());
+            } else {
+#if ENABLE(JIT_CONSTANT_BLINDING)
+                GPRTemporary scratch(this);
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr(), scratch.gpr()));
+#else
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
+#endif
+            }
 
 
-        lengthDoesNotNeedUpdate.link(&m_jit);
-        notHoleValue.link(&m_jit);
+            integerResult(result.gpr(), m_compileIndex);
+            return;
+        }
+            
+        if (isNumberConstant(node.child1().index())) {
+            int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
+            SpeculateIntegerOperand op2(this, node.child2());
+            GPRTemporary result(this);
+                
+            m_jit.move(Imm32(imm1), result.gpr());
+            if (nodeCanTruncateInteger(node.arithNodeFlags()))
+                m_jit.sub32(op2.gpr(), result.gpr());
+            else
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
+                
+            integerResult(result.gpr(), m_compileIndex);
+            return;
+        }
+            
+        SpeculateIntegerOperand op1(this, node.child1());
+        SpeculateIntegerOperand op2(this, node.child2());
+        GPRTemporary result(this);
 
 
-        // Store the value to the array.
-        m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+        if (nodeCanTruncateInteger(node.arithNodeFlags())) {
+            m_jit.move(op1.gpr(), result.gpr());
+            m_jit.sub32(op2.gpr(), result.gpr());
+        } else
+            speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
 
 
-        noResult(m_compileIndex);
-        break;
+        integerResult(result.gpr(), m_compileIndex);
+        return;
     }
     }
+        
+    SpeculateDoubleOperand op1(this, node.child1());
+    SpeculateDoubleOperand op2(this, node.child2());
+    FPRTemporary result(this, op1);
 
 
-    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.
+    FPRReg reg1 = op1.fpr();
+    FPRReg reg2 = op2.fpr();
+    m_jit.subDouble(reg1, reg2, result.fpr());
 
 
-        // Get the array storage.
-        GPRReg storageReg = storage.gpr();
-        m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSArray::storageOffset()), storageReg);
+    doubleResult(result.fpr(), m_compileIndex);
+}
 
 
-        // Map property & value into registers.
-        GPRReg propertyReg = property.gpr();
-        GPRReg valueReg = value.gpr();
+void SpeculativeJIT::compileArithNegate(Node& node)
+{
+    if (m_jit.graph().negateShouldSpeculateInteger(node)) {
+        SpeculateIntegerOperand op1(this, node.child1());
+        GPRTemporary result(this);
 
 
-        // Store the value to the array.
-        m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+        m_jit.move(op1.gpr(), result.gpr());
 
 
-        noResult(m_compileIndex);
-        break;
-    }
+        if (nodeCanTruncateInteger(node.arithNodeFlags()))
+            m_jit.neg32(result.gpr());
+        else {
+            speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchNeg32(MacroAssembler::Overflow, result.gpr()));
+            if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags()))
+                speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, result.gpr()));
+        }
 
 
-    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;
+        integerResult(result.gpr(), m_compileIndex);
+        return;
     }
     }
+        
+    SpeculateDoubleOperand op1(this, node.child1());
+    FPRTemporary result(this);
 
 
-    case Branch: {
-        JSValueOperand value(this, node.child1);
-        GPRReg valueReg = value.gpr();
+    m_jit.negateDouble(op1.fpr(), result.fpr());
 
 
-        BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
-        BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
+    doubleResult(result.fpr(), m_compileIndex);
+}
 
 
-        // 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);
+void SpeculativeJIT::compileArithMul(Node& node)
+{
+    if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
+        SpeculateIntegerOperand op1(this, node.child1());
+        SpeculateIntegerOperand op2(this, node.child2());
+        GPRTemporary result(this);
 
 
-        // 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)))));
+        GPRReg reg1 = op1.gpr();
+        GPRReg reg2 = op2.gpr();
 
 
-        if (taken == (m_block + 1))
-            isNonZeroInteger.link(&m_jit);
-        else {
-            addBranch(isNonZeroInteger, taken);
-            addBranch(m_jit.jump(), taken);
+        // What is unfortunate is that we cannot take advantage of nodeCanTruncateInteger()
+        // here. A multiply on integers performed in the double domain and then truncated to
+        // an integer will give a different result than a multiply performed in the integer
+        // domain and then truncated, if the integer domain result would have resulted in
+        // something bigger than what a 32-bit integer can hold. JavaScript mandates that
+        // the semantics are always as if the multiply had been performed in the double
+        // domain.
+            
+        speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
+            
+        // Check for negative zero, if the users of this node care about such things.
+        if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
+            MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
+            speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
+            speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
+            resultNonZero.link(&m_jit);
         }
 
         }
 
-        noResult(m_compileIndex);
-        break;
+        integerResult(result.gpr(), m_compileIndex);
+        return;
     }
 
     }
 
-    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);
+    SpeculateDoubleOperand op1(this, node.child1());
+    SpeculateDoubleOperand op2(this, node.child2());
+    FPRTemporary result(this, op1, op2);
 
 
-        // 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();
+    FPRReg reg1 = op1.fpr();
+    FPRReg reg2 = op2.fpr();
         
         
-        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)));
+    m_jit.mulDouble(reg1, reg2, result.fpr());
+        
+    doubleResult(result.fpr(), m_compileIndex);
+}
 
 
-        cellResult(thisValue.gpr(), m_compileIndex);
-        break;
+#if CPU(X86) || CPU(X86_64)
+void SpeculativeJIT::compileIntegerArithDivForX86(Node& node)
+{
+    SpeculateIntegerOperand op1(this, node.child1());
+    SpeculateIntegerOperand op2(this, node.child2());
+    GPRTemporary eax(this, X86Registers::eax);
+    GPRTemporary edx(this, X86Registers::edx);
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    
+    GPRReg op2TempGPR;
+    GPRReg temp;
+    if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
+        op2TempGPR = allocate();
+        temp = op2TempGPR;
+    } else {
+        op2TempGPR = InvalidGPRReg;
+        if (op1GPR == X86Registers::eax)
+            temp = X86Registers::edx;
+        else
+            temp = X86Registers::eax;
     }
     }
-
-    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;
+    
+    ASSERT(temp != op1GPR);
+    ASSERT(temp != op2GPR);
+    
+    m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
+    
+    JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
+    
+    JITCompiler::Jump done;
+    if (nodeUsedAsNumber(node.arithNodeFlags())) {
+        speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
+        speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
+    } else {
+        JITCompiler::Jump zero = m_jit.branchTest32(JITCompiler::Zero, op2GPR);
+        JITCompiler::Jump notNeg2ToThe31 = m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1));
+        zero.link(&m_jit);
+        m_jit.move(TrustedImm32(0), eax.gpr());
+        done = m_jit.jump();
+        notNeg2ToThe31.link(&m_jit);
     }
     }
-
-    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;
+    
+    safeDenominator.link(&m_jit);
+            
+    // If the user cares about negative zero, then speculate that we're not about
+    // to produce negative zero.
+    if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
+        MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
+        speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
+        numeratorNonZero.link(&m_jit);
     }
     }
-
-    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;
+    
+    if (op2TempGPR != InvalidGPRReg) {
+        m_jit.move(op2GPR, op2TempGPR);
+        op2GPR = op2TempGPR;
     }
     }
+            
+    m_jit.move(op1GPR, eax.gpr());
+    m_jit.assembler().cdq();
+    m_jit.assembler().idivl_r(op2GPR);
+            
+    if (op2TempGPR != InvalidGPRReg)
+        unlock(op2TempGPR);
+
+    // Check that there was no remainder. If there had been, then we'd be obligated to
+    // produce a double result instead.
+    if (nodeUsedAsNumber(node.arithNodeFlags()))
+        speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::NonZero, edx.gpr()));
+    else
+        done.link(&m_jit);
+            
+    integerResult(eax.gpr(), m_compileIndex);
+}
+#endif // CPU(X86) || CPU(X86_64)
 
 
-    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;
+void SpeculativeJIT::compileArithMod(Node& node)
+{
+    if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))
+        && node.canSpeculateInteger()) {
+        compileSoftModulo(node);
+        return;
     }
     }
+        
+    SpeculateDoubleOperand op1(this, node.child1());
+    SpeculateDoubleOperand op2(this, node.child2());
+        
+    FPRReg op1FPR = op1.fpr();
+    FPRReg op2FPR = op2.fpr();
+        
+    flushRegisters();
+        
+    FPRResult result(this);
 
 
-    case PutGlobalVar: {
-        JSValueOperand value(this, node.child1);
-        GPRTemporary temp(this);
+    callOperation(fmodAsDFGOperation, result.fpr(), op1FPR, op2FPR);
+        
+    doubleResult(result.fpr(), m_compileIndex);
+}
 
 
-        JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
-        m_jit.loadPtr(globalObject->addressOfRegisters(), temp.gpr());
-        m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(temp.gpr(), node.varNumber()));
+// Returns true if the compare is fused with a subsequent branch.
+bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
+{
+    if (compilePeepHoleBranch(node, condition, doubleCondition, operation))
+        return true;
 
 
-        noResult(m_compileIndex);
-        break;
+    if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
+        compileIntegerCompare(node, condition);
+        return false;
     }
     }
-
-    case Phi:
-        ASSERT_NOT_REACHED();
+    
+    if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
+        compileDoubleCompare(node, doubleCondition);
+        return false;
     }
     }
-
-    if (node.hasResult() && node.mustGenerate())
-        use(m_compileIndex);
+    
+    if (node.op() == CompareEq) {
+        if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
+            compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
+            return false;
+        }
+        
+        if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
+            compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
+            return false;
+        }
+        
+        if (at(node.child1()).shouldSpeculateFinalObject()
+            && at(node.child2()).shouldSpeculateFinalObjectOrOther()) {
+            compileObjectToObjectOrOtherEquality(
+                node.child1(), node.child2(), &JSFinalObject::s_info,
+                isFinalObjectPrediction);
+            return false;
+        }
+        
+        if (at(node.child1()).shouldSpeculateFinalObjectOrOther()
+            && at(node.child2()).shouldSpeculateFinalObject()) {
+            compileObjectToObjectOrOtherEquality(
+                node.child2(), node.child1(), &JSFinalObject::s_info,
+                isFinalObjectPrediction);
+            return false;
+        }
+        
+        if (at(node.child1()).shouldSpeculateArray()
+            && at(node.child2()).shouldSpeculateArrayOrOther()) {
+            compileObjectToObjectOrOtherEquality(
+                node.child1(), node.child2(), &JSArray::s_info,
+                isArrayPrediction);
+            return false;
+        }
+        
+        if (at(node.child1()).shouldSpeculateArrayOrOther()
+            && at(node.child2()).shouldSpeculateArray()) {
+            compileObjectToObjectOrOtherEquality(
+                node.child2(), node.child1(), &JSArray::s_info,
+                isArrayPrediction);
+            return false;
+        }
+    }
+    
+    nonSpeculativeNonPeepholeCompare(node, condition, operation);
+    return false;
 }
 
 }
 
-void SpeculativeJIT::compile(BasicBlock& block)
+bool SpeculativeJIT::compileStrictEqForConstant(Node& node, Edge value, JSValue constant)
 {
 {
-    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;
+    JSValueOperand op1(this, value);
+    
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock != UINT_MAX) {
+        NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+        Node& branchNode = at(branchNodeIndex);
+        BlockIndex taken = branchNode.takenBlockIndex();
+        BlockIndex notTaken = branchNode.notTakenBlockIndex();
+        MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
+        
+        // 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 = MacroAssembler::NotEqual;
+            BlockIndex tmp = taken;
+            taken = notTaken;
+            notTaken = tmp;
+        }
 
 
-#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();
+#if USE(JSVALUE64)
+        branchPtr(condition, op1.gpr(), MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant))), taken);
+#else
+        GPRReg payloadGPR = op1.payloadGPR();
+        GPRReg tagGPR = op1.tagGPR();
+        if (condition == MacroAssembler::Equal) {
+            // Drop down if not equal, go elsewhere if equal.
+            MacroAssembler::Jump notEqual = m_jit.branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()));
+            branch32(MacroAssembler::Equal, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
+            notEqual.link(&m_jit);
+        } else {
+            // Drop down if equal, go elsehwere if not equal.
+            branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()), taken);
+            branch32(MacroAssembler::NotEqual, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
+        }
 #endif
 #endif
-        checkConsistency();
-        compile(node);
-        if (!m_compileOkay)
-            return;
-        checkConsistency();
+        
+        jump(notTaken);
+        
+        use(node.child1());
+        use(node.child2());
+        m_indexInBlock = branchIndexInBlock;
+        m_compileIndex = branchNodeIndex;
+        return true;
     }
     }
+    
+    GPRTemporary result(this);
+    
+#if USE(JSVALUE64)
+    GPRReg op1GPR = op1.gpr();
+    GPRReg resultGPR = result.gpr();
+    m_jit.move(MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(ValueFalse)), resultGPR);
+    MacroAssembler::Jump notEqual = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant))));
+    m_jit.or32(MacroAssembler::TrustedImm32(1), resultGPR);
+    notEqual.link(&m_jit);
+    jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
+#else
+    GPRReg op1PayloadGPR = op1.payloadGPR();
+    GPRReg op1TagGPR = op1.tagGPR();
+    GPRReg resultGPR = result.gpr();
+    m_jit.move(TrustedImm32(0), resultGPR);
+    MacroAssembler::JumpList notEqual;
+    notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, MacroAssembler::Imm32(constant.tag())));
+    notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1PayloadGPR, MacroAssembler::Imm32(constant.payload())));
+    m_jit.move(TrustedImm32(1), resultGPR);
+    notEqual.link(&m_jit);
+    booleanResult(resultGPR, m_compileIndex);
+#endif
+    
+    return false;
 }
 
 }
 
-// If we are making type predictions about our arguments then
-// we need to check that they are correct on function entry.
-void SpeculativeJIT::checkArgumentTypes()
+bool SpeculativeJIT::compileStrictEq(Node& node)
 {
 {
-    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;
+    // 1) If either operand is a constant and that constant is not a double, integer,
+    //    or string, then do a JSValue comparison.
+    
+    if (isJSConstant(node.child1().index())) {
+        JSValue value = valueOfJSConstant(node.child1().index());
+        if (!value.isNumber() && !value.isString())
+            return compileStrictEqForConstant(node, node.child2(), value);
+    }
+    
+    if (isJSConstant(node.child2().index())) {
+        JSValue value = valueOfJSConstant(node.child2().index());
+        if (!value.isNumber() && !value.isString())
+            return compileStrictEqForConstant(node, node.child1(), value);
+    }
+    
+    // 2) If the operands are predicted integer, do an integer comparison.
+    
+    if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
+        unsigned branchIndexInBlock = detectPeepHoleBranch();
+        if (branchIndexInBlock != UINT_MAX) {
+            NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+            compilePeepHoleIntegerBranch(node, branchNodeIndex, MacroAssembler::Equal);
+            use(node.child1());
+            use(node.child2());
+            m_indexInBlock = branchIndexInBlock;
+            m_compileIndex = branchNodeIndex;
+            return true;
         }
         }
-
-        default:
-            break;
+        compileIntegerCompare(node, MacroAssembler::Equal);
+        return false;
+    }
+    
+    // 3) If the operands are predicted double, do a double comparison.
+    
+    if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
+        unsigned branchIndexInBlock = detectPeepHoleBranch();
+        if (branchIndexInBlock != UINT_MAX) {
+            NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+            compilePeepHoleDoubleBranch(node, branchNodeIndex, MacroAssembler::DoubleEqual);
+            use(node.child1());
+            use(node.child2());
+            m_indexInBlock = branchIndexInBlock;
+            m_compileIndex = branchNodeIndex;
+            return true;
         }
         }
+        compileDoubleCompare(node, MacroAssembler::DoubleEqual);
+        return false;
     }
     }
+    
+    // 4) If the operands are predicted final object or array, then do a final object
+    //    or array comparison.
+    
+    if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
+        unsigned branchIndexInBlock = detectPeepHoleBranch();
+        if (branchIndexInBlock != UINT_MAX) {
+            NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+            compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
+            use(node.child1());
+            use(node.child2());
+            m_indexInBlock = branchIndexInBlock;
+            m_compileIndex = branchNodeIndex;
+            return true;
+        }
+        compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
+        return false;
+    }
+    
+    if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
+        unsigned branchIndexInBlock = detectPeepHoleBranch();
+        if (branchIndexInBlock != UINT_MAX) {
+            NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+            compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
+            use(node.child1());
+            use(node.child2());
+            m_indexInBlock = branchIndexInBlock;
+            m_compileIndex = branchNodeIndex;
+            return true;
+        }
+        compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
+        return false;
+    }
+    
+    // 5) Fall back to non-speculative strict equality.
+    
+    return nonSpeculativeStrictEq(node);
 }
 
 }
 
-// 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()
+void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
 {
 {
-    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));
+    if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) {
+        terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+        return;
+    }
+        
+    SpeculateCellOperand base(this, node.child1());
+    GPRReg baseReg = base.gpr();
+    
+    PredictedType basePrediction = at(node.child2()).prediction();
+    if (!(basePrediction & PredictInt32) && basePrediction) {
+        ASSERT_NOT_REACHED();
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        noResult(m_compileIndex);
+        return;
+    }
+    
+    GPRTemporary storage(this);
+    GPRReg storageReg = storage.gpr();
+    if (at(node.child1()).prediction() == PredictString) {
+        if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
+
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), storageReg);
+        
+        // Speculate that we're not accessing a rope
+        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, storageReg));
+
+        m_jit.loadPtr(MacroAssembler::Address(storageReg, StringImpl::dataOffset()), storageReg);
+    } else if (at(node.child1()).shouldSpeculateInt8Array()) {
+        const TypedArrayDescriptor& descriptor = m_jit.globalData()->int8ArrayDescriptor();
+        if (!isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+    } else if (at(node.child1()).shouldSpeculateInt16Array()) {
+        const TypedArrayDescriptor& descriptor = m_jit.globalData()->int16ArrayDescriptor();
+        if (!isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+    } else if (at(node.child1()).shouldSpeculateInt32Array()) {
+        const TypedArrayDescriptor& descriptor = m_jit.globalData()->int32ArrayDescriptor();
+        if (!isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+    } else if (at(node.child1()).shouldSpeculateUint8Array()) {
+        const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ArrayDescriptor();
+        if (!isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+    } else if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+        const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ClampedArrayDescriptor();
+        if (!isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+    } else if (at(node.child1()).shouldSpeculateUint16Array()) {
+        const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint16ArrayDescriptor();
+        if (!isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+    } else if (at(node.child1()).shouldSpeculateUint32Array()) {
+        const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint32ArrayDescriptor();
+        if (!isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+    } else if (at(node.child1()).shouldSpeculateFloat32Array()) {
+        const TypedArrayDescriptor& descriptor = m_jit.globalData()->float32ArrayDescriptor();
+        if (!isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+    } else if (at(node.child1()).shouldSpeculateFloat64Array()) {
+        const TypedArrayDescriptor& descriptor = m_jit.globalData()->float64ArrayDescriptor();
+        if (!isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+    } else {
+        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
     }
     }
+    storageResult(storageReg, m_compileIndex);
 }
 
 }
 
-bool SpeculativeJIT::compile()
+void SpeculativeJIT::compileNewFunctionNoCheck(Node& node)
 {
 {
-    checkArgumentTypes();
-    initializeVariableTypes();
+    GPRResult result(this);
+    GPRReg resultGPR = result.gpr();
+    flushRegisters();
+    callOperation(
+        operationNewFunction, resultGPR, m_jit.codeBlock()->functionDecl(node.functionDeclIndex()));
+    cellResult(resultGPR, m_compileIndex);
+}
 
 
-    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;
+void SpeculativeJIT::compileNewFunctionExpression(Node& node)
+{
+    GPRResult result(this);
+    GPRReg resultGPR = result.gpr();
+    flushRegisters();
+    callOperation(
+        operationNewFunctionExpression,
+        resultGPR,
+        m_jit.codeBlock()->functionExpr(node.functionExprIndex()));
+    cellResult(resultGPR, m_compileIndex);
+}
+
+bool SpeculativeJIT::compileRegExpExec(Node& node)
+{
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock == UINT_MAX)
+        return false;
+    NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+    ASSERT(node.adjustedRefCount() == 1);
+
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+    
+    bool invert = false;
+    if (taken == (m_block + 1)) {
+        invert = true;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
     }
     }
-    linkBranches();
+
+    SpeculateCellOperand base(this, node.child1());
+    SpeculateCellOperand argument(this, node.child2());
+    GPRReg baseGPR = base.gpr();
+    GPRReg argumentGPR = argument.gpr();
+    
+    flushRegisters();
+    GPRResult result(this);
+    callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
+
+    branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, result.gpr(), taken);
+    jump(notTaken);
+
+    use(node.child1());
+    use(node.child2());
+    m_indexInBlock = branchIndexInBlock;
+    m_compileIndex = branchNodeIndex;
+
     return true;
 }
 
     return true;
 }
 
index 82fd403305af6dfdc987fae51ca5d675dcc53a49..9241df9d6728767f4544323855f1d685a81d1310 100644 (file)
 
 #if ENABLE(DFG_JIT)
 
 
 #if ENABLE(DFG_JIT)
 
-#include <dfg/DFGJITCodeGenerator.h>
+#include "DFGAbstractState.h"
+#include "DFGGenerationInfo.h"
+#include "DFGJITCompiler.h"
+#include "DFGOSRExit.h"
+#include "DFGOperations.h"
+#include "MarkedAllocator.h"
+#include "ValueRecovery.h"
 
 namespace JSC { namespace DFG {
 
 
 namespace JSC { namespace DFG {
 
+class JSValueOperand;
 class SpeculativeJIT;
 class SpeculativeJIT;
+class SpeculateIntegerOperand;
+class SpeculateStrictInt32Operand;
+class SpeculateDoubleOperand;
+class SpeculateCellOperand;
+class SpeculateBooleanOperand;
 
 
-// This enum describes the types of additional recovery that
-// may need be performed should a speculation check fail.
-enum SpeculationRecoveryType {
-    SpeculativeAdd
+
+enum ValueSourceKind {
+    SourceNotSet,
+    ValueInRegisterFile,
+    Int32InRegisterFile,
+    CellInRegisterFile,
+    BooleanInRegisterFile,
+    DoubleInRegisterFile,
+    SourceIsDead,
+    HaveNode
+};
+
+class ValueSource {
+public:
+    ValueSource()
+        : m_nodeIndex(nodeIndexFromKind(SourceNotSet))
+    {
+    }
+    
+    explicit ValueSource(ValueSourceKind valueSourceKind)
+        : m_nodeIndex(nodeIndexFromKind(valueSourceKind))
+    {
+        ASSERT(kind() != SourceNotSet);
+        ASSERT(kind() != HaveNode);
+    }
+    
+    explicit ValueSource(NodeIndex nodeIndex)
+        : m_nodeIndex(nodeIndex)
+    {
+        ASSERT(kind() == HaveNode);
+    }
+    
+    static ValueSource forPrediction(PredictedType prediction)
+    {
+        if (isInt32Prediction(prediction))
+            return ValueSource(Int32InRegisterFile);
+        if (isArrayPrediction(prediction))
+            return ValueSource(CellInRegisterFile);
+        if (isBooleanPrediction(prediction))
+            return ValueSource(BooleanInRegisterFile);
+        return ValueSource(ValueInRegisterFile);
+    }
+    
+    bool isSet() const
+    {
+        return kindFromNodeIndex(m_nodeIndex) != SourceNotSet;
+    }
+    
+    ValueSourceKind kind() const
+    {
+        return kindFromNodeIndex(m_nodeIndex);
+    }
+    
+    NodeIndex nodeIndex() const
+    {
+        ASSERT(kind() == HaveNode);
+        return m_nodeIndex;
+    }
+    
+    void dump(FILE* out) const;
+    
+private:
+    static NodeIndex nodeIndexFromKind(ValueSourceKind kind)
+    {
+        ASSERT(kind >= SourceNotSet && kind < HaveNode);
+        return NoNode - kind;
+    }
+    
+    static ValueSourceKind kindFromNodeIndex(NodeIndex nodeIndex)
+    {
+        unsigned kind = static_cast<unsigned>(NoNode - nodeIndex);
+        if (kind >= static_cast<unsigned>(HaveNode))
+            return HaveNode;
+        return static_cast<ValueSourceKind>(kind);
+    }
+    
+    NodeIndex m_nodeIndex;
+};
+
+
+enum GeneratedOperandType { GeneratedOperandTypeUnknown, GeneratedOperandInteger, GeneratedOperandDouble, GeneratedOperandJSValue};
+
+// === 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 {
+    friend struct OSRExit;
+private:
+    typedef JITCompiler::TrustedImm32 TrustedImm32;
+    typedef JITCompiler::Imm32 Imm32;
+    typedef JITCompiler::TrustedImmPtr TrustedImmPtr;
+    typedef JITCompiler::ImmPtr ImmPtr;
+
+    // These constants are used to set priorities for spill order for
+    // the register allocator.
+#if USE(JSVALUE64)
+    enum SpillOrder {
+        SpillOrderConstant = 1, // no spill, and cheap fill
+        SpillOrderSpilled  = 2, // no spill
+        SpillOrderJS       = 4, // needs spill
+        SpillOrderCell     = 4, // needs spill
+        SpillOrderStorage  = 4, // needs spill
+        SpillOrderInteger  = 5, // needs spill and box
+        SpillOrderBoolean  = 5, // needs spill and box
+        SpillOrderDouble   = 6, // needs spill and convert
+    };
+#elif USE(JSVALUE32_64)
+    enum SpillOrder {
+        SpillOrderConstant = 1, // no spill, and cheap fill
+        SpillOrderSpilled  = 2, // no spill
+        SpillOrderJS       = 4, // needs spill
+        SpillOrderStorage  = 4, // needs spill
+        SpillOrderDouble   = 4, // needs spill
+        SpillOrderInteger  = 5, // needs spill and box
+        SpillOrderCell     = 5, // needs spill and box
+        SpillOrderBoolean  = 5, // needs spill and box
+    };
+#endif
+
+    enum UseChildrenMode { CallUseChildren, UseChildrenCalledExplicitly };
+    
+public:
+    SpeculativeJIT(JITCompiler&);
+
+    bool compile();
+    void createOSREntries();
+    void linkOSREntries(LinkBuffer&);
+
+    Node& at(NodeIndex nodeIndex)
+    {
+        return m_jit.graph()[nodeIndex];
+    }
+    Node& at(Edge nodeUse)
+    {
+        return at(nodeUse.index());
+    }
+    
+    GPRReg fillInteger(NodeIndex, DataFormat& returnFormat);
+    FPRReg fillDouble(NodeIndex);
+#if USE(JSVALUE64)
+    GPRReg fillJSValue(NodeIndex);
+#elif USE(JSVALUE32_64)
+    bool fillJSValue(NodeIndex, GPRReg&, GPRReg&, FPRReg&);
+#endif
+    GPRReg fillStorage(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 = at(nodeIndex).virtualRegister();
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        return info.canReuse();
+    }
+    bool canReuse(Edge nodeUse)
+    {
+        return canReuse(nodeUse.index());
+    }
+    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) {
+#if USE(JSVALUE32_64)
+            GenerationInfo& info = m_generationInfo[spillMe];
+            ASSERT(info.registerFormat() != DataFormatJSDouble);
+            if ((info.registerFormat() & DataFormatJS))
+                m_gprs.release(info.tagGPR() == gpr ? info.payloadGPR() : info.tagGPR());
+#endif
+            spill(spillMe);
+        }
+        return gpr;
+    }
+    GPRReg allocate(GPRReg specific)
+    {
+        VirtualRegister spillMe = m_gprs.allocateSpecific(specific);
+        if (spillMe != InvalidVirtualRegister) {
+#if USE(JSVALUE32_64)
+            GenerationInfo& info = m_generationInfo[spillMe];
+            ASSERT(info.registerFormat() != DataFormatJSDouble);
+            if ((info.registerFormat() & DataFormatJS))
+                m_gprs.release(info.tagGPR() == specific ? info.payloadGPR() : info.tagGPR());
+#endif
+            spill(spillMe);
+        }
+        return specific;
+    }
+    GPRReg tryAllocate()
+    {
+        return m_gprs.tryAllocate();
+    }
+    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 = at(nodeIndex).virtualRegister();
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        return info.registerFormat() != DataFormatNone;
+    }
+    bool isFilledDouble(NodeIndex nodeIndex)
+    {
+        VirtualRegister virtualRegister = at(nodeIndex).virtualRegister();
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        return info.registerFormat() == DataFormatDouble;
+    }
+
+    // Called on an operand once it has been consumed by a parent node.
+    void use(NodeIndex nodeIndex)
+    {
+        VirtualRegister virtualRegister = at(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 USE(JSVALUE64)
+        if (registerFormat == DataFormatDouble)
+            m_fprs.release(info.fpr());
+        else if (registerFormat != DataFormatNone)
+            m_gprs.release(info.gpr());
+#elif USE(JSVALUE32_64)
+        if (registerFormat == DataFormatDouble || registerFormat == DataFormatJSDouble)
+            m_fprs.release(info.fpr());
+        else if (registerFormat & DataFormatJS) {
+            m_gprs.release(info.tagGPR());
+            m_gprs.release(info.payloadGPR());
+        } else if (registerFormat != DataFormatNone)
+            m_gprs.release(info.gpr());
+#endif
+    }
+    void use(Edge nodeUse)
+    {
+        use(nodeUse.index());
+    }
+
+    static void markCellCard(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2);
+    static void writeBarrier(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, WriteBarrierUseKind);
+
+    void writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg);
+    void writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg);
+    void writeBarrier(JSCell* owner, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg);
+
+    static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg)
+    {
+        return AssemblyHelpers::selectScratchGPR(preserve1, preserve2, preserve3, preserve4);
+    }
+
+    // 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);
+    FPRReg fillSpeculateDouble(NodeIndex);
+    GPRReg fillSpeculateCell(NodeIndex);
+    GPRReg fillSpeculateBoolean(NodeIndex);
+    GeneratedOperandType checkGeneratedTypeForToInt32(NodeIndex);
+
+private:
+    void compile(Node&);
+    void compileMovHint(Node&);
+    void compile(BasicBlock&);
+
+    void checkArgumentTypes();
+
+    void clearGenerationInfo();
+
+    // 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 source)
+    {
+        GenerationInfo& info = m_generationInfo[spillMe];
+        ASSERT(info.registerFormat() != DataFormatNone);
+        ASSERT(info.registerFormat() != DataFormatDouble);
+
+        if (!info.needsSpill())
+            return;
+
+        DataFormat registerFormat = info.registerFormat();
+
+#if USE(JSVALUE64)
+        ASSERT(info.gpr() == source);
+        if (registerFormat == DataFormatInteger)
+            m_jit.store32(source, JITCompiler::addressFor(spillMe));
+        else {
+            ASSERT(registerFormat & DataFormatJS || registerFormat == DataFormatCell || registerFormat == DataFormatStorage);
+            m_jit.storePtr(source, JITCompiler::addressFor(spillMe));
+        }
+#elif USE(JSVALUE32_64)
+        if (registerFormat & DataFormatJS) {
+            ASSERT(info.tagGPR() == source || info.payloadGPR() == source);
+            m_jit.store32(source, source == info.tagGPR() ? JITCompiler::tagFor(spillMe) : JITCompiler::payloadFor(spillMe));
+        } else {
+            ASSERT(info.gpr() == source);
+            m_jit.store32(source, JITCompiler::payloadFor(spillMe));
+        }
+#endif
+    }
+    void silentSpillFPR(VirtualRegister spillMe, FPRReg source)
+    {
+        GenerationInfo& info = m_generationInfo[spillMe];
+        ASSERT(info.registerFormat() == DataFormatDouble);
+
+        if (!info.needsSpill()) {
+            // it's either a constant or it's already been spilled
+            ASSERT(at(info.nodeIndex()).hasConstant() || info.spillFormat() != DataFormatNone);
+            return;
+        }
+        
+        // it's neither a constant nor has it been spilled.
+        ASSERT(!at(info.nodeIndex()).hasConstant());
+        ASSERT(info.spillFormat() == DataFormatNone);
+        ASSERT(info.fpr() == source);
+
+        m_jit.storeDouble(source, JITCompiler::addressFor(spillMe));
+    }
+
+    void silentFillGPR(VirtualRegister spillMe, GPRReg target)
+    {
+        GenerationInfo& info = m_generationInfo[spillMe];
+
+        NodeIndex nodeIndex = info.nodeIndex();
+        Node& node = at(nodeIndex);
+        ASSERT(info.registerFormat() != DataFormatNone);
+        ASSERT(info.registerFormat() != DataFormatDouble);
+        DataFormat registerFormat = info.registerFormat();
+
+        if (registerFormat == DataFormatInteger) {
+            ASSERT(info.gpr() == target);
+            ASSERT(isJSInteger(info.registerFormat()));
+            if (node.hasConstant()) {
+                ASSERT(isInt32Constant(nodeIndex));
+                m_jit.move(Imm32(valueOfInt32Constant(nodeIndex)), target);
+            } else
+                m_jit.load32(JITCompiler::payloadFor(spillMe), target);
+            return;
+        }
+        
+        if (registerFormat == DataFormatBoolean) {
+#if USE(JSVALUE64)
+            ASSERT_NOT_REACHED();
+#elif USE(JSVALUE32_64)
+            ASSERT(info.gpr() == target);
+            if (node.hasConstant()) {
+                ASSERT(isBooleanConstant(nodeIndex));
+                m_jit.move(TrustedImm32(valueOfBooleanConstant(nodeIndex)), target);
+            } else
+                m_jit.load32(JITCompiler::payloadFor(spillMe), target);
+#endif
+            return;
+        }
+
+        if (registerFormat == DataFormatCell) {
+            ASSERT(info.gpr() == target);
+            if (node.hasConstant()) {
+                JSValue value = valueOfJSConstant(nodeIndex);
+                ASSERT(value.isCell());
+                m_jit.move(TrustedImmPtr(value.asCell()), target);
+            } else
+                m_jit.loadPtr(JITCompiler::payloadFor(spillMe), target);
+            return;
+        }
+
+        if (registerFormat == DataFormatStorage) {
+            ASSERT(info.gpr() == target);
+            m_jit.loadPtr(JITCompiler::addressFor(spillMe), target);
+            return;
+        }
+
+        ASSERT(registerFormat & DataFormatJS);
+#if USE(JSVALUE64)
+        ASSERT(info.gpr() == target);
+        if (node.hasConstant()) {
+            if (valueOfJSConstant(nodeIndex).isCell())
+                m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex).asTrustedImmPtr(), target);
+            else
+                m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex), target);
+        } else if (info.spillFormat() == DataFormatInteger) {
+            ASSERT(registerFormat == DataFormatJSInteger);
+            m_jit.load32(JITCompiler::payloadFor(spillMe), target);
+            m_jit.orPtr(GPRInfo::tagTypeNumberRegister, target);
+        } else if (info.spillFormat() == DataFormatDouble) {
+            ASSERT(registerFormat == DataFormatJSDouble);
+            m_jit.loadPtr(JITCompiler::addressFor(spillMe), target);
+            m_jit.subPtr(GPRInfo::tagTypeNumberRegister, target);
+        } else
+            m_jit.loadPtr(JITCompiler::addressFor(spillMe), target);
+#else
+        ASSERT(info.tagGPR() == target || info.payloadGPR() == target);
+        if (node.hasConstant()) {
+            JSValue v = valueOfJSConstant(nodeIndex);
+            m_jit.move(info.tagGPR() == target ? Imm32(v.tag()) : Imm32(v.payload()), target);
+        } else if (info.payloadGPR() == target)
+            m_jit.load32(JITCompiler::payloadFor(spillMe), target);
+        else { // Fill the Tag
+            switch (info.spillFormat()) {
+            case DataFormatInteger:
+                ASSERT(registerFormat == DataFormatJSInteger);
+                m_jit.move(TrustedImm32(JSValue::Int32Tag), target);
+                break;
+            case DataFormatCell:
+                ASSERT(registerFormat == DataFormatJSCell);
+                m_jit.move(TrustedImm32(JSValue::CellTag), target);
+                break;
+            case DataFormatBoolean:
+                ASSERT(registerFormat == DataFormatJSBoolean);
+                m_jit.move(TrustedImm32(JSValue::BooleanTag), target);
+                break;
+            default:
+                m_jit.load32(JITCompiler::tagFor(spillMe), target);
+                break;
+            }
+        }
+#endif
+    }
+
+    void silentFillFPR(VirtualRegister spillMe, GPRReg canTrample, FPRReg target)
+    {
+        GenerationInfo& info = m_generationInfo[spillMe];
+        ASSERT(info.fpr() == target);
+
+        NodeIndex nodeIndex = info.nodeIndex();
+        Node& node = at(nodeIndex);
+#if USE(JSVALUE64)
+        ASSERT(info.registerFormat() == DataFormatDouble);
+
+        if (node.hasConstant()) {
+            ASSERT(isNumberConstant(nodeIndex));
+            m_jit.move(ImmPtr(bitwise_cast<void*>(valueOfNumberConstant(nodeIndex))), canTrample);
+            m_jit.movePtrToDouble(canTrample, target);
+            return;
+        }
+        
+        if (info.spillFormat() != DataFormatNone && info.spillFormat() != DataFormatDouble) {
+            // it was already spilled previously and not as a double, which means we need unboxing.
+            ASSERT(info.spillFormat() & DataFormatJS);
+            m_jit.loadPtr(JITCompiler::addressFor(spillMe), canTrample);
+            unboxDouble(canTrample, target);
+            return;
+        }
+
+        m_jit.loadDouble(JITCompiler::addressFor(spillMe), target);
+#elif USE(JSVALUE32_64)
+        UNUSED_PARAM(canTrample);
+        ASSERT(info.registerFormat() == DataFormatDouble || info.registerFormat() == DataFormatJSDouble);
+        if (node.hasConstant()) {
+            ASSERT(isNumberConstant(nodeIndex));
+            m_jit.loadDouble(addressOfDoubleConstant(nodeIndex), target);
+        } else
+            m_jit.loadDouble(JITCompiler::addressFor(spillMe), target);
+#endif
+    }
+
+    void silentSpillAllRegisters(GPRReg exclude, GPRReg exclude2 = InvalidGPRReg)
+    {
+        for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+            GPRReg gpr = iter.regID();
+            if (iter.name() != InvalidVirtualRegister && gpr != exclude && gpr != exclude2)
+                silentSpillGPR(iter.name(), gpr);
+        }
+        for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                silentSpillFPR(iter.name(), iter.regID());
+        }
+    }
+    void silentSpillAllRegisters(FPRReg exclude)
+    {
+        for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                silentSpillGPR(iter.name(), iter.regID());
+        }
+        for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+            FPRReg fpr = iter.regID();
+            if (iter.name() != InvalidVirtualRegister && fpr != exclude)
+                silentSpillFPR(iter.name(), fpr);
+        }
+    }
+
+    void silentFillAllRegisters(GPRReg exclude, GPRReg exclude2 = InvalidGPRReg)
+    {
+        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, iter.regID());
+        }
+        for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+            GPRReg gpr = iter.regID();
+            if (iter.name() != InvalidVirtualRegister && gpr != exclude && gpr != exclude2)
+                silentFillGPR(iter.name(), gpr);
+        }
+    }
+    void silentFillAllRegisters(FPRReg exclude)
+    {
+        GPRReg canTrample = GPRInfo::regT0;
+        
+        for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+            FPRReg fpr = iter.regID();
+            if (iter.name() != InvalidVirtualRegister && fpr != exclude)
+                silentFillFPR(iter.name(), canTrample, fpr);
+        }
+        for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                silentFillGPR(iter.name(), iter.regID());
+        }
+    }
+
+    // These methods convert between doubles, and doubles boxed and JSValues.
+#if USE(JSVALUE64)
+    GPRReg boxDouble(FPRReg fpr, GPRReg gpr)
+    {
+        return m_jit.boxDouble(fpr, gpr);
+    }
+    FPRReg unboxDouble(GPRReg gpr, FPRReg fpr)
+    {
+        return m_jit.unboxDouble(gpr, fpr);
+    }
+    GPRReg boxDouble(FPRReg fpr)
+    {
+        return boxDouble(fpr, allocate());
+    }
+#elif USE(JSVALUE32_64)
+    void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR)
+    {
+        m_jit.boxDouble(fpr, tagGPR, payloadGPR);
+    }
+    void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, FPRReg scratchFPR)
+    {
+        m_jit.unboxDouble(tagGPR, payloadGPR, fpr, scratchFPR);
+    }
+#endif
+
+    // Spill a VirtualRegister to the RegisterFile.
+    void spill(VirtualRegister spillMe)
+    {
+        GenerationInfo& info = m_generationInfo[spillMe];
+
+#if USE(JSVALUE32_64)
+        if (info.registerFormat() == DataFormatNone) // it has been spilled. JS values which have two GPRs can reach here
+            return;
+#endif
+        // 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();
+        switch (spillFormat) {
+        case DataFormatStorage: {
+            // This is special, since it's not a JS value - as in it's not visible to JS
+            // code.
+            m_jit.storePtr(info.gpr(), JITCompiler::addressFor(spillMe));
+            info.spill(DataFormatStorage);
+            return;
+        }
+
+        case DataFormatInteger: {
+            m_jit.store32(info.gpr(), JITCompiler::payloadFor(spillMe));
+            info.spill(DataFormatInteger);
+            return;
+        }
+
+#if USE(JSVALUE64)
+        case DataFormatDouble: {
+            m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe));
+            info.spill(DataFormatDouble);
+            return;
+        }
+            
+        default:
+            // The following code handles JSValues, int32s, and cells.
+            ASSERT(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));
+            return;
+#elif USE(JSVALUE32_64)
+        case DataFormatCell:
+        case DataFormatBoolean: {
+            m_jit.store32(info.gpr(), JITCompiler::payloadFor(spillMe));
+            info.spill(spillFormat);
+            return;
+        }
+
+        case DataFormatDouble:
+        case DataFormatJSDouble: {
+            // On JSVALUE32_64 boxing a double is a no-op.
+            m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe));
+            info.spill(DataFormatJSDouble);
+            return;
+        }
+
+        default:
+            // The following code handles JSValues.
+            ASSERT(spillFormat & DataFormatJS);
+            m_jit.store32(info.tagGPR(), JITCompiler::tagFor(spillMe));
+            m_jit.store32(info.payloadGPR(), JITCompiler::payloadFor(spillMe));
+            info.spill(spillFormat);
+            return;
+#endif
+        }
+    }
+    
+    bool isStrictInt32(NodeIndex);
+    
+    bool isKnownInteger(NodeIndex);
+    bool isKnownNumeric(NodeIndex);
+    bool isKnownCell(NodeIndex);
+    
+    bool isKnownNotInteger(NodeIndex);
+    bool isKnownNotNumber(NodeIndex);
+
+    bool isKnownNotCell(NodeIndex);
+    
+    // Checks/accessors for constant values.
+    bool isConstant(NodeIndex nodeIndex) { return m_jit.graph().isConstant(nodeIndex); }
+    bool isJSConstant(NodeIndex nodeIndex) { return m_jit.graph().isJSConstant(nodeIndex); }
+    bool isInt32Constant(NodeIndex nodeIndex) { return m_jit.graph().isInt32Constant(nodeIndex); }
+    bool isDoubleConstant(NodeIndex nodeIndex) { return m_jit.graph().isDoubleConstant(nodeIndex); }
+    bool isNumberConstant(NodeIndex nodeIndex) { return m_jit.graph().isNumberConstant(nodeIndex); }
+    bool isBooleanConstant(NodeIndex nodeIndex) { return m_jit.graph().isBooleanConstant(nodeIndex); }
+    bool isFunctionConstant(NodeIndex nodeIndex) { return m_jit.graph().isFunctionConstant(nodeIndex); }
+    int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return m_jit.graph().valueOfInt32Constant(nodeIndex); }
+    double valueOfNumberConstant(NodeIndex nodeIndex) { return m_jit.graph().valueOfNumberConstant(nodeIndex); }
+    int32_t valueOfNumberConstantAsInt32(NodeIndex nodeIndex)
+    {
+        if (isInt32Constant(nodeIndex))
+            return valueOfInt32Constant(nodeIndex);
+        return JSC::toInt32(valueOfNumberConstant(nodeIndex));
+    }
+#if USE(JSVALUE32_64)
+    void* addressOfDoubleConstant(NodeIndex nodeIndex) { return m_jit.addressOfDoubleConstant(nodeIndex); }
+#endif
+    JSValue valueOfJSConstant(NodeIndex nodeIndex) { return m_jit.graph().valueOfJSConstant(nodeIndex); }
+    bool valueOfBooleanConstant(NodeIndex nodeIndex) { return m_jit.graph().valueOfBooleanConstant(nodeIndex); }
+    JSFunction* valueOfFunctionConstant(NodeIndex nodeIndex) { return m_jit.graph().valueOfFunctionConstant(nodeIndex); }
+    bool isNullConstant(NodeIndex nodeIndex)
+    {
+        if (!isConstant(nodeIndex))
+            return false;
+        return valueOfJSConstant(nodeIndex).isNull();
+    }
+
+    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
+
+#if USE(JSVALUE64)
+    MacroAssembler::ImmPtr valueOfJSConstantAsImmPtr(NodeIndex nodeIndex)
+    {
+        return MacroAssembler::ImmPtr(JSValue::encode(valueOfJSConstant(nodeIndex)));
+    }
+#endif
+
+    // 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();
+        }
+    }
+    
+    // Returns the index of the branch node if peephole is okay, UINT_MAX otherwise.
+    unsigned detectPeepHoleBranch()
+    {
+        BasicBlock* block = m_jit.graph().m_blocks[m_block].get();
+
+        // Check that no intervening nodes will be generated.
+        for (unsigned index = m_indexInBlock + 1; index < block->size() - 1; ++index) {
+            NodeIndex nodeIndex = block->at(index);
+            if (at(nodeIndex).shouldGenerate())
+                return UINT_MAX;
+        }
+
+        // Check if the lastNode is a branch on this node.
+        Node& lastNode = at(block->last());
+        return lastNode.op() == Branch && lastNode.child1().index() == m_compileIndex ? block->size() - 1 : UINT_MAX;
+    }
+    
+    void nonSpeculativeValueToNumber(Node&);
+    void nonSpeculativeValueToInt32(Node&);
+    void nonSpeculativeUInt32ToNumber(Node&);
+
+    enum SpillRegistersMode { NeedToSpill, DontSpill };
+#if USE(JSVALUE64)
+    JITCompiler::Call cachedGetById(CodeOrigin, GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
+    void cachedPutById(CodeOrigin, GPRReg base, GPRReg value, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
+#elif USE(JSVALUE32_64)
+    JITCompiler::Call cachedGetById(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
+    void cachedPutById(CodeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
+#endif
+
+    void nonSpeculativeNonPeepholeCompareNull(Edge operand, bool invert = false);
+    void nonSpeculativePeepholeBranchNull(Edge operand, NodeIndex branchNodeIndex, bool invert = false);
+    bool nonSpeculativeCompareNull(Node&, Edge operand, bool invert = false);
+    
+    void nonSpeculativePeepholeBranch(Node&, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition, S_DFGOperation_EJJ helperFunction);
+    void nonSpeculativeNonPeepholeCompare(Node&, MacroAssembler::RelationalCondition, S_DFGOperation_EJJ helperFunction);
+    bool nonSpeculativeCompare(Node&, MacroAssembler::RelationalCondition, S_DFGOperation_EJJ helperFunction);
+    
+    void nonSpeculativePeepholeStrictEq(Node&, NodeIndex branchNodeIndex, bool invert = false);
+    void nonSpeculativeNonPeepholeStrictEq(Node&, bool invert = false);
+    bool nonSpeculativeStrictEq(Node&, bool invert = false);
+    
+    void compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchAndResultReg);
+    void compileInstanceOf(Node&);
+    
+    // Access to our fixed callee CallFrame.
+    MacroAssembler::Address callFrameSlot(int slot)
+    {
+        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + slot) * static_cast<int>(sizeof(Register)));
+    }
+
+    // Access to our fixed callee CallFrame.
+    MacroAssembler::Address argumentSlot(int argument)
+    {
+        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)));
+    }
+
+    MacroAssembler::Address callFrameTagSlot(int slot)
+    {
+        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + slot) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+    }
+
+    MacroAssembler::Address callFramePayloadSlot(int slot)
+    {
+        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + slot) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+    }
+
+    MacroAssembler::Address argumentTagSlot(int argument)
+    {
+        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+    }
+
+    MacroAssembler::Address argumentPayloadSlot(int argument)
+    {
+        return MacroAssembler::Address(GPRInfo::callFrameRegister, (m_jit.codeBlock()->m_numCalleeRegisters + argumentToOperand(argument)) * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+    }
+
+    void emitCall(Node&);
+    
+    // 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, UseChildrenMode mode = CallUseChildren)
+    {
+        Node& node = at(nodeIndex);
+        if (mode == CallUseChildren)
+            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 {
+#if USE(JSVALUE64)
+            ASSERT(format == DataFormatJSInteger);
+            m_jit.jitAssertIsJSInt32(reg);
+            m_gprs.retain(reg, virtualRegister, SpillOrderJS);
+            info.initJSValue(nodeIndex, node.refCount(), reg, format);
+#elif USE(JSVALUE32_64)
+            ASSERT_NOT_REACHED();
+#endif
+        }
+    }
+    void integerResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode)
+    {
+        integerResult(reg, nodeIndex, DataFormatInteger, mode);
+    }
+    void noResult(NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
+    {
+        if (mode == UseChildrenCalledExplicitly)
+            return;
+        Node& node = at(nodeIndex);
+        useChildren(node);
+    }
+    void cellResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
+    {
+        Node& node = at(nodeIndex);
+        if (mode == CallUseChildren)
+            useChildren(node);
+
+        VirtualRegister virtualRegister = node.virtualRegister();
+        m_gprs.retain(reg, virtualRegister, SpillOrderCell);
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        info.initCell(nodeIndex, node.refCount(), reg);
+    }
+    void booleanResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
+    {
+        Node& node = at(nodeIndex);
+        if (mode == CallUseChildren)
+            useChildren(node);
+
+        VirtualRegister virtualRegister = node.virtualRegister();
+        m_gprs.retain(reg, virtualRegister, SpillOrderBoolean);
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        info.initBoolean(nodeIndex, node.refCount(), reg);
+    }
+#if USE(JSVALUE64)
+    void jsValueResult(GPRReg reg, NodeIndex nodeIndex, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
+    {
+        if (format == DataFormatJSInteger)
+            m_jit.jitAssertIsJSInt32(reg);
+        
+        Node& node = at(nodeIndex);
+        if (mode == CallUseChildren)
+            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 jsValueResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode)
+    {
+        jsValueResult(reg, nodeIndex, DataFormatJS, mode);
+    }
+#elif USE(JSVALUE32_64)
+    void jsValueResult(GPRReg tag, GPRReg payload, NodeIndex nodeIndex, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
+    {
+        Node& node = at(nodeIndex);
+        if (mode == CallUseChildren)
+            useChildren(node);
+
+        VirtualRegister virtualRegister = node.virtualRegister();
+        m_gprs.retain(tag, virtualRegister, SpillOrderJS);
+        m_gprs.retain(payload, virtualRegister, SpillOrderJS);
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        info.initJSValue(nodeIndex, node.refCount(), tag, payload, format);
+    }
+    void jsValueResult(GPRReg tag, GPRReg payload, NodeIndex nodeIndex, UseChildrenMode mode)
+    {
+        jsValueResult(tag, payload, nodeIndex, DataFormatJS, mode);
+    }
+#endif
+    void storageResult(GPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
+    {
+        Node& node = at(nodeIndex);
+        if (mode == CallUseChildren)
+            useChildren(node);
+        
+        VirtualRegister virtualRegister = node.virtualRegister();
+        m_gprs.retain(reg, virtualRegister, SpillOrderStorage);
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        info.initStorage(nodeIndex, node.refCount(), reg);
+    }
+    void doubleResult(FPRReg reg, NodeIndex nodeIndex, UseChildrenMode mode = CallUseChildren)
+    {
+        Node& node = at(nodeIndex);
+        if (mode == CallUseChildren)
+            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) || isNumberConstant(nodeIndex) || isJSConstant(nodeIndex));
+        Node& node = at(nodeIndex);
+        m_generationInfo[node.virtualRegister()].initConstant(nodeIndex, node.refCount());
+    }
+    
+    // These methods add calls to C++ helper functions.
+    // These methods are broadly value representation specific (i.e.
+    // deal with the fact that a JSValue may be passed in one or two
+    // machine registers, and delegate the calling convention specific
+    // decision as to how to fill the regsiters to setupArguments* methods.
+#if USE(JSVALUE64)
+    JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg result, void* pointer)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(Z_DFGOperation_D operation, GPRReg result, FPRReg arg1)
+    {
+        m_jit.setupArguments(arg1);
+        JITCompiler::Call call = m_jit.appendCall(operation);
+        m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
+        return call;
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EGI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EI operation, GPRReg result, Identifier* identifier)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(identifier));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EA operation, GPRReg result, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg result, void* pointer, size_t size)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_ESS operation, GPRReg result, int startConstant, int numConstants)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImm32(startConstant), TrustedImm32(numConstants));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg result, GPRReg arg1, void* pointer)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(pointer));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_ECI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg result, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
+    {
+        m_jit.setupArgumentsExecState();
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, JSCell* cell)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(S_DFGOperation_J operation, GPRReg result, GPRReg arg1)
+    {
+        m_jit.setupArguments(arg1);
+        return appendCallSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(S_DFGOperation_EJ operation, GPRReg result, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(S_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(S_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, MacroAssembler::TrustedImm32 imm)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, MacroAssembler::TrustedImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value)))));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg result, MacroAssembler::TrustedImm32 imm, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(MacroAssembler::TrustedImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value)))), arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_ECJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_EC operation, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1, GPRReg arg2, void* pointer)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(pointer));
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_EJCI operation, GPRReg arg1, GPRReg arg2, Identifier* identifier)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(identifier));
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_EJJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_EPZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_EAZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_ECJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(D_DFGOperation_EJ operation, FPRReg result, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(D_DFGOperation_ZZ operation, FPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArguments(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
+    {
+        m_jit.setupArguments(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+#else
+    JITCompiler::Call callOperation(Z_DFGOperation_D operation, GPRReg result, FPRReg arg1)
+    {
+        prepareForExternalCall();
+        m_jit.setupArguments(arg1);
+        JITCompiler::Call call = m_jit.appendCall(operation);
+        m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
+        return call;
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, void* pointer)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer));
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, void* pointer)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(pointer));
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EGI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, Identifier* identifier)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EI operation, GPRReg resultTag, GPRReg resultPayload, Identifier* identifier)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(identifier));
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EA operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg resultTag, GPRReg resultPayload, void* pointer, size_t size)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(pointer), TrustedImmPtr(size));
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_ESS operation, GPRReg resultTag, GPRReg resultPayload, int startConstant, int numConstants)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImm32(startConstant), TrustedImm32(numConstants));
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, void* pointer)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, TrustedImmPtr(pointer));
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJP operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_ECI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, Identifier* identifier)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier));
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, Identifier* identifier)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, TrustedImmPtr(identifier));
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJI operation, GPRReg resultTag, GPRReg resultPayload, int32_t arg1Tag, GPRReg arg1Payload, Identifier* identifier)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, TrustedImm32(arg1Tag), TrustedImmPtr(identifier));
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
+    {
+        m_jit.setupArgumentsExecState();
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_DFGOperation_EC operation, GPRReg result, JSCell* cell)
+    {
+        m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(S_DFGOperation_J operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
+    {
+        m_jit.setupArguments(arg1Payload, arg1Tag);
+        return appendCallSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(S_DFGOperation_EJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(S_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(S_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2Payload, arg2Tag);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2Payload, arg2Tag);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, MacroAssembler::TrustedImm32 imm)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, imm, TrustedImm32(JSValue::Int32Tag));
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_EJJ operation, GPRReg resultTag, GPRReg resultPayload, MacroAssembler::TrustedImm32 imm, GPRReg arg2Tag, GPRReg arg2Payload)
+    {
+        m_jit.setupArgumentsWithExecState(imm, TrustedImm32(JSValue::Int32Tag), arg2Payload, arg2Tag);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_ECJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_DFGOperation_ECC operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_EC operation, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_EJPP operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, void* pointer)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2, TrustedImmPtr(pointer));
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_EJCI operation, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2, Identifier* identifier)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2, TrustedImmPtr(identifier));
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_ECJJ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, arg3Payload, arg3Tag);
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_EPZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3Payload, arg3Tag);
+        return appendCallWithExceptionCheck(operation);
+    }
+    JITCompiler::Call callOperation(V_DFGOperation_EAZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3Payload, arg3Tag);
+        return appendCallWithExceptionCheck(operation);
+    }
+
+    JITCompiler::Call callOperation(D_DFGOperation_EJ operation, FPRReg result, GPRReg arg1Tag, GPRReg arg1Payload)
+    {
+        m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+
+    JITCompiler::Call callOperation(D_DFGOperation_ZZ operation, FPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArguments(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
+    {
+        m_jit.setupArguments(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+#endif
+    
+#if !defined(NDEBUG) && !CPU(ARM_THUMB2)
+    void prepareForExternalCall()
+    {
+        for (unsigned i = 0; i < sizeof(void*) / 4; i++)
+            m_jit.store32(TrustedImm32(0xbadbeef), reinterpret_cast<char*>(&m_jit.globalData()->topCallFrame) + i * 4);
+    }
+#else
+    void prepareForExternalCall() { }
+#endif
+
+    // These methods add call instructions, with optional exception checks & setting results.
+    JITCompiler::Call appendCallWithExceptionCheck(const FunctionPtr& function)
+    {
+        prepareForExternalCall();
+        CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
+        CallBeginToken token = m_jit.beginCall();
+        JITCompiler::Call call = m_jit.appendCall(function);
+        m_jit.addExceptionCheck(call, codeOrigin, token);
+        return call;
+    }
+    JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result)
+    {
+        JITCompiler::Call call = appendCallWithExceptionCheck(function);
+        m_jit.move(GPRInfo::returnValueGPR, result);
+        return call;
+    }
+    JITCompiler::Call appendCallSetResult(const FunctionPtr& function, GPRReg result)
+    {
+        prepareForExternalCall();
+        JITCompiler::Call call = m_jit.appendCall(function);
+        m_jit.move(GPRInfo::returnValueGPR, result);
+        return call;
+    }
+    JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result1, GPRReg result2)
+    {
+        JITCompiler::Call call = appendCallWithExceptionCheck(function);
+        m_jit.setupResults(result1, result2);
+        return call;
+    }
+#if CPU(X86)
+    JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, FPRReg result)
+    {
+        JITCompiler::Call call = appendCallWithExceptionCheck(function);
+        m_jit.assembler().fstpl(0, JITCompiler::stackPointerRegister);
+        m_jit.loadDouble(JITCompiler::stackPointerRegister, result);
+        return call;
+    }
+    JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
+    {
+        JITCompiler::Call call = m_jit.appendCall(function);
+        m_jit.assembler().fstpl(0, JITCompiler::stackPointerRegister);
+        m_jit.loadDouble(JITCompiler::stackPointerRegister, result);
+        return call;
+    }
+#elif CPU(ARM)
+    JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, FPRReg result)
+    {
+        JITCompiler::Call call = appendCallWithExceptionCheck(function);
+        m_jit.assembler().vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+        return call;
+    }
+    JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
+    {
+        JITCompiler::Call call = m_jit.appendCall(function);
+        m_jit.assembler().vmov(result, GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+        return call;
+    }
+#else
+    JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, FPRReg result)
+    {
+        JITCompiler::Call call = appendCallWithExceptionCheck(function);
+        m_jit.moveDouble(FPRInfo::returnValueFPR, result);
+        return call;
+    }
+    JITCompiler::Call appendCallSetResult(const FunctionPtr& function, FPRReg result)
+    {
+        JITCompiler::Call call = m_jit.appendCall(function);
+        m_jit.moveDouble(FPRInfo::returnValueFPR, result);
+        return call;
+    }
+#endif
+    
+    void branchDouble(JITCompiler::DoubleCondition cond, FPRReg left, FPRReg right, BlockIndex destination)
+    {
+        if (!haveEdgeCodeToEmit(destination))
+            return addBranch(m_jit.branchDouble(cond, left, right), destination);
+        
+        JITCompiler::Jump notTaken = m_jit.branchDouble(JITCompiler::invert(cond), left, right);
+        emitEdgeCode(destination);
+        addBranch(m_jit.jump(), destination);
+        notTaken.link(&m_jit);
+    }
+    
+    void branchDoubleNonZero(FPRReg value, FPRReg scratch, BlockIndex destination)
+    {
+        if (!haveEdgeCodeToEmit(destination))
+            return addBranch(m_jit.branchDoubleNonZero(value, scratch), destination);
+        
+        JITCompiler::Jump notTaken = m_jit.branchDoubleZeroOrNaN(value, scratch);
+        emitEdgeCode(destination);
+        addBranch(m_jit.jump(), destination);
+        notTaken.link(&m_jit);
+    }
+    
+    template<typename T, typename U>
+    void branch32(JITCompiler::RelationalCondition cond, T left, U right, BlockIndex destination)
+    {
+        if (!haveEdgeCodeToEmit(destination))
+            return addBranch(m_jit.branch32(cond, left, right), destination);
+        
+        JITCompiler::Jump notTaken = m_jit.branch32(JITCompiler::invert(cond), left, right);
+        emitEdgeCode(destination);
+        addBranch(m_jit.jump(), destination);
+        notTaken.link(&m_jit);
+    }
+    
+    template<typename T, typename U>
+    void branchTest32(JITCompiler::ResultCondition cond, T value, U mask, BlockIndex destination)
+    {
+        ASSERT(JITCompiler::isInvertible(cond));
+        
+        if (!haveEdgeCodeToEmit(destination))
+            return addBranch(m_jit.branchTest32(cond, value, mask), destination);
+        
+        JITCompiler::Jump notTaken = m_jit.branchTest32(JITCompiler::invert(cond), value, mask);
+        emitEdgeCode(destination);
+        addBranch(m_jit.jump(), destination);
+        notTaken.link(&m_jit);
+    }
+    
+    template<typename T>
+    void branchTest32(JITCompiler::ResultCondition cond, T value, BlockIndex destination)
+    {
+        ASSERT(JITCompiler::isInvertible(cond));
+        
+        if (!haveEdgeCodeToEmit(destination))
+            return addBranch(m_jit.branchTest32(cond, value), destination);
+        
+        JITCompiler::Jump notTaken = m_jit.branchTest32(JITCompiler::invert(cond), value);
+        emitEdgeCode(destination);
+        addBranch(m_jit.jump(), destination);
+        notTaken.link(&m_jit);
+    }
+    
+    template<typename T, typename U>
+    void branchPtr(JITCompiler::RelationalCondition cond, T left, U right, BlockIndex destination)
+    {
+        if (!haveEdgeCodeToEmit(destination))
+            return addBranch(m_jit.branchPtr(cond, left, right), destination);
+        
+        JITCompiler::Jump notTaken = m_jit.branchPtr(JITCompiler::invert(cond), left, right);
+        emitEdgeCode(destination);
+        addBranch(m_jit.jump(), destination);
+        notTaken.link(&m_jit);
+    }
+    
+    template<typename T, typename U>
+    void branchTestPtr(JITCompiler::ResultCondition cond, T value, U mask, BlockIndex destination)
+    {
+        ASSERT(JITCompiler::isInvertible(cond));
+        
+        if (!haveEdgeCodeToEmit(destination))
+            return addBranch(m_jit.branchTestPtr(cond, value, mask), destination);
+        
+        JITCompiler::Jump notTaken = m_jit.branchTestPtr(JITCompiler::invert(cond), value, mask);
+        emitEdgeCode(destination);
+        addBranch(m_jit.jump(), destination);
+        notTaken.link(&m_jit);
+    }
+    
+    template<typename T>
+    void branchTestPtr(JITCompiler::ResultCondition cond, T value, BlockIndex destination)
+    {
+        ASSERT(JITCompiler::isInvertible(cond));
+        
+        if (!haveEdgeCodeToEmit(destination))
+            return addBranch(m_jit.branchTestPtr(cond, value), destination);
+        
+        JITCompiler::Jump notTaken = m_jit.branchTestPtr(JITCompiler::invert(cond), value);
+        emitEdgeCode(destination);
+        addBranch(m_jit.jump(), destination);
+        notTaken.link(&m_jit);
+    }
+    
+    template<typename T, typename U>
+    void branchTest8(JITCompiler::ResultCondition cond, T value, U mask, BlockIndex destination)
+    {
+        ASSERT(JITCompiler::isInvertible(cond));
+        
+        if (!haveEdgeCodeToEmit(destination))
+            return addBranch(m_jit.branchTest8(cond, value, mask), destination);
+        
+        JITCompiler::Jump notTaken = m_jit.branchTest8(JITCompiler::invert(cond), value, mask);
+        emitEdgeCode(destination);
+        addBranch(m_jit.jump(), destination);
+        notTaken.link(&m_jit);
+    }
+    
+    template<typename T>
+    void branchTest8(JITCompiler::ResultCondition cond, T value, BlockIndex destination)
+    {
+        ASSERT(JITCompiler::isInvertible(cond));
+        
+        if (!haveEdgeCodeToEmit(destination))
+            return addBranch(m_jit.branchTest8(cond, value), destination);
+        
+        JITCompiler::Jump notTaken = m_jit.branchTest8(JITCompiler::invert(cond), value);
+        emitEdgeCode(destination);
+        addBranch(m_jit.jump(), destination);
+        notTaken.link(&m_jit);
+    }
+    
+    enum FallThroughMode {
+        AtFallThroughPoint,
+        ForceJump
+    };
+    void jump(BlockIndex destination, FallThroughMode fallThroughMode = AtFallThroughPoint)
+    {
+        if (haveEdgeCodeToEmit(destination))
+            emitEdgeCode(destination);
+        if (destination == m_block + 1
+            && fallThroughMode == AtFallThroughPoint)
+            return;
+        addBranch(m_jit.jump(), destination);
+    }
+    
+    inline bool haveEdgeCodeToEmit(BlockIndex)
+    {
+        return DFG_ENABLE_EDGE_CODE_VERIFICATION;
+    }
+    void emitEdgeCode(BlockIndex destination)
+    {
+        if (!DFG_ENABLE_EDGE_CODE_VERIFICATION)
+            return;
+        m_jit.move(TrustedImm32(destination), GPRInfo::regT0);
+    }
+
+    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);
+        }
+    }
+
+    BasicBlock* block()
+    {
+        return m_jit.graph().m_blocks[m_block].get();
+    }
+
+#ifndef NDEBUG
+    void dump(const char* label = 0);
+#endif
+
+#if DFG_ENABLE(CONSISTENCY_CHECK)
+    void checkConsistency();
+#else
+    void checkConsistency() { }
+#endif
+
+    bool isInteger(NodeIndex nodeIndex)
+    {
+        Node& node = at(nodeIndex);
+        if (node.hasInt32Result())
+            return true;
+
+        if (isInt32Constant(nodeIndex))
+            return true;
+
+        VirtualRegister virtualRegister = node.virtualRegister();
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        
+        return info.isJSInteger();
+    }
+    
+    bool compare(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
+    bool compilePeepHoleBranch(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
+    void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition);
+    void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition);
+    void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, const ClassInfo*, PredictionChecker);
+    void compilePeepHoleObjectToObjectOrOtherEquality(
+        Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex, const ClassInfo*, PredictionChecker);
+    void compileObjectEquality(Node&, const ClassInfo*, PredictionChecker);
+    void compileObjectToObjectOrOtherEquality(
+        Edge leftChild, Edge rightChild, const ClassInfo*, PredictionChecker);
+    void compileValueAdd(Node&);
+    void compileObjectOrOtherLogicalNot(Edge value, const ClassInfo*, bool needSpeculationCheck);
+    void compileLogicalNot(Node&);
+    void emitObjectOrOtherBranch(Edge value, BlockIndex taken, BlockIndex notTaken, const ClassInfo*, bool needSpeculationCheck);
+    void emitBranch(Node&);
+    
+    void compileIntegerCompare(Node&, MacroAssembler::RelationalCondition);
+    void compileDoubleCompare(Node&, MacroAssembler::DoubleCondition);
+    
+    bool compileStrictEqForConstant(Node&, Edge value, JSValue constant);
+    
+    bool compileStrictEq(Node&);
+    
+    void compileGetCharCodeAt(Node&);
+    void compileGetByValOnString(Node&);
+    void compileValueToInt32(Node&);
+    void compileUInt32ToNumber(Node&);
+    void compileDoubleAsInt32(Node&);
+    void compileInt32ToDouble(Node&);
+    void compileAdd(Node&);
+    void compileArithSub(Node&);
+    void compileArithNegate(Node&);
+    void compileArithMul(Node&);
+#if CPU(X86) || CPU(X86_64)
+    void compileIntegerArithDivForX86(Node&);
+#endif
+    void compileArithMod(Node&);
+    void compileSoftModulo(Node&);
+    void compileGetTypedArrayLength(const TypedArrayDescriptor&, Node&, bool needsSpeculationCheck);
+    enum TypedArraySpeculationRequirements {
+        NoTypedArraySpecCheck,
+        NoTypedArrayTypeSpecCheck,
+        AllTypedArraySpecChecks
+    };
+    enum TypedArraySignedness {
+        SignedTypedArray,
+        UnsignedTypedArray
+    };
+    enum TypedArrayRounding {
+        TruncateRounding,
+        ClampRounding
+    };
+    void compileGetIndexedPropertyStorage(Node&);
+    void compileGetByValOnIntTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness);
+    void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness, TypedArrayRounding = TruncateRounding);
+    void compileGetByValOnFloatTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements);
+    void compilePutByValForFloatTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements);
+    void compileNewFunctionNoCheck(Node&);
+    void compileNewFunctionExpression(Node&);
+    bool compileRegExpExec(Node&);
+    
+    template <typename ClassType, bool destructor, typename StructureType> 
+    void emitAllocateBasicJSObject(StructureType structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
+    {
+        MarkedAllocator* allocator = 0;
+        if (destructor)
+            allocator = &m_jit.globalData()->heap.allocatorForObjectWithDestructor(sizeof(ClassType));
+        else
+            allocator = &m_jit.globalData()->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType));
+
+        m_jit.loadPtr(&allocator->m_freeList.head, resultGPR);
+        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
+        
+        // The object is half-allocated: we have what we know is a fresh object, but
+        // it's still on the GC's free list.
+        
+        // Ditch the structure by placing it into the structure slot, so that we can reuse
+        // scratchGPR.
+        m_jit.storePtr(structure, MacroAssembler::Address(resultGPR, JSObject::structureOffset()));
+        
+        // Now that we have scratchGPR back, remove the object from the free list
+        m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR);
+        m_jit.storePtr(scratchGPR, &allocator->m_freeList.head);
+        
+        // Initialize the object's classInfo pointer
+        m_jit.storePtr(MacroAssembler::TrustedImmPtr(&ClassType::s_info), MacroAssembler::Address(resultGPR, JSCell::classInfoOffset()));
+        
+        // Initialize the object's inheritorID.
+        m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID()));
+        
+        // Initialize the object's property storage pointer.
+        m_jit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSObject)), resultGPR, scratchGPR);
+        m_jit.storePtr(scratchGPR, MacroAssembler::Address(resultGPR, ClassType::offsetOfPropertyStorage()));
+    }
+
+    // It is acceptable to have structure be equal to scratch, so long as you're fine
+    // with the structure GPR being clobbered.
+    template<typename T>
+    void emitAllocateJSFinalObject(T structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath)
+    {
+        return emitAllocateBasicJSObject<JSFinalObject, false>(structure, resultGPR, scratchGPR, slowPath);
+    }
+
+#if USE(JSVALUE64) 
+    JITCompiler::Jump convertToDouble(GPRReg value, FPRReg result, GPRReg tmp);
+#elif USE(JSVALUE32_64)
+    JITCompiler::Jump convertToDouble(JSValueOperand&, FPRReg result);
+#endif
+
+    // Add a speculation check without additional recovery.
+    void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail)
+    {
+        if (!m_compileOkay)
+            return;
+        m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this));
+    }
+    void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
+    {
+        speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail);
+    }
+    // Add a set of speculation checks without additional recovery.
+    void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail)
+    {
+        Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps();
+        for (unsigned i = 0; i < jumpVector.size(); ++i)
+            speculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i]);
+    }
+    void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::JumpList& jumpsToFail)
+    {
+        speculationCheck(kind, jsValueSource, nodeUse.index(), jumpsToFail);
+    }
+    // Add a speculation check with additional recovery.
+    void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
+    {
+        if (!m_compileOkay)
+            return;
+        m_jit.codeBlock()->appendSpeculationRecovery(recovery);
+        m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_jit.codeBlock()->numberOfSpeculationRecoveries()));
+    }
+    void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
+    {
+        speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery);
+    }
+    void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery)
+    {
+        speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail);
+        
+        unsigned setLocalIndexInBlock = m_indexInBlock + 1;
+        
+        Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock));
+        
+        if (setLocal->op() == Int32ToDouble) {
+            setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));
+            ASSERT(at(setLocal->child1()).child1() == m_compileIndex);
+        } else
+            ASSERT(setLocal->child1() == m_compileIndex);
+        
+        ASSERT(setLocal->op() == SetLocal);
+        ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin);
+
+        Node* nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1));
+        if (nextNode->codeOrigin == at(m_compileIndex).codeOrigin) {
+            ASSERT(nextNode->op() == Flush);
+            nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 2));
+            ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin); // duplicate the same assertion as below so that if we fail, we'll know we came down this path.
+        }
+        ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin);
+        
+        OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
+        exit.m_codeOrigin = nextNode->codeOrigin;
+        exit.m_lastSetOperand = setLocal->local();
+        
+        exit.valueRecoveryForOperand(setLocal->local()) = valueRecovery;
+    }
+    void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery)
+    {
+        Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps();
+        for (unsigned i = 0; i < jumpVector.size(); ++i)
+            forwardSpeculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i], valueRecovery);
+    }
+
+    // Called when we statically determine that a speculation will fail.
+    void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex)
+    {
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("SpeculativeJIT was terminated.\n");
+#endif
+        if (!m_compileOkay)
+            return;
+        speculationCheck(kind, jsValueRegs, nodeIndex, m_jit.jump());
+        m_compileOkay = false;
+    }
+    void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse)
+    {
+        terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.index());
+    }
+    
+    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;
+    
+    // Tracking for which nodes are currently holding the values of arguments and bytecode
+    // operand-indexed variables.
+    
+    ValueSource valueSourceForOperand(int operand)
+    {
+        return valueSourceReferenceForOperand(operand);
+    }
+    
+    void setNodeIndexForOperand(NodeIndex nodeIndex, int operand)
+    {
+        valueSourceReferenceForOperand(operand) = ValueSource(nodeIndex);
+    }
+    
+    // Call this with care, since it both returns a reference into an array
+    // and potentially resizes the array. So it would not be right to call this
+    // twice and then perform operands on both references, since the one from
+    // the first call may no longer be valid.
+    ValueSource& valueSourceReferenceForOperand(int operand)
+    {
+        if (operandIsArgument(operand)) {
+            int argument = operandToArgument(operand);
+            return m_arguments[argument];
+        }
+        
+        if ((unsigned)operand >= m_variables.size())
+            m_variables.resize(operand + 1);
+        
+        return m_variables[operand];
+    }
+    
+    // The JIT, while also provides MacroAssembler functionality.
+    JITCompiler& m_jit;
+    // The current node being generated.
+    BlockIndex m_block;
+    NodeIndex m_compileIndex;
+    unsigned m_indexInBlock;
+    // Virtual and physical register maps.
+    Vector<GenerationInfo, 32> m_generationInfo;
+    RegisterBank<GPRInfo> m_gprs;
+    RegisterBank<FPRInfo> m_fprs;
+
+    Vector<MacroAssembler::Label> m_blockHeads;
+    Vector<MacroAssembler::Label> m_osrEntryHeads;
+    
+    struct BranchRecord {
+        BranchRecord(MacroAssembler::Jump jump, BlockIndex destination)
+            : jump(jump)
+            , destination(destination)
+        {
+        }
+
+        MacroAssembler::Jump jump;
+        BlockIndex destination;
+    };
+    Vector<BranchRecord, 8> m_branches;
+
+    Vector<ValueSource, 0> m_arguments;
+    Vector<ValueSource, 0> m_variables;
+    int m_lastSetOperand;
+    CodeOrigin m_codeOriginForOSR;
+    
+    AbstractState m_state;
+    
+    ValueRecovery computeValueRecoveryFor(const ValueSource&);
+
+    ValueRecovery computeValueRecoveryFor(int operand)
+    {
+        return computeValueRecoveryFor(valueSourceForOperand(operand));
+    }
 };
 
 };
 
-// === 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)
+
+// === 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(SpeculativeJIT* jit, Edge use)
+        : m_jit(jit)
+        , m_index(use.index())
+        , m_gprOrInvalid(InvalidGPRReg)
+#ifndef NDEBUG
+        , m_format(DataFormatNone)
+#endif
+    {
+        ASSERT(m_jit);
+        ASSERT(use.useKind() != DoubleUse);
+        if (jit->isFilled(m_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;
     }
 
     }
 
-    SpeculationRecoveryType type() { return m_type; }
-    GPRReg dest() { return m_dest; }
-    GPRReg src() { return m_src; }
+    GPRReg gpr()
+    {
+        if (m_gprOrInvalid == InvalidGPRReg)
+            m_gprOrInvalid = m_jit->fillInteger(index(), m_format);
+        return m_gprOrInvalid;
+    }
+    
+    void use()
+    {
+        m_jit->use(m_index);
+    }
 
 private:
 
 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;
+    SpeculativeJIT* m_jit;
+    NodeIndex m_index;
+    GPRReg m_gprOrInvalid;
+    DataFormat m_format;
 };
 
 };
 
-// === 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;
+class DoubleOperand {
+public:
+    explicit DoubleOperand(SpeculativeJIT* jit, Edge use)
+        : m_jit(jit)
+        , m_index(use.index())
+        , m_fprOrInvalid(InvalidFPRReg)
+    {
+        ASSERT(m_jit);
+        
+        // This is counter-intuitive but correct. DoubleOperand is intended to
+        // be used only when you're a node that is happy to accept an untyped
+        // value, but will special-case for doubles (using DoubleOperand) if the
+        // value happened to already be represented as a double. The implication
+        // is that you will not try to force the value to become a double if it
+        // is not one already.
+        ASSERT(use.useKind() != DoubleUse);
+        
+        if (jit->isFilledDouble(m_index))
+            fpr();
+    }
 
 
+    ~DoubleOperand()
+    {
+        ASSERT(m_fprOrInvalid != InvalidFPRReg);
+        m_jit->unlock(m_fprOrInvalid);
+    }
 
 
-// === 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;
+    NodeIndex index() const
+    {
+        return m_index;
+    }
+
+    FPRReg fpr()
+    {
+        if (m_fprOrInvalid == InvalidFPRReg)
+            m_fprOrInvalid = m_jit->fillDouble(index());
+        return m_fprOrInvalid;
+    }
+    
+    void use()
+    {
+        m_jit->use(m_index);
+    }
+
+private:
+    SpeculativeJIT* m_jit;
+    NodeIndex m_index;
+    FPRReg m_fprOrInvalid;
+};
+
+class JSValueOperand {
 public:
 public:
-    SpeculativeJIT(JITCompiler& jit)
-        : JITCodeGenerator(jit, true)
-        , m_compileOkay(true)
+    explicit JSValueOperand(SpeculativeJIT* jit, Edge use)
+        : m_jit(jit)
+        , m_index(use.index())
+#if USE(JSVALUE64)
+        , m_gprOrInvalid(InvalidGPRReg)
+#elif USE(JSVALUE32_64)
+        , m_isDouble(false)
+#endif
     {
     {
+        ASSERT(m_jit);
+        ASSERT(use.useKind() != DoubleUse);
+#if USE(JSVALUE64)
+        if (jit->isFilled(m_index))
+            gpr();
+#elif USE(JSVALUE32_64)
+        m_register.pair.tagGPR = InvalidGPRReg;
+        m_register.pair.payloadGPR = InvalidGPRReg;
+        if (jit->isFilled(m_index))
+            fill();
+#endif
     }
 
     }
 
-    bool compile();
+    ~JSValueOperand()
+    {
+#if USE(JSVALUE64)
+        ASSERT(m_gprOrInvalid != InvalidGPRReg);
+        m_jit->unlock(m_gprOrInvalid);
+#elif USE(JSVALUE32_64)
+        if (m_isDouble) {
+            ASSERT(m_register.fpr != InvalidFPRReg);
+            m_jit->unlock(m_register.fpr);
+        } else {
+            ASSERT(m_register.pair.tagGPR != InvalidGPRReg && m_register.pair.payloadGPR != InvalidGPRReg);
+            m_jit->unlock(m_register.pair.tagGPR);
+            m_jit->unlock(m_register.pair.payloadGPR);
+        }
+#endif
+    }
+
+    NodeIndex index() const
+    {
+        return m_index;
+    }
 
 
-    // Retrieve the list of bail-outs from the speculative path,
-    // and additional recovery information.
-    SpeculationCheckVector& speculationChecks()
+#if USE(JSVALUE64)
+    GPRReg gpr()
     {
     {
-        return m_speculationChecks;
+        if (m_gprOrInvalid == InvalidGPRReg)
+            m_gprOrInvalid = m_jit->fillJSValue(index());
+        return m_gprOrInvalid;
     }
     }
-    SpeculationRecovery* speculationRecovery(size_t index)
+    JSValueRegs jsValueRegs()
     {
     {
-        // SpeculationCheck::m_recoveryIndex is offset by 1,
-        // 0 means no recovery.
-        return index ? &m_speculationRecoveryList[index - 1] : 0;
+        return JSValueRegs(gpr());
     }
     }
+#elif USE(JSVALUE32_64)
+    bool isDouble() { return m_isDouble; }
 
 
-    // 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);
+    void fill()
+    {
+        if (m_register.pair.tagGPR == InvalidGPRReg && m_register.pair.payloadGPR == InvalidGPRReg)
+            m_isDouble = !m_jit->fillJSValue(index(), m_register.pair.tagGPR, m_register.pair.payloadGPR, m_register.fpr);
+    }
 
 
-private:
-    void compile(Node&);
-    void compile(BasicBlock&);
+    GPRReg tagGPR()
+    {
+        fill();
+        ASSERT(!m_isDouble);
+        return m_register.pair.tagGPR;
+    }
 
 
-    void checkArgumentTypes();
-    void initializeVariableTypes();
+    GPRReg payloadGPR()
+    {
+        fill();
+        ASSERT(!m_isDouble);
+        return m_register.pair.payloadGPR;
+    }
 
 
-    bool isDoubleConstantWithInt32Value(NodeIndex nodeIndex, int32_t& out)
+    JSValueRegs jsValueRegs()
     {
     {
-        if (!m_jit.isDoubleConstant(nodeIndex))
-            return false;
-        double value = m_jit.valueOfDoubleConstant(nodeIndex);
+        return JSValueRegs(tagGPR(), payloadGPR());
+    }
 
 
-        int32_t asInt32 = static_cast<int32_t>(value);
-        if (value != asInt32)
-            return false;
-        if (!asInt32 && signbit(value))
-            return false;
+    FPRReg fpr()
+    {
+        fill();
+        ASSERT(m_isDouble);
+        return m_register.fpr;
+    }
+#endif
 
 
-        out = asInt32;
-        return true;
+    void use()
+    {
+        m_jit->use(m_index);
     }
 
     }
 
-    bool isJSConstantWithInt32Value(NodeIndex nodeIndex, int32_t& out)
+private:
+    SpeculativeJIT* m_jit;
+    NodeIndex m_index;
+#if USE(JSVALUE64)
+    GPRReg m_gprOrInvalid;
+#elif USE(JSVALUE32_64)
+    union {
+        struct {
+            GPRReg tagGPR;
+            GPRReg payloadGPR;
+        } pair;
+        FPRReg fpr;
+    } m_register;
+    bool m_isDouble;
+#endif
+};
+
+class StorageOperand {
+public:
+    explicit StorageOperand(SpeculativeJIT* jit, Edge use)
+        : m_jit(jit)
+        , m_index(use.index())
+        , m_gprOrInvalid(InvalidGPRReg)
     {
     {
-        if (!m_jit.isJSConstant(nodeIndex))
-            return false;
-        JSValue value = m_jit.valueOfJSConstant(nodeIndex);
+        ASSERT(m_jit);
+        ASSERT(use.useKind() != DoubleUse);
+        if (jit->isFilled(m_index))
+            gpr();
+    }
+    
+    ~StorageOperand()
+    {
+        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->fillStorage(index());
+        return m_gprOrInvalid;
+    }
+    
+    void use()
+    {
+        m_jit->use(m_index);
+    }
+    
+private:
+    SpeculativeJIT* m_jit;
+    NodeIndex m_index;
+    GPRReg m_gprOrInvalid;
+};
 
 
-        if (!value.isInt32())
-            return false;
-        
-        out = value.asInt32();
-        return true;
+
+// === 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();
+    GPRTemporary(SpeculativeJIT*);
+    GPRTemporary(SpeculativeJIT*, GPRReg specific);
+    GPRTemporary(SpeculativeJIT*, SpeculateIntegerOperand&);
+    GPRTemporary(SpeculativeJIT*, SpeculateIntegerOperand&, SpeculateIntegerOperand&);
+    GPRTemporary(SpeculativeJIT*, SpeculateStrictInt32Operand&);
+    GPRTemporary(SpeculativeJIT*, IntegerOperand&);
+    GPRTemporary(SpeculativeJIT*, IntegerOperand&, IntegerOperand&);
+    GPRTemporary(SpeculativeJIT*, SpeculateCellOperand&);
+    GPRTemporary(SpeculativeJIT*, SpeculateBooleanOperand&);
+#if USE(JSVALUE64)
+    GPRTemporary(SpeculativeJIT*, JSValueOperand&);
+#elif USE(JSVALUE32_64)
+    GPRTemporary(SpeculativeJIT*, JSValueOperand&, bool tag = true);
+#endif
+    GPRTemporary(SpeculativeJIT*, StorageOperand&);
+
+    void adopt(GPRTemporary&);
+
+    ~GPRTemporary()
+    {
+        if (m_jit && m_gpr != InvalidGPRReg)
+            m_jit->unlock(gpr());
     }
 
     }
 
-    bool detectPeepHoleBranch()
+    GPRReg gpr()
     {
     {
-        // Check if the block contains precisely one more node.
-        if (m_compileIndex + 2 != m_jit.graph().m_blocks[m_block]->end)
-            return false;
+        return m_gpr;
+    }
 
 
-        // 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;
+private:
+    SpeculativeJIT* m_jit;
+    GPRReg m_gpr;
+};
+
+class FPRTemporary {
+public:
+    FPRTemporary(SpeculativeJIT*);
+    FPRTemporary(SpeculativeJIT*, DoubleOperand&);
+    FPRTemporary(SpeculativeJIT*, DoubleOperand&, DoubleOperand&);
+    FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&);
+    FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&, SpeculateDoubleOperand&);
+#if USE(JSVALUE32_64)
+    FPRTemporary(SpeculativeJIT*, JSValueOperand&);
+#endif
+
+    ~FPRTemporary()
+    {
+        m_jit->unlock(fpr());
     }
 
     }
 
-    void compilePeepHoleBranch(Node&, JITCompiler::RelationalCondition);
+    FPRReg fpr() const
+    {
+        ASSERT(m_fpr != InvalidFPRReg);
+        return m_fpr;
+    }
 
 
-    // Add a speculation check without additional recovery.
-    void speculationCheck(MacroAssembler::Jump jumpToFail)
+protected:
+    FPRTemporary(SpeculativeJIT* jit, FPRReg lockedFPR)
+        : m_jit(jit)
+        , m_fpr(lockedFPR)
     {
     {
-        m_speculationChecks.append(SpeculationCheck(jumpToFail, this));
     }
     }
-    // Add a speculation check with additional recovery.
-    void speculationCheck(MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
+
+private:
+    SpeculativeJIT* 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(SpeculativeJIT* jit)
+        : GPRTemporary(jit, GPRInfo::returnValueGPR)
     {
     {
-        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()
+#if USE(JSVALUE32_64)
+class GPRResult2 : public GPRTemporary {
+public:
+    GPRResult2(SpeculativeJIT* jit)
+        : GPRTemporary(jit, GPRInfo::returnValueGPR2)
     {
     {
-        // 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());
     }
     }
+};
+#endif
 
 
-    template<bool strict>
-    GPRReg fillSpeculateIntInternal(NodeIndex, DataFormat& returnFormat);
+class FPRResult : public FPRTemporary {
+public:
+    FPRResult(SpeculativeJIT* jit)
+        : FPRTemporary(jit, lockedResult(jit))
+    {
+    }
 
 
-    // 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;
+private:
+    static FPRReg lockedResult(SpeculativeJIT* jit)
+    {
+        jit->lock(FPRInfo::returnValueFPR);
+        return FPRInfo::returnValueFPR;
+    }
 };
 
 
 };
 
 
@@ -223,23 +2409,24 @@ private:
 // SpeculateIntegerOperand, SpeculateStrictInt32Operand and SpeculateCellOperand.
 //
 // These are used to lock the operands to a node into machine registers within the
 // 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.
+// SpeculativeJIT. The classes operate like those above, 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:
 
 class SpeculateIntegerOperand {
 public:
-    explicit SpeculateIntegerOperand(SpeculativeJIT* jit, NodeIndex index)
+    explicit SpeculateIntegerOperand(SpeculativeJIT* jit, Edge use)
         : m_jit(jit)
         : m_jit(jit)
-        , m_index(index)
+        , m_index(use.index())
         , m_gprOrInvalid(InvalidGPRReg)
 #ifndef NDEBUG
         , m_format(DataFormatNone)
 #endif
     {
         ASSERT(m_jit);
         , m_gprOrInvalid(InvalidGPRReg)
 #ifndef NDEBUG
         , m_format(DataFormatNone)
 #endif
     {
         ASSERT(m_jit);
-        if (jit->isFilled(index))
+        ASSERT(use.useKind() != DoubleUse);
+        if (jit->isFilled(m_index))
             gpr();
     }
 
             gpr();
     }
 
@@ -277,13 +2464,14 @@ private:
 
 class SpeculateStrictInt32Operand {
 public:
 
 class SpeculateStrictInt32Operand {
 public:
-    explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, NodeIndex index)
+    explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, Edge use)
         : m_jit(jit)
         : m_jit(jit)
-        , m_index(index)
+        , m_index(use.index())
         , m_gprOrInvalid(InvalidGPRReg)
     {
         ASSERT(m_jit);
         , m_gprOrInvalid(InvalidGPRReg)
     {
         ASSERT(m_jit);
-        if (jit->isFilled(index))
+        ASSERT(use.useKind() != DoubleUse);
+        if (jit->isFilled(m_index))
             gpr();
     }
 
             gpr();
     }
 
@@ -304,6 +2492,11 @@ public:
             m_gprOrInvalid = m_jit->fillSpeculateIntStrict(index());
         return m_gprOrInvalid;
     }
             m_gprOrInvalid = m_jit->fillSpeculateIntStrict(index());
         return m_gprOrInvalid;
     }
+    
+    void use()
+    {
+        m_jit->use(m_index);
+    }
 
 private:
     SpeculativeJIT* m_jit;
 
 private:
     SpeculativeJIT* m_jit;
@@ -311,15 +2504,53 @@ private:
     GPRReg m_gprOrInvalid;
 };
 
     GPRReg m_gprOrInvalid;
 };
 
+class SpeculateDoubleOperand {
+public:
+    explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge use)
+        : m_jit(jit)
+        , m_index(use.index())
+        , m_fprOrInvalid(InvalidFPRReg)
+    {
+        ASSERT(m_jit);
+        ASSERT(use.useKind() == DoubleUse);
+        if (jit->isFilled(m_index))
+            fpr();
+    }
+
+    ~SpeculateDoubleOperand()
+    {
+        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->fillSpeculateDouble(index());
+        return m_fprOrInvalid;
+    }
+
+private:
+    SpeculativeJIT* m_jit;
+    NodeIndex m_index;
+    FPRReg m_fprOrInvalid;
+};
+
 class SpeculateCellOperand {
 public:
 class SpeculateCellOperand {
 public:
-    explicit SpeculateCellOperand(SpeculativeJIT* jit, NodeIndex index)
+    explicit SpeculateCellOperand(SpeculativeJIT* jit, Edge use)
         : m_jit(jit)
         : m_jit(jit)
-        , m_index(index)
+        , m_index(use.index())
         , m_gprOrInvalid(InvalidGPRReg)
     {
         ASSERT(m_jit);
         , m_gprOrInvalid(InvalidGPRReg)
     {
         ASSERT(m_jit);
-        if (jit->isFilled(index))
+        ASSERT(use.useKind() != DoubleUse);
+        if (jit->isFilled(m_index))
             gpr();
     }
 
             gpr();
     }
 
@@ -340,6 +2571,11 @@ public:
             m_gprOrInvalid = m_jit->fillSpeculateCell(index());
         return m_gprOrInvalid;
     }
             m_gprOrInvalid = m_jit->fillSpeculateCell(index());
         return m_gprOrInvalid;
     }
+    
+    void use()
+    {
+        m_jit->use(m_index);
+    }
 
 private:
     SpeculativeJIT* m_jit;
 
 private:
     SpeculativeJIT* m_jit;
@@ -347,37 +2583,61 @@ private:
     GPRReg m_gprOrInvalid;
 };
 
     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 {
+class SpeculateBooleanOperand {
 public:
 public:
-    SpeculationCheckIndexIterator(SpeculationCheckVector& speculationChecks)
-        : m_speculationChecks(speculationChecks)
-        , m_iter(m_speculationChecks.begin())
-        , m_end(m_speculationChecks.end())
+    explicit SpeculateBooleanOperand(SpeculativeJIT* jit, Edge use)
+        : m_jit(jit)
+        , m_index(use.index())
+        , m_gprOrInvalid(InvalidGPRReg)
     {
     {
+        ASSERT(m_jit);
+        ASSERT(use.useKind() != DoubleUse);
+        if (jit->isFilled(m_index))
+            gpr();
     }
     }
-
-    bool hasCheckAtIndex(NodeIndex nodeIndex)
+    
+    ~SpeculateBooleanOperand()
     {
     {
-        while (m_iter != m_end) {
-            NodeIndex current = m_iter->m_nodeIndex;
-            if (current >= nodeIndex)
-                return current == nodeIndex;
-            ++m_iter;
-        }
-        return false;
+        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->fillSpeculateBoolean(index());
+        return m_gprOrInvalid;
+    }
+    
+    void use()
+    {
+        m_jit->use(m_index);
     }
 
 private:
     }
 
 private:
-    SpeculationCheckVector& m_speculationChecks;
-    SpeculationCheckVector::Iterator m_iter;
-    SpeculationCheckVector::Iterator m_end;
+    SpeculativeJIT* m_jit;
+    NodeIndex m_index;
+    GPRReg m_gprOrInvalid;
 };
 
 };
 
+inline SpeculativeJIT::SpeculativeJIT(JITCompiler& jit)
+    : m_compileOkay(true)
+    , m_jit(jit)
+    , m_compileIndex(0)
+    , m_indexInBlock(0)
+    , m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters)
+    , m_blockHeads(jit.graph().m_blocks.size())
+    , m_arguments(jit.codeBlock()->numParameters())
+    , m_variables(jit.graph().m_localVars)
+    , m_lastSetOperand(std::numeric_limits<int>::max())
+    , m_state(m_jit.graph())
+{
+}
 
 } } // namespace JSC::DFG
 
 
 } } // namespace JSC::DFG
 
diff --git a/dfg/DFGSpeculativeJIT32_64.cpp b/dfg/DFGSpeculativeJIT32_64.cpp
new file mode 100644 (file)
index 0000000..f78402a
--- /dev/null
@@ -0,0 +1,3822 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this 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 {
+
+#if USE(JSVALUE32_64)
+
+GPRReg SpeculativeJIT::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat)
+{
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    if (info.registerFormat() == DataFormatNone) {
+        GPRReg gpr = allocate();
+
+        if (node.hasConstant()) {
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+            if (isInt32Constant(nodeIndex))
+                m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
+            else if (isNumberConstant(nodeIndex))
+                ASSERT_NOT_REACHED();
+            else {
+                ASSERT(isJSConstant(nodeIndex));
+                JSValue jsValue = valueOfJSConstant(nodeIndex);
+                m_jit.move(MacroAssembler::Imm32(jsValue.payload()), gpr);
+            }
+        } else {
+            ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger || info.spillFormat() == DataFormatInteger);
+            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
+        }
+
+        info.fillInteger(gpr);
+        returnFormat = DataFormatInteger;
+        return gpr;
+    }
+
+    switch (info.registerFormat()) {
+    case DataFormatNone:
+        // Should have filled, above.
+    case DataFormatJSDouble:
+    case DataFormatDouble:
+    case DataFormatJS:
+    case DataFormatCell:
+    case DataFormatJSCell:
+    case DataFormatBoolean:
+    case DataFormatJSBoolean:
+    case DataFormatStorage:
+        // Should only be calling this function if we know this operand to be integer.
+        ASSERT_NOT_REACHED();
+
+    case DataFormatJSInteger: {
+        GPRReg tagGPR = info.tagGPR();
+        GPRReg payloadGPR = info.payloadGPR();
+        m_gprs.lock(tagGPR);
+        m_jit.jitAssertIsJSInt32(tagGPR);
+        m_gprs.unlock(tagGPR);
+        m_gprs.lock(payloadGPR);
+        m_gprs.release(tagGPR);
+        m_gprs.release(payloadGPR);
+        m_gprs.retain(payloadGPR, virtualRegister, SpillOrderInteger);
+        info.fillInteger(payloadGPR);
+        returnFormat = DataFormatInteger;
+        return payloadGPR;
+    }
+
+    case DataFormatInteger: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        m_jit.jitAssertIsInt32(gpr);
+        returnFormat = DataFormatInteger;
+        return gpr;
+    }
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+FPRReg SpeculativeJIT::fillDouble(NodeIndex nodeIndex)
+{
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    if (info.registerFormat() == DataFormatNone) {
+
+        if (node.hasConstant()) {
+            if (isInt32Constant(nodeIndex)) {
+                // FIXME: should not be reachable?
+                GPRReg gpr = allocate();
+                m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
+                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+                info.fillInteger(gpr);
+                unlock(gpr);
+            } else if (isNumberConstant(nodeIndex)) {
+                FPRReg fpr = fprAllocate();
+                m_jit.loadDouble(addressOfDoubleConstant(nodeIndex), fpr);
+                m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+                info.fillDouble(fpr);
+                return fpr;
+            } else {
+                // FIXME: should not be reachable?
+                ASSERT_NOT_REACHED();
+            }
+        } else {
+            DataFormat spillFormat = info.spillFormat();
+            ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
+            if (spillFormat == DataFormatJSDouble) {
+                FPRReg fpr = fprAllocate();
+                m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
+                m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
+                info.fillDouble(fpr);
+                return fpr;
+            }
+
+            FPRReg fpr = fprAllocate();
+            JITCompiler::Jump hasUnboxedDouble;
+
+            if (spillFormat != DataFormatJSInteger && spillFormat != DataFormatInteger) {
+                JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));
+                m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
+                hasUnboxedDouble = m_jit.jump();
+                isInteger.link(&m_jit);
+            }
+
+            m_jit.convertInt32ToDouble(JITCompiler::payloadFor(virtualRegister), fpr);
+
+            if (hasUnboxedDouble.isSet())
+                hasUnboxedDouble.link(&m_jit);
+
+            m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
+            info.fillDouble(fpr);
+            return fpr;
+        }
+    }
+
+    switch (info.registerFormat()) {
+    case DataFormatNone:
+        // Should have filled, above.
+    case DataFormatCell:
+    case DataFormatJSCell:
+    case DataFormatBoolean:
+    case DataFormatJSBoolean:
+    case DataFormatStorage:
+        // Should only be calling this function if we know this operand to be numeric.
+        ASSERT_NOT_REACHED();
+
+    case DataFormatJSInteger:
+    case DataFormatJS: {
+        GPRReg tagGPR = info.tagGPR();
+        GPRReg payloadGPR = info.payloadGPR();
+        FPRReg fpr = fprAllocate();
+        m_gprs.lock(tagGPR);
+        m_gprs.lock(payloadGPR);
+
+        JITCompiler::Jump hasUnboxedDouble;
+
+        if (info.registerFormat() != DataFormatJSInteger) {
+            FPRTemporary scratch(this);
+            JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
+            m_jit.jitAssertIsJSDouble(tagGPR);
+            unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
+            hasUnboxedDouble = m_jit.jump();
+            isInteger.link(&m_jit);
+        }
+
+        m_jit.convertInt32ToDouble(payloadGPR, fpr);
+
+        if (hasUnboxedDouble.isSet())
+            hasUnboxedDouble.link(&m_jit);
+
+        m_gprs.release(tagGPR);
+        m_gprs.release(payloadGPR);
+        m_gprs.unlock(tagGPR);
+        m_gprs.unlock(payloadGPR);
+        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+        info.fillDouble(fpr);
+        info.killSpilled();
+        return fpr;
+    }
+
+    case DataFormatInteger: {
+        FPRReg fpr = fprAllocate();
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        m_jit.convertInt32ToDouble(gpr, fpr);
+        m_gprs.unlock(gpr);
+        return fpr;
+    }
+
+    case DataFormatJSDouble: 
+    case DataFormatDouble: {
+        FPRReg fpr = info.fpr();
+        m_fprs.lock(fpr);
+        return fpr;
+    }
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidFPRReg;
+}
+
+bool SpeculativeJIT::fillJSValue(NodeIndex nodeIndex, GPRReg& tagGPR, GPRReg& payloadGPR, FPRReg& fpr)
+{
+    // FIXME: For double we could fill with a FPR.
+    UNUSED_PARAM(fpr);
+
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    switch (info.registerFormat()) {
+    case DataFormatNone: {
+
+        if (node.hasConstant()) {
+            tagGPR = allocate();
+            payloadGPR = allocate();
+            m_jit.move(Imm32(valueOfJSConstant(nodeIndex).tag()), tagGPR);
+            m_jit.move(Imm32(valueOfJSConstant(nodeIndex).payload()), payloadGPR);
+            m_gprs.retain(tagGPR, virtualRegister, SpillOrderConstant);
+            m_gprs.retain(payloadGPR, virtualRegister, SpillOrderConstant);
+            info.fillJSValue(tagGPR, payloadGPR, isInt32Constant(nodeIndex) ? DataFormatJSInteger : DataFormatJS);
+        } else {
+            DataFormat spillFormat = info.spillFormat();
+            ASSERT(spillFormat != DataFormatNone && spillFormat != DataFormatStorage);
+            tagGPR = allocate();
+            payloadGPR = allocate();
+            switch (spillFormat) {
+            case DataFormatInteger:
+                m_jit.move(TrustedImm32(JSValue::Int32Tag), tagGPR);
+                spillFormat = DataFormatJSInteger; // This will be used as the new register format.
+                break;
+            case DataFormatCell:
+                m_jit.move(TrustedImm32(JSValue::CellTag), tagGPR);
+                spillFormat = DataFormatJSCell; // This will be used as the new register format.
+                break;
+            case DataFormatBoolean:
+                m_jit.move(TrustedImm32(JSValue::BooleanTag), tagGPR);
+                spillFormat = DataFormatJSBoolean; // This will be used as the new register format.
+                break;
+            default:
+                m_jit.load32(JITCompiler::tagFor(virtualRegister), tagGPR);
+                break;
+            }
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), payloadGPR);
+            m_gprs.retain(tagGPR, virtualRegister, SpillOrderSpilled);
+            m_gprs.retain(payloadGPR, virtualRegister, SpillOrderSpilled);
+            info.fillJSValue(tagGPR, payloadGPR, spillFormat == DataFormatJSDouble ? DataFormatJS : spillFormat);
+        }
+
+        return true;
+    }
+
+    case DataFormatInteger:
+    case DataFormatCell:
+    case DataFormatBoolean: {
+        GPRReg gpr = info.gpr();
+        // If the register has already been locked we need to take a copy.
+        if (m_gprs.isLocked(gpr)) {
+            payloadGPR = allocate();
+            m_jit.move(gpr, payloadGPR);
+        } else {
+            payloadGPR = gpr;
+            m_gprs.lock(gpr);
+        }
+        tagGPR = allocate();
+        uint32_t tag = JSValue::EmptyValueTag;
+        DataFormat fillFormat = DataFormatJS;
+        switch (info.registerFormat()) {
+        case DataFormatInteger:
+            tag = JSValue::Int32Tag;
+            fillFormat = DataFormatJSInteger;
+            break;
+        case DataFormatCell:
+            tag = JSValue::CellTag;
+            fillFormat = DataFormatJSCell;
+            break;
+        case DataFormatBoolean:
+            tag = JSValue::BooleanTag;
+            fillFormat = DataFormatJSBoolean;
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+            break;
+        }
+        m_jit.move(TrustedImm32(tag), tagGPR);
+        m_gprs.release(gpr);
+        m_gprs.retain(tagGPR, virtualRegister, SpillOrderJS);
+        m_gprs.retain(payloadGPR, virtualRegister, SpillOrderJS);
+        info.fillJSValue(tagGPR, payloadGPR, fillFormat);
+        return true;
+    }
+
+    case DataFormatJSDouble:
+    case DataFormatDouble: {
+        FPRReg oldFPR = info.fpr();
+        m_fprs.lock(oldFPR);
+        tagGPR = allocate();
+        payloadGPR = allocate();
+        boxDouble(oldFPR, tagGPR, payloadGPR);
+        m_fprs.unlock(oldFPR);
+        m_fprs.release(oldFPR);
+        m_gprs.retain(tagGPR, virtualRegister, SpillOrderJS);
+        m_gprs.retain(payloadGPR, virtualRegister, SpillOrderJS);
+        info.fillJSValue(tagGPR, payloadGPR, DataFormatJS);
+        return true;
+    }
+
+    case DataFormatJS:
+    case DataFormatJSInteger:
+    case DataFormatJSCell:
+    case DataFormatJSBoolean: {
+        tagGPR = info.tagGPR();
+        payloadGPR = info.payloadGPR();
+        m_gprs.lock(tagGPR);
+        m_gprs.lock(payloadGPR);
+        return true;
+    }
+        
+    case DataFormatStorage:
+        // this type currently never occurs
+        ASSERT_NOT_REACHED();
+    }
+
+    ASSERT_NOT_REACHED();
+    return true;
+}
+
+void SpeculativeJIT::nonSpeculativeValueToNumber(Node& node)
+{
+    if (isKnownNumeric(node.child1().index())) {
+        JSValueOperand op1(this, node.child1());
+        op1.fill();
+        if (op1.isDouble()) {
+            FPRTemporary result(this, op1);
+            m_jit.moveDouble(op1.fpr(), result.fpr());
+            doubleResult(result.fpr(), m_compileIndex);
+        } else {
+            GPRTemporary resultTag(this, op1);
+            GPRTemporary resultPayload(this, op1, false);
+            m_jit.move(op1.tagGPR(), resultTag.gpr());
+            m_jit.move(op1.payloadGPR(), resultPayload.gpr());
+            jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
+        }
+        return;
+    }
+
+    JSValueOperand op1(this, node.child1());
+    GPRTemporary resultTag(this, op1);
+    GPRTemporary resultPayload(this, op1, false);
+
+    ASSERT(!isInt32Constant(node.child1().index()));
+    ASSERT(!isNumberConstant(node.child1().index()));
+
+    GPRReg tagGPR = op1.tagGPR();
+    GPRReg payloadGPR = op1.payloadGPR();
+    GPRReg resultTagGPR = resultTag.gpr();
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+    op1.use();
+
+    JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
+    JITCompiler::Jump nonNumeric = m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag));
+
+    // First, if we get here we have a double encoded as a JSValue
+    JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
+
+    // Next handle cells (& other JS immediates)
+    nonNumeric.link(&m_jit);
+    silentSpillAllRegisters(resultTagGPR, resultPayloadGPR);
+    callOperation(dfgConvertJSValueToNumber, FPRInfo::returnValueFPR, tagGPR, payloadGPR);
+    boxDouble(FPRInfo::returnValueFPR, resultTagGPR, resultPayloadGPR);
+    silentFillAllRegisters(resultTagGPR, resultPayloadGPR);
+    JITCompiler::Jump hasCalledToNumber = m_jit.jump();
+    
+    // Finally, handle integers.
+    isInteger.link(&m_jit);
+    hasUnboxedDouble.link(&m_jit);
+    m_jit.move(tagGPR, resultTagGPR);
+    m_jit.move(payloadGPR, resultPayloadGPR);
+    hasCalledToNumber.link(&m_jit);
+    jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+}
+
+void SpeculativeJIT::nonSpeculativeValueToInt32(Node& node)
+{
+    ASSERT(!isInt32Constant(node.child1().index()));
+
+    if (isKnownInteger(node.child1().index())) {
+        IntegerOperand op1(this, node.child1());
+        GPRTemporary result(this, op1);
+        m_jit.move(op1.gpr(), result.gpr());
+        integerResult(result.gpr(), m_compileIndex);
+        return;
+    }
+
+    GenerationInfo& childInfo = m_generationInfo[at(node.child1()).virtualRegister()];
+    if (childInfo.isJSDouble()) {
+        DoubleOperand op1(this, node.child1());
+        GPRTemporary result(this);
+        FPRReg fpr = op1.fpr();
+        GPRReg gpr = result.gpr();
+        op1.use();
+        JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
+
+        silentSpillAllRegisters(gpr);
+        callOperation(toInt32, gpr, fpr);
+        silentFillAllRegisters(gpr);
+
+        truncatedToInteger.link(&m_jit);
+        integerResult(gpr, m_compileIndex, UseChildrenCalledExplicitly);
+        return;
+    }
+
+    JSValueOperand op1(this, node.child1());
+    GPRTemporary result(this);
+    GPRReg tagGPR = op1.tagGPR();
+    GPRReg payloadGPR = op1.payloadGPR();
+    GPRReg resultGPR = result.gpr();
+    op1.use();
+
+    JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
+
+    // First handle non-integers
+    silentSpillAllRegisters(resultGPR);
+    callOperation(dfgConvertJSValueToInt32, GPRInfo::returnValueGPR, tagGPR, payloadGPR);
+    m_jit.move(GPRInfo::returnValueGPR, resultGPR);
+    silentFillAllRegisters(resultGPR);
+    JITCompiler::Jump hasCalledToInt32 = m_jit.jump();
+
+    // Then handle integers.
+    isInteger.link(&m_jit);
+    m_jit.move(payloadGPR, resultGPR);
+    hasCalledToInt32.link(&m_jit);
+    integerResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+}
+
+void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node& node)
+{
+    IntegerOperand op1(this, node.child1());
+    FPRTemporary boxer(this);
+    GPRTemporary resultTag(this, op1);
+    GPRTemporary resultPayload(this);
+        
+    JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
+        
+    m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());
+    m_jit.move(JITCompiler::TrustedImmPtr(&AssemblyHelpers::twoToThe32), resultPayload.gpr()); // reuse resultPayload register here.
+    m_jit.addDouble(JITCompiler::Address(resultPayload.gpr(), 0), boxer.fpr());
+        
+    boxDouble(boxer.fpr(), resultTag.gpr(), resultPayload.gpr());
+        
+    JITCompiler::Jump done = m_jit.jump();
+        
+    positive.link(&m_jit);
+        
+    m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTag.gpr());
+    m_jit.move(op1.gpr(), resultPayload.gpr());
+        
+    done.link(&m_jit);
+
+    jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
+}
+
+JITCompiler::Call SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
+{
+    JITCompiler::DataLabelPtr structureToCompare;
+    JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
+    
+    m_jit.loadPtr(JITCompiler::Address(basePayloadGPR, JSObject::offsetOfPropertyStorage()), resultPayloadGPR);
+    JITCompiler::DataLabelCompact tagLoadWithPatch = m_jit.load32WithCompactAddressOffsetPatch(JITCompiler::Address(resultPayloadGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
+    JITCompiler::DataLabelCompact payloadLoadWithPatch = m_jit.load32WithCompactAddressOffsetPatch(JITCompiler::Address(resultPayloadGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
+    
+    JITCompiler::Jump done = m_jit.jump();
+
+    structureCheck.m_jump.link(&m_jit);
+    
+    if (slowPathTarget.isSet())
+        slowPathTarget.link(&m_jit);
+    
+    JITCompiler::Label slowCase = m_jit.label();
+
+    if (spillMode == NeedToSpill)
+        silentSpillAllRegisters(resultTagGPR, resultPayloadGPR);
+    JITCompiler::Call functionCall;
+    if (baseTagGPROrNone == InvalidGPRReg)
+        functionCall = callOperation(operationGetByIdOptimize, resultTagGPR, resultPayloadGPR, JSValue::CellTag, basePayloadGPR, identifier(identifierNumber));
+    else
+        functionCall = callOperation(operationGetByIdOptimize, resultTagGPR, resultPayloadGPR, baseTagGPROrNone, basePayloadGPR, identifier(identifierNumber));
+    if (spillMode == NeedToSpill)
+        silentFillAllRegisters(resultTagGPR, resultPayloadGPR);
+    
+    done.link(&m_jit);
+    
+    JITCompiler::Label doneLabel = m_jit.label();
+
+    m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, tagLoadWithPatch, payloadLoadWithPatch, slowCase, doneLabel, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(resultTagGPR), safeCast<int8_t>(resultPayloadGPR), safeCast<int8_t>(scratchGPR), spillMode == NeedToSpill ? PropertyAccessRecord::RegistersInUse : PropertyAccessRecord::RegistersFlushed));
+    
+    return functionCall;
+}
+
+void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
+{
+    JITCompiler::DataLabelPtr structureToCompare;
+    JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
+
+    writeBarrier(basePayloadGPR, valueTagGPR, valueUse, WriteBarrierForPropertyAccess, scratchGPR);
+
+    m_jit.loadPtr(JITCompiler::Address(basePayloadGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
+    JITCompiler::DataLabel32 tagStoreWithPatch = m_jit.store32WithAddressOffsetPatch(valueTagGPR, JITCompiler::Address(scratchGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+    JITCompiler::DataLabel32 payloadStoreWithPatch = m_jit.store32WithAddressOffsetPatch(valuePayloadGPR, JITCompiler::Address(scratchGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+
+    JITCompiler::Jump done = m_jit.jump();
+
+    structureCheck.m_jump.link(&m_jit);
+
+    if (slowPathTarget.isSet())
+        slowPathTarget.link(&m_jit);
+
+    JITCompiler::Label slowCase = m_jit.label();
+
+    silentSpillAllRegisters(InvalidGPRReg);
+    V_DFGOperation_EJCI optimizedCall;
+    if (m_jit.strictModeFor(at(m_compileIndex).codeOrigin)) {
+        if (putKind == Direct)
+            optimizedCall = operationPutByIdDirectStrictOptimize;
+        else
+            optimizedCall = operationPutByIdStrictOptimize;
+    } else {
+        if (putKind == Direct)
+            optimizedCall = operationPutByIdDirectNonStrictOptimize;
+        else
+            optimizedCall = operationPutByIdNonStrictOptimize;
+    }
+    JITCompiler::Call functionCall = callOperation(optimizedCall, valueTagGPR, valuePayloadGPR, basePayloadGPR, identifier(identifierNumber));
+    silentFillAllRegisters(InvalidGPRReg);
+
+    done.link(&m_jit);
+    JITCompiler::Label doneLabel = m_jit.label();
+
+    m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(tagStoreWithPatch.label()), JITCompiler::DataLabelCompact(payloadStoreWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(valueTagGPR), safeCast<int8_t>(valuePayloadGPR), safeCast<int8_t>(scratchGPR)));
+}
+
+void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool invert)
+{
+    JSValueOperand arg(this, operand);
+    GPRReg argTagGPR = arg.tagGPR();
+    GPRReg argPayloadGPR = arg.payloadGPR();
+
+    GPRTemporary resultPayload(this, arg, false);
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+
+    JITCompiler::Jump notCell;
+    if (!isKnownCell(operand.index()))
+        notCell = m_jit.branch32(MacroAssembler::NotEqual, argTagGPR, TrustedImm32(JSValue::CellTag));
+    
+    m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureOffset()), resultPayloadGPR);
+    m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultPayloadGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultPayloadGPR);
+    
+    if (!isKnownCell(operand.index())) {
+        JITCompiler::Jump done = m_jit.jump();
+        
+        notCell.link(&m_jit);
+        // null or undefined?
+        COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
+        m_jit.move(argTagGPR, resultPayloadGPR);
+        m_jit.or32(TrustedImm32(1), resultPayloadGPR);
+        m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultPayloadGPR, TrustedImm32(JSValue::NullTag), resultPayloadGPR);
+
+        done.link(&m_jit);
+    }
+    
+    booleanResult(resultPayloadGPR, m_compileIndex);
+}
+
+void SpeculativeJIT::nonSpeculativePeepholeBranchNull(Edge operand, NodeIndex branchNodeIndex, bool invert)
+{
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+    
+    if (taken == (m_block + 1)) {
+        invert = !invert;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+
+    JSValueOperand arg(this, operand);
+    GPRReg argTagGPR = arg.tagGPR();
+    GPRReg argPayloadGPR = arg.payloadGPR();
+    
+    GPRTemporary result(this, arg);
+    GPRReg resultGPR = result.gpr();
+    
+    JITCompiler::Jump notCell;
+    
+    if (!isKnownCell(operand.index()))
+        notCell = m_jit.branch32(MacroAssembler::NotEqual, argTagGPR, TrustedImm32(JSValue::CellTag));
+    
+    m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureOffset()), resultGPR);
+    branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), taken);
+    
+    if (!isKnownCell(operand.index())) {
+        jump(notTaken, ForceJump);
+        
+        notCell.link(&m_jit);
+        // null or undefined?
+        COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
+        m_jit.move(argTagGPR, resultGPR);
+        m_jit.or32(TrustedImm32(1), resultGPR);
+        branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(JSValue::NullTag), taken);
+    }
+    
+    jump(notTaken);
+}
+
+bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, Edge operand, bool invert)
+{
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock != UINT_MAX) {
+        NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+
+        ASSERT(node.adjustedRefCount() == 1);
+        
+        nonSpeculativePeepholeBranchNull(operand, branchNodeIndex, invert);
+    
+        use(node.child1());
+        use(node.child2());
+        m_indexInBlock = branchIndexInBlock;
+        m_compileIndex = branchNodeIndex;
+        
+        return true;
+    }
+    
+    nonSpeculativeNonPeepholeCompareNull(operand, invert);
+    
+    return false;
+}
+
+void SpeculativeJIT::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
+{
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+
+    JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
+
+    // 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)) {
+        cond = JITCompiler::invert(cond);
+        callResultCondition = JITCompiler::Zero;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+
+    JSValueOperand arg1(this, node.child1());
+    JSValueOperand arg2(this, node.child2());
+    GPRReg arg1TagGPR = arg1.tagGPR();
+    GPRReg arg1PayloadGPR = arg1.payloadGPR();
+    GPRReg arg2TagGPR = arg2.tagGPR();
+    GPRReg arg2PayloadGPR = arg2.payloadGPR();
+    
+    JITCompiler::JumpList slowPath;
+    
+    if (isKnownNotInteger(node.child1().index()) || isKnownNotInteger(node.child2().index())) {
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        arg1.use();
+        arg2.use();
+
+        flushRegisters();
+        callOperation(helperFunction, resultGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
+
+        branchTest32(callResultCondition, resultGPR, taken);
+    } else {
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
+    
+        arg1.use();
+        arg2.use();
+
+        if (!isKnownInteger(node.child1().index()))
+            slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
+        if (!isKnownInteger(node.child2().index()))
+            slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
+    
+        branch32(cond, arg1PayloadGPR, arg2PayloadGPR, taken);
+    
+        if (!isKnownInteger(node.child1().index()) || !isKnownInteger(node.child2().index())) {
+            jump(notTaken, ForceJump);
+    
+            slowPath.link(&m_jit);
+    
+            silentSpillAllRegisters(resultGPR);
+            callOperation(helperFunction, resultGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
+            silentFillAllRegisters(resultGPR);
+        
+            branchTest32(callResultCondition, resultGPR, taken);
+        }
+    }
+
+    jump(notTaken);
+    
+    m_indexInBlock = m_jit.graph().m_blocks[m_block]->size() - 1;
+    m_compileIndex = branchNodeIndex;
+}
+
+void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
+{
+    JSValueOperand arg1(this, node.child1());
+    JSValueOperand arg2(this, node.child2());
+    GPRReg arg1TagGPR = arg1.tagGPR();
+    GPRReg arg1PayloadGPR = arg1.payloadGPR();
+    GPRReg arg2TagGPR = arg2.tagGPR();
+    GPRReg arg2PayloadGPR = arg2.payloadGPR();
+    
+    JITCompiler::JumpList slowPath;
+    
+    if (isKnownNotInteger(node.child1().index()) || isKnownNotInteger(node.child2().index())) {
+        GPRResult result(this);
+        GPRReg resultPayloadGPR = result.gpr();
+    
+        arg1.use();
+        arg2.use();
+
+        flushRegisters();
+        callOperation(helperFunction, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
+        
+        booleanResult(resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+    } else {
+        GPRTemporary resultPayload(this, arg1, false);
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+
+        arg1.use();
+        arg2.use();
+    
+        if (!isKnownInteger(node.child1().index()))
+            slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
+        if (!isKnownInteger(node.child2().index()))
+            slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)));
+
+        m_jit.compare32(cond, arg1PayloadGPR, arg2PayloadGPR, resultPayloadGPR);
+    
+        if (!isKnownInteger(node.child1().index()) || !isKnownInteger(node.child2().index())) {
+            JITCompiler::Jump haveResult = m_jit.jump();
+    
+            slowPath.link(&m_jit);
+        
+            silentSpillAllRegisters(resultPayloadGPR);
+            callOperation(helperFunction, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
+            silentFillAllRegisters(resultPayloadGPR);
+        
+            m_jit.andPtr(TrustedImm32(1), resultPayloadGPR);
+        
+            haveResult.link(&m_jit);
+        }
+        
+        booleanResult(resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+    }
+}
+
+void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branchNodeIndex, bool invert)
+{
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+
+    // 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)) {
+        invert = !invert;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+    
+    JSValueOperand arg1(this, node.child1());
+    JSValueOperand arg2(this, node.child2());
+    GPRReg arg1TagGPR = arg1.tagGPR();
+    GPRReg arg1PayloadGPR = arg1.payloadGPR();
+    GPRReg arg2TagGPR = arg2.tagGPR();
+    GPRReg arg2PayloadGPR = arg2.payloadGPR();
+    
+    GPRTemporary resultPayload(this, arg1, false);
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+    
+    arg1.use();
+    arg2.use();
+    
+    if (isKnownCell(node.child1().index()) && isKnownCell(node.child2().index())) {
+        // see if we get lucky: if the arguments are cells and they reference the same
+        // cell, then they must be strictly equal.
+        branchPtr(JITCompiler::Equal, arg1PayloadGPR, arg2PayloadGPR, invert ? notTaken : taken);
+        
+        silentSpillAllRegisters(resultPayloadGPR);
+        callOperation(operationCompareStrictEqCell, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
+        silentFillAllRegisters(resultPayloadGPR);
+        
+        branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultPayloadGPR, taken);
+    } else {
+        // FIXME: Add fast paths for twoCells, number etc.
+
+        silentSpillAllRegisters(resultPayloadGPR);
+        callOperation(operationCompareStrictEq, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
+        silentFillAllRegisters(resultPayloadGPR);
+        
+        branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultPayloadGPR, taken);
+    }
+    
+    jump(notTaken);
+}
+
+void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)
+{
+    JSValueOperand arg1(this, node.child1());
+    JSValueOperand arg2(this, node.child2());
+    GPRReg arg1TagGPR = arg1.tagGPR();
+    GPRReg arg1PayloadGPR = arg1.payloadGPR();
+    GPRReg arg2TagGPR = arg2.tagGPR();
+    GPRReg arg2PayloadGPR = arg2.payloadGPR();
+    
+    GPRTemporary resultPayload(this, arg1, false);
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+    
+    arg1.use();
+    arg2.use();
+    
+    if (isKnownCell(node.child1().index()) && isKnownCell(node.child2().index())) {
+        // see if we get lucky: if the arguments are cells and they reference the same
+        // cell, then they must be strictly equal.
+        JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1PayloadGPR, arg2PayloadGPR);
+        
+        m_jit.move(JITCompiler::TrustedImm32(!invert), resultPayloadGPR);
+        JITCompiler::Jump done = m_jit.jump();
+
+        notEqualCase.link(&m_jit);
+        
+        silentSpillAllRegisters(resultPayloadGPR);
+        callOperation(operationCompareStrictEqCell, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
+        silentFillAllRegisters(resultPayloadGPR);
+        
+        m_jit.andPtr(JITCompiler::TrustedImm32(1), resultPayloadGPR);
+        
+        done.link(&m_jit);
+    } else {
+        // FIXME: Add fast paths.
+
+        silentSpillAllRegisters(resultPayloadGPR);
+        callOperation(operationCompareStrictEq, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR);
+        silentFillAllRegisters(resultPayloadGPR);
+        
+        m_jit.andPtr(JITCompiler::TrustedImm32(1), resultPayloadGPR);
+    }
+
+    booleanResult(resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+}
+
+void SpeculativeJIT::emitCall(Node& node)
+{
+    P_DFGOperation_E slowCallFunction;
+
+    if (node.op() == Call)
+        slowCallFunction = operationLinkCall;
+    else {
+        ASSERT(node.op() == Construct);
+        slowCallFunction = operationLinkConstruct;
+    }
+
+    // For constructors, the this argument is not passed but we have to make space
+    // for it.
+    int dummyThisArgument = node.op() == Call ? 0 : 1;
+
+    CallLinkInfo::CallType callType = node.op() == Call ? CallLinkInfo::Call : CallLinkInfo::Construct;
+
+    Edge calleeEdge = m_jit.graph().m_varArgChildren[node.firstChild()];
+    JSValueOperand callee(this, calleeEdge);
+    GPRReg calleeTagGPR = callee.tagGPR();
+    GPRReg calleePayloadGPR = callee.payloadGPR();
+    use(calleeEdge);
+
+    // The call instruction's first child is either the function (normal call) or the
+    // receiver (method call). subsequent children are the arguments.
+    int numPassedArgs = node.numChildren() - 1;
+
+    m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs + dummyThisArgument), callFramePayloadSlot(RegisterFile::ArgumentCount));
+    m_jit.storePtr(GPRInfo::callFrameRegister, callFramePayloadSlot(RegisterFile::CallerFrame));
+    m_jit.store32(calleePayloadGPR, callFramePayloadSlot(RegisterFile::Callee));
+    m_jit.store32(calleeTagGPR, callFrameTagSlot(RegisterFile::Callee));
+
+    for (int i = 0; i < numPassedArgs; i++) {
+        Edge argEdge = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i];
+        JSValueOperand arg(this, argEdge);
+        GPRReg argTagGPR = arg.tagGPR();
+        GPRReg argPayloadGPR = arg.payloadGPR();
+        use(argEdge);
+
+        m_jit.store32(argTagGPR, argumentTagSlot(i + dummyThisArgument));
+        m_jit.store32(argPayloadGPR, argumentPayloadSlot(i + dummyThisArgument));
+    }
+
+    flushRegisters();
+
+    GPRResult resultPayload(this);
+    GPRResult2 resultTag(this);
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+    GPRReg resultTagGPR = resultTag.gpr();
+
+    JITCompiler::DataLabelPtr targetToCheck;
+    JITCompiler::JumpList slowPath;
+
+    slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck));
+    slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, calleeTagGPR, TrustedImm32(JSValue::CellTag)));
+    m_jit.loadPtr(MacroAssembler::Address(calleePayloadGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultPayloadGPR);
+    m_jit.storePtr(resultPayloadGPR, callFramePayloadSlot(RegisterFile::ScopeChain));
+    m_jit.store32(MacroAssembler::TrustedImm32(JSValue::CellTag), callFrameTagSlot(RegisterFile::ScopeChain));
+
+    m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
+
+    CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
+    CallBeginToken token = m_jit.beginCall();
+    JITCompiler::Call fastCall = m_jit.nearCall();
+    m_jit.notifyCall(fastCall, codeOrigin, token);
+
+    JITCompiler::Jump done = m_jit.jump();
+
+    slowPath.link(&m_jit);
+
+    m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    m_jit.poke(GPRInfo::argumentGPR0);
+    token = m_jit.beginCall();
+    JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction);
+    m_jit.addFastExceptionCheck(slowCall, codeOrigin, token);
+    m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
+    token = m_jit.beginCall();
+    JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR);
+    m_jit.notifyCall(theCall, codeOrigin, token);
+
+    done.link(&m_jit);
+
+    m_jit.setupResults(resultPayloadGPR, resultTagGPR);
+
+    jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly);
+
+    m_jit.addJSCall(fastCall, slowCall, targetToCheck, callType, at(m_compileIndex).codeOrigin);
+}
+
+template<bool strict>
+GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat& returnFormat)
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("SpecInt@%d   ", nodeIndex);
+#endif
+    if (isKnownNotInteger(nodeIndex)) {
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        returnFormat = DataFormatInteger;
+        return allocate();
+    }
+
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    switch (info.registerFormat()) {
+    case DataFormatNone: {
+
+        if (node.hasConstant()) {
+            ASSERT(isInt32Constant(nodeIndex));
+            GPRReg gpr = allocate();
+            m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+            info.fillInteger(gpr);
+            returnFormat = DataFormatInteger;
+            return gpr;
+        }
+
+        DataFormat spillFormat = info.spillFormat();
+        ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
+
+        // If we know this was spilled as an integer we can fill without checking.
+        if (spillFormat != DataFormatJSInteger && spillFormat != DataFormatInteger)
+            speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
+
+        GPRReg gpr = allocate();
+        m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
+        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+        info.fillInteger(gpr);
+        returnFormat = DataFormatInteger;
+        return gpr;
+    }
+
+    case DataFormatJSInteger:
+    case DataFormatJS: {
+        // Check the value is an integer.
+        GPRReg tagGPR = info.tagGPR();
+        GPRReg payloadGPR = info.payloadGPR();
+        m_gprs.lock(tagGPR);
+        m_gprs.lock(payloadGPR);
+        if (info.registerFormat() != DataFormatJSInteger) 
+            speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::Int32Tag)));
+        m_gprs.unlock(tagGPR);
+        m_gprs.release(tagGPR);
+        m_gprs.release(payloadGPR);
+        m_gprs.retain(payloadGPR, virtualRegister, SpillOrderInteger);
+        info.fillInteger(payloadGPR);
+        // If !strict we're done, return.
+        returnFormat = DataFormatInteger;
+        return payloadGPR;
+    }
+
+    case DataFormatInteger: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        returnFormat = DataFormatInteger;
+        return gpr;
+    }
+
+    case DataFormatDouble:
+    case DataFormatCell:
+    case DataFormatBoolean:
+    case DataFormatJSDouble:
+    case DataFormatJSCell:
+    case DataFormatJSBoolean:
+    case DataFormatStorage:
+        ASSERT_NOT_REACHED();
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+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;
+}
+
+FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("SpecDouble@%d   ", nodeIndex);
+#endif
+    if (isKnownNotNumber(nodeIndex)) {
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        return fprAllocate();
+    }
+
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    if (info.registerFormat() == DataFormatNone) {
+
+        if (node.hasConstant()) {
+            if (isInt32Constant(nodeIndex)) {
+                GPRReg gpr = allocate();
+                m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
+                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+                info.fillInteger(gpr);
+                unlock(gpr);
+            } else if (isNumberConstant(nodeIndex)) {
+                FPRReg fpr = fprAllocate();
+                m_jit.loadDouble(addressOfDoubleConstant(nodeIndex), fpr);
+                m_fprs.retain(fpr, virtualRegister, SpillOrderConstant);
+                info.fillDouble(fpr);
+                return fpr;
+            } else
+                ASSERT_NOT_REACHED();
+        } else {
+            DataFormat spillFormat = info.spillFormat();
+            ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
+            if (spillFormat == DataFormatJSDouble || spillFormat == DataFormatDouble) {
+                FPRReg fpr = fprAllocate();
+                m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
+                m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
+                info.fillDouble(fpr);
+                return fpr;
+            }
+
+            FPRReg fpr = fprAllocate();
+            JITCompiler::Jump hasUnboxedDouble;
+
+            if (spillFormat != DataFormatJSInteger && spillFormat != DataFormatInteger) {
+                JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));
+                speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::AboveOrEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::LowestTag)));
+                m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
+                hasUnboxedDouble = m_jit.jump();
+
+                isInteger.link(&m_jit);
+            }
+
+            m_jit.convertInt32ToDouble(JITCompiler::payloadFor(virtualRegister), fpr);
+
+            if (hasUnboxedDouble.isSet())
+                hasUnboxedDouble.link(&m_jit);
+
+            m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
+            info.fillDouble(fpr);
+            info.killSpilled();
+            return fpr;
+        }
+    }
+
+    switch (info.registerFormat()) {
+    case DataFormatJS:
+    case DataFormatJSInteger: {
+        GPRReg tagGPR = info.tagGPR();
+        GPRReg payloadGPR = info.payloadGPR();
+        FPRReg fpr = fprAllocate();
+
+        m_gprs.lock(tagGPR);
+        m_gprs.lock(payloadGPR);
+
+        JITCompiler::Jump hasUnboxedDouble;
+
+        if (info.registerFormat() != DataFormatJSInteger) {
+            FPRTemporary scratch(this);
+            JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
+            speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
+            unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
+            hasUnboxedDouble = m_jit.jump();
+            isInteger.link(&m_jit);
+        }
+
+        m_jit.convertInt32ToDouble(payloadGPR, fpr);
+
+        if (hasUnboxedDouble.isSet())
+            hasUnboxedDouble.link(&m_jit);
+
+        m_gprs.release(tagGPR);
+        m_gprs.release(payloadGPR);
+        m_gprs.unlock(tagGPR);
+        m_gprs.unlock(payloadGPR);
+        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+        info.fillDouble(fpr);
+        info.killSpilled();
+        return fpr;
+    }
+
+    case DataFormatInteger: {
+        FPRReg fpr = fprAllocate();
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        m_jit.convertInt32ToDouble(gpr, fpr);
+        m_gprs.unlock(gpr);
+        return fpr;
+    }
+
+    case DataFormatJSDouble:
+    case DataFormatDouble: {
+        FPRReg fpr = info.fpr();
+        m_fprs.lock(fpr);
+        return fpr;
+    }
+
+    case DataFormatNone:
+    case DataFormatStorage:
+    case DataFormatCell:
+    case DataFormatJSCell:
+    case DataFormatBoolean:
+    case DataFormatJSBoolean:
+        ASSERT_NOT_REACHED();
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidFPRReg;
+}
+
+GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("SpecCell@%d   ", nodeIndex);
+#endif
+    if (isKnownNotCell(nodeIndex)) {
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        return allocate();
+    }
+
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    switch (info.registerFormat()) {
+    case DataFormatNone: {
+
+        if (node.hasConstant()) {
+            JSValue jsValue = valueOfJSConstant(nodeIndex);
+            ASSERT(jsValue.isCell());
+            GPRReg gpr = allocate();
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+            m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
+            info.fillCell(gpr);
+            return gpr;
+        }
+
+        ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatCell);
+        if (info.spillFormat() != DataFormatJSCell && info.spillFormat() != DataFormatCell)
+            speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)));
+        GPRReg gpr = allocate();
+        m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
+        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+        info.fillCell(gpr);
+        return gpr;
+    }
+
+    case DataFormatCell: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        return gpr;
+    }
+
+    case DataFormatJSCell:
+    case DataFormatJS: {
+        GPRReg tagGPR = info.tagGPR();
+        GPRReg payloadGPR = info.payloadGPR();
+        m_gprs.lock(tagGPR);
+        m_gprs.lock(payloadGPR);
+        if (info.spillFormat() != DataFormatJSCell)
+            speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::CellTag)));
+        m_gprs.unlock(tagGPR);
+        m_gprs.release(tagGPR);
+        m_gprs.release(payloadGPR);
+        m_gprs.retain(payloadGPR, virtualRegister, SpillOrderCell);
+        info.fillCell(payloadGPR);
+        return payloadGPR;
+    }
+
+    case DataFormatJSInteger:
+    case DataFormatInteger:
+    case DataFormatJSDouble:
+    case DataFormatDouble:
+    case DataFormatJSBoolean:
+    case DataFormatBoolean:
+    case DataFormatStorage:
+        ASSERT_NOT_REACHED();
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+     dataLog("SpecBool@%d   ", nodeIndex);
+#endif
+    Node& node = m_jit.graph()[nodeIndex];
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+    if ((node.hasConstant() && !valueOfJSConstant(nodeIndex).isBoolean())
+        || !(info.isJSBoolean() || info.isUnknownJS())) {
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        return allocate();
+    }
+
+    switch (info.registerFormat()) {
+    case DataFormatNone: {
+
+        if (node.hasConstant()) {
+            JSValue jsValue = valueOfJSConstant(nodeIndex);
+            ASSERT(jsValue.isBoolean());
+            GPRReg gpr = allocate();
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+            m_jit.move(MacroAssembler::TrustedImm32(jsValue.asBoolean()), gpr);
+            info.fillBoolean(gpr);
+            return gpr;
+        }
+
+        ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatBoolean);
+
+        if (info.spillFormat() != DataFormatJSBoolean && info.spillFormat() != DataFormatBoolean)
+            speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
+
+        GPRReg gpr = allocate();
+        m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
+        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+        info.fillBoolean(gpr);
+        return gpr;
+    }
+
+    case DataFormatBoolean: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        return gpr;
+    }
+
+    case DataFormatJSBoolean:
+    case DataFormatJS: {
+        GPRReg tagGPR = info.tagGPR();
+        GPRReg payloadGPR = info.payloadGPR();
+        m_gprs.lock(tagGPR);
+        m_gprs.lock(payloadGPR);
+        if (info.registerFormat() != DataFormatJSBoolean)
+            speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::BooleanTag)));
+
+        m_gprs.unlock(tagGPR);
+        m_gprs.release(tagGPR);
+        m_gprs.release(payloadGPR);
+        m_gprs.retain(payloadGPR, virtualRegister, SpillOrderBoolean);
+        info.fillBoolean(payloadGPR);
+        return payloadGPR;
+    }
+
+    case DataFormatJSInteger:
+    case DataFormatInteger:
+    case DataFormatJSDouble:
+    case DataFormatDouble:
+    case DataFormatJSCell:
+    case DataFormatCell:
+    case DataFormatStorage:
+        ASSERT_NOT_REACHED();
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+JITCompiler::Jump SpeculativeJIT::convertToDouble(JSValueOperand& op, FPRReg result)
+{
+    FPRTemporary scratch(this);
+
+    JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, op.tagGPR(), TrustedImm32(JSValue::Int32Tag));
+    JITCompiler::Jump notNumber = m_jit.branch32(MacroAssembler::AboveOrEqual, op.payloadGPR(), TrustedImm32(JSValue::LowestTag));
+
+    unboxDouble(op.tagGPR(), op.payloadGPR(), result, scratch.fpr());
+    JITCompiler::Jump done = m_jit.jump();
+
+    isInteger.link(&m_jit);
+    m_jit.convertInt32ToDouble(op.payloadGPR(), result);
+
+    done.link(&m_jit);
+
+    return notNumber;
+}
+
+void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, PredictionChecker predictionCheck)
+{
+    SpeculateCellOperand op1(this, node.child1());
+    SpeculateCellOperand op2(this, node.child2());
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    
+    if (!predictionCheck(m_state.forNode(node.child1()).m_type))
+        speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
+    if (!predictionCheck(m_state.forNode(node.child2()).m_type))
+        speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
+    
+    GPRTemporary resultPayload(this, op2);
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+    
+    MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
+    m_jit.move(TrustedImm32(1), resultPayloadGPR);
+    MacroAssembler::Jump done = m_jit.jump();
+    falseCase.link(&m_jit);
+    m_jit.move(TrustedImm32(0), resultPayloadGPR);
+    done.link(&m_jit);
+
+    booleanResult(resultPayloadGPR, m_compileIndex);
+}
+
+void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
+    Edge leftChild, Edge rightChild,
+    const ClassInfo* classInfo, PredictionChecker predictionCheck)
+{
+    SpeculateCellOperand op1(this, leftChild);
+    JSValueOperand op2(this, rightChild);
+    GPRTemporary result(this);
+    
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2TagGPR = op2.tagGPR();
+    GPRReg op2PayloadGPR = op2.payloadGPR();
+    GPRReg resultGPR = result.gpr();
+    
+    if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+        speculationCheck(
+            BadType, JSValueSource::unboxedCell(op1GPR), leftChild.index(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual,
+                MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()),
+                MacroAssembler::TrustedImmPtr(classInfo)));
+    }
+    
+    // It seems that most of the time when programs do a == b where b may be either null/undefined
+    // or an object, b is usually an object. Balance the branches to make that case fast.
+    MacroAssembler::Jump rightNotCell =
+        m_jit.branch32(MacroAssembler::NotEqual, op2TagGPR, TrustedImm32(JSValue::CellTag));
+    
+    // We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
+    // proof, when filtered on cell, demonstrates that we have an object of the desired type
+    // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+    // speculation.
+    if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+        speculationCheck(
+            BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual,
+                MacroAssembler::Address(op2PayloadGPR, JSCell::classInfoOffset()),
+                MacroAssembler::TrustedImmPtr(classInfo)));
+    }
+    
+    // At this point we know that we can perform a straight-forward equality comparison on pointer
+    // values because both left and right are pointers to objects that have no special equality
+    // protocols.
+    MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2PayloadGPR);
+    MacroAssembler::Jump trueCase = m_jit.jump();
+    
+    rightNotCell.link(&m_jit);
+    
+    // We know that within this branch, rightChild must not be a cell. Check if that is enough to
+    // prove that it is either null or undefined.
+    if (!isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell)) {
+        m_jit.move(op2TagGPR, resultGPR);
+        m_jit.or32(TrustedImm32(1), resultGPR);
+        
+        speculationCheck(
+            BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(),
+            m_jit.branch32(
+                MacroAssembler::NotEqual, resultGPR,
+                MacroAssembler::TrustedImm32(JSValue::NullTag)));
+    }
+    
+    falseCase.link(&m_jit);
+    m_jit.move(TrustedImm32(0), resultGPR);
+    MacroAssembler::Jump done = m_jit.jump();
+    trueCase.link(&m_jit);
+    m_jit.move(TrustedImm32(1), resultGPR);
+    done.link(&m_jit);
+    
+    booleanResult(resultGPR, m_compileIndex);
+}
+
+void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
+    Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex,
+    const ClassInfo* classInfo, PredictionChecker predictionCheck)
+{
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+    
+    SpeculateCellOperand op1(this, leftChild);
+    JSValueOperand op2(this, rightChild);
+    GPRTemporary result(this);
+    
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2TagGPR = op2.tagGPR();
+    GPRReg op2PayloadGPR = op2.payloadGPR();
+    GPRReg resultGPR = result.gpr();
+    
+    if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+        speculationCheck(
+            BadType, JSValueSource::unboxedCell(op1GPR), leftChild.index(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual,
+                MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()),
+                MacroAssembler::TrustedImmPtr(classInfo)));
+    }
+    
+    // It seems that most of the time when programs do a == b where b may be either null/undefined
+    // or an object, b is usually an object. Balance the branches to make that case fast.
+    MacroAssembler::Jump rightNotCell =
+        m_jit.branch32(MacroAssembler::NotEqual, op2TagGPR, TrustedImm32(JSValue::CellTag));
+    
+    // We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
+    // proof, when filtered on cell, demonstrates that we have an object of the desired type
+    // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+    // speculation.
+    if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+        speculationCheck(
+            BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual,
+                MacroAssembler::Address(op2PayloadGPR, JSCell::classInfoOffset()),
+                MacroAssembler::TrustedImmPtr(classInfo)));
+    }
+    
+    // At this point we know that we can perform a straight-forward equality comparison on pointer
+    // values because both left and right are pointers to objects that have no special equality
+    // protocols.
+    branch32(MacroAssembler::Equal, op1GPR, op2PayloadGPR, taken);
+    
+    // We know that within this branch, rightChild must not be a cell. Check if that is enough to
+    // prove that it is either null or undefined.
+    if (isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell))
+        rightNotCell.link(&m_jit);
+    else {
+        jump(notTaken, ForceJump);
+        
+        rightNotCell.link(&m_jit);
+        m_jit.move(op2TagGPR, resultGPR);
+        m_jit.or32(TrustedImm32(1), resultGPR);
+        
+        speculationCheck(
+            BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(),
+            m_jit.branch32(
+                MacroAssembler::NotEqual, resultGPR,
+                MacroAssembler::TrustedImm32(JSValue::NullTag)));
+    }
+    
+    jump(notTaken);
+}
+
+void SpeculativeJIT::compileIntegerCompare(Node& node, MacroAssembler::RelationalCondition condition)
+{
+    SpeculateIntegerOperand op1(this, node.child1());
+    SpeculateIntegerOperand op2(this, node.child2());
+    GPRTemporary resultPayload(this);
+    
+    m_jit.compare32(condition, op1.gpr(), op2.gpr(), resultPayload.gpr());
+    
+    // If we add a DataFormatBool, we should use it here.
+    booleanResult(resultPayload.gpr(), m_compileIndex);
+}
+
+void SpeculativeJIT::compileDoubleCompare(Node& node, MacroAssembler::DoubleCondition condition)
+{
+    SpeculateDoubleOperand op1(this, node.child1());
+    SpeculateDoubleOperand op2(this, node.child2());
+    GPRTemporary resultPayload(this);
+    
+    m_jit.move(TrustedImm32(1), resultPayload.gpr());
+    MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
+    m_jit.move(TrustedImm32(0), resultPayload.gpr());
+    trueCase.link(&m_jit);
+    
+    booleanResult(resultPayload.gpr(), m_compileIndex);
+}
+
+void SpeculativeJIT::compileValueAdd(Node& node)
+{
+    JSValueOperand op1(this, node.child1());
+    JSValueOperand op2(this, node.child2());
+
+    GPRReg op1TagGPR = op1.tagGPR();
+    GPRReg op1PayloadGPR = op1.payloadGPR();
+    GPRReg op2TagGPR = op2.tagGPR();
+    GPRReg op2PayloadGPR = op2.payloadGPR();
+
+    flushRegisters();
+    
+    GPRResult2 resultTag(this);
+    GPRResult resultPayload(this);
+    if (isKnownNotNumber(node.child1().index()) || isKnownNotNumber(node.child2().index()))
+        callOperation(operationValueAddNotNumber, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR);
+    else
+        callOperation(operationValueAdd, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR);
+    
+    jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
+}
+
+void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse, const ClassInfo* classInfo, bool needSpeculationCheck)
+{
+    JSValueOperand value(this, nodeUse);
+    GPRTemporary resultPayload(this);
+    GPRReg valueTagGPR = value.tagGPR();
+    GPRReg valuePayloadGPR = value.payloadGPR();
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+    
+    MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag));
+    if (needSpeculationCheck)
+        speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
+    m_jit.move(TrustedImm32(0), resultPayloadGPR);
+    MacroAssembler::Jump done = m_jit.jump();
+    
+    notCell.link(&m_jit);
+    COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
+    if (needSpeculationCheck) {
+        m_jit.move(valueTagGPR, resultPayloadGPR);
+        m_jit.or32(TrustedImm32(1), resultPayloadGPR);
+        speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, m_jit.branch32(MacroAssembler::NotEqual, resultPayloadGPR, TrustedImm32(JSValue::NullTag)));
+    }
+    m_jit.move(TrustedImm32(1), resultPayloadGPR);
+    
+    done.link(&m_jit);
+    
+    booleanResult(resultPayloadGPR, m_compileIndex);
+}
+
+void SpeculativeJIT::compileLogicalNot(Node& node)
+{
+    if (at(node.child1()).shouldSpeculateBoolean()) {
+        SpeculateBooleanOperand value(this, node.child1());
+        GPRTemporary result(this, value);
+        m_jit.xor32(TrustedImm32(1), value.gpr(), result.gpr());
+        booleanResult(result.gpr(), m_compileIndex);
+        return;
+    }
+    if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
+        compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+        return;
+    }
+    if (at(node.child1()).shouldSpeculateArrayOrOther()) {
+        compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+        return;
+    }
+    if (at(node.child1()).shouldSpeculateInteger()) {
+        SpeculateIntegerOperand value(this, node.child1());
+        GPRTemporary resultPayload(this, value);
+        m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), resultPayload.gpr());
+        booleanResult(resultPayload.gpr(), m_compileIndex);
+        return;
+    }
+    if (at(node.child1()).shouldSpeculateNumber()) {
+        SpeculateDoubleOperand value(this, node.child1());
+        FPRTemporary scratch(this);
+        GPRTemporary resultPayload(this);
+        m_jit.move(TrustedImm32(0), resultPayload.gpr());
+        MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
+        m_jit.move(TrustedImm32(1), resultPayload.gpr());
+        nonZero.link(&m_jit);
+        booleanResult(resultPayload.gpr(), m_compileIndex);
+        return;
+    }
+
+    JSValueOperand arg1(this, node.child1());
+    GPRTemporary resultPayload(this, arg1, false);
+    GPRReg arg1TagGPR = arg1.tagGPR();
+    GPRReg arg1PayloadGPR = arg1.payloadGPR();
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+        
+    arg1.use();
+
+    JITCompiler::Jump fastCase = m_jit.branch32(JITCompiler::Equal, arg1TagGPR, TrustedImm32(JSValue::BooleanTag));
+        
+    silentSpillAllRegisters(resultPayloadGPR);
+    callOperation(dfgConvertJSValueToBoolean, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR);
+    silentFillAllRegisters(resultPayloadGPR);
+    JITCompiler::Jump doNot = m_jit.jump();
+        
+    fastCase.link(&m_jit);
+    m_jit.move(arg1PayloadGPR, resultPayloadGPR);
+
+    doNot.link(&m_jit);
+    m_jit.xor32(TrustedImm32(1), resultPayloadGPR);
+    booleanResult(resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+}
+
+void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck)
+{
+    JSValueOperand value(this, nodeUse);
+    GPRTemporary scratch(this);
+    GPRReg valueTagGPR = value.tagGPR();
+    GPRReg valuePayloadGPR = value.payloadGPR();
+    GPRReg scratchGPR = scratch.gpr();
+    
+    MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag));
+    if (needSpeculationCheck)
+        speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
+    jump(taken, ForceJump);
+    
+    notCell.link(&m_jit);
+    
+    COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
+    if (needSpeculationCheck) {
+        m_jit.move(valueTagGPR, scratchGPR);
+        m_jit.or32(TrustedImm32(1), scratchGPR);
+        speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag)));
+    }
+
+    jump(notTaken);
+    
+    noResult(m_compileIndex);
+}
+
+void SpeculativeJIT::emitBranch(Node& node)
+{
+    BlockIndex taken = node.takenBlockIndex();
+    BlockIndex notTaken = node.notTakenBlockIndex();
+
+    if (at(node.child1()).shouldSpeculateBoolean()) {
+        SpeculateBooleanOperand value(this, node.child1());
+        MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
+
+        if (taken == (m_block + 1)) {
+            condition = MacroAssembler::Zero;
+            BlockIndex tmp = taken;
+            taken = notTaken;
+            notTaken = tmp;
+        }
+
+        branchTest32(condition, value.gpr(), TrustedImm32(1), taken);
+        jump(notTaken);
+
+        noResult(m_compileIndex);
+    } else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
+        emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+    } else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
+        emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+    } else if (at(node.child1()).shouldSpeculateNumber()) {
+        if (at(node.child1()).shouldSpeculateInteger()) {
+            bool invert = false;
+            
+            if (taken == (m_block + 1)) {
+                invert = true;
+                BlockIndex tmp = taken;
+                taken = notTaken;
+                notTaken = tmp;
+            }
+
+            SpeculateIntegerOperand value(this, node.child1());
+            branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
+        } else {
+            SpeculateDoubleOperand value(this, node.child1());
+            FPRTemporary scratch(this);
+            branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
+        }
+        
+        jump(notTaken);
+        
+        noResult(m_compileIndex);
+    } else {
+        JSValueOperand value(this, node.child1());
+        value.fill();
+        GPRReg valueTagGPR = value.tagGPR();
+        GPRReg valuePayloadGPR = value.payloadGPR();
+
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
+    
+        use(node.child1());
+    
+        JITCompiler::Jump fastPath = m_jit.branch32(JITCompiler::Equal, valueTagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag));
+        JITCompiler::Jump slowPath = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::BooleanTag));
+
+        fastPath.link(&m_jit);
+        branchTest32(JITCompiler::Zero, valuePayloadGPR, notTaken);
+        jump(taken, ForceJump);
+
+        slowPath.link(&m_jit);
+        silentSpillAllRegisters(resultGPR);
+        callOperation(dfgConvertJSValueToBoolean, resultGPR, valueTagGPR, valuePayloadGPR);
+        silentFillAllRegisters(resultGPR);
+    
+        branchTest32(JITCompiler::NonZero, resultGPR, taken);
+        jump(notTaken);
+    
+        noResult(m_compileIndex, UseChildrenCalledExplicitly);
+    }
+}
+
+void SpeculativeJIT::compile(Node& node)
+{
+    NodeType op = node.op();
+
+    switch (op) {
+    case JSConstant:
+        initConstantInfo(m_compileIndex);
+        break;
+
+    case WeakJSConstant:
+        m_jit.addWeakReference(node.weakConstant());
+        initConstantInfo(m_compileIndex);
+        break;
+
+    case GetLocal: {
+        PredictedType prediction = node.variableAccessData()->prediction();
+        AbstractValue& value = block()->valuesAtHead.operand(node.local());
+
+        // If we have no prediction for this local, then don't attempt to compile.
+        if (prediction == PredictNone || value.isClear()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        if (!m_jit.graph().isCaptured(node.local())) {
+            if (node.variableAccessData()->shouldUseDoubleFormat()) {
+                FPRTemporary result(this);
+                m_jit.loadDouble(JITCompiler::addressFor(node.local()), result.fpr());
+                VirtualRegister virtualRegister = node.virtualRegister();
+                m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
+                m_generationInfo[virtualRegister].initDouble(m_compileIndex, node.refCount(), result.fpr());
+                break;
+            }
+        
+            if (isInt32Prediction(prediction)) {
+                GPRTemporary result(this);
+                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());
+                break;
+            }
+
+            if (isArrayPrediction(prediction)) {
+                GPRTemporary result(this);
+                m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
+
+                // Like cellResult, 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, SpillOrderCell);
+                m_generationInfo[virtualRegister].initCell(m_compileIndex, node.refCount(), result.gpr());
+                break;
+            }
+
+            if (isBooleanPrediction(prediction)) {
+                GPRTemporary result(this);
+                m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
+
+                // Like booleanResult, 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, SpillOrderBoolean);
+                m_generationInfo[virtualRegister].initBoolean(m_compileIndex, node.refCount(), result.gpr());
+                break;
+            }
+        }
+
+        GPRTemporary result(this);
+        GPRTemporary tag(this);
+        m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
+        m_jit.load32(JITCompiler::tagFor(node.local()), tag.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_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
+
+        DataFormat format;
+        if (isCellPrediction(value.m_type)
+            && !m_jit.graph().isCaptured(node.local()))
+            format = DataFormatJSCell;
+        else
+            format = DataFormatJS;
+        m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), tag.gpr(), result.gpr(), format);
+        break;
+    }
+
+    case SetLocal: {
+        // SetLocal doubles as a hint as to where a node will be stored and
+        // as a speculation point. So before we speculate make sure that we
+        // know where the child of this node needs to go in the virtual
+        // register file.
+        compileMovHint(node);
+        
+        // As far as OSR is concerned, we're on the bytecode index corresponding
+        // to the *next* instruction, since we've already "executed" the
+        // SetLocal and whatever other DFG Nodes are associated with the same
+        // bytecode index as the SetLocal.
+        ASSERT(m_codeOriginForOSR == node.codeOrigin);
+        Node* nextNode = &at(block()->at(m_indexInBlock + 1));
+
+        // But even more oddly, we need to be super careful about the following
+        // sequence:
+        //
+        // a: Foo()
+        // b: SetLocal(@a)
+        // c: Flush(@b)
+        //
+        // This next piece of crazy takes care of this.
+        if (nextNode->op() == Flush && nextNode->child1() == m_compileIndex)
+            nextNode = &at(block()->at(m_indexInBlock + 2));
+        
+        // Oddly, it's possible for the bytecode index for the next node to be
+        // equal to ours. This will happen for op_post_inc. And, even more oddly,
+        // this is just fine. Ordinarily, this wouldn't be fine, since if the
+        // next node failed OSR then we'd be OSR-ing with this SetLocal's local
+        // variable already set even though from the standpoint of the old JIT,
+        // this SetLocal should not have executed. But for op_post_inc, it's just
+        // fine, because this SetLocal's local (i.e. the LHS in a x = y++
+        // statement) would be dead anyway - so the fact that DFG would have
+        // already made the assignment, and baked it into the register file during
+        // OSR exit, would not be visible to the old JIT in any way.
+        m_codeOriginForOSR = nextNode->codeOrigin;
+        
+        if (!m_jit.graph().isCaptured(node.local())) {
+            if (node.variableAccessData()->shouldUseDoubleFormat()) {
+                SpeculateDoubleOperand value(this, node.child1());
+                m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local()));
+                noResult(m_compileIndex);
+                // Indicate that it's no longer necessary to retrieve the value of
+                // this bytecode variable from registers or other locations in the register file,
+                // but that it is stored as a double.
+                valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile);
+                break;
+            }
+            PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction();
+            if (m_generationInfo[at(node.child1()).virtualRegister()].registerFormat() == DataFormatDouble) {
+                DoubleOperand value(this, node.child1());
+                m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local()));
+                noResult(m_compileIndex);
+                valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile);
+                break;
+            }
+            if (isInt32Prediction(predictedType)) {
+                SpeculateIntegerOperand value(this, node.child1());
+                m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
+                noResult(m_compileIndex);
+                valueSourceReferenceForOperand(node.local()) = ValueSource(Int32InRegisterFile);
+                break;
+            }
+            if (isArrayPrediction(predictedType)) {
+                SpeculateCellOperand cell(this, node.child1());
+                GPRReg cellGPR = cell.gpr();
+                if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+                    speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+                m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local()));
+                noResult(m_compileIndex);
+                valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile);
+                break;
+            }
+            if (isBooleanPrediction(predictedType)) {
+                SpeculateBooleanOperand value(this, node.child1());
+                m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
+                noResult(m_compileIndex);
+                valueSourceReferenceForOperand(node.local()) = ValueSource(BooleanInRegisterFile);
+                break;
+            }
+        }
+        JSValueOperand value(this, node.child1());
+        m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node.local()));
+        m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node.local()));
+        noResult(m_compileIndex);
+        valueSourceReferenceForOperand(node.local()) = ValueSource(ValueInRegisterFile);
+        break;
+    }
+
+    case SetArgument:
+        // This is a no-op; it just marks the fact that the argument is being used.
+        // But it may be profitable to use this as a hook to run speculation checks
+        // on arguments, thereby allowing us to trivially eliminate such checks if
+        // the argument is not used.
+        break;
+
+    case BitAnd:
+    case BitOr:
+    case BitXor:
+        if (isInt32Constant(node.child1().index())) {
+            SpeculateIntegerOperand op2(this, node.child2());
+            GPRTemporary result(this, op2);
+
+            bitOp(op, valueOfInt32Constant(node.child1().index()), op2.gpr(), result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        } else if (isInt32Constant(node.child2().index())) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            GPRTemporary result(this, op1);
+
+            bitOp(op, valueOfInt32Constant(node.child2().index()), 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().index())) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            GPRTemporary result(this, op1);
+
+            shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2().index()) & 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: {
+        compileUInt32ToNumber(node);
+        break;
+    }
+        
+    case DoubleAsInt32: {
+        compileDoubleAsInt32(node);
+        break;
+    }
+
+    case ValueToInt32: {
+        compileValueToInt32(node);
+        break;
+    }
+        
+    case Int32ToDouble: {
+        compileInt32ToDouble(node);
+        break;
+    }
+        
+    case CheckNumber: {
+        if (!isNumberPrediction(m_state.forNode(node.child1()).m_type)) {
+            JSValueOperand op1(this, node.child1());
+            JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, op1.tagGPR(), TrustedImm32(JSValue::Int32Tag));
+            speculationCheck(
+                BadType, JSValueRegs(op1.tagGPR(), op1.payloadGPR()), node.child1().index(),
+                m_jit.branch32(MacroAssembler::AboveOrEqual, op1.tagGPR(), TrustedImm32(JSValue::LowestTag)));
+            isInteger.link(&m_jit);
+        }
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case ValueAdd:
+    case ArithAdd:
+        compileAdd(node);
+        break;
+
+    case ArithSub:
+        compileArithSub(node);
+        break;
+
+    case ArithNegate:
+        compileArithNegate(node);
+        break;
+
+    case ArithMul:
+        compileArithMul(node);
+        break;
+
+    case ArithDiv: {
+        if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
+#if CPU(X86)
+            compileIntegerArithDivForX86(node);
+#else // CPU(X86) -> so non-X86 code follows
+            ASSERT_NOT_REACHED(); // should have been coverted into a double divide.
+#endif // CPU(X86)
+            break;
+        }
+        
+        SpeculateDoubleOperand op1(this, node.child1());
+        SpeculateDoubleOperand 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: {
+        compileArithMod(node);
+        break;
+    }
+
+    case ArithAbs: {
+        if (at(node.child1()).shouldSpeculateInteger() && node.canSpeculateInteger()) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            GPRTemporary result(this, op1);
+            GPRTemporary scratch(this);
+            
+            m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
+            m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
+            m_jit.add32(scratch.gpr(), result.gpr());
+            m_jit.xor32(scratch.gpr(), result.gpr());
+            speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 << 31)));
+            integerResult(result.gpr(), m_compileIndex);
+            break;
+        }
+        
+        SpeculateDoubleOperand op1(this, node.child1());
+        FPRTemporary result(this);
+        
+        m_jit.absDouble(op1.fpr(), result.fpr());
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+        
+    case ArithMin:
+    case ArithMax: {
+        if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
+            SpeculateStrictInt32Operand op1(this, node.child1());
+            SpeculateStrictInt32Operand op2(this, node.child2());
+            GPRTemporary result(this, op1);
+            
+            MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
+            m_jit.move(op2.gpr(), result.gpr());
+            if (op1.gpr() != result.gpr()) {
+                MacroAssembler::Jump done = m_jit.jump();
+                op1Less.link(&m_jit);
+                m_jit.move(op1.gpr(), result.gpr());
+                done.link(&m_jit);
+            } else
+                op1Less.link(&m_jit);
+            
+            integerResult(result.gpr(), m_compileIndex);
+            break;
+        }
+        
+        SpeculateDoubleOperand op1(this, node.child1());
+        SpeculateDoubleOperand op2(this, node.child2());
+        FPRTemporary result(this, op1);
+        
+        MacroAssembler::JumpList done;
+        
+        MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr());
+        
+        // op2 is eather the lesser one or one of then is NaN
+        MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1.fpr(), op2.fpr());
+        
+        // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
+        // op1 + op2 and putting it into result.
+        m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr());
+        done.append(m_jit.jump());
+        
+        op2Less.link(&m_jit);
+        m_jit.moveDouble(op2.fpr(), result.fpr());
+        
+        if (op1.fpr() != result.fpr()) {
+            done.append(m_jit.jump());
+            
+            op1Less.link(&m_jit);
+            m_jit.moveDouble(op1.fpr(), result.fpr());
+        } else
+            op1Less.link(&m_jit);
+        
+        done.link(&m_jit);
+        
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+        
+    case ArithSqrt: {
+        SpeculateDoubleOperand op1(this, node.child1());
+        FPRTemporary result(this, op1);
+        
+        m_jit.sqrtDouble(op1.fpr(), result.fpr());
+        
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+
+    case LogicalNot:
+        compileLogicalNot(node);
+        break;
+
+    case CompareLess:
+        if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
+            return;
+        break;
+
+    case CompareLessEq:
+        if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
+            return;
+        break;
+
+    case CompareGreater:
+        if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
+            return;
+        break;
+
+    case CompareGreaterEq:
+        if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
+            return;
+        break;
+
+    case CompareEq:
+        if (isNullConstant(node.child1().index())) {
+            if (nonSpeculativeCompareNull(node, node.child2()))
+                return;
+            break;
+        }
+        if (isNullConstant(node.child2().index())) {
+            if (nonSpeculativeCompareNull(node, node.child1()))
+                return;
+            break;
+        }
+        if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
+            return;
+        break;
+
+    case CompareStrictEq:
+        if (compileStrictEq(node))
+            return;
+        break;
+
+    case StringCharCodeAt: {
+        compileGetCharCodeAt(node);
+        break;
+    }
+
+    case StringCharAt: {
+        // Relies on StringCharAt node having same basic layout as GetByVal
+        compileGetByValOnString(node);
+        break;
+    }
+
+    case GetByVal: {
+        if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArrayPrediction(at(node.child1()).prediction())) {
+            SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.
+            JSValueOperand property(this, node.child2());
+            GPRReg baseGPR = base.gpr();
+            GPRReg propertyTagGPR = property.tagGPR();
+            GPRReg propertyPayloadGPR = property.payloadGPR();
+            
+            flushRegisters();
+            GPRResult2 resultTag(this);
+            GPRResult resultPayload(this);
+            callOperation(operationGetByValCell, resultTag.gpr(), resultPayload.gpr(), baseGPR, propertyTagGPR, propertyPayloadGPR);
+            
+            jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
+            break;
+        }
+
+        if (at(node.child1()).prediction() == PredictString) {
+            compileGetByValOnString(node);
+            if (!m_compileOkay)
+                return;
+            break;
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt8Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt16Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt32Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint8Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+
+        if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;
+        }
+
+        if (at(node.child1()).shouldSpeculateUint16Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint32Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        ASSERT(at(node.child1()).shouldSpeculateArray());
+
+        SpeculateStrictInt32Operand property(this, node.child2());
+        StorageOperand storage(this, node.child3());
+        GPRReg propertyReg = property.gpr();
+        GPRReg storageReg = storage.gpr();
+        
+        if (!m_compileOkay)
+            return;
+
+        // 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.
+        {
+            SpeculateCellOperand base(this, node.child1());
+            GPRReg baseReg = base.gpr();
+            if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+                speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
+        }
+
+        GPRTemporary resultTag(this);
+        GPRTemporary resultPayload(this);
+
+        // 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.
+        m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
+        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)));
+        m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
+
+        jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
+        break;
+    }
+
+    case PutByVal: {
+        if (!at(node.child1()).prediction() || !at(node.child2()).prediction()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        if (!at(node.child2()).shouldSpeculateInteger() || !isActionableMutableArrayPrediction(at(node.child1()).prediction())) {
+            SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.
+            JSValueOperand property(this, node.child2());
+            JSValueOperand value(this, node.child3());
+            GPRReg baseGPR = base.gpr();
+            GPRReg propertyTagGPR = property.tagGPR();
+            GPRReg propertyPayloadGPR = property.payloadGPR();
+            GPRReg valueTagGPR = value.tagGPR();
+            GPRReg valuePayloadGPR = value.payloadGPR();
+            
+            flushRegisters();
+            callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyTagGPR, propertyPayloadGPR, valueTagGPR, valuePayloadGPR);
+            
+            noResult(m_compileIndex);
+            break;
+        }
+
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateStrictInt32Operand property(this, node.child2());
+        if (at(node.child1()).shouldSpeculateInt8Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt16Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt32Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint8Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray, ClampRounding);
+            if (!m_compileOkay)
+                return;
+            break;
+        }
+
+        if (at(node.child1()).shouldSpeculateUint16Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint32Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        ASSERT(at(node.child1()).shouldSpeculateArray());
+
+        JSValueOperand value(this, node.child3());
+        GPRTemporary scratch(this);
+
+        // Map base, property & value into registers, allocate a scratch register.
+        GPRReg baseReg = base.gpr();
+        GPRReg propertyReg = property.gpr();
+        GPRReg valueTagReg = value.tagGPR();
+        GPRReg valuePayloadReg = value.payloadGPR();
+        GPRReg scratchReg = scratch.gpr();
+        
+        if (!m_compileOkay)
+            return;
+        
+        writeBarrier(baseReg, valueTagReg, node.child3(), WriteBarrierForPropertyAccess, scratchReg);
+
+        // 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.
+        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+
+        base.use();
+        property.use();
+        value.use();
+        
+        MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
+
+        // Code to handle put beyond array bounds.
+        silentSpillAllRegisters(scratchReg);
+        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, baseReg, propertyReg, valueTagReg, valuePayloadReg);
+        silentFillAllRegisters(scratchReg);
+        JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
+
+        withinArrayBounds.link(&m_jit);
+
+        // Get the array storage.
+        GPRReg storageReg = scratchReg;
+        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.branch32(MacroAssembler::NotEqual, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
+        m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+
+        // If we're writing to a hole we might be growing the array; 
+        MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, 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.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+        m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+
+        wasBeyondArrayBounds.link(&m_jit);
+
+        noResult(m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+
+    case PutByValAlias: {
+        if (!at(node.child1()).prediction() || !at(node.child2()).prediction()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        ASSERT(isActionableMutableArrayPrediction(at(node.child1()).prediction()));
+        ASSERT(at(node.child2()).shouldSpeculateInteger());
+
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateStrictInt32Operand property(this, node.child2());
+
+        if (at(node.child1()).shouldSpeculateInt8Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), NoTypedArraySpecCheck, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt16Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), NoTypedArraySpecCheck, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt32Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), NoTypedArraySpecCheck, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint8Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+
+        if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray, ClampRounding);
+            if (!m_compileOkay)
+                return;
+            break;
+        }
+
+        if (at(node.child1()).shouldSpeculateUint16Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), NoTypedArraySpecCheck, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint32Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), NoTypedArraySpecCheck, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), NoTypedArraySpecCheck);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), NoTypedArraySpecCheck);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+
+        ASSERT(at(node.child1()).shouldSpeculateArray());
+
+        JSValueOperand value(this, node.child3());
+        GPRTemporary scratch(this, base);
+        
+        GPRReg baseReg = base.gpr();
+        GPRReg scratchReg = scratch.gpr();
+
+        writeBarrier(baseReg, value.tagGPR(), node.child3(), WriteBarrierForPropertyAccess, scratchReg);
+
+        // Get the array storage.
+        GPRReg storageReg = scratchReg;
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
+
+        // Store the value to the array.
+        GPRReg propertyReg = property.gpr();
+        m_jit.store32(value.tagGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+        m_jit.store32(value.payloadGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case RegExpExec: {
+        if (compileRegExpExec(node))
+            return;
+
+        if (!node.adjustedRefCount()) {
+            SpeculateCellOperand base(this, node.child1());
+            SpeculateCellOperand argument(this, node.child2());
+            GPRReg baseGPR = base.gpr();
+            GPRReg argumentGPR = argument.gpr();
+            
+            flushRegisters();
+            GPRResult result(this);
+            callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
+            
+            // Must use jsValueResult because otherwise we screw up register
+            // allocation, which thinks that this node has a result.
+            booleanResult(result.gpr(), m_compileIndex);
+            break;
+        }
+
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateCellOperand argument(this, node.child2());
+        GPRReg baseGPR = base.gpr();
+        GPRReg argumentGPR = argument.gpr();
+        
+        flushRegisters();
+        GPRResult2 resultTag(this);
+        GPRResult resultPayload(this);
+        callOperation(operationRegExpExec, resultTag.gpr(), resultPayload.gpr(), baseGPR, argumentGPR);
+        
+        jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
+        break;
+    }
+        
+    case RegExpTest: {
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateCellOperand argument(this, node.child2());
+        GPRReg baseGPR = base.gpr();
+        GPRReg argumentGPR = argument.gpr();
+        
+        flushRegisters();
+        GPRResult result(this);
+        callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
+        
+        // If we add a DataFormatBool, we should use it here.
+        booleanResult(result.gpr(), m_compileIndex);
+        break;
+    }
+        
+    case ArrayPush: {
+        SpeculateCellOperand base(this, node.child1());
+        JSValueOperand value(this, node.child2());
+        GPRTemporary storage(this);
+        GPRTemporary storageLength(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg valueTagGPR = value.tagGPR();
+        GPRReg valuePayloadGPR = value.payloadGPR();
+        GPRReg storageGPR = storage.gpr();
+        GPRReg storageLengthGPR = storageLength.gpr();
+        
+        writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
+
+        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        
+        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
+        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
+        
+        // Refuse to handle bizarre lengths.
+        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
+        
+        MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
+        
+        m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+        m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+        
+        m_jit.add32(TrustedImm32(1), storageLengthGPR);
+        m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
+        m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+        m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
+        
+        MacroAssembler::Jump done = m_jit.jump();
+        
+        slowPath.link(&m_jit);
+        
+        silentSpillAllRegisters(storageGPR, storageLengthGPR);
+        callOperation(operationArrayPush, storageGPR, storageLengthGPR, valueTagGPR, valuePayloadGPR, baseGPR);
+        silentFillAllRegisters(storageGPR, storageLengthGPR);
+        
+        done.link(&m_jit);
+        
+        jsValueResult(storageGPR, storageLengthGPR, m_compileIndex);
+        break;
+    }
+        
+    case ArrayPop: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary valueTag(this);
+        GPRTemporary valuePayload(this);
+        GPRTemporary storage(this);
+        GPRTemporary storageLength(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg valueTagGPR = valueTag.gpr();
+        GPRReg valuePayloadGPR = valuePayload.gpr();
+        GPRReg storageGPR = storage.gpr();
+        GPRReg storageLengthGPR = storageLength.gpr();
+        
+        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        
+        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
+        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
+        
+        MacroAssembler::Jump emptyArrayCase = m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
+        
+        m_jit.sub32(TrustedImm32(1), storageLengthGPR);
+        
+        MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
+        
+        m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), valueTagGPR);
+        m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), valuePayloadGPR);
+        
+        m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
+
+        MacroAssembler::Jump holeCase = m_jit.branch32(MacroAssembler::Equal, TrustedImm32(JSValue::EmptyValueTag), valueTagGPR);
+        
+        m_jit.store32(TrustedImm32(JSValue::EmptyValueTag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+
+        m_jit.sub32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+        
+        MacroAssembler::JumpList done;
+        
+        done.append(m_jit.jump());
+        
+        holeCase.link(&m_jit);
+        emptyArrayCase.link(&m_jit);
+        m_jit.move(MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR);
+        m_jit.move(MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR);
+        done.append(m_jit.jump());
+        
+        slowCase.link(&m_jit);
+        
+        silentSpillAllRegisters(valueTagGPR, valuePayloadGPR);
+        callOperation(operationArrayPop, valueTagGPR, valuePayloadGPR, baseGPR);
+        silentFillAllRegisters(valueTagGPR, valuePayloadGPR);
+        
+        done.link(&m_jit);
+        
+        jsValueResult(valueTagGPR, valuePayloadGPR, m_compileIndex);
+        break;
+    }
+
+    case DFG::Jump: {
+        BlockIndex taken = node.takenBlockIndex();
+        jump(taken);
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case Branch:
+        if (isStrictInt32(node.child1().index()) || at(node.child1()).shouldSpeculateInteger()) {
+            SpeculateIntegerOperand op(this, node.child1());
+            
+            BlockIndex taken = node.takenBlockIndex();
+            BlockIndex notTaken = node.notTakenBlockIndex();
+            
+            MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
+            
+            if (taken == (m_block + 1)) {
+                condition = MacroAssembler::Zero;
+                BlockIndex tmp = taken;
+                taken = notTaken;
+                notTaken = tmp;
+            }
+            
+            branchTest32(condition, op.gpr(), taken);
+            jump(notTaken);
+            
+            noResult(m_compileIndex);
+            break;
+        }
+        emitBranch(node);
+        break;
+
+    case Return: {
+        ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT2);
+        ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
+        ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
+
+#if DFG_ENABLE(SUCCESS_STATS)
+        static SamplingCounter counter("SpeculativeJIT");
+        m_jit.emitCount(counter);
+#endif
+
+        // Return the result in returnValueGPR.
+        JSValueOperand op1(this, node.child1());
+        op1.fill();
+        if (op1.isDouble())
+            boxDouble(op1.fpr(), GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR);
+        else {
+            if (op1.payloadGPR() == GPRInfo::returnValueGPR2 && op1.tagGPR() == GPRInfo::returnValueGPR)
+                m_jit.swap(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
+            else if (op1.payloadGPR() == GPRInfo::returnValueGPR2) {
+                m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
+                m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
+            } else {
+                m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
+                m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
+            }
+        }
+
+        // Grab the return address.
+        m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT2);
+        // Restore our caller's "r".
+        m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
+        // Return.
+        m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT2);
+        m_jit.ret();
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case Throw:
+    case ThrowReferenceError: {
+        // We expect that throw statements are rare and are intended to exit the code block
+        // anyway, so we just OSR back to the old JIT for now.
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        break;
+    }
+        
+    case ToPrimitive: {
+        if (at(node.child1()).shouldSpeculateInteger()) {
+            // It's really profitable to speculate integer, since it's really cheap,
+            // it means we don't have to do any real work, and we emit a lot less code.
+            
+            SpeculateIntegerOperand op1(this, node.child1());
+            GPRTemporary result(this, op1);
+            
+            ASSERT(op1.format() == DataFormatInteger);
+            m_jit.move(op1.gpr(), result.gpr());
+            
+            integerResult(result.gpr(), m_compileIndex);
+            break;
+        }
+        
+        // FIXME: Add string speculation here.
+        
+        JSValueOperand op1(this, node.child1());
+        GPRTemporary resultTag(this, op1);
+        GPRTemporary resultPayload(this, op1, false);
+        
+        GPRReg op1TagGPR = op1.tagGPR();
+        GPRReg op1PayloadGPR = op1.payloadGPR();
+        GPRReg resultTagGPR = resultTag.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        
+        op1.use();
+        
+        if (!(m_state.forNode(node.child1()).m_type & ~(PredictNumber | PredictBoolean))) {
+            m_jit.move(op1TagGPR, resultTagGPR);
+            m_jit.move(op1PayloadGPR, resultPayloadGPR);
+        } else {
+            MacroAssembler::JumpList alreadyPrimitive;
+            
+            alreadyPrimitive.append(m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, TrustedImm32(JSValue::CellTag)));
+            alreadyPrimitive.append(m_jit.branchPtr(MacroAssembler::Equal, MacroAssembler::Address(op1PayloadGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
+            
+            silentSpillAllRegisters(resultTagGPR, resultPayloadGPR);
+            callOperation(operationToPrimitive, resultTagGPR, resultPayloadGPR, op1TagGPR, op1PayloadGPR);
+            silentFillAllRegisters(resultTagGPR, resultPayloadGPR);
+            
+            MacroAssembler::Jump done = m_jit.jump();
+            
+            alreadyPrimitive.link(&m_jit);
+            m_jit.move(op1TagGPR, resultTagGPR);
+            m_jit.move(op1PayloadGPR, resultPayloadGPR);
+            
+            done.link(&m_jit);
+        }
+        
+        jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+        
+    case StrCat:
+    case NewArray: {
+        // We really don't want to grow the register file just to do a StrCat or NewArray.
+        // Say we have 50 functions on the stack that all have a StrCat in them that has
+        // upwards of 10 operands. In the DFG this would mean that each one gets
+        // some random virtual register, and then to do the StrCat we'd need a second
+        // span of 10 operands just to have somewhere to copy the 10 operands to, where
+        // they'd be contiguous and we could easily tell the C code how to find them.
+        // Ugly! So instead we use the scratchBuffer infrastructure in JSGlobalData. That
+        // way, those 50 functions will share the same scratchBuffer for offloading their
+        // StrCat operands. It's about as good as we can do, unless we start doing
+        // virtual register coalescing to ensure that operands to StrCat get spilled
+        // in exactly the place where StrCat wants them, or else have the StrCat
+        // refer to those operands' SetLocal instructions to force them to spill in
+        // the right place. Basically, any way you cut it, the current approach
+        // probably has the best balance of performance and sensibility in the sense
+        // that it does not increase the complexity of the DFG JIT just to make StrCat
+        // fast and pretty.
+
+        size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
+        ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
+        EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
+        
+        for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
+            JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
+            GPRReg opTagGPR = operand.tagGPR();
+            GPRReg opPayloadGPR = operand.payloadGPR();
+            operand.use();
+            
+            m_jit.store32(opTagGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+            m_jit.store32(opPayloadGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+        }
+        
+        flushRegisters();
+
+        if (scratchSize) {
+            GPRTemporary scratch(this);
+
+            // Tell GC mark phase how much of the scratch buffer is active during call.
+            m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
+            m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
+        }
+
+        GPRResult resultPayload(this);
+        GPRResult2 resultTag(this);
+        
+        callOperation(op == StrCat ? operationStrCat : operationNewArray, resultTag.gpr(), resultPayload.gpr(), static_cast<void *>(buffer), node.numChildren());
+
+        if (scratchSize) {
+            GPRTemporary scratch(this);
+
+            m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
+            m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
+        }
+
+        // FIXME: make the callOperation above explicitly return a cell result, or jitAssert the tag is a cell tag.
+        cellResult(resultPayload.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+
+    case NewArrayBuffer: {
+        flushRegisters();
+        GPRResult resultPayload(this);
+        GPRResult2 resultTag(this);
+        
+        callOperation(operationNewArrayBuffer, resultTag.gpr(), resultPayload.gpr(), node.startConstant(), node.numConstants());
+        
+        // FIXME: make the callOperation above explicitly return a cell result, or jitAssert the tag is a cell tag.
+        cellResult(resultPayload.gpr(), m_compileIndex);
+        break;
+    }
+        
+    case NewRegexp: {
+        flushRegisters();
+        GPRResult resultPayload(this);
+        GPRResult2 resultTag(this);
+        
+        callOperation(operationNewRegexp, resultTag.gpr(), resultPayload.gpr(), m_jit.codeBlock()->regexp(node.regexpIndex()));
+        
+        // FIXME: make the callOperation above explicitly return a cell result, or jitAssert the tag is a cell tag.
+        cellResult(resultPayload.gpr(), m_compileIndex);
+        break;
+    }
+        
+    case ConvertThis: {
+        if (isObjectPrediction(m_state.forNode(node.child1()).m_type)) {
+            SpeculateCellOperand thisValue(this, node.child1());
+            GPRTemporary result(this, thisValue);
+            m_jit.move(thisValue.gpr(), result.gpr());
+            cellResult(result.gpr(), m_compileIndex);
+            break;
+        }
+        
+        if (isOtherPrediction(at(node.child1()).prediction())) {
+            JSValueOperand thisValue(this, node.child1());
+            GPRTemporary scratch(this);
+            
+            GPRReg thisValueTagGPR = thisValue.tagGPR();
+            GPRReg scratchGPR = scratch.gpr();
+            
+            COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
+            m_jit.move(thisValueTagGPR, scratchGPR);
+            m_jit.or32(TrustedImm32(1), scratchGPR);
+            // This is hard. It would be better to save the value, but we can't quite do it,
+            // since this operation does not otherwise get the payload.
+            speculationCheck(BadType, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag)));
+            
+            m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalThisObjectFor(node.codeOrigin)), scratchGPR);
+            cellResult(scratchGPR, m_compileIndex);
+            break;
+        }
+        
+        if (isObjectPrediction(at(node.child1()).prediction())) {
+            SpeculateCellOperand thisValue(this, node.child1());
+            GPRReg thisValueGPR = thisValue.gpr();
+            
+            if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
+                speculationCheck(BadType, JSValueSource::unboxedCell(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info)));
+            
+            GPRTemporary result(this, thisValue);
+            GPRReg resultGPR = result.gpr();
+            m_jit.move(thisValueGPR, resultGPR);
+            cellResult(resultGPR, m_compileIndex);
+            break;
+        }
+        
+        JSValueOperand thisValue(this, node.child1());
+        GPRReg thisValueTagGPR = thisValue.tagGPR();
+        GPRReg thisValuePayloadGPR = thisValue.payloadGPR();
+        
+        flushRegisters();
+        
+        GPRResult2 resultTag(this);
+        GPRResult resultPayload(this);
+        callOperation(operationConvertThis, resultTag.gpr(), resultPayload.gpr(), thisValueTagGPR, thisValuePayloadGPR);
+        
+        cellResult(resultPayload.gpr(), m_compileIndex);
+        break;
+    }
+
+    case CreateThis: {
+        // Note that there is not so much profit to speculate here. The only things we
+        // speculate on are (1) that it's a cell, since that eliminates cell checks
+        // later if the proto is reused, and (2) if we have a FinalObject prediction
+        // then we speculate because we want to get recompiled if it isn't (since
+        // otherwise we'd start taking slow path a lot).
+        
+        SpeculateCellOperand proto(this, node.child1());
+        GPRTemporary result(this);
+        GPRTemporary scratch(this);
+        
+        GPRReg protoGPR = proto.gpr();
+        GPRReg resultGPR = result.gpr();
+        GPRReg scratchGPR = scratch.gpr();
+        
+        proto.use();
+        
+        MacroAssembler::JumpList slowPath;
+        
+        // Need to verify that the prototype is an object. If we have reason to believe
+        // that it's a FinalObject then we speculate on that directly. Otherwise we
+        // do the slow (structure-based) check.
+        if (at(node.child1()).shouldSpeculateFinalObject()) {
+            if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
+                speculationCheck(BadType, JSValueSource::unboxedCell(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info)));
+        } else {
+            m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
+            slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
+        }
+        
+        // Load the inheritorID (the Structure that objects who have protoGPR as the prototype
+        // use to refer to that prototype). If the inheritorID is not set, go to slow path.
+        m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
+        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));
+        
+        emitAllocateJSFinalObject(scratchGPR, resultGPR, scratchGPR, slowPath);
+        
+        MacroAssembler::Jump done = m_jit.jump();
+        
+        slowPath.link(&m_jit);
+        
+        silentSpillAllRegisters(resultGPR);
+        if (node.codeOrigin.inlineCallFrame)
+            callOperation(operationCreateThisInlined, resultGPR, protoGPR, node.codeOrigin.inlineCallFrame->callee.get());
+        else
+            callOperation(operationCreateThis, resultGPR, protoGPR);
+        silentFillAllRegisters(resultGPR);
+        
+        done.link(&m_jit);
+        
+        cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+
+    case NewObject: {
+        GPRTemporary result(this);
+        GPRTemporary scratch(this);
+        
+        GPRReg resultGPR = result.gpr();
+        GPRReg scratchGPR = scratch.gpr();
+        
+        MacroAssembler::JumpList slowPath;
+        
+        emitAllocateJSFinalObject(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)->emptyObjectStructure()), resultGPR, scratchGPR, slowPath);
+        
+        MacroAssembler::Jump done = m_jit.jump();
+        
+        slowPath.link(&m_jit);
+        
+        silentSpillAllRegisters(resultGPR);
+        callOperation(operationNewObject, resultGPR);
+        silentFillAllRegisters(resultGPR);
+        
+        done.link(&m_jit);
+        
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
+
+    case GetCallee: {
+        GPRTemporary result(this);
+        m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::Callee)), result.gpr());
+        cellResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case GetScopeChain: {
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
+
+        m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::ScopeChain)), resultGPR);
+        bool checkTopLevel = m_jit.codeBlock()->codeType() == FunctionCode && m_jit.codeBlock()->needsFullScopeChain();
+        int skip = node.scopeChainDepth();
+        ASSERT(skip || !checkTopLevel);
+        if (checkTopLevel && skip--) {
+            JITCompiler::Jump activationNotCreated;
+            if (checkTopLevel)
+                activationNotCreated = m_jit.branchTestPtr(JITCompiler::Zero, JITCompiler::addressFor(static_cast<VirtualRegister>(m_jit.codeBlock()->activationRegister())));
+            m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
+            activationNotCreated.link(&m_jit);
+        }
+        while (skip--)
+            m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
+        
+        m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, object)), resultGPR);
+
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
+    case GetScopedVar: {
+        SpeculateCellOperand scopeChain(this, node.child1());
+        GPRTemporary resultTag(this);
+        GPRTemporary resultPayload(this);
+        GPRReg resultTagGPR = resultTag.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), resultPayloadGPR);
+        m_jit.load32(JITCompiler::Address(resultPayloadGPR, node.varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
+        m_jit.load32(JITCompiler::Address(resultPayloadGPR, node.varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
+        jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex);
+        break;
+    }
+    case PutScopedVar: {
+        SpeculateCellOperand scopeChain(this, node.child1());
+        GPRTemporary scratchRegister(this);
+        GPRReg scratchGPR = scratchRegister.gpr();
+        m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), scratchGPR);
+        JSValueOperand value(this, node.child2());
+        m_jit.store32(value.tagGPR(), JITCompiler::Address(scratchGPR, node.varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+        m_jit.store32(value.payloadGPR(), JITCompiler::Address(scratchGPR, node.varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+        writeBarrier(scopeChain.gpr(), value.tagGPR(), node.child2(), WriteBarrierForVariableAccess, scratchGPR);
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case GetById: {
+        if (!node.prediction()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        if (isCellPrediction(at(node.child1()).prediction())) {
+            SpeculateCellOperand base(this, node.child1());
+            GPRTemporary resultTag(this, base);
+            GPRTemporary resultPayload(this);
+            
+            GPRReg baseGPR = base.gpr();
+            GPRReg resultTagGPR = resultTag.gpr();
+            GPRReg resultPayloadGPR = resultPayload.gpr();
+            GPRReg scratchGPR;
+            
+            if (resultTagGPR == baseGPR)
+                scratchGPR = resultPayloadGPR;
+            else
+                scratchGPR = resultTagGPR;
+            
+            base.use();
+            
+            cachedGetById(node.codeOrigin, InvalidGPRReg, baseGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber());
+            
+            jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+            break;
+        }
+        
+        JSValueOperand base(this, node.child1());
+        GPRTemporary resultTag(this, base);
+        GPRTemporary resultPayload(this);
+        
+        GPRReg baseTagGPR = base.tagGPR();
+        GPRReg basePayloadGPR = base.payloadGPR();
+        GPRReg resultTagGPR = resultTag.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        GPRReg scratchGPR;
+
+        if (resultTagGPR == basePayloadGPR)
+            scratchGPR = resultPayloadGPR;
+        else
+            scratchGPR = resultTagGPR;
+        
+        base.use();
+        
+        JITCompiler::Jump notCell = m_jit.branch32(JITCompiler::NotEqual, baseTagGPR, TrustedImm32(JSValue::CellTag));
+        
+        cachedGetById(node.codeOrigin, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber(), notCell);
+        
+        jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+
+    case GetByIdFlush: {
+        if (!node.prediction()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        if (isCellPrediction(at(node.child1()).prediction())) {
+            SpeculateCellOperand base(this, node.child1());
+            
+            GPRReg baseGPR = base.gpr();
+
+            GPRResult resultTag(this);
+            GPRResult2 resultPayload(this);
+            GPRReg resultTagGPR = resultTag.gpr();
+            GPRReg resultPayloadGPR = resultPayload.gpr();
+
+            GPRReg scratchGPR = selectScratchGPR(baseGPR, resultTagGPR, resultPayloadGPR);
+            
+            base.use();
+            
+            flushRegisters();
+            
+            cachedGetById(node.codeOrigin, InvalidGPRReg, baseGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber(), JITCompiler::Jump(), DontSpill);
+            
+            jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+            break;
+        }
+        
+        JSValueOperand base(this, node.child1());
+        GPRReg baseTagGPR = base.tagGPR();
+        GPRReg basePayloadGPR = base.payloadGPR();
+
+        GPRResult resultTag(this);
+        GPRResult2 resultPayload(this);
+        GPRReg resultTagGPR = resultTag.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+
+        GPRReg scratchGPR = selectScratchGPR(baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR);
+        
+        base.use();
+        
+        flushRegisters();
+        
+        JITCompiler::Jump notCell = m_jit.branch32(JITCompiler::NotEqual, baseTagGPR, TrustedImm32(JSValue::CellTag));
+        
+        cachedGetById(node.codeOrigin, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, scratchGPR, node.identifierNumber(), notCell, DontSpill);
+        
+        jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+
+    case GetArrayLength: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRReg baseGPR = base.gpr();
+        
+        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
+
+        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
+        m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR);
+        
+        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultGPR, MacroAssembler::TrustedImm32(0)));
+        
+        integerResult(resultGPR, m_compileIndex);
+        break;
+    }
+
+    case GetStringLength: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary result(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
+        
+        m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
+
+        integerResult(resultGPR, m_compileIndex);
+        break;
+    }
+
+    case GetInt8ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetInt16ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->int16ArrayDescriptor(), node, !isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetInt32ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->int32ArrayDescriptor(), node, !isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetUint8ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetUint8ClampedArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetUint16ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetUint32ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->uint32ArrayDescriptor(), node, !isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetFloat32ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->float32ArrayDescriptor(), node, !isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetFloat64ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->float64ArrayDescriptor(), node, !isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+
+    case CheckFunction: {
+        SpeculateCellOperand function(this, node.child1());
+        speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, function.gpr(), node.function()));
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case CheckStructure: {
+        if (m_state.forNode(node.child1()).m_structure.isSubsetOf(node.structureSet())) {
+            noResult(m_compileIndex);
+            break;
+        }
+        
+        SpeculateCellOperand base(this, node.child1());
+        
+        ASSERT(node.structureSet().size());
+        
+        if (node.structureSet().size() == 1)
+            speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(base.gpr(), JSCell::structureOffset()), node.structureSet()[0]));
+        else {
+            GPRTemporary structure(this);
+            
+            m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
+            
+            JITCompiler::JumpList done;
+            
+            for (size_t i = 0; i < node.structureSet().size() - 1; ++i)
+                done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node.structureSet()[i]));
+            
+            speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, structure.gpr(), node.structureSet().last()));
+            
+            done.link(&m_jit);
+        }
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case PutStructure: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRReg baseGPR = base.gpr();
+        
+        m_jit.addWeakReferenceTransition(
+            node.codeOrigin.codeOriginOwner(),
+            node.structureTransitionData().previousStructure,
+            node.structureTransitionData().newStructure);
+        
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        // Must always emit this write barrier as the structure transition itself requires it
+        writeBarrier(baseGPR, node.structureTransitionData().newStructure, WriteBarrierForGenericAccess);
+#endif
+        
+        m_jit.storePtr(MacroAssembler::TrustedImmPtr(node.structureTransitionData().newStructure), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case GetPropertyStorage: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary result(this, base);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
+        
+        storageResult(resultGPR, m_compileIndex);
+        break;
+    }
+
+    case GetIndexedPropertyStorage: {
+        compileGetIndexedPropertyStorage(node);
+        break;
+    }
+
+    case GetByOffset: {
+        StorageOperand storage(this, node.child1());
+        GPRTemporary resultTag(this, storage);
+        GPRTemporary resultPayload(this);
+        
+        GPRReg storageGPR = storage.gpr();
+        GPRReg resultTagGPR = resultTag.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        
+        StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
+        
+        m_jit.load32(JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
+        m_jit.load32(JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
+        
+        jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex);
+        break;
+    }
+        
+    case PutByOffset: {
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        SpeculateCellOperand base(this, node.child1());
+#endif
+        StorageOperand storage(this, node.child2());
+        JSValueOperand value(this, node.child3());
+
+        GPRReg storageGPR = storage.gpr();
+        GPRReg valueTagGPR = value.tagGPR();
+        GPRReg valuePayloadGPR = value.payloadGPR();
+        
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        writeBarrier(base.gpr(), valueTagGPR, node.child3(), WriteBarrierForPropertyAccess);
+#endif
+
+        StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
+        
+        m_jit.storePtr(valueTagGPR, JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+        m_jit.storePtr(valuePayloadGPR, JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case PutById: {
+        SpeculateCellOperand base(this, node.child1());
+        JSValueOperand value(this, node.child2());
+        GPRTemporary scratch(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg valueTagGPR = value.tagGPR();
+        GPRReg valuePayloadGPR = value.payloadGPR();
+        GPRReg scratchGPR = scratch.gpr();
+        
+        base.use();
+        value.use();
+
+        cachedPutById(node.codeOrigin, baseGPR, valueTagGPR, valuePayloadGPR, node.child2(), scratchGPR, node.identifierNumber(), NotDirect);
+        
+        noResult(m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+
+    case PutByIdDirect: {
+        SpeculateCellOperand base(this, node.child1());
+        JSValueOperand value(this, node.child2());
+        GPRTemporary scratch(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg valueTagGPR = value.tagGPR();
+        GPRReg valuePayloadGPR = value.payloadGPR();
+        GPRReg scratchGPR = scratch.gpr();
+        
+        base.use();
+        value.use();
+
+        cachedPutById(node.codeOrigin, baseGPR, valueTagGPR, valuePayloadGPR, node.child2(), scratchGPR, node.identifierNumber(), Direct);
+
+        noResult(m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+
+    case GetGlobalVar: {
+        GPRTemporary result(this);
+        GPRTemporary scratch(this);
+
+        JSVariableObject* globalObject = m_jit.globalObjectFor(node.codeOrigin);
+        m_jit.loadPtr(const_cast<WriteBarrier<Unknown>**>(globalObject->addressOfRegisters()), result.gpr());
+        m_jit.load32(JITCompiler::tagForGlobalVar(result.gpr(), node.varNumber()), scratch.gpr());
+        m_jit.load32(JITCompiler::payloadForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
+
+        jsValueResult(scratch.gpr(), result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case PutGlobalVar: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary globalObject(this);
+        GPRTemporary scratch(this);
+        
+        GPRReg globalObjectReg = globalObject.gpr();
+        GPRReg scratchReg = scratch.gpr();
+
+        m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectReg);
+
+        writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.tagGPR(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+
+        m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
+        m_jit.store32(value.tagGPR(), JITCompiler::tagForGlobalVar(scratchReg, node.varNumber()));
+        m_jit.store32(value.payloadGPR(), JITCompiler::payloadForGlobalVar(scratchReg, node.varNumber()));
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case CheckHasInstance: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary structure(this);
+
+        // Speculate that base 'ImplementsDefaultHasInstance'.
+        m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
+        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(structure.gpr(), Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case InstanceOf: {
+        compileInstanceOf(node);
+        break;
+    }
+
+    case IsUndefined: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this);
+        
+        JITCompiler::Jump isCell = m_jit.branch32(JITCompiler::Equal, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::CellTag));
+        
+        m_jit.compare32(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::UndefinedTag), result.gpr());
+        JITCompiler::Jump done = m_jit.jump();
+        
+        isCell.link(&m_jit);
+        m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureOffset()), result.gpr());
+        m_jit.test8(JITCompiler::NonZero, JITCompiler::Address(result.gpr(), Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), result.gpr());
+        
+        done.link(&m_jit);
+        booleanResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case IsBoolean: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this, value);
+        
+        m_jit.compare32(JITCompiler::Equal, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::BooleanTag), result.gpr());
+        booleanResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case IsNumber: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this, value);
+        
+        m_jit.add32(TrustedImm32(1), value.tagGPR(), result.gpr());
+        m_jit.compare32(JITCompiler::Below, result.gpr(), JITCompiler::TrustedImm32(JSValue::LowestTag + 1), result.gpr());
+        booleanResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case IsString: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this, value);
+        
+        JITCompiler::Jump isNotCell = m_jit.branch32(JITCompiler::NotEqual, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::CellTag));
+        
+        m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureOffset()), result.gpr());
+        m_jit.compare8(JITCompiler::Equal, JITCompiler::Address(result.gpr(), Structure::typeInfoTypeOffset()), TrustedImm32(StringType), result.gpr());
+        JITCompiler::Jump done = m_jit.jump();
+        
+        isNotCell.link(&m_jit);
+        m_jit.move(TrustedImm32(0), result.gpr());
+        
+        done.link(&m_jit);
+        booleanResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case IsObject: {
+        JSValueOperand value(this, node.child1());
+        GPRReg valueTagGPR = value.tagGPR();
+        GPRReg valuePayloadGPR = value.payloadGPR();
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+        flushRegisters();
+        callOperation(operationIsObject, resultGPR, valueTagGPR, valuePayloadGPR);
+        booleanResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case IsFunction: {
+        JSValueOperand value(this, node.child1());
+        GPRReg valueTagGPR = value.tagGPR();
+        GPRReg valuePayloadGPR = value.payloadGPR();
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+        flushRegisters();
+        callOperation(operationIsFunction, resultGPR, valueTagGPR, valuePayloadGPR);
+        booleanResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case Phi:
+    case Flush:
+        break;
+
+    case Breakpoint:
+#if ENABLE(DEBUG_WITH_BREAKPOINT)
+        m_jit.breakpoint();
+#else
+        ASSERT_NOT_REACHED();
+#endif
+        break;
+        
+    case Call:
+    case Construct:
+        emitCall(node);
+        break;
+
+    case Resolve: {
+        flushRegisters();
+        GPRResult resultPayload(this);
+        GPRResult2 resultTag(this);
+        callOperation(operationResolve, resultTag.gpr(), resultPayload.gpr(), identifier(node.identifierNumber()));
+        jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
+        break;
+    }
+
+    case ResolveBase: {
+        flushRegisters();
+        GPRResult resultPayload(this);
+        GPRResult2 resultTag(this);
+        callOperation(operationResolveBase, resultTag.gpr(), resultPayload.gpr(), identifier(node.identifierNumber()));
+        jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
+        break;
+    }
+
+    case ResolveBaseStrictPut: {
+        flushRegisters();
+        GPRResult resultPayload(this);
+        GPRResult2 resultTag(this);
+        callOperation(operationResolveBaseStrictPut, resultTag.gpr(), resultPayload.gpr(), identifier(node.identifierNumber()));
+        jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
+        break;
+    }
+
+    case ResolveGlobal: {
+        GPRTemporary globalObject(this);
+        GPRTemporary resolveInfo(this);
+        GPRTemporary resultTag(this);
+        GPRTemporary resultPayload(this);
+
+        GPRReg globalObjectGPR = globalObject.gpr();
+        GPRReg resolveInfoGPR = resolveInfo.gpr();
+        GPRReg resultTagGPR = resultTag.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+
+        ResolveGlobalData& data = m_jit.graph().m_resolveGlobalData[node.resolveGlobalDataIndex()];
+        GlobalResolveInfo* resolveInfoAddress = &(m_jit.codeBlock()->globalResolveInfo(data.resolveInfoIndex));
+
+        // Check Structure of global object
+        m_jit.move(JITCompiler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectGPR);
+        m_jit.move(JITCompiler::TrustedImmPtr(resolveInfoAddress), resolveInfoGPR);
+        m_jit.loadPtr(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, structure)), resultPayloadGPR);
+
+        JITCompiler::Jump structuresNotMatch = m_jit.branchPtr(JITCompiler::NotEqual, resultPayloadGPR, JITCompiler::Address(globalObjectGPR, JSCell::structureOffset()));
+
+        // Fast case
+        m_jit.loadPtr(JITCompiler::Address(globalObjectGPR, JSObject::offsetOfPropertyStorage()), resultPayloadGPR);
+        m_jit.load32(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), resolveInfoGPR);
+        m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR);
+        m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
+
+        JITCompiler::Jump wasFast = m_jit.jump();
+
+        structuresNotMatch.link(&m_jit);
+        silentSpillAllRegisters(resultTagGPR, resultPayloadGPR);
+        callOperation(operationResolveGlobal, resultTagGPR, resultPayloadGPR, resolveInfoGPR, &m_jit.codeBlock()->identifier(data.identifierNumber));
+        silentFillAllRegisters(resultTagGPR, resultPayloadGPR);
+
+        wasFast.link(&m_jit);
+
+        jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex);
+        break;
+    }
+
+    case CreateActivation: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this, value, false);
+        
+        GPRReg valueTagGPR = value.tagGPR();
+        GPRReg valuePayloadGPR = value.payloadGPR();
+        GPRReg resultGPR = result.gpr();
+        
+        m_jit.move(valuePayloadGPR, resultGPR);
+        
+        JITCompiler::Jump alreadyCreated = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
+        
+        silentSpillAllRegisters(resultGPR);
+        callOperation(operationCreateActivation, resultGPR);
+        silentFillAllRegisters(resultGPR);
+        
+        alreadyCreated.link(&m_jit);
+        
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
+        
+    case TearOffActivation: {
+        JSValueOperand value(this, node.child1());
+        
+        GPRReg valueTagGPR = value.tagGPR();
+        GPRReg valuePayloadGPR = value.payloadGPR();
+        
+        JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
+        
+        silentSpillAllRegisters(InvalidGPRReg);
+        callOperation(operationTearOffActivation, valuePayloadGPR);
+        silentFillAllRegisters(InvalidGPRReg);
+        
+        notCreated.link(&m_jit);
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case NewFunctionNoCheck:
+        compileNewFunctionNoCheck(node);
+        break;
+        
+    case NewFunction: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this, value, false);
+        
+        GPRReg valueTagGPR = value.tagGPR();
+        GPRReg valuePayloadGPR = value.payloadGPR();
+        GPRReg resultGPR = result.gpr();
+        
+        m_jit.move(valuePayloadGPR, resultGPR);
+        
+        JITCompiler::Jump alreadyCreated = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
+        
+        silentSpillAllRegisters(resultGPR);
+        callOperation(
+            operationNewFunction, resultGPR, m_jit.codeBlock()->functionDecl(node.functionDeclIndex()));
+        silentFillAllRegisters(resultGPR);
+        
+        alreadyCreated.link(&m_jit);
+        
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
+        
+    case NewFunctionExpression:
+        compileNewFunctionExpression(node);
+        break;
+
+    case ForceOSRExit: {
+        terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+        break;
+    }
+
+    case Phantom:
+        // This is a no-op.
+        noResult(m_compileIndex);
+        break;
+
+    case InlineStart:
+    case Nop:
+    case LastNodeType:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+    
+    if (!m_compileOkay)
+        return;
+    
+    if (node.hasResult() && node.mustGenerate())
+        use(m_compileIndex);
+}
+
+#endif
+
+} } // namespace JSC::DFG
+
+#endif
diff --git a/dfg/DFGSpeculativeJIT64.cpp b/dfg/DFGSpeculativeJIT64.cpp
new file mode 100644 (file)
index 0000000..3d976bd
--- /dev/null
@@ -0,0 +1,3816 @@
+/*
+ * 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 {
+
+#if USE(JSVALUE64)
+
+GPRReg SpeculativeJIT::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat)
+{
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    if (info.registerFormat() == DataFormatNone) {
+        GPRReg gpr = allocate();
+
+        if (node.hasConstant()) {
+            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 (isNumberConstant(nodeIndex)) {
+                JSValue jsValue = jsNumber(valueOfNumberConstant(nodeIndex));
+                m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+            } else {
+                ASSERT(isJSConstant(nodeIndex));
+                JSValue jsValue = valueOfJSConstant(nodeIndex);
+                m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsValue)), gpr);
+            }
+        } else if (info.spillFormat() == DataFormatInteger) {
+            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+            m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
+            // Tag it, since fillInteger() is used when we want a boxed integer.
+            m_jit.orPtr(GPRInfo::tagTypeNumberRegister, 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:
+    case DataFormatBoolean:
+    case DataFormatJSBoolean:
+    case DataFormatStorage:
+        // 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 SpeculativeJIT::fillDouble(NodeIndex nodeIndex)
+{
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    if (info.registerFormat() == DataFormatNone) {
+        if (node.hasConstant()) {
+            GPRReg gpr = allocate();
+        
+            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 (isNumberConstant(nodeIndex)) {
+                FPRReg fpr = fprAllocate();
+                m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(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::TrustedImmPtr(JSValue::encode(jsValue)), gpr);
+                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+                info.fillJSValue(gpr, DataFormatJS);
+                unlock(gpr);
+            }
+        } else {
+            DataFormat spillFormat = info.spillFormat();
+            switch (spillFormat) {
+            case DataFormatDouble: {
+                FPRReg fpr = fprAllocate();
+                m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
+                m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+                info.fillDouble(fpr);
+                return fpr;
+            }
+                
+            case DataFormatInteger: {
+                GPRReg gpr = allocate();
+                
+                m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+                m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
+                info.fillInteger(gpr);
+                unlock(gpr);
+                break;
+            }
+
+            default:
+                GPRReg gpr = allocate();
+        
+                ASSERT(spillFormat & DataFormatJS);
+                m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+                m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+                info.fillJSValue(gpr, spillFormat);
+                unlock(gpr);
+                break;
+            }
+        }
+    }
+
+    switch (info.registerFormat()) {
+    case DataFormatNone:
+        // Should have filled, above.
+    case DataFormatCell:
+    case DataFormatJSCell:
+    case DataFormatBoolean:
+    case DataFormatJSBoolean:
+    case DataFormatStorage:
+        // 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);
+        unboxDouble(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);
+        info.killSpilled();
+        return fpr;
+    }
+
+    case DataFormatJSInteger:
+    case DataFormatInteger: {
+        FPRReg fpr = fprAllocate();
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        m_jit.convertInt32ToDouble(gpr, fpr);
+        m_gprs.unlock(gpr);
+        return fpr;
+    }
+
+    // Unbox the double
+    case DataFormatJSDouble: {
+        GPRReg gpr = info.gpr();
+        FPRReg fpr = fprAllocate();
+        if (m_gprs.isLocked(gpr)) {
+            // Make sure we don't trample gpr if it is in use.
+            GPRReg temp = allocate();
+            m_jit.move(gpr, temp);
+            unboxDouble(temp, fpr);
+            unlock(temp);
+        } else
+            unboxDouble(gpr, fpr);
+
+        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 SpeculativeJIT::fillJSValue(NodeIndex nodeIndex)
+{
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+    
+    switch (info.registerFormat()) {
+    case DataFormatNone: {
+        GPRReg gpr = allocate();
+
+        if (node.hasConstant()) {
+            if (isInt32Constant(nodeIndex)) {
+                info.fillJSValue(gpr, DataFormatJSInteger);
+                JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
+                m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+            } else if (isNumberConstant(nodeIndex)) {
+                info.fillJSValue(gpr, DataFormatJSDouble);
+                JSValue jsValue(JSValue::EncodeAsDouble, valueOfNumberConstant(nodeIndex));
+                m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+            } else {
+                ASSERT(isJSConstant(nodeIndex));
+                JSValue jsValue = valueOfJSConstant(nodeIndex);
+                m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsValue)), gpr);
+                info.fillJSValue(gpr, DataFormatJS);
+            }
+
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+        } else {
+            DataFormat spillFormat = info.spillFormat();
+            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+            if (spillFormat == DataFormatInteger) {
+                m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
+                m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
+                spillFormat = DataFormatJSInteger;
+            } else {
+                m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+                if (spillFormat == DataFormatDouble) {
+                    // Need to box the double, since we want a JSValue.
+                    m_jit.subPtr(GPRInfo::tagTypeNumberRegister, gpr);
+                    spillFormat = DataFormatJSDouble;
+                } else
+                    ASSERT(spillFormat & DataFormatJS);
+            }
+            info.fillJSValue(gpr, spillFormat);
+        }
+        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:
+    case DataFormatJSBoolean: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        return gpr;
+    }
+        
+    case DataFormatBoolean:
+    case DataFormatStorage:
+        // this type currently never occurs
+        ASSERT_NOT_REACHED();
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+void SpeculativeJIT::nonSpeculativeValueToNumber(Node& node)
+{
+    if (isKnownNumeric(node.child1().index())) {
+        JSValueOperand op1(this, node.child1());
+        GPRTemporary result(this, op1);
+        m_jit.move(op1.gpr(), result.gpr());
+        jsValueResult(result.gpr(), m_compileIndex);
+        return;
+    }
+
+    JSValueOperand op1(this, node.child1());
+    GPRTemporary result(this);
+    
+    ASSERT(!isInt32Constant(node.child1().index()));
+    ASSERT(!isNumberConstant(node.child1().index()));
+    
+    GPRReg jsValueGpr = op1.gpr();
+    GPRReg gpr = result.gpr();
+    op1.use();
+
+    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, gpr);
+    JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
+
+    // Next handle cells (& other JS immediates)
+    nonNumeric.link(&m_jit);
+    silentSpillAllRegisters(gpr);
+    callOperation(dfgConvertJSValueToNumber, FPRInfo::returnValueFPR, jsValueGpr);
+    boxDouble(FPRInfo::returnValueFPR, gpr);
+    silentFillAllRegisters(gpr);
+    JITCompiler::Jump hasCalledToNumber = m_jit.jump();
+    
+    // Finally, handle integers.
+    isInteger.link(&m_jit);
+    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, jsValueGpr, gpr);
+    hasUnboxedDouble.link(&m_jit);
+    hasCalledToNumber.link(&m_jit);
+    
+    jsValueResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
+}
+
+void SpeculativeJIT::nonSpeculativeValueToInt32(Node& node)
+{
+    ASSERT(!isInt32Constant(node.child1().index()));
+    
+    if (isKnownInteger(node.child1().index())) {
+        IntegerOperand op1(this, node.child1());
+        GPRTemporary result(this, op1);
+        m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
+        integerResult(result.gpr(), m_compileIndex);
+        return;
+    }
+    
+    GenerationInfo& childInfo = m_generationInfo[at(node.child1()).virtualRegister()];
+    if (childInfo.isJSDouble()) {
+        DoubleOperand op1(this, node.child1());
+        GPRTemporary result(this);
+        FPRReg fpr = op1.fpr();
+        GPRReg gpr = result.gpr();
+        op1.use();
+        JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
+        
+        silentSpillAllRegisters(gpr);
+        callOperation(toInt32, gpr, fpr);
+        silentFillAllRegisters(gpr);
+        
+        truncatedToInteger.link(&m_jit);
+        integerResult(gpr, m_compileIndex, UseChildrenCalledExplicitly);
+        return;
+    }
+    
+    JSValueOperand op1(this, node.child1());
+    GPRTemporary result(this, op1);
+    GPRReg jsValueGpr = op1.gpr();
+    GPRReg resultGPR = result.gpr();
+    op1.use();
+
+    JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
+
+    // First handle non-integers
+    silentSpillAllRegisters(resultGPR);
+    callOperation(dfgConvertJSValueToInt32, resultGPR, jsValueGpr);
+    silentFillAllRegisters(resultGPR);
+    JITCompiler::Jump hasCalledToInt32 = m_jit.jump();
+
+    // Then handle integers.
+    isInteger.link(&m_jit);
+    m_jit.zeroExtend32ToPtr(jsValueGpr, resultGPR);
+    hasCalledToInt32.link(&m_jit);
+    integerResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+}
+
+void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node& node)
+{
+    IntegerOperand op1(this, node.child1());
+    FPRTemporary boxer(this);
+    GPRTemporary result(this, op1);
+    
+    JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
+    
+    m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());
+    m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), boxer.fpr());
+    
+    boxDouble(boxer.fpr(), result.gpr());
+    
+    JITCompiler::Jump done = m_jit.jump();
+    
+    positive.link(&m_jit);
+    
+    m_jit.orPtr(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr());
+    
+    done.link(&m_jit);
+    
+    jsValueResult(result.gpr(), m_compileIndex);
+}
+
+JITCompiler::Call SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
+{
+    JITCompiler::DataLabelPtr structureToCompare;
+    JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
+    
+    m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
+    JITCompiler::DataLabelCompact loadWithPatch = m_jit.loadPtrWithCompactAddressOffsetPatch(JITCompiler::Address(resultGPR, 0), resultGPR);
+    
+    JITCompiler::Jump done = m_jit.jump();
+
+    structureCheck.m_jump.link(&m_jit);
+    
+    if (slowPathTarget.isSet())
+        slowPathTarget.link(&m_jit);
+    
+    JITCompiler::Label slowCase = m_jit.label();
+
+    if (spillMode == NeedToSpill)
+        silentSpillAllRegisters(resultGPR);
+    JITCompiler::Call functionCall = callOperation(operationGetByIdOptimize, resultGPR, baseGPR, identifier(identifierNumber));
+    if (spillMode == NeedToSpill)
+        silentFillAllRegisters(resultGPR);
+    
+    done.link(&m_jit);
+    
+    JITCompiler::Label doneLabel = m_jit.label();
+
+    m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, loadWithPatch, slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(resultGPR), safeCast<int8_t>(scratchGPR), spillMode == NeedToSpill ? PropertyAccessRecord::RegistersInUse : PropertyAccessRecord::RegistersFlushed));
+    
+    if (scratchGPR != resultGPR && scratchGPR != InvalidGPRReg && spillMode == NeedToSpill)
+        unlock(scratchGPR);
+    
+    return functionCall;
+}
+
+void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
+{
+    
+    JITCompiler::DataLabelPtr structureToCompare;
+    JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
+
+    writeBarrier(baseGPR, valueGPR, valueUse, WriteBarrierForPropertyAccess, scratchGPR);
+
+    m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
+    JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
+
+    JITCompiler::Jump done = m_jit.jump();
+
+    structureCheck.m_jump.link(&m_jit);
+
+    if (slowPathTarget.isSet())
+        slowPathTarget.link(&m_jit);
+
+    JITCompiler::Label slowCase = m_jit.label();
+
+    silentSpillAllRegisters(InvalidGPRReg);
+    V_DFGOperation_EJCI optimizedCall;
+    if (m_jit.strictModeFor(at(m_compileIndex).codeOrigin)) {
+        if (putKind == Direct)
+            optimizedCall = operationPutByIdDirectStrictOptimize;
+        else
+            optimizedCall = operationPutByIdStrictOptimize;
+    } else {
+        if (putKind == Direct)
+            optimizedCall = operationPutByIdDirectNonStrictOptimize;
+        else
+            optimizedCall = operationPutByIdNonStrictOptimize;
+    }
+    JITCompiler::Call functionCall = callOperation(optimizedCall, valueGPR, baseGPR, identifier(identifierNumber));
+    silentFillAllRegisters(InvalidGPRReg);
+
+    done.link(&m_jit);
+    JITCompiler::Label doneLabel = m_jit.label();
+
+    m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(storeWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), safeCast<int8_t>(scratchGPR)));
+}
+
+void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool invert)
+{
+    JSValueOperand arg(this, operand);
+    GPRReg argGPR = arg.gpr();
+    
+    GPRTemporary result(this, arg);
+    GPRReg resultGPR = result.gpr();
+    
+    JITCompiler::Jump notCell;
+    
+    if (!isKnownCell(operand.index()))
+        notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
+    
+    m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
+    m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultGPR);
+    
+    if (!isKnownCell(operand.index())) {
+        JITCompiler::Jump done = m_jit.jump();
+        
+        notCell.link(&m_jit);
+        
+        m_jit.move(argGPR, resultGPR);
+        m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
+        m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);
+        
+        done.link(&m_jit);
+    }
+    
+    m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
+    jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
+}
+
+void SpeculativeJIT::nonSpeculativePeepholeBranchNull(Edge operand, NodeIndex branchNodeIndex, bool invert)
+{
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+    
+    if (taken == (m_block + 1)) {
+        invert = !invert;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+
+    JSValueOperand arg(this, operand);
+    GPRReg argGPR = arg.gpr();
+    
+    GPRTemporary result(this, arg);
+    GPRReg resultGPR = result.gpr();
+    
+    JITCompiler::Jump notCell;
+    
+    if (!isKnownCell(operand.index()))
+        notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
+    
+    m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
+    branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), taken);
+    
+    if (!isKnownCell(operand.index())) {
+        jump(notTaken, ForceJump);
+        
+        notCell.link(&m_jit);
+        
+        m_jit.move(argGPR, resultGPR);
+        m_jit.andPtr(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
+        branchPtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)), taken);
+    }
+    
+    jump(notTaken);
+}
+
+bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, Edge operand, bool invert)
+{
+    unsigned branchIndexInBlock = detectPeepHoleBranch();
+    if (branchIndexInBlock != UINT_MAX) {
+        NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
+
+        ASSERT(node.adjustedRefCount() == 1);
+        
+        nonSpeculativePeepholeBranchNull(operand, branchNodeIndex, invert);
+    
+        use(node.child1());
+        use(node.child2());
+        m_indexInBlock = branchIndexInBlock;
+        m_compileIndex = branchNodeIndex;
+        
+        return true;
+    }
+    
+    nonSpeculativeNonPeepholeCompareNull(operand, invert);
+    
+    return false;
+}
+
+void SpeculativeJIT::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
+{
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+
+    JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
+
+    // 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)) {
+        cond = JITCompiler::invert(cond);
+        callResultCondition = JITCompiler::Zero;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+
+    JSValueOperand arg1(this, node.child1());
+    JSValueOperand arg2(this, node.child2());
+    GPRReg arg1GPR = arg1.gpr();
+    GPRReg arg2GPR = arg2.gpr();
+    
+    JITCompiler::JumpList slowPath;
+    
+    if (isKnownNotInteger(node.child1().index()) || isKnownNotInteger(node.child2().index())) {
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+    
+        arg1.use();
+        arg2.use();
+    
+        flushRegisters();
+        callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
+
+        branchTest32(callResultCondition, resultGPR, taken);
+    } else {
+        GPRTemporary result(this, arg2);
+        GPRReg resultGPR = result.gpr();
+    
+        arg1.use();
+        arg2.use();
+    
+        if (!isKnownInteger(node.child1().index()))
+            slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
+        if (!isKnownInteger(node.child2().index()))
+            slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
+    
+        branch32(cond, arg1GPR, arg2GPR, taken);
+    
+        if (!isKnownInteger(node.child1().index()) || !isKnownInteger(node.child2().index())) {
+            jump(notTaken, ForceJump);
+    
+            slowPath.link(&m_jit);
+    
+            silentSpillAllRegisters(resultGPR);
+            callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
+            silentFillAllRegisters(resultGPR);
+        
+            branchTest32(callResultCondition, resultGPR, taken);
+        }
+    }
+
+    jump(notTaken);
+
+    m_indexInBlock = m_jit.graph().m_blocks[m_block]->size() - 1;
+    m_compileIndex = branchNodeIndex;
+}
+
+void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
+{
+    JSValueOperand arg1(this, node.child1());
+    JSValueOperand arg2(this, node.child2());
+    GPRReg arg1GPR = arg1.gpr();
+    GPRReg arg2GPR = arg2.gpr();
+    
+    JITCompiler::JumpList slowPath;
+    
+    if (isKnownNotInteger(node.child1().index()) || isKnownNotInteger(node.child2().index())) {
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+    
+        arg1.use();
+        arg2.use();
+    
+        flushRegisters();
+        callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
+        
+        m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
+        jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
+    } else {
+        GPRTemporary result(this, arg2);
+        GPRReg resultGPR = result.gpr();
+
+        arg1.use();
+        arg2.use();
+    
+        if (!isKnownInteger(node.child1().index()))
+            slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
+        if (!isKnownInteger(node.child2().index()))
+            slowPath.append(m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
+    
+        m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);
+    
+        if (!isKnownInteger(node.child1().index()) || !isKnownInteger(node.child2().index())) {
+            JITCompiler::Jump haveResult = m_jit.jump();
+    
+            slowPath.link(&m_jit);
+        
+            silentSpillAllRegisters(resultGPR);
+            callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
+            silentFillAllRegisters(resultGPR);
+        
+            m_jit.andPtr(TrustedImm32(1), resultGPR);
+        
+            haveResult.link(&m_jit);
+        }
+        
+        m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
+        
+        jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
+    }
+}
+
+void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branchNodeIndex, bool invert)
+{
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+
+    // 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)) {
+        invert = !invert;
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+    
+    JSValueOperand arg1(this, node.child1());
+    JSValueOperand arg2(this, node.child2());
+    GPRReg arg1GPR = arg1.gpr();
+    GPRReg arg2GPR = arg2.gpr();
+    
+    GPRTemporary result(this);
+    GPRReg resultGPR = result.gpr();
+    
+    arg1.use();
+    arg2.use();
+    
+    if (isKnownCell(node.child1().index()) && isKnownCell(node.child2().index())) {
+        // see if we get lucky: if the arguments are cells and they reference the same
+        // cell, then they must be strictly equal.
+        branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
+        
+        silentSpillAllRegisters(resultGPR);
+        callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
+        silentFillAllRegisters(resultGPR);
+        
+        branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
+    } else {
+        m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
+        
+        JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
+        
+        JITCompiler::Jump leftOK = m_jit.branchPtr(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister);
+        JITCompiler::Jump leftDouble = m_jit.branchTestPtr(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister);
+        leftOK.link(&m_jit);
+        JITCompiler::Jump rightOK = m_jit.branchPtr(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
+        JITCompiler::Jump rightDouble = m_jit.branchTestPtr(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister);
+        rightOK.link(&m_jit);
+        
+        branchPtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, taken);
+        jump(notTaken, ForceJump);
+        
+        twoCellsCase.link(&m_jit);
+        branchPtr(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
+        
+        leftDouble.link(&m_jit);
+        rightDouble.link(&m_jit);
+        
+        silentSpillAllRegisters(resultGPR);
+        callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
+        silentFillAllRegisters(resultGPR);
+        
+        branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
+    }
+    
+    jump(notTaken);
+}
+
+void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)
+{
+    JSValueOperand arg1(this, node.child1());
+    JSValueOperand arg2(this, node.child2());
+    GPRReg arg1GPR = arg1.gpr();
+    GPRReg arg2GPR = arg2.gpr();
+    
+    GPRTemporary result(this);
+    GPRReg resultGPR = result.gpr();
+    
+    arg1.use();
+    arg2.use();
+    
+    if (isKnownCell(node.child1().index()) && isKnownCell(node.child2().index())) {
+        // see if we get lucky: if the arguments are cells and they reference the same
+        // cell, then they must be strictly equal.
+        JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
+        
+        m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
+        
+        JITCompiler::Jump done = m_jit.jump();
+
+        notEqualCase.link(&m_jit);
+        
+        silentSpillAllRegisters(resultGPR);
+        callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
+        silentFillAllRegisters(resultGPR);
+        
+        m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
+        m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
+        
+        done.link(&m_jit);
+    } else {
+        m_jit.orPtr(arg1GPR, arg2GPR, resultGPR);
+        
+        JITCompiler::Jump twoCellsCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
+        
+        JITCompiler::Jump leftOK = m_jit.branchPtr(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister);
+        JITCompiler::Jump leftDouble = m_jit.branchTestPtr(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister);
+        leftOK.link(&m_jit);
+        JITCompiler::Jump rightOK = m_jit.branchPtr(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
+        JITCompiler::Jump rightDouble = m_jit.branchTestPtr(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister);
+        rightOK.link(&m_jit);
+        
+        m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
+        
+        JITCompiler::Jump done1 = m_jit.jump();
+        
+        twoCellsCase.link(&m_jit);
+        JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1GPR, arg2GPR);
+        
+        m_jit.move(JITCompiler::TrustedImmPtr(JSValue::encode(jsBoolean(!invert))), resultGPR);
+        
+        JITCompiler::Jump done2 = m_jit.jump();
+        
+        leftDouble.link(&m_jit);
+        rightDouble.link(&m_jit);
+        notEqualCase.link(&m_jit);
+        
+        silentSpillAllRegisters(resultGPR);
+        callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
+        silentFillAllRegisters(resultGPR);
+        
+        m_jit.andPtr(JITCompiler::TrustedImm32(1), resultGPR);
+
+        done1.link(&m_jit);
+
+        m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
+        
+        done2.link(&m_jit);
+    }
+    
+    jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
+}
+
+void SpeculativeJIT::emitCall(Node& node)
+{
+    P_DFGOperation_E slowCallFunction;
+
+    if (node.op() == Call)
+        slowCallFunction = operationLinkCall;
+    else {
+        ASSERT(node.op() == Construct);
+        slowCallFunction = operationLinkConstruct;
+    }
+
+    // For constructors, the this argument is not passed but we have to make space
+    // for it.
+    int dummyThisArgument = node.op() == Call ? 0 : 1;
+    
+    CallLinkInfo::CallType callType = node.op() == Call ? CallLinkInfo::Call : CallLinkInfo::Construct;
+    
+    Edge calleeEdge = m_jit.graph().m_varArgChildren[node.firstChild()];
+    JSValueOperand callee(this, calleeEdge);
+    GPRReg calleeGPR = callee.gpr();
+    use(calleeEdge);
+    
+    // The call instruction's first child is either the function (normal call) or the
+    // receiver (method call). subsequent children are the arguments.
+    int numPassedArgs = node.numChildren() - 1;
+    
+    m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs + dummyThisArgument), callFramePayloadSlot(RegisterFile::ArgumentCount));
+    m_jit.storePtr(GPRInfo::callFrameRegister, callFrameSlot(RegisterFile::CallerFrame));
+    m_jit.storePtr(calleeGPR, callFrameSlot(RegisterFile::Callee));
+    
+    for (int i = 0; i < numPassedArgs; i++) {
+        Edge argEdge = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i];
+        JSValueOperand arg(this, argEdge);
+        GPRReg argGPR = arg.gpr();
+        use(argEdge);
+        
+        m_jit.storePtr(argGPR, argumentSlot(i + dummyThisArgument));
+    }
+
+    flushRegisters();
+
+    GPRResult result(this);
+    GPRReg resultGPR = result.gpr();
+
+    JITCompiler::DataLabelPtr targetToCheck;
+    JITCompiler::Jump slowPath;
+
+    slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(JSValue::encode(JSValue())));
+    m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), resultGPR);
+    m_jit.storePtr(resultGPR, callFrameSlot(RegisterFile::ScopeChain));
+
+    m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
+    
+    CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
+    CallBeginToken token = m_jit.beginCall();
+    JITCompiler::Call fastCall = m_jit.nearCall();
+    m_jit.notifyCall(fastCall, codeOrigin, token);
+    
+    JITCompiler::Jump done = m_jit.jump();
+    
+    slowPath.link(&m_jit);
+    
+    m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    token = m_jit.beginCall();
+    JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction);
+    m_jit.addFastExceptionCheck(slowCall, codeOrigin, token);
+    m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
+    token = m_jit.beginCall();
+    JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR);
+    m_jit.notifyCall(theCall, codeOrigin, token);
+    
+    done.link(&m_jit);
+    
+    m_jit.move(GPRInfo::returnValueGPR, resultGPR);
+    
+    jsValueResult(resultGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly);
+    
+    m_jit.addJSCall(fastCall, slowCall, targetToCheck, callType, at(m_compileIndex).codeOrigin);
+}
+
+template<bool strict>
+GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat& returnFormat)
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("SpecInt@%d   ", nodeIndex);
+#endif
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    switch (info.registerFormat()) {
+    case DataFormatNone: {
+        if ((node.hasConstant() && !isInt32Constant(nodeIndex)) || info.spillFormat() == DataFormatDouble) {
+            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            returnFormat = DataFormatInteger;
+            return allocate();
+        }
+        
+        GPRReg gpr = allocate();
+
+        if (node.hasConstant()) {
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+            ASSERT(isInt32Constant(nodeIndex));
+            m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
+            info.fillInteger(gpr);
+            returnFormat = DataFormatInteger;
+            return gpr;
+        }
+        
+        DataFormat spillFormat = info.spillFormat();
+        
+        ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
+        
+        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+        
+        if (spillFormat == DataFormatJSInteger || spillFormat == DataFormatInteger) {
+            // 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;
+            }
+            if (spillFormat == DataFormatInteger) {
+                m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
+                m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
+            } else
+                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(BadType, JSValueRegs(gpr), nodeIndex, 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 DataFormatJSDouble: {
+        if (node.hasConstant() && isInt32Constant(nodeIndex)) {
+            GPRReg gpr = allocate();
+            ASSERT(isInt32Constant(nodeIndex));
+            m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
+            returnFormat = DataFormatInteger;
+            return gpr;
+        }
+    }
+    case DataFormatCell:
+    case DataFormatBoolean:
+    case DataFormatJSCell:
+    case DataFormatJSBoolean: {
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        returnFormat = DataFormatInteger;
+        return allocate();
+    }
+
+    case DataFormatStorage:
+        ASSERT_NOT_REACHED();
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+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;
+}
+
+FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("SpecDouble@%d   ", nodeIndex);
+#endif
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    if (info.registerFormat() == DataFormatNone) {
+        if (node.hasConstant()) {
+            GPRReg gpr = allocate();
+
+            if (isInt32Constant(nodeIndex)) {
+                FPRReg fpr = fprAllocate();
+                m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(static_cast<double>(valueOfInt32Constant(nodeIndex))))), gpr);
+                m_jit.movePtrToDouble(gpr, fpr);
+                unlock(gpr);
+
+                m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+                info.fillDouble(fpr);
+                return fpr;
+            }
+            if (isNumberConstant(nodeIndex)) {
+                FPRReg fpr = fprAllocate();
+                m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(nodeIndex)))), gpr);
+                m_jit.movePtrToDouble(gpr, fpr);
+                unlock(gpr);
+
+                m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+                info.fillDouble(fpr);
+                return fpr;
+            }
+            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            return fprAllocate();
+        }
+        
+        DataFormat spillFormat = info.spillFormat();
+        switch (spillFormat) {
+        case DataFormatDouble: {
+            FPRReg fpr = fprAllocate();
+            m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
+            m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+            info.fillDouble(fpr);
+            return fpr;
+        }
+            
+        case DataFormatInteger: {
+            GPRReg gpr = allocate();
+            
+            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+            m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
+            info.fillInteger(gpr);
+            unlock(gpr);
+            break;
+        }
+
+        default:
+            GPRReg gpr = allocate();
+
+            ASSERT(spillFormat & DataFormatJS);
+            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+            info.fillJSValue(gpr, spillFormat);
+            unlock(gpr);
+            break;
+        }
+    }
+
+    switch (info.registerFormat()) {
+    case DataFormatNone: // Should have filled, above.
+    case DataFormatBoolean: // This type never occurs.
+    case DataFormatStorage:
+        ASSERT_NOT_REACHED();
+
+    case DataFormatCell:
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        return fprAllocate();
+
+    case DataFormatJSCell:
+    case DataFormatJS:
+    case DataFormatJSBoolean: {
+        GPRReg jsValueGpr = info.gpr();
+        m_gprs.lock(jsValueGpr);
+        FPRReg fpr = fprAllocate();
+        GPRReg tempGpr = allocate();
+
+        JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
+
+        speculationCheck(BadType, JSValueRegs(jsValueGpr), nodeIndex, 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);
+        unboxDouble(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);
+        info.killSpilled();
+        return fpr;
+    }
+
+    case DataFormatJSInteger:
+    case DataFormatInteger: {
+        FPRReg fpr = fprAllocate();
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        m_jit.convertInt32ToDouble(gpr, fpr);
+        m_gprs.unlock(gpr);
+        return fpr;
+    }
+
+    // Unbox the double
+    case DataFormatJSDouble: {
+        GPRReg gpr = info.gpr();
+        FPRReg fpr = fprAllocate();
+        if (m_gprs.isLocked(gpr)) {
+            // Make sure we don't trample gpr if it is in use.
+            GPRReg temp = allocate();
+            m_jit.move(gpr, temp);
+            unboxDouble(temp, fpr);
+            unlock(temp);
+        } else
+            unboxDouble(gpr, fpr);
+
+        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 SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("SpecCell@%d   ", nodeIndex);
+#endif
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    switch (info.registerFormat()) {
+    case DataFormatNone: {
+        if (info.spillFormat() == DataFormatInteger || info.spillFormat() == DataFormatDouble) {
+            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            return allocate();
+        }
+        
+        GPRReg gpr = allocate();
+
+        if (node.hasConstant()) {
+            JSValue jsValue = valueOfJSConstant(nodeIndex);
+            if (jsValue.isCell()) {
+                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+                m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
+                info.fillJSValue(gpr, DataFormatJSCell);
+                return gpr;
+            }
+            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            return gpr;
+        }
+        ASSERT(info.spillFormat() & DataFormatJS);
+        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+        m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+
+        info.fillJSValue(gpr, DataFormatJS);
+        if (info.spillFormat() != DataFormatJSCell)
+            speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, 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(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
+        info.fillJSValue(gpr, DataFormatJSCell);
+        return gpr;
+    }
+
+    case DataFormatJSInteger:
+    case DataFormatInteger:
+    case DataFormatJSDouble:
+    case DataFormatDouble:
+    case DataFormatJSBoolean:
+    case DataFormatBoolean: {
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        return allocate();
+    }
+
+    case DataFormatStorage:
+        ASSERT_NOT_REACHED();
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
+{
+#if DFG_ENABLE(DEBUG_VERBOSE)
+    dataLog("SpecBool@%d   ", nodeIndex);
+#endif
+    Node& node = at(nodeIndex);
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    switch (info.registerFormat()) {
+    case DataFormatNone: {
+        if (info.spillFormat() == DataFormatInteger || info.spillFormat() == DataFormatDouble) {
+            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            return allocate();
+        }
+        
+        GPRReg gpr = allocate();
+
+        if (node.hasConstant()) {
+            JSValue jsValue = valueOfJSConstant(nodeIndex);
+            if (jsValue.isBoolean()) {
+                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+                m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsValue)), gpr);
+                info.fillJSValue(gpr, DataFormatJSBoolean);
+                return gpr;
+            }
+            terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+            return gpr;
+        }
+        ASSERT(info.spillFormat() & DataFormatJS);
+        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+        m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+
+        info.fillJSValue(gpr, DataFormatJS);
+        if (info.spillFormat() != DataFormatJSBoolean) {
+            m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
+            speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
+            m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
+        }
+        info.fillJSValue(gpr, DataFormatJSBoolean);
+        return gpr;
+    }
+
+    case DataFormatBoolean:
+    case DataFormatJSBoolean: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        return gpr;
+    }
+
+    case DataFormatJS: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
+        speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
+        m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
+        info.fillJSValue(gpr, DataFormatJSBoolean);
+        return gpr;
+    }
+
+    case DataFormatJSInteger:
+    case DataFormatInteger:
+    case DataFormatJSDouble:
+    case DataFormatDouble:
+    case DataFormatJSCell:
+    case DataFormatCell: {
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        return allocate();
+    }
+        
+    case DataFormatStorage:
+        ASSERT_NOT_REACHED();
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, GPRReg tmp)
+{
+    JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, value, GPRInfo::tagTypeNumberRegister);
+    
+    JITCompiler::Jump notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, value, GPRInfo::tagTypeNumberRegister);
+    
+    m_jit.move(value, tmp);
+    unboxDouble(tmp, result);
+    
+    JITCompiler::Jump done = m_jit.jump();
+    
+    isInteger.link(&m_jit);
+    
+    m_jit.convertInt32ToDouble(value, result);
+    
+    done.link(&m_jit);
+
+    return notNumber;
+}
+
+void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, PredictionChecker predictionCheck)
+{
+    SpeculateCellOperand op1(this, node.child1());
+    SpeculateCellOperand op2(this, node.child2());
+    GPRTemporary result(this, op1);
+    
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    GPRReg resultGPR = result.gpr();
+    
+    if (!predictionCheck(m_state.forNode(node.child1()).m_type))
+        speculationCheck(BadType, JSValueRegs(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
+    if (!predictionCheck(m_state.forNode(node.child2()).m_type))
+        speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
+    
+    MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
+    m_jit.move(TrustedImm32(ValueTrue), resultGPR);
+    MacroAssembler::Jump done = m_jit.jump();
+    falseCase.link(&m_jit);
+    m_jit.move(TrustedImm32(ValueFalse), resultGPR);
+    done.link(&m_jit);
+
+    jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
+}
+
+void SpeculativeJIT::compileObjectToObjectOrOtherEquality(
+    Edge leftChild, Edge rightChild,
+    const ClassInfo* classInfo, PredictionChecker predictionCheck)
+{
+    SpeculateCellOperand op1(this, leftChild);
+    JSValueOperand op2(this, rightChild);
+    GPRTemporary result(this);
+    
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    GPRReg resultGPR = result.gpr();
+    
+    if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+        speculationCheck(
+            BadType, JSValueRegs(op1GPR), leftChild.index(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual,
+                MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()),
+                MacroAssembler::TrustedImmPtr(classInfo)));
+    }
+    
+    // It seems that most of the time when programs do a == b where b may be either null/undefined
+    // or an object, b is usually an object. Balance the branches to make that case fast.
+    MacroAssembler::Jump rightNotCell =
+        m_jit.branchTestPtr(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister);
+    
+    // We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
+    // proof, when filtered on cell, demonstrates that we have an object of the desired type
+    // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+    // speculation.
+    if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+        speculationCheck(
+            BadType, JSValueRegs(op2GPR), rightChild.index(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual,
+                MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()),
+                MacroAssembler::TrustedImmPtr(classInfo)));
+    }
+    
+    // At this point we know that we can perform a straight-forward equality comparison on pointer
+    // values because both left and right are pointers to objects that have no special equality
+    // protocols.
+    MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
+    MacroAssembler::Jump trueCase = m_jit.jump();
+    
+    rightNotCell.link(&m_jit);
+    
+    // We know that within this branch, rightChild must not be a cell. Check if that is enough to
+    // prove that it is either null or undefined.
+    if (!isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell)) {
+        m_jit.move(op2GPR, resultGPR);
+        m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
+        
+        speculationCheck(
+            BadType, JSValueRegs(op2GPR), rightChild.index(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual, resultGPR,
+                MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
+    }
+    
+    falseCase.link(&m_jit);
+    m_jit.move(TrustedImm32(ValueFalse), resultGPR);
+    MacroAssembler::Jump done = m_jit.jump();
+    trueCase.link(&m_jit);
+    m_jit.move(TrustedImm32(ValueTrue), resultGPR);
+    done.link(&m_jit);
+    
+    jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
+}
+
+void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(
+    Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex,
+    const ClassInfo* classInfo, PredictionChecker predictionCheck)
+{
+    Node& branchNode = at(branchNodeIndex);
+    BlockIndex taken = branchNode.takenBlockIndex();
+    BlockIndex notTaken = branchNode.notTakenBlockIndex();
+    
+    SpeculateCellOperand op1(this, leftChild);
+    JSValueOperand op2(this, rightChild);
+    GPRTemporary result(this);
+    
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    GPRReg resultGPR = result.gpr();
+    
+    if (!predictionCheck(m_state.forNode(leftChild).m_type)) {
+        speculationCheck(
+            BadType, JSValueRegs(op1GPR), leftChild.index(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual,
+                MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()),
+                MacroAssembler::TrustedImmPtr(classInfo)));
+    }
+    
+    // It seems that most of the time when programs do a == b where b may be either null/undefined
+    // or an object, b is usually an object. Balance the branches to make that case fast.
+    MacroAssembler::Jump rightNotCell =
+        m_jit.branchTestPtr(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister);
+    
+    // We know that within this branch, rightChild must be a cell. If the CFA can tell us that the
+    // proof, when filtered on cell, demonstrates that we have an object of the desired type
+    // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the
+    // speculation.
+    if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) {
+        speculationCheck(
+            BadType, JSValueRegs(op2GPR), rightChild.index(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual,
+                MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()),
+                MacroAssembler::TrustedImmPtr(classInfo)));
+    }
+    
+    // At this point we know that we can perform a straight-forward equality comparison on pointer
+    // values because both left and right are pointers to objects that have no special equality
+    // protocols.
+    branchPtr(MacroAssembler::Equal, op1GPR, op2GPR, taken);
+    
+    // We know that within this branch, rightChild must not be a cell. Check if that is enough to
+    // prove that it is either null or undefined.
+    if (isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell))
+        rightNotCell.link(&m_jit);
+    else {
+        jump(notTaken, ForceJump);
+        
+        rightNotCell.link(&m_jit);
+        m_jit.move(op2GPR, resultGPR);
+        m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
+        
+        speculationCheck(
+            BadType, JSValueRegs(op2GPR), rightChild.index(),
+            m_jit.branchPtr(
+                MacroAssembler::NotEqual, resultGPR,
+                MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
+    }
+    
+    jump(notTaken);
+}
+
+void SpeculativeJIT::compileIntegerCompare(Node& node, MacroAssembler::RelationalCondition condition)
+{
+    SpeculateIntegerOperand op1(this, node.child1());
+    SpeculateIntegerOperand op2(this, node.child2());
+    GPRTemporary result(this, op1, op2);
+    
+    m_jit.compare32(condition, 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, DataFormatJSBoolean);
+}
+
+void SpeculativeJIT::compileDoubleCompare(Node& node, MacroAssembler::DoubleCondition condition)
+{
+    SpeculateDoubleOperand op1(this, node.child1());
+    SpeculateDoubleOperand op2(this, node.child2());
+    GPRTemporary result(this);
+    
+    m_jit.move(TrustedImm32(ValueTrue), result.gpr());
+    MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
+    m_jit.xorPtr(TrustedImm32(true), result.gpr());
+    trueCase.link(&m_jit);
+    
+    jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+}
+
+void SpeculativeJIT::compileValueAdd(Node& node)
+{
+    JSValueOperand op1(this, node.child1());
+    JSValueOperand op2(this, node.child2());
+    
+    GPRReg op1GPR = op1.gpr();
+    GPRReg op2GPR = op2.gpr();
+    
+    flushRegisters();
+    
+    GPRResult result(this);
+    if (isKnownNotNumber(node.child1().index()) || isKnownNotNumber(node.child2().index()))
+        callOperation(operationValueAddNotNumber, result.gpr(), op1GPR, op2GPR);
+    else
+        callOperation(operationValueAdd, result.gpr(), op1GPR, op2GPR);
+    
+    jsValueResult(result.gpr(), m_compileIndex);
+}
+
+void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse, const ClassInfo* classInfo, bool needSpeculationCheck)
+{
+    JSValueOperand value(this, nodeUse);
+    GPRTemporary result(this);
+    GPRReg valueGPR = value.gpr();
+    GPRReg resultGPR = result.gpr();
+    
+    MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
+    if (needSpeculationCheck)
+        speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
+    m_jit.move(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
+    MacroAssembler::Jump done = m_jit.jump();
+    
+    notCell.link(&m_jit);
+    
+    if (needSpeculationCheck) {
+        m_jit.move(valueGPR, resultGPR);
+        m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
+        speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, m_jit.branchPtr(MacroAssembler::NotEqual, resultGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
+    }
+    m_jit.move(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
+    
+    done.link(&m_jit);
+    
+    jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
+}
+
+void SpeculativeJIT::compileLogicalNot(Node& node)
+{
+    if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
+        compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+        return;
+    }
+    if (at(node.child1()).shouldSpeculateArrayOrOther()) {
+        compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+        return;
+    }
+    if (at(node.child1()).shouldSpeculateInteger()) {
+        SpeculateIntegerOperand value(this, node.child1());
+        GPRTemporary result(this, value);
+        m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), result.gpr());
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+        return;
+    }
+    if (at(node.child1()).shouldSpeculateNumber()) {
+        SpeculateDoubleOperand value(this, node.child1());
+        FPRTemporary scratch(this);
+        GPRTemporary result(this);
+        m_jit.move(TrustedImm32(ValueFalse), result.gpr());
+        MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
+        m_jit.xor32(TrustedImm32(true), result.gpr());
+        nonZero.link(&m_jit);
+        jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+        return;
+    }
+    
+    PredictedType prediction = m_jit.getPrediction(node.child1());
+    if (isBooleanPrediction(prediction)) {
+        if (isBooleanPrediction(m_state.forNode(node.child1()).m_type)) {
+            SpeculateBooleanOperand value(this, node.child1());
+            GPRTemporary result(this, value);
+            
+            m_jit.move(value.gpr(), result.gpr());
+            m_jit.xorPtr(TrustedImm32(true), result.gpr());
+            
+            jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+            return;
+        }
+        
+        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(BadType, JSValueRegs(value.gpr()), node.child1(), 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, DataFormatJSBoolean);
+        return;
+    }
+    
+    JSValueOperand arg1(this, node.child1());
+    GPRTemporary result(this);
+    
+    GPRReg arg1GPR = arg1.gpr();
+    GPRReg resultGPR = result.gpr();
+    
+    arg1.use();
+    
+    m_jit.move(arg1GPR, resultGPR);
+    m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
+    JITCompiler::Jump fastCase = m_jit.branchTestPtr(JITCompiler::Zero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));
+    
+    silentSpillAllRegisters(resultGPR);
+    callOperation(dfgConvertJSValueToBoolean, resultGPR, arg1GPR);
+    silentFillAllRegisters(resultGPR);
+    
+    fastCase.link(&m_jit);
+    
+    m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
+    jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
+}
+
+void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck)
+{
+    JSValueOperand value(this, nodeUse);
+    GPRTemporary scratch(this);
+    GPRReg valueGPR = value.gpr();
+    GPRReg scratchGPR = scratch.gpr();
+    
+    MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
+    if (needSpeculationCheck)
+        speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
+    jump(taken, ForceJump);
+    
+    notCell.link(&m_jit);
+    
+    if (needSpeculationCheck) {
+        m_jit.move(valueGPR, scratchGPR);
+        m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
+        speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
+    }
+    jump(notTaken);
+    
+    noResult(m_compileIndex);
+}
+
+void SpeculativeJIT::emitBranch(Node& node)
+{
+    BlockIndex taken = node.takenBlockIndex();
+    BlockIndex notTaken = node.notTakenBlockIndex();
+    
+    if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
+        emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+    } else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
+        emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+    } else if (at(node.child1()).shouldSpeculateNumber()) {
+        if (at(node.child1()).shouldSpeculateInteger()) {
+            bool invert = false;
+            
+            if (taken == (m_block + 1)) {
+                invert = true;
+                BlockIndex tmp = taken;
+                taken = notTaken;
+                notTaken = tmp;
+            }
+
+            SpeculateIntegerOperand value(this, node.child1());
+            branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
+        } else {
+            SpeculateDoubleOperand value(this, node.child1());
+            FPRTemporary scratch(this);
+            branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
+        }
+        
+        jump(notTaken);
+        
+        noResult(m_compileIndex);
+    } else {
+        JSValueOperand value(this, node.child1());
+        GPRReg valueGPR = value.gpr();
+        
+        bool predictBoolean = isBooleanPrediction(m_jit.getPrediction(node.child1()));
+    
+        if (predictBoolean) {
+            if (isBooleanPrediction(m_state.forNode(node.child1()).m_type)) {
+                MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
+                
+                if (taken == (m_block + 1)) {
+                    condition = MacroAssembler::Zero;
+                    BlockIndex tmp = taken;
+                    taken = notTaken;
+                    notTaken = tmp;
+                }
+                
+                branchTest32(condition, valueGPR, TrustedImm32(true), taken);
+                jump(notTaken);
+            } else {
+                branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), notTaken);
+                branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), taken);
+                
+                speculationCheck(BadType, JSValueRegs(valueGPR), node.child1(), m_jit.jump());
+            }
+            value.use();
+        } else {
+            GPRTemporary result(this);
+            GPRReg resultGPR = result.gpr();
+        
+            branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(0))), notTaken);
+            branchPtr(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken);
+    
+            if (!predictBoolean) {
+                branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), notTaken);
+                branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), taken);
+            }
+    
+            value.use();
+    
+            silentSpillAllRegisters(resultGPR);
+            callOperation(dfgConvertJSValueToBoolean, resultGPR, valueGPR);
+            silentFillAllRegisters(resultGPR);
+    
+            branchTest32(MacroAssembler::NonZero, resultGPR, taken);
+            jump(notTaken);
+        }
+        
+        noResult(m_compileIndex, UseChildrenCalledExplicitly);
+    }
+}
+
+void SpeculativeJIT::compile(Node& node)
+{
+    NodeType op = node.op();
+
+    switch (op) {
+    case JSConstant:
+        initConstantInfo(m_compileIndex);
+        break;
+
+    case WeakJSConstant:
+        m_jit.addWeakReference(node.weakConstant());
+        initConstantInfo(m_compileIndex);
+        break;
+
+    case GetLocal: {
+        PredictedType prediction = node.variableAccessData()->prediction();
+        AbstractValue& value = block()->valuesAtHead.operand(node.local());
+
+        // If we have no prediction for this local, then don't attempt to compile.
+        if (prediction == PredictNone || value.isClear()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        if (!m_jit.graph().isCaptured(node.local())) {
+            if (node.variableAccessData()->shouldUseDoubleFormat()) {
+                FPRTemporary result(this);
+                m_jit.loadDouble(JITCompiler::addressFor(node.local()), result.fpr());
+                VirtualRegister virtualRegister = node.virtualRegister();
+                m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
+                m_generationInfo[virtualRegister].initDouble(m_compileIndex, node.refCount(), result.fpr());
+                break;
+            }
+            
+            if (isInt32Prediction(value.m_type)) {
+                GPRTemporary result(this);
+                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());
+                break;
+            }
+        }
+
+        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);
+
+        DataFormat format;
+        if (m_jit.graph().isCaptured(node.local()))
+            format = DataFormatJS;
+        else if (isCellPrediction(value.m_type))
+            format = DataFormatJSCell;
+        else if (isBooleanPrediction(value.m_type))
+            format = DataFormatJSBoolean;
+        else
+            format = DataFormatJS;
+
+        m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), format);
+        break;
+    }
+
+    case SetLocal: {
+        // SetLocal doubles as a hint as to where a node will be stored and
+        // as a speculation point. So before we speculate make sure that we
+        // know where the child of this node needs to go in the virtual
+        // register file.
+        compileMovHint(node);
+        
+        // As far as OSR is concerned, we're on the bytecode index corresponding
+        // to the *next* instruction, since we've already "executed" the
+        // SetLocal and whatever other DFG Nodes are associated with the same
+        // bytecode index as the SetLocal.
+        ASSERT(m_codeOriginForOSR == node.codeOrigin);
+        Node* nextNode = &at(block()->at(m_indexInBlock + 1));
+
+        // But even more oddly, we need to be super careful about the following
+        // sequence:
+        //
+        // a: Foo()
+        // b: SetLocal(@a)
+        // c: Flush(@b)
+        //
+        // This next piece of crazy takes care of this.
+        if (nextNode->op() == Flush && nextNode->child1() == m_compileIndex)
+            nextNode = &at(block()->at(m_indexInBlock + 2));
+        
+        // Oddly, it's possible for the bytecode index for the next node to be
+        // equal to ours. This will happen for op_post_inc. And, even more oddly,
+        // this is just fine. Ordinarily, this wouldn't be fine, since if the
+        // next node failed OSR then we'd be OSR-ing with this SetLocal's local
+        // variable already set even though from the standpoint of the old JIT,
+        // this SetLocal should not have executed. But for op_post_inc, it's just
+        // fine, because this SetLocal's local (i.e. the LHS in a x = y++
+        // statement) would be dead anyway - so the fact that DFG would have
+        // already made the assignment, and baked it into the register file during
+        // OSR exit, would not be visible to the old JIT in any way.
+        m_codeOriginForOSR = nextNode->codeOrigin;
+        
+        if (!m_jit.graph().isCaptured(node.local())) {
+            if (node.variableAccessData()->shouldUseDoubleFormat()) {
+                SpeculateDoubleOperand value(this, node.child1());
+                m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local()));
+                noResult(m_compileIndex);
+                // Indicate that it's no longer necessary to retrieve the value of
+                // this bytecode variable from registers or other locations in the register file,
+                // but that it is stored as a double.
+                valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile);
+                break;
+            }
+        
+            PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction();
+            if (isInt32Prediction(predictedType)) {
+                SpeculateIntegerOperand value(this, node.child1());
+                m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
+                noResult(m_compileIndex);
+                valueSourceReferenceForOperand(node.local()) = ValueSource(Int32InRegisterFile);
+                break;
+            }
+            if (isArrayPrediction(predictedType)) {
+                SpeculateCellOperand cell(this, node.child1());
+                GPRReg cellGPR = cell.gpr();
+                if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+                    speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+                m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
+                noResult(m_compileIndex);
+                valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile);
+                break;
+            }
+            if (isBooleanPrediction(predictedType)) {
+                SpeculateBooleanOperand boolean(this, node.child1());
+                m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local()));
+                noResult(m_compileIndex);
+                valueSourceReferenceForOperand(node.local()) = ValueSource(BooleanInRegisterFile);
+                break;
+            }
+        }
+        
+        JSValueOperand value(this, node.child1());
+        m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
+        noResult(m_compileIndex);
+
+        valueSourceReferenceForOperand(node.local()) = ValueSource(ValueInRegisterFile);
+        break;
+    }
+
+    case SetArgument:
+        // This is a no-op; it just marks the fact that the argument is being used.
+        // But it may be profitable to use this as a hook to run speculation checks
+        // on arguments, thereby allowing us to trivially eliminate such checks if
+        // the argument is not used.
+        break;
+
+    case BitAnd:
+    case BitOr:
+    case BitXor:
+        if (isInt32Constant(node.child1().index())) {
+            SpeculateIntegerOperand op2(this, node.child2());
+            GPRTemporary result(this, op2);
+
+            bitOp(op, valueOfInt32Constant(node.child1().index()), op2.gpr(), result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        } else if (isInt32Constant(node.child2().index())) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            GPRTemporary result(this, op1);
+
+            bitOp(op, valueOfInt32Constant(node.child2().index()), 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().index())) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            GPRTemporary result(this, op1);
+
+            shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2().index()) & 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: {
+        compileUInt32ToNumber(node);
+        break;
+    }
+
+    case DoubleAsInt32: {
+        compileDoubleAsInt32(node);
+        break;
+    }
+
+    case ValueToInt32: {
+        compileValueToInt32(node);
+        break;
+    }
+        
+    case Int32ToDouble: {
+        compileInt32ToDouble(node);
+        break;
+    }
+        
+    case CheckNumber: {
+        if (!isNumberPrediction(m_state.forNode(node.child1()).m_type)) {
+            JSValueOperand op1(this, node.child1());
+            JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, op1.gpr(), GPRInfo::tagTypeNumberRegister);
+            speculationCheck(
+                BadType, JSValueRegs(op1.gpr()), node.child1().index(),
+                m_jit.branchTestPtr(MacroAssembler::Zero, op1.gpr(), GPRInfo::tagTypeNumberRegister));
+            isInteger.link(&m_jit);
+        }
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case ValueAdd:
+    case ArithAdd:
+        compileAdd(node);
+        break;
+
+    case ArithSub:
+        compileArithSub(node);
+        break;
+
+    case ArithNegate:
+        compileArithNegate(node);
+        break;
+
+    case ArithMul:
+        compileArithMul(node);
+        break;
+
+    case ArithDiv: {
+        if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
+            compileIntegerArithDivForX86(node);
+            break;
+        }
+        
+        SpeculateDoubleOperand op1(this, node.child1());
+        SpeculateDoubleOperand 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: {
+        compileArithMod(node);
+        break;
+    }
+
+    case ArithAbs: {
+        if (at(node.child1()).shouldSpeculateInteger() && node.canSpeculateInteger()) {
+            SpeculateIntegerOperand op1(this, node.child1());
+            GPRTemporary result(this);
+            GPRTemporary scratch(this);
+            
+            m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
+            m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
+            m_jit.add32(scratch.gpr(), result.gpr());
+            m_jit.xor32(scratch.gpr(), result.gpr());
+            speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 << 31)));
+            integerResult(result.gpr(), m_compileIndex);
+            break;
+        }
+        
+        SpeculateDoubleOperand op1(this, node.child1());
+        FPRTemporary result(this);
+        
+        m_jit.absDouble(op1.fpr(), result.fpr());
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+        
+    case ArithMin:
+    case ArithMax: {
+        if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
+            SpeculateStrictInt32Operand op1(this, node.child1());
+            SpeculateStrictInt32Operand op2(this, node.child2());
+            GPRTemporary result(this, op1);
+            
+            MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
+            m_jit.move(op2.gpr(), result.gpr());
+            if (op1.gpr() != result.gpr()) {
+                MacroAssembler::Jump done = m_jit.jump();
+                op1Less.link(&m_jit);
+                m_jit.move(op1.gpr(), result.gpr());
+                done.link(&m_jit);
+            } else
+                op1Less.link(&m_jit);
+            
+            integerResult(result.gpr(), m_compileIndex);
+            break;
+        }
+        
+        SpeculateDoubleOperand op1(this, node.child1());
+        SpeculateDoubleOperand op2(this, node.child2());
+        FPRTemporary result(this, op1);
+        
+        MacroAssembler::JumpList done;
+        
+        MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr());
+        
+        // op2 is eather the lesser one or one of then is NaN
+        MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1.fpr(), op2.fpr());
+        
+        // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
+        // op1 + op2 and putting it into result.
+        m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr());
+        done.append(m_jit.jump());
+        
+        op2Less.link(&m_jit);
+        m_jit.moveDouble(op2.fpr(), result.fpr());
+        
+        if (op1.fpr() != result.fpr()) {
+            done.append(m_jit.jump());
+            
+            op1Less.link(&m_jit);
+            m_jit.moveDouble(op1.fpr(), result.fpr());
+        } else
+            op1Less.link(&m_jit);
+        
+        done.link(&m_jit);
+        
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+        
+    case ArithSqrt: {
+        SpeculateDoubleOperand op1(this, node.child1());
+        FPRTemporary result(this, op1);
+        
+        m_jit.sqrtDouble(op1.fpr(), result.fpr());
+        
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+
+    case LogicalNot:
+        compileLogicalNot(node);
+        break;
+
+    case CompareLess:
+        if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
+            return;
+        break;
+
+    case CompareLessEq:
+        if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
+            return;
+        break;
+
+    case CompareGreater:
+        if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
+            return;
+        break;
+
+    case CompareGreaterEq:
+        if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
+            return;
+        break;
+
+    case CompareEq:
+        if (isNullConstant(node.child1().index())) {
+            if (nonSpeculativeCompareNull(node, node.child2()))
+                return;
+            break;
+        }
+        if (isNullConstant(node.child2().index())) {
+            if (nonSpeculativeCompareNull(node, node.child1()))
+                return;
+            break;
+        }
+        if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
+            return;
+        break;
+
+    case CompareStrictEq:
+        if (compileStrictEq(node))
+            return;
+        break;
+
+    case StringCharCodeAt: {
+        compileGetCharCodeAt(node);
+        break;
+    }
+
+    case StringCharAt: {
+        // Relies on StringCharAt node having same basic layout as GetByVal
+        compileGetByValOnString(node);
+        break;
+    }
+
+    case GetByVal: {
+        if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArrayPrediction(at(node.child1()).prediction())) {
+            JSValueOperand base(this, node.child1());
+            JSValueOperand property(this, node.child2());
+            GPRReg baseGPR = base.gpr();
+            GPRReg propertyGPR = property.gpr();
+            
+            flushRegisters();
+            GPRResult result(this);
+            callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
+            
+            jsValueResult(result.gpr(), m_compileIndex);
+            break;
+        }
+        
+        if (at(node.child1()).prediction() == PredictString) {
+            compileGetByValOnString(node);
+            if (!m_compileOkay)
+                return;
+            break;
+        }
+
+        if (at(node.child1()).shouldSpeculateInt8Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt16Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt32Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+
+        if (at(node.child1()).shouldSpeculateUint8Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+
+        if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;
+        }
+
+        if (at(node.child1()).shouldSpeculateUint16Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint32Array()) {
+            compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        ASSERT(at(node.child1()).shouldSpeculateArray());
+
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateStrictInt32Operand property(this, node.child2());
+        StorageOperand storage(this, node.child3());
+
+        GPRReg baseReg = base.gpr();
+        GPRReg propertyReg = property.gpr();
+        GPRReg storageReg = storage.gpr();
+        
+        if (!m_compileOkay)
+            return;
+
+        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        speculationCheck(Uncountable, JSValueRegs(), NoNode, 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(this);
+        m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
+        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()));
+
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case PutByVal: {
+        if (!at(node.child1()).prediction() || !at(node.child2()).prediction()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        if (!at(node.child2()).shouldSpeculateInteger() || !isActionableMutableArrayPrediction(at(node.child1()).prediction())) {
+            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();
+            
+            callOperation(m_jit.strictModeFor(node.codeOrigin) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
+            
+            noResult(m_compileIndex);
+            break;
+        }
+
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateStrictInt32Operand property(this, node.child2());
+        if (at(node.child1()).shouldSpeculateInt8Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt16Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+
+        if (at(node.child1()).shouldSpeculateInt32Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint8Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+
+        if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray, ClampRounding);
+            break;
+        }
+
+        if (at(node.child1()).shouldSpeculateUint16Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint32Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+            
+        ASSERT(at(node.child1()).shouldSpeculateArray());
+
+        JSValueOperand value(this, node.child3());
+        GPRTemporary scratch(this);
+
+        // Map base, property & value into registers, allocate a scratch register.
+        GPRReg baseReg = base.gpr();
+        GPRReg propertyReg = property.gpr();
+        GPRReg valueReg = value.gpr();
+        GPRReg scratchReg = scratch.gpr();
+        
+        if (!m_compileOkay)
+            return;
+        
+        writeBarrier(baseReg, value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg);
+
+        // 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.
+        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+
+        base.use();
+        property.use();
+        value.use();
+        
+        MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
+
+        // Code to handle put beyond array bounds.
+        silentSpillAllRegisters(scratchReg);
+        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, baseReg, propertyReg, valueReg);
+        silentFillAllRegisters(scratchReg);
+        JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
+
+        withinArrayBounds.link(&m_jit);
+
+        // Get the array storage.
+        GPRReg storageReg = scratchReg;
+        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])));
+
+        wasBeyondArrayBounds.link(&m_jit);
+
+        noResult(m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+
+    case PutByValAlias: {
+        if (!at(node.child1()).prediction() || !at(node.child2()).prediction()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        ASSERT(isActionableMutableArrayPrediction(at(node.child1()).prediction()));
+        ASSERT(at(node.child2()).shouldSpeculateInteger());
+
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateStrictInt32Operand property(this, node.child2());
+        if (at(node.child1()).shouldSpeculateInt8Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), NoTypedArraySpecCheck, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt16Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), NoTypedArraySpecCheck, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateInt32Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), NoTypedArraySpecCheck, SignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint8Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+
+        if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray, ClampRounding);
+            if (!m_compileOkay)
+                return;
+            break;
+        }
+
+        if (at(node.child1()).shouldSpeculateUint16Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), NoTypedArraySpecCheck, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateUint32Array()) {
+            compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), NoTypedArraySpecCheck, UnsignedTypedArray);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), NoTypedArraySpecCheck);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), NoTypedArraySpecCheck);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        ASSERT(at(node.child1()).shouldSpeculateArray());
+
+        JSValueOperand value(this, node.child3());
+        GPRTemporary scratch(this);
+        
+        GPRReg baseReg = base.gpr();
+        GPRReg scratchReg = scratch.gpr();
+
+        writeBarrier(base.gpr(), value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg);
+
+        // Get the array storage.
+        GPRReg storageReg = scratchReg;
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
+
+        // Store the value to the array.
+        GPRReg propertyReg = property.gpr();
+        GPRReg valueReg = value.gpr();
+        m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case RegExpExec: {
+        if (compileRegExpExec(node))
+            return;
+        if (!node.adjustedRefCount()) {
+            SpeculateCellOperand base(this, node.child1());
+            SpeculateCellOperand argument(this, node.child2());
+            GPRReg baseGPR = base.gpr();
+            GPRReg argumentGPR = argument.gpr();
+            
+            flushRegisters();
+            GPRResult result(this);
+            callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
+            
+            // Must use jsValueResult because otherwise we screw up register
+            // allocation, which thinks that this node has a result.
+            jsValueResult(result.gpr(), m_compileIndex);
+            break;
+        }
+
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateCellOperand argument(this, node.child2());
+        GPRReg baseGPR = base.gpr();
+        GPRReg argumentGPR = argument.gpr();
+        
+        flushRegisters();
+        GPRResult result(this);
+        callOperation(operationRegExpExec, result.gpr(), baseGPR, argumentGPR);
+        
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case RegExpTest: {
+        SpeculateCellOperand base(this, node.child1());
+        SpeculateCellOperand argument(this, node.child2());
+        GPRReg baseGPR = base.gpr();
+        GPRReg argumentGPR = argument.gpr();
+        
+        flushRegisters();
+        GPRResult result(this);
+        callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
+        
+        // If we add a DataFormatBool, we should use it here.
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+        break;
+    }
+        
+    case ArrayPush: {
+        SpeculateCellOperand base(this, node.child1());
+        JSValueOperand value(this, node.child2());
+        GPRTemporary storage(this);
+        GPRTemporary storageLength(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg valueGPR = value.gpr();
+        GPRReg storageGPR = storage.gpr();
+        GPRReg storageLengthGPR = storageLength.gpr();
+        
+        writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
+
+        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        
+        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
+        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
+        
+        // Refuse to handle bizarre lengths.
+        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
+        
+        MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
+        
+        m_jit.storePtr(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+        
+        m_jit.add32(TrustedImm32(1), storageLengthGPR);
+        m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
+        m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+        m_jit.orPtr(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
+        
+        MacroAssembler::Jump done = m_jit.jump();
+        
+        slowPath.link(&m_jit);
+        
+        silentSpillAllRegisters(storageLengthGPR);
+        callOperation(operationArrayPush, storageLengthGPR, valueGPR, baseGPR);
+        silentFillAllRegisters(storageLengthGPR);
+        
+        done.link(&m_jit);
+        
+        jsValueResult(storageLengthGPR, m_compileIndex);
+        break;
+    }
+        
+    case ArrayPop: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary value(this);
+        GPRTemporary storage(this);
+        GPRTemporary storageLength(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg valueGPR = value.gpr();
+        GPRReg storageGPR = storage.gpr();
+        GPRReg storageLengthGPR = storageLength.gpr();
+        
+        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        
+        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
+        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
+        
+        MacroAssembler::Jump emptyArrayCase = m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
+        
+        m_jit.sub32(TrustedImm32(1), storageLengthGPR);
+        
+        MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
+        
+        m_jit.loadPtr(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), valueGPR);
+        
+        m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
+
+        MacroAssembler::Jump holeCase = m_jit.branchTestPtr(MacroAssembler::Zero, valueGPR);
+        
+        m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+        m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+        
+        MacroAssembler::JumpList done;
+        
+        done.append(m_jit.jump());
+        
+        holeCase.link(&m_jit);
+        emptyArrayCase.link(&m_jit);
+        m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsUndefined())), valueGPR);
+        done.append(m_jit.jump());
+        
+        slowCase.link(&m_jit);
+        
+        silentSpillAllRegisters(valueGPR);
+        callOperation(operationArrayPop, valueGPR, baseGPR);
+        silentFillAllRegisters(valueGPR);
+        
+        done.link(&m_jit);
+        
+        jsValueResult(valueGPR, m_compileIndex);
+        break;
+    }
+
+    case DFG::Jump: {
+        BlockIndex taken = node.takenBlockIndex();
+        jump(taken);
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case Branch:
+        if (isStrictInt32(node.child1().index()) || at(node.child1()).shouldSpeculateInteger()) {
+            SpeculateIntegerOperand op(this, node.child1());
+            
+            BlockIndex taken = node.takenBlockIndex();
+            BlockIndex notTaken = node.notTakenBlockIndex();
+            
+            MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
+            
+            if (taken == (m_block + 1)) {
+                condition = MacroAssembler::Zero;
+                BlockIndex tmp = taken;
+                taken = notTaken;
+                notTaken = tmp;
+            }
+            
+            branchTest32(condition, op.gpr(), taken);
+            jump(notTaken);
+            
+            noResult(m_compileIndex);
+            break;
+        }
+        emitBranch(node);
+        break;
+
+    case Return: {
+        ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
+        ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
+        ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
+
+#if DFG_ENABLE(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 Throw:
+    case ThrowReferenceError: {
+        // We expect that throw statements are rare and are intended to exit the code block
+        // anyway, so we just OSR back to the old JIT for now.
+        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
+        break;
+    }
+        
+    case ToPrimitive: {
+        if (at(node.child1()).shouldSpeculateInteger()) {
+            // It's really profitable to speculate integer, since it's really cheap,
+            // it means we don't have to do any real work, and we emit a lot less code.
+            
+            SpeculateIntegerOperand op1(this, node.child1());
+            GPRTemporary result(this, op1);
+            
+            m_jit.move(op1.gpr(), result.gpr());
+            if (op1.format() == DataFormatInteger)
+                m_jit.orPtr(GPRInfo::tagTypeNumberRegister, result.gpr());
+            
+            jsValueResult(result.gpr(), m_compileIndex);
+            break;
+        }
+        
+        // FIXME: Add string speculation here.
+        
+        JSValueOperand op1(this, node.child1());
+        GPRTemporary result(this, op1);
+        
+        GPRReg op1GPR = op1.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        op1.use();
+        
+        if (!(m_state.forNode(node.child1()).m_type & ~(PredictNumber | PredictBoolean)))
+            m_jit.move(op1GPR, resultGPR);
+        else {
+            MacroAssembler::JumpList alreadyPrimitive;
+            
+            alreadyPrimitive.append(m_jit.branchTestPtr(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister));
+            alreadyPrimitive.append(m_jit.branchPtr(MacroAssembler::Equal, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
+            
+            silentSpillAllRegisters(resultGPR);
+            callOperation(operationToPrimitive, resultGPR, op1GPR);
+            silentFillAllRegisters(resultGPR);
+            
+            MacroAssembler::Jump done = m_jit.jump();
+            
+            alreadyPrimitive.link(&m_jit);
+            m_jit.move(op1GPR, resultGPR);
+            
+            done.link(&m_jit);
+        }
+        
+        jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+        
+    case StrCat:
+    case NewArray: {
+        // We really don't want to grow the register file just to do a StrCat or NewArray.
+        // Say we have 50 functions on the stack that all have a StrCat in them that has
+        // upwards of 10 operands. In the DFG this would mean that each one gets
+        // some random virtual register, and then to do the StrCat we'd need a second
+        // span of 10 operands just to have somewhere to copy the 10 operands to, where
+        // they'd be contiguous and we could easily tell the C code how to find them.
+        // Ugly! So instead we use the scratchBuffer infrastructure in JSGlobalData. That
+        // way, those 50 functions will share the same scratchBuffer for offloading their
+        // StrCat operands. It's about as good as we can do, unless we start doing
+        // virtual register coalescing to ensure that operands to StrCat get spilled
+        // in exactly the place where StrCat wants them, or else have the StrCat
+        // refer to those operands' SetLocal instructions to force them to spill in
+        // the right place. Basically, any way you cut it, the current approach
+        // probably has the best balance of performance and sensibility in the sense
+        // that it does not increase the complexity of the DFG JIT just to make StrCat
+        // fast and pretty.
+
+        size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
+        ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
+        EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
+        
+        for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
+            JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
+            GPRReg opGPR = operand.gpr();
+            operand.use();
+            
+            m_jit.storePtr(opGPR, buffer + operandIdx);
+        }
+        
+        flushRegisters();
+
+        if (scratchSize) {
+            GPRTemporary scratch(this);
+
+            // Tell GC mark phase how much of the scratch buffer is active during call.
+            m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
+            m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
+        }
+
+        GPRResult result(this);
+        
+        callOperation(op == StrCat ? operationStrCat : operationNewArray, result.gpr(), static_cast<void *>(buffer), node.numChildren());
+
+        if (scratchSize) {
+            GPRTemporary scratch(this);
+
+            m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
+            m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
+        }
+
+        cellResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+        
+    case NewArrayBuffer: {
+        flushRegisters();
+        GPRResult result(this);
+        
+        callOperation(operationNewArrayBuffer, result.gpr(), node.startConstant(), node.numConstants());
+        
+        cellResult(result.gpr(), m_compileIndex);
+        break;
+    }
+        
+    case NewRegexp: {
+        flushRegisters();
+        GPRResult result(this);
+        
+        callOperation(operationNewRegexp, result.gpr(), m_jit.codeBlock()->regexp(node.regexpIndex()));
+        
+        cellResult(result.gpr(), m_compileIndex);
+        break;
+    }
+        
+    case ConvertThis: {
+        if (isObjectPrediction(m_state.forNode(node.child1()).m_type)) {
+            SpeculateCellOperand thisValue(this, node.child1());
+            GPRTemporary result(this, thisValue);
+            m_jit.move(thisValue.gpr(), result.gpr());
+            cellResult(result.gpr(), m_compileIndex);
+            break;
+        }
+        
+        if (isOtherPrediction(at(node.child1()).prediction())) {
+            JSValueOperand thisValue(this, node.child1());
+            GPRTemporary scratch(this, thisValue);
+            GPRReg thisValueGPR = thisValue.gpr();
+            GPRReg scratchGPR = scratch.gpr();
+            
+            if (!isOtherPrediction(m_state.forNode(node.child1()).m_type)) {
+                m_jit.move(thisValueGPR, scratchGPR);
+                m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
+                speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
+            }
+            
+            m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalThisObjectFor(node.codeOrigin)), scratchGPR);
+            cellResult(scratchGPR, m_compileIndex);
+            break;
+        }
+        
+        if (isObjectPrediction(at(node.child1()).prediction())) {
+            SpeculateCellOperand thisValue(this, node.child1());
+            GPRTemporary result(this, thisValue);
+            GPRReg thisValueGPR = thisValue.gpr();
+            GPRReg resultGPR = result.gpr();
+            
+            if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
+                speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info)));
+            
+            m_jit.move(thisValueGPR, resultGPR);
+            
+            cellResult(resultGPR, m_compileIndex);
+            break;
+        }
+        
+        JSValueOperand thisValue(this, node.child1());
+        GPRReg thisValueGPR = thisValue.gpr();
+        
+        flushRegisters();
+        
+        GPRResult result(this);
+        callOperation(operationConvertThis, result.gpr(), thisValueGPR);
+        
+        cellResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case CreateThis: {
+        // Note that there is not so much profit to speculate here. The only things we
+        // speculate on are (1) that it's a cell, since that eliminates cell checks
+        // later if the proto is reused, and (2) if we have a FinalObject prediction
+        // then we speculate because we want to get recompiled if it isn't (since
+        // otherwise we'd start taking slow path a lot).
+        
+        SpeculateCellOperand proto(this, node.child1());
+        GPRTemporary result(this);
+        GPRTemporary scratch(this);
+        
+        GPRReg protoGPR = proto.gpr();
+        GPRReg resultGPR = result.gpr();
+        GPRReg scratchGPR = scratch.gpr();
+        
+        proto.use();
+        
+        MacroAssembler::JumpList slowPath;
+        
+        // Need to verify that the prototype is an object. If we have reason to believe
+        // that it's a FinalObject then we speculate on that directly. Otherwise we
+        // do the slow (structure-based) check.
+        if (at(node.child1()).shouldSpeculateFinalObject()) {
+            if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
+                speculationCheck(BadType, JSValueRegs(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info)));
+        } else {
+            m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
+            slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
+        }
+        
+        // Load the inheritorID (the Structure that objects who have protoGPR as the prototype
+        // use to refer to that prototype). If the inheritorID is not set, go to slow path.
+        m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
+        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));
+        
+        emitAllocateJSFinalObject(scratchGPR, resultGPR, scratchGPR, slowPath);
+        
+        MacroAssembler::Jump done = m_jit.jump();
+        
+        slowPath.link(&m_jit);
+        
+        silentSpillAllRegisters(resultGPR);
+        if (node.codeOrigin.inlineCallFrame)
+            callOperation(operationCreateThisInlined, resultGPR, protoGPR, node.codeOrigin.inlineCallFrame->callee.get());
+        else
+            callOperation(operationCreateThis, resultGPR, protoGPR);
+        silentFillAllRegisters(resultGPR);
+        
+        done.link(&m_jit);
+        
+        cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+
+    case NewObject: {
+        GPRTemporary result(this);
+        GPRTemporary scratch(this);
+        
+        GPRReg resultGPR = result.gpr();
+        GPRReg scratchGPR = scratch.gpr();
+        
+        MacroAssembler::JumpList slowPath;
+        
+        emitAllocateJSFinalObject(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)->emptyObjectStructure()), resultGPR, scratchGPR, slowPath);
+        
+        MacroAssembler::Jump done = m_jit.jump();
+        
+        slowPath.link(&m_jit);
+        
+        silentSpillAllRegisters(resultGPR);
+        callOperation(operationNewObject, resultGPR);
+        silentFillAllRegisters(resultGPR);
+        
+        done.link(&m_jit);
+        
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
+
+    case GetCallee: {
+        GPRTemporary result(this);
+        m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::Callee)), result.gpr());
+        cellResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case GetScopeChain: {
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
+
+        m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::ScopeChain)), resultGPR);
+        bool checkTopLevel = m_jit.codeBlock()->codeType() == FunctionCode && m_jit.codeBlock()->needsFullScopeChain();
+        int skip = node.scopeChainDepth();
+        ASSERT(skip || !checkTopLevel);
+        if (checkTopLevel && skip--) {
+            JITCompiler::Jump activationNotCreated;
+            if (checkTopLevel)
+                activationNotCreated = m_jit.branchTestPtr(JITCompiler::Zero, JITCompiler::addressFor(static_cast<VirtualRegister>(m_jit.codeBlock()->activationRegister())));
+            m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
+            activationNotCreated.link(&m_jit);
+        }
+        while (skip--)
+            m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
+        
+        m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, object)), resultGPR);
+
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
+    case GetScopedVar: {
+        SpeculateCellOperand scopeChain(this, node.child1());
+        GPRTemporary result(this);
+        GPRReg resultGPR = result.gpr();
+        m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), resultGPR);
+        m_jit.loadPtr(JITCompiler::Address(resultGPR, node.varNumber() * sizeof(Register)), resultGPR);
+        jsValueResult(resultGPR, m_compileIndex);
+        break;
+    }
+    case PutScopedVar: {
+        SpeculateCellOperand scopeChain(this, node.child1());
+        GPRTemporary scratchRegister(this);
+        GPRReg scratchGPR = scratchRegister.gpr();
+        m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), scratchGPR);
+        JSValueOperand value(this, node.child2());
+        m_jit.storePtr(value.gpr(), JITCompiler::Address(scratchGPR, node.varNumber() * sizeof(Register)));
+        writeBarrier(scopeChain.gpr(), value.gpr(), node.child2(), WriteBarrierForVariableAccess, scratchGPR);
+        noResult(m_compileIndex);
+        break;
+    }
+    case GetById: {
+        if (!node.prediction()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        if (isCellPrediction(at(node.child1()).prediction())) {
+            SpeculateCellOperand base(this, node.child1());
+            GPRTemporary result(this, base);
+            
+            GPRReg baseGPR = base.gpr();
+            GPRReg resultGPR = result.gpr();
+            GPRReg scratchGPR;
+            
+            if (resultGPR == baseGPR)
+                scratchGPR = tryAllocate();
+            else
+                scratchGPR = resultGPR;
+            
+            base.use();
+            
+            cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber());
+            
+            jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+            break;
+        }
+        
+        JSValueOperand base(this, node.child1());
+        GPRTemporary result(this, base);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg resultGPR = result.gpr();
+        GPRReg scratchGPR;
+        
+        if (resultGPR == baseGPR)
+            scratchGPR = tryAllocate();
+        else
+            scratchGPR = resultGPR;
+        
+        base.use();
+        
+        JITCompiler::Jump notCell = m_jit.branchTestPtr(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
+        
+        cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber(), notCell);
+        
+        jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+        
+        break;
+    }
+
+    case GetByIdFlush: {
+        if (!node.prediction()) {
+            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+            break;
+        }
+        
+        if (isCellPrediction(at(node.child1()).prediction())) {
+            SpeculateCellOperand base(this, node.child1());
+            GPRReg baseGPR = base.gpr();
+
+            GPRResult result(this);
+            
+            GPRReg resultGPR = result.gpr();
+            
+            GPRReg scratchGPR = selectScratchGPR(baseGPR, resultGPR);
+            
+            base.use();
+            
+            flushRegisters();
+            
+            cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber(), JITCompiler::Jump(), DontSpill);
+            
+            jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+            break;
+        }
+        
+        JSValueOperand base(this, node.child1());
+        GPRReg baseGPR = base.gpr();
+
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+        
+        GPRReg scratchGPR = selectScratchGPR(baseGPR, resultGPR);
+        
+        base.use();
+        flushRegisters();
+        
+        JITCompiler::Jump notCell = m_jit.branchTestPtr(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
+        
+        cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber(), notCell, DontSpill);
+        
+        jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+        
+        break;
+    }
+
+    case GetArrayLength: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary result(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
+        
+        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
+        m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR);
+        
+        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultGPR, MacroAssembler::TrustedImm32(0)));
+        
+        integerResult(resultGPR, m_compileIndex);
+        break;
+    }
+
+    case GetStringLength: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary result(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
+            speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
+        
+        m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
+
+        integerResult(resultGPR, m_compileIndex);
+        break;
+    }
+
+    case GetInt8ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetInt16ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->int16ArrayDescriptor(), node, !isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetInt32ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->int32ArrayDescriptor(), node, !isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetUint8ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetUint8ClampedArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetUint16ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetUint32ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->uint32ArrayDescriptor(), node, !isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetFloat32ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->float32ArrayDescriptor(), node, !isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case GetFloat64ArrayLength: {
+        compileGetTypedArrayLength(m_jit.globalData()->float64ArrayDescriptor(), node, !isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type));
+        break;
+    }
+    case CheckFunction: {
+        SpeculateCellOperand function(this, node.child1());
+        speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, function.gpr(), node.function()));
+        noResult(m_compileIndex);
+        break;
+    }
+    case CheckStructure: {
+        if (m_state.forNode(node.child1()).m_structure.isSubsetOf(node.structureSet())) {
+            noResult(m_compileIndex);
+            break;
+        }
+        
+        SpeculateCellOperand base(this, node.child1());
+        
+        ASSERT(node.structureSet().size());
+        
+        if (node.structureSet().size() == 1)
+            speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(base.gpr(), JSCell::structureOffset()), node.structureSet()[0]));
+        else {
+            GPRTemporary structure(this);
+            
+            m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
+            
+            JITCompiler::JumpList done;
+            
+            for (size_t i = 0; i < node.structureSet().size() - 1; ++i)
+                done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node.structureSet()[i]));
+            
+            speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, structure.gpr(), node.structureSet().last()));
+            
+            done.link(&m_jit);
+        }
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case PutStructure: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRReg baseGPR = base.gpr();
+        
+        m_jit.addWeakReferenceTransition(
+            node.codeOrigin.codeOriginOwner(),
+            node.structureTransitionData().previousStructure,
+            node.structureTransitionData().newStructure);
+        
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        // Must always emit this write barrier as the structure transition itself requires it
+        writeBarrier(baseGPR, node.structureTransitionData().newStructure, WriteBarrierForGenericAccess);
+#endif
+        
+        m_jit.storePtr(MacroAssembler::TrustedImmPtr(node.structureTransitionData().newStructure), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case GetPropertyStorage: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary result(this, base);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
+        
+        storageResult(resultGPR, m_compileIndex);
+        break;
+    }
+
+    case GetIndexedPropertyStorage: {
+        compileGetIndexedPropertyStorage(node);
+        break;
+    }
+        
+    case GetByOffset: {
+        StorageOperand storage(this, node.child1());
+        GPRTemporary result(this, storage);
+        
+        GPRReg storageGPR = storage.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
+        
+        m_jit.loadPtr(JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue)), resultGPR);
+        
+        jsValueResult(resultGPR, m_compileIndex);
+        break;
+    }
+        
+    case PutByOffset: {
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        SpeculateCellOperand base(this, node.child1());
+#endif
+        StorageOperand storage(this, node.child2());
+        JSValueOperand value(this, node.child3());
+
+        GPRReg storageGPR = storage.gpr();
+        GPRReg valueGPR = value.gpr();
+        
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        writeBarrier(base.gpr(), value.gpr(), node.child3(), WriteBarrierForPropertyAccess);
+#endif
+
+        StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
+        
+        m_jit.storePtr(valueGPR, JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue)));
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case PutById: {
+        SpeculateCellOperand base(this, node.child1());
+        JSValueOperand value(this, node.child2());
+        GPRTemporary scratch(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg valueGPR = value.gpr();
+        GPRReg scratchGPR = scratch.gpr();
+        
+        base.use();
+        value.use();
+
+        cachedPutById(node.codeOrigin, baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), NotDirect);
+        
+        noResult(m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+
+    case PutByIdDirect: {
+        SpeculateCellOperand base(this, node.child1());
+        JSValueOperand value(this, node.child2());
+        GPRTemporary scratch(this);
+        
+        GPRReg baseGPR = base.gpr();
+        GPRReg valueGPR = value.gpr();
+        GPRReg scratchGPR = scratch.gpr();
+        
+        base.use();
+        value.use();
+
+        cachedPutById(node.codeOrigin, baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), Direct);
+
+        noResult(m_compileIndex, UseChildrenCalledExplicitly);
+        break;
+    }
+
+    case GetGlobalVar: {
+        GPRTemporary result(this);
+
+        JSVariableObject* globalObject = m_jit.globalObjectFor(node.codeOrigin);
+        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 globalObject(this);
+        GPRTemporary scratch(this);
+        
+        GPRReg globalObjectReg = globalObject.gpr();
+        GPRReg scratchReg = scratch.gpr();
+
+        m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectReg);
+
+        writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
+
+        m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
+        m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case CheckHasInstance: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRTemporary structure(this);
+
+        // Speculate that base 'ImplementsDefaultHasInstance'.
+        m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
+        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(structure.gpr(), Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case InstanceOf: {
+        compileInstanceOf(node);
+        break;
+    }
+        
+    case IsUndefined: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this);
+        
+        JITCompiler::Jump isCell = m_jit.branchTestPtr(JITCompiler::Zero, value.gpr(), GPRInfo::tagMaskRegister);
+        
+        m_jit.comparePtr(JITCompiler::Equal, value.gpr(), TrustedImm32(ValueUndefined), result.gpr());
+        JITCompiler::Jump done = m_jit.jump();
+        
+        isCell.link(&m_jit);
+        m_jit.loadPtr(JITCompiler::Address(value.gpr(), JSCell::structureOffset()), result.gpr());
+        m_jit.test8(JITCompiler::NonZero, JITCompiler::Address(result.gpr(), Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), result.gpr());
+        
+        done.link(&m_jit);
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+        break;
+    }
+        
+    case IsBoolean: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this, value);
+        
+        m_jit.move(value.gpr(), result.gpr());
+        m_jit.xorPtr(JITCompiler::TrustedImm32(ValueFalse), result.gpr());
+        m_jit.testPtr(JITCompiler::Zero, result.gpr(), JITCompiler::TrustedImm32(static_cast<int32_t>(~1)), result.gpr());
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+        break;
+    }
+        
+    case IsNumber: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this, value);
+        
+        m_jit.testPtr(JITCompiler::NonZero, value.gpr(), GPRInfo::tagTypeNumberRegister, result.gpr());
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+        break;
+    }
+        
+    case IsString: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this, value);
+        
+        JITCompiler::Jump isNotCell = m_jit.branchTestPtr(JITCompiler::NonZero, value.gpr(), GPRInfo::tagMaskRegister);
+        
+        m_jit.loadPtr(JITCompiler::Address(value.gpr(), JSCell::structureOffset()), result.gpr());
+        m_jit.compare8(JITCompiler::Equal, JITCompiler::Address(result.gpr(), Structure::typeInfoTypeOffset()), TrustedImm32(StringType), result.gpr());
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        JITCompiler::Jump done = m_jit.jump();
+        
+        isNotCell.link(&m_jit);
+        m_jit.move(TrustedImm32(ValueFalse), result.gpr());
+        
+        done.link(&m_jit);
+        jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+        break;
+    }
+        
+    case IsObject: {
+        JSValueOperand value(this, node.child1());
+        GPRReg valueGPR = value.gpr();
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+        flushRegisters();
+        callOperation(operationIsObject, resultGPR, valueGPR);
+        m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
+        jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+        break;
+    }
+
+    case IsFunction: {
+        JSValueOperand value(this, node.child1());
+        GPRReg valueGPR = value.gpr();
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+        flushRegisters();
+        callOperation(operationIsFunction, resultGPR, valueGPR);
+        m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
+        jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
+        break;
+    }
+
+    case Flush:
+    case Phi:
+        break;
+
+    case Breakpoint:
+#if ENABLE(DEBUG_WITH_BREAKPOINT)
+        m_jit.breakpoint();
+#else
+        ASSERT_NOT_REACHED();
+#endif
+        break;
+        
+    case Call:
+    case Construct:
+        emitCall(node);
+        break;
+
+    case Resolve: {
+        flushRegisters();
+        GPRResult result(this);
+        callOperation(operationResolve, result.gpr(), identifier(node.identifierNumber()));
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case ResolveBase: {
+        flushRegisters();
+        GPRResult result(this);
+        callOperation(operationResolveBase, result.gpr(), identifier(node.identifierNumber()));
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case ResolveBaseStrictPut: {
+        flushRegisters();
+        GPRResult result(this);
+        callOperation(operationResolveBaseStrictPut, result.gpr(), identifier(node.identifierNumber()));
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case ResolveGlobal: {
+        GPRTemporary globalObject(this);
+        GPRTemporary resolveInfo(this);
+        GPRTemporary result(this);
+
+        GPRReg globalObjectGPR = globalObject.gpr();
+        GPRReg resolveInfoGPR = resolveInfo.gpr();
+        GPRReg resultGPR = result.gpr();
+
+        ResolveGlobalData& data = m_jit.graph().m_resolveGlobalData[node.resolveGlobalDataIndex()];
+        GlobalResolveInfo* resolveInfoAddress = &(m_jit.codeBlock()->globalResolveInfo(data.resolveInfoIndex));
+
+        // Check Structure of global object
+        m_jit.move(JITCompiler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectGPR);
+        m_jit.move(JITCompiler::TrustedImmPtr(resolveInfoAddress), resolveInfoGPR);
+        m_jit.loadPtr(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, structure)), resultGPR);
+        JITCompiler::Jump structuresMatch = m_jit.branchPtr(JITCompiler::Equal, resultGPR, JITCompiler::Address(globalObjectGPR, JSCell::structureOffset()));
+
+        silentSpillAllRegisters(resultGPR);
+        callOperation(operationResolveGlobal, resultGPR, resolveInfoGPR, &m_jit.codeBlock()->identifier(data.identifierNumber));
+        silentFillAllRegisters(resultGPR);
+
+        JITCompiler::Jump wasSlow = m_jit.jump();
+
+        // Fast case
+        structuresMatch.link(&m_jit);
+        m_jit.loadPtr(JITCompiler::Address(globalObjectGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
+        m_jit.load32(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), resolveInfoGPR);
+        m_jit.loadPtr(JITCompiler::BaseIndex(resultGPR, resolveInfoGPR, JITCompiler::ScalePtr), resultGPR);
+
+        wasSlow.link(&m_jit);
+
+        jsValueResult(resultGPR, m_compileIndex);
+        break;
+    }
+        
+    case CreateActivation: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this, value);
+        
+        GPRReg valueGPR = value.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        m_jit.move(valueGPR, resultGPR);
+        
+        JITCompiler::Jump alreadyCreated = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR);
+        
+        silentSpillAllRegisters(resultGPR);
+        callOperation(operationCreateActivation, resultGPR);
+        silentFillAllRegisters(resultGPR);
+        
+        alreadyCreated.link(&m_jit);
+        
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
+        
+    case TearOffActivation: {
+        JSValueOperand value(this, node.child1());
+        GPRReg valueGPR = value.gpr();
+        
+        JITCompiler::Jump notCreated = m_jit.branchTestPtr(JITCompiler::Zero, valueGPR);
+        
+        silentSpillAllRegisters(InvalidGPRReg);
+        callOperation(operationTearOffActivation, valueGPR);
+        silentFillAllRegisters(InvalidGPRReg);
+        
+        notCreated.link(&m_jit);
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case NewFunctionNoCheck:
+        compileNewFunctionNoCheck(node);
+        break;
+        
+    case NewFunction: {
+        JSValueOperand value(this, node.child1());
+        GPRTemporary result(this, value);
+        
+        GPRReg valueGPR = value.gpr();
+        GPRReg resultGPR = result.gpr();
+        
+        m_jit.move(valueGPR, resultGPR);
+        
+        JITCompiler::Jump alreadyCreated = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR);
+        
+        silentSpillAllRegisters(resultGPR);
+        callOperation(
+            operationNewFunction, resultGPR, m_jit.codeBlock()->functionDecl(node.functionDeclIndex()));
+        silentFillAllRegisters(resultGPR);
+        
+        alreadyCreated.link(&m_jit);
+        
+        cellResult(resultGPR, m_compileIndex);
+        break;
+    }
+        
+    case NewFunctionExpression:
+        compileNewFunctionExpression(node);
+        break;
+
+    case ForceOSRExit: {
+        terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
+        break;
+    }
+
+    case Phantom:
+        // This is a no-op.
+        noResult(m_compileIndex);
+        break;
+        
+    case InlineStart:
+    case Nop:
+        ASSERT_NOT_REACHED();
+        break;
+        
+    case LastNodeType:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+
+    if (!m_compileOkay)
+        return;
+    
+    if (node.hasResult() && node.mustGenerate())
+        use(m_compileIndex);
+}
+
+#endif
+
+} } // namespace JSC::DFG
+
+#endif
diff --git a/dfg/DFGThunks.cpp b/dfg/DFGThunks.cpp
new file mode 100644 (file)
index 0000000..1ed46c1
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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 "DFGThunks.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGFPRInfo.h"
+#include "DFGGPRInfo.h"
+#include "DFGOSRExitCompiler.h"
+#include "MacroAssembler.h"
+
+namespace JSC { namespace DFG {
+
+MacroAssemblerCodeRef osrExitGenerationThunkGenerator(JSGlobalData* globalData)
+{
+    MacroAssembler jit;
+    
+    size_t scratchSize = sizeof(EncodedJSValue) * (GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters);
+    ScratchBuffer* scratchBuffer = globalData->scratchBufferForSize(scratchSize);
+    EncodedJSValue* buffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer());
+    
+    for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i)
+        jit.storePtr(GPRInfo::toRegister(i), buffer + i);
+    for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
+        jit.move(MacroAssembler::TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
+        jit.storeDouble(FPRInfo::toRegister(i), GPRInfo::regT0);
+    }
+    
+    // Tell GC mark phase how much of the scratch buffer is active during call.
+    jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->activeLengthPtr()), GPRInfo::regT0);
+    jit.storePtr(MacroAssembler::TrustedImmPtr(scratchSize), GPRInfo::regT0);
+
+    // Set up one argument.
+#if CPU(X86)
+    jit.poke(GPRInfo::callFrameRegister, 0);
+#else
+    jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+#endif
+
+    MacroAssembler::Call functionCall = jit.call();
+
+    jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->activeLengthPtr()), GPRInfo::regT0);
+    jit.storePtr(MacroAssembler::TrustedImmPtr(0), GPRInfo::regT0);
+
+    for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
+        jit.move(MacroAssembler::TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
+        jit.loadDouble(GPRInfo::regT0, FPRInfo::toRegister(i));
+    }
+    for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i)
+        jit.loadPtr(buffer + i, GPRInfo::toRegister(i));
+    
+    jit.jump(MacroAssembler::AbsoluteAddress(&globalData->osrExitJumpDestination));
+    
+    LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
+    
+    patchBuffer.link(functionCall, compileOSRExit);
+    
+    return patchBuffer.finalizeCode();
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
diff --git a/dfg/DFGThunks.h b/dfg/DFGThunks.h
new file mode 100644 (file)
index 0000000..3db6244
--- /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 DFGThunks_h
+#define DFGThunks_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "MacroAssemblerCodeRef.h"
+
+namespace JSC {
+
+class JSGlobalData;
+
+namespace DFG {
+
+MacroAssemblerCodeRef osrExitGenerationThunkGenerator(JSGlobalData*);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGThunks_h
diff --git a/dfg/DFGVariableAccessData.h b/dfg/DFGVariableAccessData.h
new file mode 100644 (file)
index 0000000..1d99ed5
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGVariableAccessData_h
+#define DFGVariableAccessData_h
+
+#include "DFGDoubleFormatState.h"
+#include "DFGNodeFlags.h"
+#include "Operands.h"
+#include "PredictedType.h"
+#include "VirtualRegister.h"
+#include <wtf/Platform.h>
+#include <wtf/UnionFind.h>
+#include <wtf/Vector.h>
+
+namespace JSC { namespace DFG {
+
+class VariableAccessData : public UnionFind<VariableAccessData> {
+public:
+    enum Ballot { VoteValue, VoteDouble };
+
+    VariableAccessData()
+        : m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min()))
+        , m_prediction(PredictNone)
+        , m_argumentAwarePrediction(PredictNone)
+        , m_flags(0)
+        , m_doubleFormatState(EmptyDoubleFormatState)
+    {
+        clearVotes();
+    }
+    
+    VariableAccessData(VirtualRegister local)
+        : m_local(local)
+        , m_prediction(PredictNone)
+        , m_argumentAwarePrediction(PredictNone)
+        , m_flags(0)
+        , m_doubleFormatState(EmptyDoubleFormatState)
+    {
+        clearVotes();
+    }
+    
+    VirtualRegister local()
+    {
+        ASSERT(m_local == find()->m_local);
+        return m_local;
+    }
+    
+    int operand()
+    {
+        return static_cast<int>(local());
+    }
+    
+    bool predict(PredictedType prediction)
+    {
+        VariableAccessData* self = find();
+        bool result = mergePrediction(self->m_prediction, prediction);
+        if (result)
+            mergePrediction(m_argumentAwarePrediction, m_prediction);
+        return result;
+    }
+    
+    PredictedType nonUnifiedPrediction()
+    {
+        return m_prediction;
+    }
+    
+    PredictedType prediction()
+    {
+        return find()->m_prediction;
+    }
+    
+    PredictedType argumentAwarePrediction()
+    {
+        return find()->m_argumentAwarePrediction;
+    }
+    
+    bool mergeArgumentAwarePrediction(PredictedType prediction)
+    {
+        return mergePrediction(find()->m_argumentAwarePrediction, prediction);
+    }
+    
+    void clearVotes()
+    {
+        ASSERT(find() == this);
+        m_votes[VoteValue] = 0;
+        m_votes[VoteDouble] = 0;
+    }
+    
+    void vote(Ballot ballot)
+    {
+        ASSERT(static_cast<unsigned>(ballot) < 2);
+        m_votes[ballot]++;
+    }
+    
+    double doubleVoteRatio()
+    {
+        ASSERT(find() == this);
+        return static_cast<double>(m_votes[VoteDouble]) / m_votes[VoteValue];
+    }
+    
+    bool shouldUseDoubleFormatAccordingToVote()
+    {
+        // We don't support this facility for arguments, yet.
+        // FIXME: make this work for arguments.
+        if (operandIsArgument(operand()))
+            return false;
+        
+        // If the variable is not a number prediction, then this doesn't
+        // make any sense.
+        if (!isNumberPrediction(prediction()))
+            return false;
+        
+        // If the variable is predicted to hold only doubles, then it's a
+        // no-brainer: it should be formatted as a double.
+        if (isDoublePrediction(prediction()))
+            return true;
+        
+        // If the variable is known to be used as an integer, then be safe -
+        // don't force it to be a double.
+        if (flags() & NodeUsedAsInt)
+            return false;
+        
+        // If the variable has been voted to become a double, then make it a
+        // double.
+        if (doubleVoteRatio() >= Options::doubleVoteRatioForDoubleFormat)
+            return true;
+        
+        return false;
+    }
+    
+    DoubleFormatState doubleFormatState()
+    {
+        return find()->m_doubleFormatState;
+    }
+    
+    bool shouldUseDoubleFormat()
+    {
+        ASSERT(isRoot());
+        return m_doubleFormatState == UsingDoubleFormat;
+    }
+    
+    bool tallyVotesForShouldUseDoubleFormat()
+    {
+        ASSERT(isRoot());
+        
+        if (m_doubleFormatState == CantUseDoubleFormat)
+            return false;
+        
+        bool newValueOfShouldUseDoubleFormat = shouldUseDoubleFormatAccordingToVote();
+        if (!newValueOfShouldUseDoubleFormat) {
+            // We monotonically convert to double. Hence, if the fixpoint leads us to conclude that we should
+            // switch back to int, we instead ignore this and stick with double.
+            return false;
+        }
+        
+        if (m_doubleFormatState == UsingDoubleFormat)
+            return false;
+        
+        return DFG::mergeDoubleFormatState(m_doubleFormatState, UsingDoubleFormat);
+    }
+    
+    bool mergeDoubleFormatState(DoubleFormatState doubleFormatState)
+    {
+        return DFG::mergeDoubleFormatState(find()->m_doubleFormatState, doubleFormatState);
+    }
+    
+    bool makePredictionForDoubleFormat()
+    {
+        ASSERT(isRoot());
+        
+        if (m_doubleFormatState != UsingDoubleFormat)
+            return false;
+        
+        return mergePrediction(m_prediction, PredictDouble);
+    }
+    
+    NodeFlags flags() const { return m_flags; }
+    
+    bool mergeFlags(NodeFlags newFlags)
+    {
+        newFlags |= m_flags;
+        if (newFlags == m_flags)
+            return false;
+        m_flags = newFlags;
+        return true;
+    }
+    
+private:
+    // This is slightly space-inefficient, since anything we're unified with
+    // will have the same operand and should have the same prediction. But
+    // putting them here simplifies the code, and we don't expect DFG space
+    // usage for variable access nodes do be significant.
+
+    VirtualRegister m_local;
+    PredictedType m_prediction;
+    PredictedType m_argumentAwarePrediction;
+    NodeFlags m_flags;
+    
+    float m_votes[2];
+    DoubleFormatState m_doubleFormatState;
+};
+
+} } // namespace JSC::DFG
+
+#endif // DFGVariableAccessData_h
diff --git a/dfg/DFGVirtualRegisterAllocationPhase.cpp b/dfg/DFGVirtualRegisterAllocationPhase.cpp
new file mode 100644 (file)
index 0000000..11ac695
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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 "DFGVirtualRegisterAllocationPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGGraph.h"
+#include "DFGScoreBoard.h"
+
+namespace JSC { namespace DFG {
+
+class VirtualRegisterAllocationPhase : public Phase {
+public:
+    VirtualRegisterAllocationPhase(Graph& graph)
+        : Phase(graph, "virtual register allocation")
+    {
+    }
+    
+    void run()
+    {
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Preserved vars: ");
+        m_graph.m_preservedVars.dump(WTF::dataFile());
+        dataLog("\n");
+#endif
+        ScoreBoard scoreBoard(m_graph, m_graph.m_preservedVars);
+        scoreBoard.assertClear();
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        bool needsNewLine = false;
+#endif
+        for (size_t blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
+            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+            for (size_t indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
+                NodeIndex nodeIndex = block->at(indexInBlock);
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                if (needsNewLine)
+                    dataLog("\n");
+                dataLog("   @%u:", nodeIndex);
+                needsNewLine = true;
+#endif
+                Node& node = m_graph[nodeIndex];
+        
+                if (!node.shouldGenerate() || node.op() == Phi || node.op() == Flush)
+                    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.
+                    if (node.flags() & NodeHasVarArgs) {
+                        for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
+                            scoreBoard.use(m_graph.m_varArgChildren[childIdx]);
+                    } else {
+                        scoreBoard.use(node.child1());
+                        scoreBoard.use(node.child2());
+                        scoreBoard.use(node.child3());
+                    }
+                }
+
+                if (!node.hasResult())
+                    continue;
+
+                VirtualRegister virtualRegister = scoreBoard.allocate();
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                dataLog(" Assigning virtual register %u to node %u.",
+                        virtualRegister, nodeIndex);
+#endif
+                node.setVirtualRegister(virtualRegister);
+                // 'mustGenerate' nodes have their useCount artificially elevated,
+                // call use now to account for this.
+                if (node.mustGenerate())
+                    scoreBoard.use(nodeIndex);
+            }
+            scoreBoard.assertClear();
+        }
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        if (needsNewLine)
+            dataLog("\n");
+#endif
+
+        // '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.highWatermark() + m_graph.m_parameterSlots;
+        size_t inlineCallFrameCount = codeBlock()->inlineCallFrames().size();
+        for (size_t i = 0; i < inlineCallFrameCount; i++) {
+            InlineCallFrame& inlineCallFrame = codeBlock()->inlineCallFrames()[i];
+            CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(&inlineCallFrame);
+            unsigned requiredCalleeRegisters = inlineCallFrame.stackOffset + codeBlock->m_numCalleeRegisters;
+            if (requiredCalleeRegisters > calleeRegisters)
+                calleeRegisters = requiredCalleeRegisters;
+        }
+        if ((unsigned)codeBlock()->m_numCalleeRegisters < calleeRegisters)
+            codeBlock()->m_numCalleeRegisters = calleeRegisters;
+#if DFG_ENABLE(DEBUG_VERBOSE)
+        dataLog("Num callee registers: %u\n", calleeRegisters);
+#endif
+    }
+};
+
+void performVirtualRegisterAllocation(Graph& graph)
+{
+    runPhase<VirtualRegisterAllocationPhase>(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
diff --git a/dfg/DFGVirtualRegisterAllocationPhase.h b/dfg/DFGVirtualRegisterAllocationPhase.h
new file mode 100644 (file)
index 0000000..abfa6ae
--- /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. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED 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 DFGVirtualRegisterAllocationPhase_h
+#define DFGVirtualRegisterAllocationPhase_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGPhase.h"
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// Prior to running this phase, we have no idea where in the call frame nodes
+// will have their values spilled. This phase fixes that by giving each node
+// a spill slot. The spill slot index (i.e. the virtual register) is also used
+// for look-up tables for the linear scan register allocator that the backend
+// uses.
+
+void performVirtualRegisterAllocation(Graph&);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGVirtualRegisterAllocationPhase_h
+
index a520344fbb51a54cdfa2cfada1dd7f933e530c9b..8a93f1d5332bf36d5567642a3adeff048a0edee1 100644 (file)
@@ -80,8 +80,7 @@
         ['exclude', '(?<!unicode)/icu/'],
         ['exclude', 'os-win32/'],
         ['exclude', 'qt/'],
         ['exclude', '(?<!unicode)/icu/'],
         ['exclude', 'os-win32/'],
         ['exclude', 'qt/'],
-        ['exclude', 'wtf/(android|brew|efl|gtk|haiku|qt|wince|wx)/'],
-        ['exclude', 'wtf/unicode/brew/'],
+        ['exclude', 'wtf/(efl|gtk|qt|wince|wx)/'],
         ['exclude', 'wtf/unicode/glib/'],
         ['exclude', 'wtf/unicode/qt4/'],
         ['exclude', 'wtf/unicode/wince/'],
         ['exclude', 'wtf/unicode/glib/'],
         ['exclude', 'wtf/unicode/qt4/'],
         ['exclude', 'wtf/unicode/wince/'],
diff --git a/headers.pri b/headers.pri
deleted file mode 100644 (file)
index 3fb886b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-JS_API_HEADERS += \
-    JSBase.h \
-    JSContextRef.h \
-    JSObjectRef.h \
-    JSStringRef.h \
-    JSStringRefCF.h \
-    JSStringRefBSTR.h \
-    JSValueRef.h \
-    JavaScriptCore.h
diff --git a/heap/BlockAllocator.cpp b/heap/BlockAllocator.cpp
new file mode 100644 (file)
index 0000000..a20ed3e
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 "BlockAllocator.h"
+
+#include "MarkedBlock.h"
+#include <wtf/CurrentTime.h>
+
+namespace JSC {
+
+BlockAllocator::BlockAllocator()
+    : m_numberOfFreeBlocks(0)
+    , m_isCurrentlyAllocating(false)
+    , m_blockFreeingThreadShouldQuit(false)
+    , m_blockFreeingThread(GCActivityCallback::s_shouldCreateGCTimer ?
+        createThread(blockFreeingThreadStartFunc, this, "JavaScriptCore::BlockFree") : 0)
+{
+    ASSERT(m_blockFreeingThread || !GCActivityCallback::s_shouldCreateGCTimer);
+}
+
+BlockAllocator::~BlockAllocator()
+{
+    releaseFreeBlocks();
+    {
+        MutexLocker locker(m_freeBlockLock);
+        m_blockFreeingThreadShouldQuit = true;
+        m_freeBlockCondition.broadcast();
+    }
+    if (GCActivityCallback::s_shouldCreateGCTimer)
+        waitForThreadCompletion(m_blockFreeingThread);
+}
+
+void BlockAllocator::releaseFreeBlocks()
+{
+    while (true) {
+        MarkedBlock* block;
+        {
+            MutexLocker locker(m_freeBlockLock);
+            if (!m_numberOfFreeBlocks)
+                block = 0;
+            else {
+                // FIXME: How do we know this is a MarkedBlock? It could be a CopiedBlock.
+                block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead());
+                ASSERT(block);
+                m_numberOfFreeBlocks--;
+            }
+        }
+        
+        if (!block)
+            break;
+        
+        MarkedBlock::destroy(block);
+    }
+}
+
+void BlockAllocator::waitForRelativeTimeWhileHoldingLock(double relative)
+{
+    if (m_blockFreeingThreadShouldQuit)
+        return;
+    m_freeBlockCondition.timedWait(m_freeBlockLock, currentTime() + relative);
+}
+
+void BlockAllocator::waitForRelativeTime(double relative)
+{
+    // If this returns early, that's fine, so long as it doesn't do it too
+    // frequently. It would only be a bug if this function failed to return
+    // when it was asked to do so.
+    
+    MutexLocker locker(m_freeBlockLock);
+    waitForRelativeTimeWhileHoldingLock(relative);
+}
+
+void BlockAllocator::blockFreeingThreadStartFunc(void* blockAllocator)
+{
+    static_cast<BlockAllocator*>(blockAllocator)->blockFreeingThreadMain();
+}
+
+void BlockAllocator::blockFreeingThreadMain()
+{
+    while (!m_blockFreeingThreadShouldQuit) {
+        // Generally wait for one second before scavenging free blocks. This
+        // may return early, particularly when we're being asked to quit.
+        waitForRelativeTime(1.0);
+        if (m_blockFreeingThreadShouldQuit)
+            break;
+        
+        if (m_isCurrentlyAllocating) {
+            m_isCurrentlyAllocating = false;
+            continue;
+        }
+
+        // Now process the list of free blocks. Keep freeing until half of the
+        // blocks that are currently on the list are gone. Assume that a size_t
+        // field can be accessed atomically.
+        size_t currentNumberOfFreeBlocks = m_numberOfFreeBlocks;
+        if (!currentNumberOfFreeBlocks)
+            continue;
+        
+        size_t desiredNumberOfFreeBlocks = currentNumberOfFreeBlocks / 2;
+        
+        while (!m_blockFreeingThreadShouldQuit) {
+            MarkedBlock* block;
+            {
+                MutexLocker locker(m_freeBlockLock);
+                if (m_numberOfFreeBlocks <= desiredNumberOfFreeBlocks)
+                    block = 0;
+                else {
+                    // FIXME: How do we know this is a MarkedBlock? It could be a CopiedBlock.
+                    block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead());
+                    ASSERT(block);
+                    m_numberOfFreeBlocks--;
+                }
+            }
+            
+            if (!block)
+                break;
+            
+            MarkedBlock::destroy(block);
+        }
+    }
+}
+
+} // namespace JSC
diff --git a/heap/BlockAllocator.h b/heap/BlockAllocator.h
new file mode 100644 (file)
index 0000000..2ae72ec
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 BlockAllocator_h
+#define BlockAllocator_h
+
+#include "GCActivityCallback.h"
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/Forward.h>
+#include <wtf/Threading.h>
+
+namespace JSC {
+
+class HeapBlock;
+
+// Simple allocator to reduce VM cost by holding onto blocks of memory for
+// short periods of time and then freeing them on a secondary thread.
+
+class BlockAllocator {
+public:
+    BlockAllocator();
+    ~BlockAllocator();
+
+    HeapBlock* allocate();
+    void deallocate(HeapBlock*);
+
+private:
+    void waitForRelativeTimeWhileHoldingLock(double relative);
+    void waitForRelativeTime(double relative);
+
+    void blockFreeingThreadMain();
+    static void blockFreeingThreadStartFunc(void* heap);
+
+    void releaseFreeBlocks();
+
+    DoublyLinkedList<HeapBlock> m_freeBlocks;
+    size_t m_numberOfFreeBlocks;
+    bool m_isCurrentlyAllocating;
+    bool m_blockFreeingThreadShouldQuit;
+    Mutex m_freeBlockLock;
+    ThreadCondition m_freeBlockCondition;
+    ThreadIdentifier m_blockFreeingThread;
+};
+
+inline HeapBlock* BlockAllocator::allocate()
+{
+    MutexLocker locker(m_freeBlockLock);
+    m_isCurrentlyAllocating = true;
+    if (!m_numberOfFreeBlocks) {
+        ASSERT(m_freeBlocks.isEmpty());
+        return 0;
+    }
+
+    ASSERT(!m_freeBlocks.isEmpty());
+    m_numberOfFreeBlocks--;
+    return m_freeBlocks.removeHead();
+}
+
+inline void BlockAllocator::deallocate(HeapBlock* block)
+{
+    {
+        MutexLocker locker(m_freeBlockLock);
+        m_freeBlocks.push(block);
+        m_numberOfFreeBlocks++;
+    }
+    if (!GCActivityCallback::s_shouldCreateGCTimer);
+        releaseFreeBlocks();
+}
+
+} // namespace JSC
+
+#endif // BlockAllocator_h
diff --git a/heap/CardSet.h b/heap/CardSet.h
new file mode 100644 (file)
index 0000000..dc44c02
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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 CardSet_h
+#define CardSet_h
+
+#include <stdint.h>
+#include <wtf/Assertions.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+template <size_t cardSize, size_t blockSize> class CardSet {
+    WTF_MAKE_NONCOPYABLE(CardSet);
+
+public:
+    static const size_t cardCount = (blockSize + cardSize - 1) / cardSize;
+
+    CardSet()
+    {
+        memset(m_cards, 0, cardCount);
+    }
+
+    bool isCardMarkedForAtom(const void*);
+    void markCardForAtom(const void*);
+    uint8_t& cardForAtom(const void*);
+    bool isCardMarked(size_t);
+    bool testAndClear(size_t);
+
+private:
+    uint8_t m_cards[cardCount];
+    COMPILE_ASSERT(!(cardSize & (cardSize - 1)), cardSet_cardSize_is_power_of_two);
+    COMPILE_ASSERT(!(cardCount & (cardCount - 1)), cardSet_cardCount_is_power_of_two);
+};
+
+template <size_t cardSize, size_t blockSize> uint8_t& CardSet<cardSize, blockSize>::cardForAtom(const void* ptr)
+{
+    ASSERT(ptr > this && ptr < (reinterpret_cast<char*>(this) + cardCount * cardSize));
+    uintptr_t card = (reinterpret_cast<uintptr_t>(ptr) / cardSize) % cardCount;
+    return m_cards[card];
+}
+
+template <size_t cardSize, size_t blockSize> bool CardSet<cardSize, blockSize>::isCardMarkedForAtom(const void* ptr)
+{
+    return cardForAtom(ptr);
+}
+
+template <size_t cardSize, size_t blockSize> void CardSet<cardSize, blockSize>::markCardForAtom(const void* ptr)
+{
+    cardForAtom(ptr) = 1;
+}
+
+template <size_t cardSize, size_t blockSize> bool CardSet<cardSize, blockSize>::isCardMarked(size_t i)
+{
+    ASSERT(i < cardCount);
+    return m_cards[i];
+}
+
+template <size_t cardSize, size_t blockSize> bool CardSet<cardSize, blockSize>::testAndClear(size_t i)
+{
+    ASSERT(i < cardCount);
+    bool result = m_cards[i];
+    m_cards[i] = 0;
+    return result;
+}
+
+}
+
+#endif
index 1aad7797cdc731af285c2c0d448219eed05c1e08..d63faebf36ca2ec348ec3fdaaa9c818a93f75bb7 100644 (file)
 #include "config.h"
 #include "ConservativeRoots.h"
 
 #include "config.h"
 #include "ConservativeRoots.h"
 
+#include "CopiedSpace.h"
+#include "CopiedSpaceInlineMethods.h"
+#include "CodeBlock.h"
+#include "DFGCodeBlocks.h"
+#include "JSCell.h"
+#include "JSObject.h"
+#include "Structure.h"
+
 namespace JSC {
 
 namespace JSC {
 
-inline bool isPointerAligned(void* p)
+ConservativeRoots::ConservativeRoots(const MarkedBlockSet* blocks, CopiedSpace* copiedSpace)
+    : m_roots(m_inlineRoots)
+    , m_size(0)
+    , m_capacity(inlineCapacity)
+    , m_blocks(blocks)
+    , m_copiedSpace(copiedSpace)
+{
+}
+
+ConservativeRoots::~ConservativeRoots()
 {
 {
-    return !((intptr_t)(p) & (sizeof(char*) - 1));
+    if (m_roots != m_inlineRoots)
+        OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*));
 }
 
 void ConservativeRoots::grow()
 }
 
 void ConservativeRoots::grow()
@@ -44,15 +62,63 @@ void ConservativeRoots::grow()
     m_roots = newRoots;
 }
 
     m_roots = newRoots;
 }
 
-void ConservativeRoots::add(void* begin, void* end)
+class DummyMarkHook {
+public:
+    void mark(void*) { }
+};
+
+template<typename MarkHook>
+inline void ConservativeRoots::genericAddPointer(void* p, TinyBloomFilter filter, MarkHook& markHook)
+{
+    markHook.mark(p);
+    
+    CopiedBlock* block;
+    if (m_copiedSpace->contains(p, block))
+        m_copiedSpace->pin(block);
+    
+    MarkedBlock* candidate = MarkedBlock::blockFor(p);
+    if (filter.ruleOut(reinterpret_cast<Bits>(candidate))) {
+        ASSERT(!candidate || !m_blocks->set().contains(candidate));
+        return;
+    }
+
+    if (!MarkedBlock::isAtomAligned(p))
+        return;
+
+    if (!m_blocks->set().contains(candidate))
+        return;
+
+    if (!candidate->isLiveCell(p))
+        return;
+
+    if (m_size == m_capacity)
+        grow();
+
+    m_roots[m_size++] = static_cast<JSCell*>(p);
+}
+
+template<typename MarkHook>
+void ConservativeRoots::genericAddSpan(void* begin, void* end, MarkHook& markHook)
 {
     ASSERT(begin <= end);
     ASSERT((static_cast<char*>(end) - static_cast<char*>(begin)) < 0x1000000);
     ASSERT(isPointerAligned(begin));
     ASSERT(isPointerAligned(end));
 
 {
     ASSERT(begin <= end);
     ASSERT((static_cast<char*>(end) - static_cast<char*>(begin)) < 0x1000000);
     ASSERT(isPointerAligned(begin));
     ASSERT(isPointerAligned(end));
 
+    TinyBloomFilter filter = m_blocks->filter(); // Make a local copy of filter to show the compiler it won't alias, and can be register-allocated.
     for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it)
     for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it)
-        add(*it);
+        genericAddPointer(*it, filter, markHook);
+}
+
+void ConservativeRoots::add(void* begin, void* end)
+{
+    DummyMarkHook hook;
+    genericAddSpan(begin, end, hook);
+}
+
+void ConservativeRoots::add(void* begin, void* end, DFGCodeBlocks& dfgCodeBlocks)
+{
+    genericAddSpan(begin, end, dfgCodeBlocks);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index d078606843132bec3203dd680bc57f32e608e38a..9d9e9ba0c518a47aa76ff84b9c9c19fbdddac32b 100644 (file)
 namespace JSC {
 
 class JSCell;
 namespace JSC {
 
 class JSCell;
+class DFGCodeBlocks;
 class Heap;
 
 class Heap;
 
-// May contain duplicates.
-
 class ConservativeRoots {
 public:
 class ConservativeRoots {
 public:
-    ConservativeRoots(Heap*);
+    ConservativeRoots(const MarkedBlockSet*, CopiedSpace*);
     ~ConservativeRoots();
 
     ~ConservativeRoots();
 
-    void add(void*);
     void add(void* begin, void* end);
     void add(void* begin, void* end);
+    void add(void* begin, void* end, DFGCodeBlocks&);
     
     size_t size();
     JSCell** roots();
     
     size_t size();
     JSCell** roots();
@@ -52,40 +51,22 @@ private:
     static const size_t inlineCapacity = 128;
     static const size_t nonInlineCapacity = 8192 / sizeof(JSCell*);
     
     static const size_t inlineCapacity = 128;
     static const size_t nonInlineCapacity = 8192 / sizeof(JSCell*);
     
+    template<typename MarkHook>
+    void genericAddPointer(void*, TinyBloomFilter, MarkHook&);
+
+    template<typename MarkHook>
+    void genericAddSpan(void*, void* end, MarkHook&);
+    
     void grow();
 
     void grow();
 
-    Heap* m_heap;
     JSCell** m_roots;
     size_t m_size;
     size_t m_capacity;
     JSCell** m_roots;
     size_t m_size;
     size_t m_capacity;
+    const MarkedBlockSet* m_blocks;
+    CopiedSpace* m_copiedSpace;
     JSCell* m_inlineRoots[inlineCapacity];
 };
 
     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 size_t ConservativeRoots::size()
 {
     return m_size;
diff --git a/heap/CopiedAllocator.h b/heap/CopiedAllocator.h
new file mode 100644 (file)
index 0000000..7455ec8
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * 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 CopiedAllocator_h
+#define CopiedAllocator_h
+
+#include "CopiedBlock.h"
+
+namespace JSC {
+
+class CopiedAllocator {
+    friend class JIT;
+public:
+    CopiedAllocator();
+    void* allocate(size_t);
+    bool fitsInCurrentBlock(size_t);
+    bool wasLastAllocation(void*, size_t);
+    void startedCopying();
+    void resetCurrentBlock(CopiedBlock*);
+    size_t currentCapacity();
+
+private:
+    CopiedBlock* currentBlock() { return m_currentBlock; }
+
+    char* m_currentOffset;
+    CopiedBlock* m_currentBlock; 
+};
+
+inline CopiedAllocator::CopiedAllocator()
+    : m_currentOffset(0)
+    , m_currentBlock(0)
+{
+}
+
+inline void* CopiedAllocator::allocate(size_t bytes)
+{
+    ASSERT(m_currentOffset);
+    ASSERT(is8ByteAligned(reinterpret_cast<void*>(bytes)));
+    ASSERT(fitsInCurrentBlock(bytes));
+    void* ptr = static_cast<void*>(m_currentOffset);
+    m_currentOffset += bytes;
+    ASSERT(is8ByteAligned(ptr));
+    return ptr;
+}
+
+inline bool CopiedAllocator::fitsInCurrentBlock(size_t bytes)
+{
+    return m_currentOffset + bytes < reinterpret_cast<char*>(m_currentBlock) + HeapBlock::s_blockSize && m_currentOffset + bytes > m_currentOffset;
+}
+
+inline bool CopiedAllocator::wasLastAllocation(void* ptr, size_t size)
+{
+    return static_cast<char*>(ptr) + size == m_currentOffset && ptr > m_currentBlock && ptr < reinterpret_cast<char*>(m_currentBlock) + HeapBlock::s_blockSize;
+}
+
+inline void CopiedAllocator::startedCopying()
+{
+    if (m_currentBlock)
+        m_currentBlock->m_offset = static_cast<void*>(m_currentOffset);
+    m_currentOffset = 0;
+    m_currentBlock = 0;
+}
+
+inline void CopiedAllocator::resetCurrentBlock(CopiedBlock* newBlock)
+{
+    if (m_currentBlock)
+        m_currentBlock->m_offset = static_cast<void*>(m_currentOffset);
+    m_currentBlock = newBlock;
+    m_currentOffset = static_cast<char*>(newBlock->m_offset);
+}
+
+inline size_t CopiedAllocator::currentCapacity()
+{
+    return m_currentBlock->capacity();
+}
+
+} // namespace JSC
+
+#endif
diff --git a/heap/CopiedBlock.h b/heap/CopiedBlock.h
new file mode 100644 (file)
index 0000000..431b86c
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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 CopiedBlock_h
+#define CopiedBlock_h
+
+#include "HeapBlock.h"
+#include "JSValue.h"
+#include "JSValueInlineMethods.h"
+
+namespace JSC {
+
+class CopiedSpace;
+
+class CopiedBlock : public HeapBlock {
+    friend class CopiedSpace;
+    friend class CopiedAllocator;
+public:
+    CopiedBlock(PageAllocationAligned& allocation)
+        : HeapBlock(allocation)
+        , m_offset(payload())
+        , m_isPinned(false)
+    {
+        ASSERT(is8ByteAligned(static_cast<void*>(m_offset)));
+#if USE(JSVALUE64)
+        char* offset = static_cast<char*>(m_offset);
+        memset(static_cast<void*>(offset), 0, static_cast<size_t>((reinterpret_cast<char*>(this) + allocation.size()) - offset));
+#else
+        JSValue emptyValue;
+        JSValue* limit = reinterpret_cast_ptr<JSValue*>(reinterpret_cast<char*>(this) + allocation.size());
+        for (JSValue* currentValue = reinterpret_cast<JSValue*>(m_offset); currentValue < limit; currentValue++)
+            *currentValue = emptyValue;
+#endif
+    }
+
+    char* payload();
+    size_t size();
+    size_t capacity();
+
+private:
+    void* m_offset;
+    uintptr_t m_isPinned;
+};
+
+inline char* CopiedBlock::payload()
+{
+    return reinterpret_cast<char*>(this) + ((sizeof(CopiedBlock) + 7) & ~7);
+}
+
+inline size_t CopiedBlock::size()
+{
+    return static_cast<size_t>(static_cast<char*>(m_offset) - payload());
+}
+
+inline size_t CopiedBlock::capacity()
+{
+    return m_allocation.size();
+}
+
+} // namespace JSC
+
+#endif
diff --git a/heap/CopiedSpace.cpp b/heap/CopiedSpace.cpp
new file mode 100644 (file)
index 0000000..94aa73e
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * 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 "CopiedSpace.h"
+
+#include "CopiedSpaceInlineMethods.h"
+#include "GCActivityCallback.h"
+
+namespace JSC {
+
+CopiedSpace::CopiedSpace(Heap* heap)
+    : m_heap(heap)
+    , m_toSpace(0)
+    , m_fromSpace(0)
+    , m_inCopyingPhase(false)
+    , m_numberOfLoanedBlocks(0)
+{
+}
+
+void CopiedSpace::init()
+{
+    m_toSpace = &m_blocks1;
+    m_fromSpace = &m_blocks2;
+    
+    if (!addNewBlock())
+        CRASH();
+}   
+
+CheckedBoolean CopiedSpace::tryAllocateSlowCase(size_t bytes, void** outPtr)
+{
+    if (isOversize(bytes))
+        return tryAllocateOversize(bytes, outPtr);
+    
+    ASSERT(m_heap->globalData()->apiLock().currentThreadIsHoldingLock());
+    m_heap->didAllocate(m_allocator.currentCapacity());
+
+    if (!addNewBlock()) {
+        *outPtr = 0;
+        return false;
+    }
+    *outPtr = m_allocator.allocate(bytes);
+    ASSERT(*outPtr);
+    return true;
+}
+
+CheckedBoolean CopiedSpace::tryAllocateOversize(size_t bytes, void** outPtr)
+{
+    ASSERT(isOversize(bytes));
+    
+    size_t blockSize = WTF::roundUpToMultipleOf(WTF::pageSize(), sizeof(CopiedBlock) + bytes);
+
+    PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, WTF::pageSize(), OSAllocator::JSGCHeapPages);
+    if (!static_cast<bool>(allocation)) {
+        *outPtr = 0;
+        return false;
+    }
+
+    CopiedBlock* block = new (NotNull, allocation.base()) CopiedBlock(allocation);
+    m_oversizeBlocks.push(block);
+    m_oversizeFilter.add(reinterpret_cast<Bits>(block));
+    
+    *outPtr = allocateFromBlock(block, bytes);
+
+    m_heap->didAllocate(blockSize);
+
+    return true;
+}
+
+CheckedBoolean CopiedSpace::tryReallocate(void** ptr, size_t oldSize, size_t newSize)
+{
+    if (oldSize >= newSize)
+        return true;
+    
+    void* oldPtr = *ptr;
+    ASSERT(!m_heap->globalData()->isInitializingObject());
+
+    if (isOversize(oldSize) || isOversize(newSize))
+        return tryReallocateOversize(ptr, oldSize, newSize);
+
+    if (m_allocator.wasLastAllocation(oldPtr, oldSize)) {
+        size_t delta = newSize - oldSize;
+        if (m_allocator.fitsInCurrentBlock(delta)) {
+            (void)m_allocator.allocate(delta);
+            return true;
+        }
+    }
+
+    void* result = 0;
+    if (!tryAllocate(newSize, &result)) {
+        *ptr = 0;
+        return false;
+    }
+    memcpy(result, oldPtr, oldSize);
+    *ptr = result;
+    return true;
+}
+
+CheckedBoolean CopiedSpace::tryReallocateOversize(void** ptr, size_t oldSize, size_t newSize)
+{
+    ASSERT(isOversize(oldSize) || isOversize(newSize));
+    ASSERT(newSize > oldSize);
+
+    void* oldPtr = *ptr;
+    
+    void* newPtr = 0;
+    if (!tryAllocateOversize(newSize, &newPtr)) {
+        *ptr = 0;
+        return false;
+    }
+
+    memcpy(newPtr, oldPtr, oldSize);
+
+    if (isOversize(oldSize)) {
+        CopiedBlock* oldBlock = oversizeBlockFor(oldPtr);
+        m_oversizeBlocks.remove(oldBlock);
+        oldBlock->m_allocation.deallocate();
+    }
+    
+    *ptr = newPtr;
+    return true;
+}
+
+void CopiedSpace::doneFillingBlock(CopiedBlock* block)
+{
+    ASSERT(block);
+    ASSERT(block->m_offset < reinterpret_cast<char*>(block) + HeapBlock::s_blockSize);
+    ASSERT(m_inCopyingPhase);
+
+    if (block->m_offset == block->payload()) {
+        recycleBlock(block);
+        return;
+    }
+
+    {
+        MutexLocker locker(m_toSpaceLock);
+        m_toSpace->push(block);
+        m_toSpaceSet.add(block);
+        m_toSpaceFilter.add(reinterpret_cast<Bits>(block));
+    }
+
+    {
+        MutexLocker locker(m_loanedBlocksLock);
+        ASSERT(m_numberOfLoanedBlocks > 0);
+        m_numberOfLoanedBlocks--;
+        if (!m_numberOfLoanedBlocks)
+            m_loanedBlocksCondition.signal();
+    }
+}
+
+void CopiedSpace::doneCopying()
+{
+    {
+        MutexLocker locker(m_loanedBlocksLock);
+        while (m_numberOfLoanedBlocks > 0)
+            m_loanedBlocksCondition.wait(m_loanedBlocksLock);
+    }
+
+    ASSERT(m_inCopyingPhase);
+    m_inCopyingPhase = false;
+    while (!m_fromSpace->isEmpty()) {
+        CopiedBlock* block = static_cast<CopiedBlock*>(m_fromSpace->removeHead());
+        if (block->m_isPinned) {
+            block->m_isPinned = false;
+            // We don't add the block to the toSpaceSet because it was never removed.
+            ASSERT(m_toSpaceSet.contains(block));
+            m_toSpaceFilter.add(reinterpret_cast<Bits>(block));
+            m_toSpace->push(block);
+            continue;
+        }
+
+        m_toSpaceSet.remove(block);
+        m_heap->blockAllocator().deallocate(block);
+    }
+
+    CopiedBlock* curr = static_cast<CopiedBlock*>(m_oversizeBlocks.head());
+    while (curr) {
+        CopiedBlock* next = static_cast<CopiedBlock*>(curr->next());
+        if (!curr->m_isPinned) {
+            m_oversizeBlocks.remove(curr);
+            curr->m_allocation.deallocate();
+        } else
+            curr->m_isPinned = false;
+        curr = next;
+    }
+
+    if (!m_toSpace->head()) {
+        if (!addNewBlock())
+            CRASH();
+    } else
+        m_allocator.resetCurrentBlock(static_cast<CopiedBlock*>(m_toSpace->head()));
+}
+
+CheckedBoolean CopiedSpace::getFreshBlock(AllocationEffort allocationEffort, CopiedBlock** outBlock)
+{
+    CopiedBlock* block = 0;
+    if (allocationEffort == AllocationMustSucceed) {
+        if (HeapBlock* heapBlock = m_heap->blockAllocator().allocate())
+            block = new (NotNull, heapBlock) CopiedBlock(heapBlock->m_allocation);
+        else if (!allocateNewBlock(&block)) {
+            *outBlock = 0;
+            ASSERT_NOT_REACHED();
+            return false;
+        }
+    } else {
+        ASSERT(allocationEffort == AllocationCanFail);
+        if (m_heap->shouldCollect())
+            m_heap->collect(Heap::DoNotSweep);
+        
+        if (!getFreshBlock(AllocationMustSucceed, &block)) {
+            *outBlock = 0;
+            ASSERT_NOT_REACHED();
+            return false;
+        }
+    }
+    ASSERT(block);
+    ASSERT(is8ByteAligned(block->m_offset));
+    *outBlock = block;
+    return true;
+}
+
+void CopiedSpace::freeAllBlocks()
+{
+    while (!m_toSpace->isEmpty())
+        m_heap->blockAllocator().deallocate(m_toSpace->removeHead());
+
+    while (!m_fromSpace->isEmpty())
+        m_heap->blockAllocator().deallocate(m_fromSpace->removeHead());
+
+    while (!m_oversizeBlocks.isEmpty())
+        m_oversizeBlocks.removeHead()->m_allocation.deallocate();
+}
+
+size_t CopiedSpace::size()
+{
+    size_t calculatedSize = 0;
+
+    for (CopiedBlock* block = static_cast<CopiedBlock*>(m_toSpace->head()); block; block = static_cast<CopiedBlock*>(block->next()))
+        calculatedSize += block->size();
+
+    for (CopiedBlock* block = static_cast<CopiedBlock*>(m_fromSpace->head()); block; block = static_cast<CopiedBlock*>(block->next()))
+        calculatedSize += block->size();
+
+    for (CopiedBlock* block = static_cast<CopiedBlock*>(m_oversizeBlocks.head()); block; block = static_cast<CopiedBlock*>(block->next()))
+        calculatedSize += block->size();
+
+    return calculatedSize;
+}
+
+size_t CopiedSpace::capacity()
+{
+    size_t calculatedCapacity = 0;
+
+    for (CopiedBlock* block = static_cast<CopiedBlock*>(m_toSpace->head()); block; block = static_cast<CopiedBlock*>(block->next()))
+        calculatedCapacity += block->capacity();
+
+    for (CopiedBlock* block = static_cast<CopiedBlock*>(m_fromSpace->head()); block; block = static_cast<CopiedBlock*>(block->next()))
+        calculatedCapacity += block->capacity();
+
+    for (CopiedBlock* block = static_cast<CopiedBlock*>(m_oversizeBlocks.head()); block; block = static_cast<CopiedBlock*>(block->next()))
+        calculatedCapacity += block->capacity();
+
+    return calculatedCapacity;
+}
+
+static bool isBlockListPagedOut(double deadline, DoublyLinkedList<HeapBlock>* list)
+{
+    unsigned itersSinceLastTimeCheck = 0;
+    HeapBlock* current = list->head();
+    while (current) {
+        current = current->next();
+        ++itersSinceLastTimeCheck;
+        if (itersSinceLastTimeCheck >= Heap::s_timeCheckResolution) {
+            double currentTime = WTF::monotonicallyIncreasingTime();
+            if (currentTime > deadline)
+                return true;
+            itersSinceLastTimeCheck = 0;
+        }
+    }
+
+    return false;
+}
+
+bool CopiedSpace::isPagedOut(double deadline)
+{
+    return isBlockListPagedOut(deadline, m_toSpace) 
+        || isBlockListPagedOut(deadline, m_fromSpace) 
+        || isBlockListPagedOut(deadline, &m_oversizeBlocks);
+}
+
+} // namespace JSC
diff --git a/heap/CopiedSpace.h b/heap/CopiedSpace.h
new file mode 100644 (file)
index 0000000..d3cc040
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * 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 CopiedSpace_h
+#define CopiedSpace_h
+
+#include "CopiedAllocator.h"
+#include "HeapBlock.h"
+#include "TinyBloomFilter.h"
+#include <wtf/Assertions.h>
+#include <wtf/CheckedBoolean.h>
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/HashSet.h>
+#include <wtf/OSAllocator.h>
+#include <wtf/PageAllocationAligned.h>
+#include <wtf/PageBlock.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/ThreadingPrimitives.h>
+
+namespace JSC {
+
+class Heap;
+class CopiedBlock;
+class HeapBlock;
+
+class CopiedSpace {
+    friend class SlotVisitor;
+    friend class JIT;
+public:
+    CopiedSpace(Heap*);
+    void init();
+
+    CheckedBoolean tryAllocate(size_t, void**);
+    CheckedBoolean tryReallocate(void**, size_t, size_t);
+    
+    CopiedAllocator& allocator() { return m_allocator; }
+
+    void startedCopying();
+    void doneCopying();
+    bool isInCopyPhase() { return m_inCopyingPhase; }
+
+    void pin(CopiedBlock*);
+    bool isPinned(void*);
+
+    bool contains(void*, CopiedBlock*&);
+
+    size_t size();
+    size_t capacity();
+
+    void freeAllBlocks();
+    bool isPagedOut(double deadline);
+
+    static CopiedBlock* blockFor(void*);
+
+private:
+    CheckedBoolean tryAllocateSlowCase(size_t, void**);
+    CheckedBoolean addNewBlock();
+    CheckedBoolean allocateNewBlock(CopiedBlock**);
+    
+    static void* allocateFromBlock(CopiedBlock*, size_t);
+    CheckedBoolean tryAllocateOversize(size_t, void**);
+    CheckedBoolean tryReallocateOversize(void**, size_t, size_t);
+    
+    static bool isOversize(size_t);
+    
+    CheckedBoolean borrowBlock(CopiedBlock**);
+    CheckedBoolean getFreshBlock(AllocationEffort, CopiedBlock**);
+    void doneFillingBlock(CopiedBlock*);
+    void recycleBlock(CopiedBlock*);
+    static bool fitsInBlock(CopiedBlock*, size_t);
+    static CopiedBlock* oversizeBlockFor(void* ptr);
+
+    Heap* m_heap;
+
+    CopiedAllocator m_allocator;
+
+    TinyBloomFilter m_toSpaceFilter;
+    TinyBloomFilter m_oversizeFilter;
+    HashSet<CopiedBlock*> m_toSpaceSet;
+
+    Mutex m_toSpaceLock;
+
+    DoublyLinkedList<HeapBlock>* m_toSpace;
+    DoublyLinkedList<HeapBlock>* m_fromSpace;
+    
+    DoublyLinkedList<HeapBlock> m_blocks1;
+    DoublyLinkedList<HeapBlock> m_blocks2;
+    DoublyLinkedList<HeapBlock> m_oversizeBlocks;
+   
+    bool m_inCopyingPhase;
+
+    Mutex m_loanedBlocksLock; 
+    ThreadCondition m_loanedBlocksCondition;
+    size_t m_numberOfLoanedBlocks;
+
+    static const size_t s_maxAllocationSize = 32 * KB;
+    static const size_t s_initialBlockNum = 16;
+    static const size_t s_blockMask = ~(HeapBlock::s_blockSize - 1);
+};
+
+} // namespace JSC
+
+#endif
diff --git a/heap/CopiedSpaceInlineMethods.h b/heap/CopiedSpaceInlineMethods.h
new file mode 100644 (file)
index 0000000..a8e4565
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * 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 CopiedSpaceInlineMethods_h
+#define CopiedSpaceInlineMethods_h
+
+#include "CopiedBlock.h"
+#include "CopiedSpace.h"
+#include "Heap.h"
+#include "HeapBlock.h"
+#include "JSGlobalData.h"
+#include <wtf/CheckedBoolean.h>
+
+namespace JSC {
+
+inline bool CopiedSpace::contains(void* ptr, CopiedBlock*& result)
+{
+    CopiedBlock* block = blockFor(ptr);
+    result = block;
+    return !m_toSpaceFilter.ruleOut(reinterpret_cast<Bits>(block)) && m_toSpaceSet.contains(block);
+}
+
+inline void CopiedSpace::pin(CopiedBlock* block)
+{
+    block->m_isPinned = true;
+}
+
+inline void CopiedSpace::startedCopying()
+{
+    DoublyLinkedList<HeapBlock>* temp = m_fromSpace;
+    m_fromSpace = m_toSpace;
+    m_toSpace = temp;
+
+    m_toSpaceFilter.reset();
+    m_allocator.startedCopying();
+
+    ASSERT(!m_inCopyingPhase);
+    ASSERT(!m_numberOfLoanedBlocks);
+    m_inCopyingPhase = true;
+}
+
+inline void CopiedSpace::recycleBlock(CopiedBlock* block)
+{
+    m_heap->blockAllocator().deallocate(block);
+
+    {
+        MutexLocker locker(m_loanedBlocksLock);
+        ASSERT(m_numberOfLoanedBlocks > 0);
+        m_numberOfLoanedBlocks--;
+        if (!m_numberOfLoanedBlocks)
+            m_loanedBlocksCondition.signal();
+    }
+}
+
+inline CheckedBoolean CopiedSpace::borrowBlock(CopiedBlock** outBlock)
+{
+    CopiedBlock* block = 0;
+    if (!getFreshBlock(AllocationMustSucceed, &block)) {
+        *outBlock = 0;
+        return false;
+    }
+
+    ASSERT(m_inCopyingPhase);
+    MutexLocker locker(m_loanedBlocksLock);
+    m_numberOfLoanedBlocks++;
+
+    ASSERT(block->m_offset == block->payload());
+    *outBlock = block;
+    return true;
+}
+
+inline CheckedBoolean CopiedSpace::addNewBlock()
+{
+    CopiedBlock* block = 0;
+    if (!getFreshBlock(AllocationCanFail, &block))
+        return false;
+        
+    m_toSpace->push(block);
+    m_toSpaceFilter.add(reinterpret_cast<Bits>(block));
+    m_toSpaceSet.add(block);
+    m_allocator.resetCurrentBlock(block);
+    return true;
+}
+
+inline CheckedBoolean CopiedSpace::allocateNewBlock(CopiedBlock** outBlock)
+{
+    PageAllocationAligned allocation = PageAllocationAligned::allocate(HeapBlock::s_blockSize, HeapBlock::s_blockSize, OSAllocator::JSGCHeapPages);
+    if (!static_cast<bool>(allocation)) {
+        *outBlock = 0;
+        return false;
+    }
+
+    *outBlock = new (NotNull, allocation.base()) CopiedBlock(allocation);
+    return true;
+}
+
+inline bool CopiedSpace::fitsInBlock(CopiedBlock* block, size_t bytes)
+{
+    return static_cast<char*>(block->m_offset) + bytes < reinterpret_cast<char*>(block) + block->capacity() && static_cast<char*>(block->m_offset) + bytes > block->m_offset;
+}
+
+inline CheckedBoolean CopiedSpace::tryAllocate(size_t bytes, void** outPtr)
+{
+    ASSERT(!m_heap->globalData()->isInitializingObject());
+
+    if (isOversize(bytes) || !m_allocator.fitsInCurrentBlock(bytes))
+        return tryAllocateSlowCase(bytes, outPtr);
+    
+    *outPtr = m_allocator.allocate(bytes);
+    ASSERT(*outPtr);
+    return true;
+}
+
+inline void* CopiedSpace::allocateFromBlock(CopiedBlock* block, size_t bytes)
+{
+    ASSERT(fitsInBlock(block, bytes));
+    ASSERT(is8ByteAligned(block->m_offset));
+    
+    void* ptr = block->m_offset;
+    ASSERT(block->m_offset >= block->payload() && block->m_offset < reinterpret_cast<char*>(block) + block->capacity());
+    block->m_offset = static_cast<void*>((static_cast<char*>(ptr) + bytes));
+    ASSERT(block->m_offset >= block->payload() && block->m_offset < reinterpret_cast<char*>(block) + block->capacity());
+
+    ASSERT(is8ByteAligned(ptr));
+    return ptr;
+}
+
+inline bool CopiedSpace::isOversize(size_t bytes)
+{
+    return bytes > s_maxAllocationSize;
+}
+
+inline bool CopiedSpace::isPinned(void* ptr)
+{
+    return blockFor(ptr)->m_isPinned;
+}
+
+inline CopiedBlock* CopiedSpace::oversizeBlockFor(void* ptr)
+{
+    return reinterpret_cast<CopiedBlock*>(reinterpret_cast<size_t>(ptr) & WTF::pageMask());
+}
+
+inline CopiedBlock* CopiedSpace::blockFor(void* ptr)
+{
+    return reinterpret_cast<CopiedBlock*>(reinterpret_cast<size_t>(ptr) & s_blockMask);
+}
+
+} // namespace JSC
+
+#endif
diff --git a/heap/DFGCodeBlocks.cpp b/heap/DFGCodeBlocks.cpp
new file mode 100644 (file)
index 0000000..f0d7c0c
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * 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 "DFGCodeBlocks.h"
+
+#include "CodeBlock.h"
+#include "SlotVisitor.h"
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+#if ENABLE(DFG_JIT)
+
+DFGCodeBlocks::DFGCodeBlocks() { }
+
+DFGCodeBlocks::~DFGCodeBlocks()
+{
+    Vector<CodeBlock*, 16> toRemove;
+    
+    for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) {
+        if ((*iter)->m_dfgData->isJettisoned)
+            toRemove.append(*iter);
+    }
+    
+    WTF::deleteAllValues(toRemove);
+}
+
+void DFGCodeBlocks::jettison(PassOwnPtr<CodeBlock> codeBlockPtr)
+{
+    // We don't want to delete it now; we just want its pointer.
+    CodeBlock* codeBlock = codeBlockPtr.leakPtr();
+    
+    ASSERT(codeBlock);
+    ASSERT(codeBlock->getJITType() == JITCode::DFGJIT);
+    
+    // It should not have already been jettisoned.
+    ASSERT(!codeBlock->m_dfgData->isJettisoned);
+
+    // We should have this block already.
+    ASSERT(m_set.find(codeBlock) != m_set.end());
+    
+    codeBlock->m_dfgData->isJettisoned = true;
+}
+
+void DFGCodeBlocks::clearMarks()
+{
+    for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) {
+        (*iter)->m_dfgData->mayBeExecuting = false;
+        (*iter)->m_dfgData->visitAggregateHasBeenCalled = false;
+    }
+}
+
+void DFGCodeBlocks::deleteUnmarkedJettisonedCodeBlocks()
+{
+    Vector<CodeBlock*, 16> toRemove;
+    
+    for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) {
+        if ((*iter)->m_dfgData->isJettisoned && !(*iter)->m_dfgData->mayBeExecuting)
+            toRemove.append(*iter);
+    }
+    
+    WTF::deleteAllValues(toRemove);
+}
+
+void DFGCodeBlocks::traceMarkedCodeBlocks(SlotVisitor& visitor)
+{
+    for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) {
+        if ((*iter)->m_dfgData->mayBeExecuting)
+            (*iter)->visitAggregate(visitor);
+    }
+}
+
+#else // ENABLE(DFG_JIT)
+
+void DFGCodeBlocks::jettison(PassOwnPtr<CodeBlock>)
+{
+}
+
+#endif // ENABLE(DFG_JIT)
+
+} // namespace JSC
+
+
diff --git a/heap/DFGCodeBlocks.h b/heap/DFGCodeBlocks.h
new file mode 100644 (file)
index 0000000..06fd5ed
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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 DFGCodeBlocks_h
+#define DFGCodeBlocks_h
+
+#include <wtf/FastAllocBase.h>
+#include <wtf/HashSet.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace JSC {
+
+class CodeBlock;
+class SlotVisitor;
+
+// DFGCodeBlocks notifies the garbage collector about optimized code blocks that
+// have different marking behavior depending on whether or not they are on the
+// stack, and that may be jettisoned. Jettisoning is the process of discarding
+// a code block after all calls to it have been unlinked. This class takes special
+// care to ensure that if there are still call frames that are using the code
+// block, then it should not be immediately deleted, but rather, it should be
+// deleted once we know that there are no longer any references to it from any
+// call frames. This class takes its name from the DFG compiler; only code blocks
+// compiled by the DFG need special marking behavior if they are on the stack, and
+// only those code blocks may be jettisoned.
+
+#if ENABLE(DFG_JIT)
+class DFGCodeBlocks {
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    DFGCodeBlocks();
+    ~DFGCodeBlocks();
+    
+    // Inform the collector that a code block has been jettisoned form its
+    // executable and should only be kept alive if there are call frames that use
+    // it. This is typically called either from a recompilation trigger, or from
+    // an unconditional finalizer associated with a CodeBlock that had weak
+    // references, where some subset of those references were dead.
+    void jettison(PassOwnPtr<CodeBlock>);
+    
+    // Clear all mark bits associated with DFG code blocks.
+    void clearMarks();
+    
+    // Mark a pointer that may be a CodeBlock that belongs to the set of DFG code
+    // blocks. This is defined inline in CodeBlock.h
+    void mark(void* candidateCodeBlock);
+    
+    // Delete all jettisoned code blocks that have not been marked (i.e. are not referenced
+    // from call frames).
+    void deleteUnmarkedJettisonedCodeBlocks();
+    
+    // Trace all marked code blocks (i.e. are referenced from call frames). The CodeBlock
+    // is free to make use of m_dfgData->isMarked and m_dfgData->isJettisoned.
+    void traceMarkedCodeBlocks(SlotVisitor&);
+
+private:
+    friend class CodeBlock;
+    
+    HashSet<CodeBlock*> m_set;
+};
+#else
+class DFGCodeBlocks {
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    void jettison(PassOwnPtr<CodeBlock>);
+    void clearMarks() { }
+    void mark(void*) { }
+    void deleteUnmarkedJettisonedCodeBlocks() { }
+    void traceMarkedCodeBlocks(SlotVisitor&) { }
+};
+#endif
+
+} // namespace JSC
+
+#endif
diff --git a/heap/GCAssertions.h b/heap/GCAssertions.h
new file mode 100644 (file)
index 0000000..9feefe1
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 GCAssertions_h
+#define GCAssertions_h
+
+#include <wtf/Assertions.h>
+
+#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
+
+#if COMPILER_SUPPORTS(HAS_TRIVIAL_DESTRUCTOR)
+#define ASSERT_HAS_TRIVIAL_DESTRUCTOR(klass) COMPILE_ASSERT(__has_trivial_destructor(klass), klass##_has_trivial_destructor_check)
+#else
+#define ASSERT_HAS_TRIVIAL_DESTRUCTOR(klass)
+#endif
+
+#endif // GCAssertions_h
index 8ed262312aabb3fc9f572c66cf8f22f88e06ac07..8bf2bd8963bc8bcc69364b9b5dcaeff731fda4e9 100644 (file)
@@ -48,7 +48,7 @@ template<typename KeyType, typename MappedType, typename FinalizerCallback, type
 
 class HandleBase {
     template <typename T> friend class Weak;
 
 class HandleBase {
     template <typename T> friend class Weak;
-    friend class HandleHeap;
+    friend class HandleSet;
     friend struct JSCallbackObjectData;
     template <typename KeyType, typename MappedType, typename FinalizerCallback, typename HashArg, typename KeyTraitsArg> friend class WeakGCMap;
 
     friend struct JSCallbackObjectData;
     template <typename KeyType, typename MappedType, typename FinalizerCallback, typename HashArg, typename KeyTraitsArg> friend class WeakGCMap;
 
@@ -59,6 +59,8 @@ public:
     typedef JSValue (HandleBase::*UnspecifiedBoolType);
     operator UnspecifiedBoolType*() const { return (m_slot && *m_slot) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
 
     typedef JSValue (HandleBase::*UnspecifiedBoolType);
     operator UnspecifiedBoolType*() const { return (m_slot && *m_slot) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
 
+    HandleSlot slot() const { return m_slot; }
+
 protected:
     HandleBase(HandleSlot slot)
         : m_slot(slot)
 protected:
     HandleBase(HandleSlot slot)
         : m_slot(slot)
@@ -67,7 +69,6 @@ protected:
     
     void swap(HandleBase& other) { std::swap(m_slot, other.m_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;
     void setSlot(HandleSlot slot)
     {
         m_slot = slot;
@@ -80,31 +81,19 @@ private:
 template <typename Base, typename T> struct HandleConverter {
     T* operator->()
     {
 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
     {
         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*()
     {
         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
     {
         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();
     }
 };
         return static_cast<const Base*>(this)->get();
     }
 };
@@ -119,9 +108,6 @@ template <typename Base> struct HandleConverter<Base, Unknown> {
 private:
     JSValue jsValue() const
     {
 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();
     }
 };
         return static_cast<const Base*>(this)->get();
     }
 };
@@ -147,7 +133,8 @@ protected:
     }
     
 private:
     }
     
 private:
-    friend class HandleHeap;
+    friend class HandleSet;
+    friend class WeakBlock;
 
     static Handle<T> wrapSlot(HandleSlot slot)
     {
 
     static Handle<T> wrapSlot(HandleSlot slot)
     {
diff --git a/heap/HandleHeap.cpp b/heap/HandleHeap.cpp
deleted file mode 100644 (file)
index 9b05db2..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 41b7fb2..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * 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/HandleSet.cpp b/heap/HandleSet.cpp
new file mode 100644 (file)
index 0000000..a6ccf29
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * 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 "HandleSet.h"
+
+#include "HeapRootVisitor.h"
+#include "JSObject.h"
+
+namespace JSC {
+
+HandleSet::HandleSet(JSGlobalData* globalData)
+    : m_globalData(globalData)
+    , m_nextToFinalize(0)
+{
+    grow();
+}
+
+void HandleSet::grow()
+{
+    Node* block = m_blockStack.grow();
+    for (int i = m_blockStack.blockLength - 1; i >= 0; --i) {
+        Node* node = &block[i];
+        new (NotNull, node) Node(this);
+        m_freeList.push(node);
+    }
+}
+
+void HandleSet::visitStrongHandles(HeapRootVisitor& heapRootVisitor)
+{
+    Node* end = m_strongList.end();
+    for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
+#if ENABLE(GC_VALIDATION)
+        if (!isLiveNode(node))
+            CRASH();
+#endif
+        heapRootVisitor.visit(node->slot());
+    }
+}
+
+void HandleSet::writeBarrier(HandleSlot slot, const JSValue& value)
+{
+    // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants.
+    // File a bug with stack trace if you hit this.
+    if (m_nextToFinalize)
+        CRASH();
+
+    if (!value == !*slot && slot->isCell() == value.isCell())
+        return;
+
+    Node* node = toNode(slot);
+#if ENABLE(GC_VALIDATION)
+    if (!isLiveNode(node))
+        CRASH();
+#endif
+    SentinelLinkedList<Node>::remove(node);
+    if (!value || !value.isCell()) {
+        m_immediateList.push(node);
+        return;
+    }
+
+    m_strongList.push(node);
+#if ENABLE(GC_VALIDATION)
+    if (!isLiveNode(node))
+        CRASH();
+#endif
+}
+
+unsigned HandleSet::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 ENABLE(GC_VALIDATION) || !ASSERT_DISABLED
+bool HandleSet::isLiveNode(Node* node)
+{
+    if (node->prev()->next() != node)
+        return false;
+    if (node->next()->prev() != node)
+        return false;
+        
+    return true;
+}
+#endif
+
+} // namespace JSC
diff --git a/heap/HandleSet.h b/heap/HandleSet.h
new file mode 100644 (file)
index 0000000..c22ffa4
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * 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 HandleSet_h
+#define HandleSet_h
+
+#include <wtf/BlockStack.h>
+#include "Handle.h"
+#include <wtf/HashCountedSet.h>
+#include <wtf/SentinelLinkedList.h>
+#include <wtf/SinglyLinkedList.h>
+
+namespace JSC {
+
+class HandleSet;
+class HeapRootVisitor;
+class JSGlobalData;
+class JSValue;
+class SlotVisitor;
+
+class HandleSet {
+public:
+    static HandleSet* heapFor(HandleSlot);
+
+    HandleSet(JSGlobalData*);
+    
+    JSGlobalData* globalData();
+
+    HandleSlot allocate();
+    void deallocate(HandleSlot);
+
+    void visitStrongHandles(HeapRootVisitor&);
+
+    JS_EXPORT_PRIVATE void writeBarrier(HandleSlot, const JSValue&);
+
+    unsigned protectedGlobalObjectCount();
+
+    template<typename Functor> void forEachStrongHandle(Functor&, const HashCountedSet<JSCell*>& skipSet);
+
+private:
+    class Node {
+    public:
+        Node(WTF::SentinelTag);
+        Node(HandleSet*);
+        
+        HandleSlot slot();
+        HandleSet* handleSet();
+
+        void setPrev(Node*);
+        Node* prev();
+
+        void setNext(Node*);
+        Node* next();
+
+    private:
+        JSValue m_value;
+        HandleSet* m_handleSet;
+        Node* m_prev;
+        Node* m_next;
+    };
+
+    static HandleSlot toHandle(Node*);
+    static Node* toNode(HandleSlot);
+
+    JS_EXPORT_PRIVATE void grow();
+    
+#if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED
+    bool isLiveNode(Node*);
+#endif
+
+    JSGlobalData* m_globalData;
+    BlockStack<Node> m_blockStack;
+
+    SentinelLinkedList<Node> m_strongList;
+    SentinelLinkedList<Node> m_immediateList;
+    SinglyLinkedList<Node> m_freeList;
+    Node* m_nextToFinalize;
+};
+
+inline HandleSet* HandleSet::heapFor(HandleSlot handle)
+{
+    return toNode(handle)->handleSet();
+}
+
+inline JSGlobalData* HandleSet::globalData()
+{
+    return m_globalData;
+}
+
+inline HandleSlot HandleSet::toHandle(Node* node)
+{
+    return reinterpret_cast<HandleSlot>(node);
+}
+
+inline HandleSet::Node* HandleSet::toNode(HandleSlot handle)
+{
+    return reinterpret_cast<Node*>(handle);
+}
+
+inline HandleSlot HandleSet::allocate()
+{
+    // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants.
+    // File a bug with stack trace if you hit this.
+    if (m_nextToFinalize)
+        CRASH();
+    if (m_freeList.isEmpty())
+        grow();
+
+    Node* node = m_freeList.pop();
+    new (NotNull, node) Node(this);
+    m_immediateList.push(node);
+    return toHandle(node);
+}
+
+inline void HandleSet::deallocate(HandleSlot handle)
+{
+    Node* node = toNode(handle);
+    if (node == m_nextToFinalize) {
+        ASSERT(m_nextToFinalize->next());
+        m_nextToFinalize = m_nextToFinalize->next();
+    }
+
+    SentinelLinkedList<Node>::remove(node);
+    m_freeList.push(node);
+}
+
+inline HandleSet::Node::Node(HandleSet* handleSet)
+    : m_handleSet(handleSet)
+    , m_prev(0)
+    , m_next(0)
+{
+}
+
+inline HandleSet::Node::Node(WTF::SentinelTag)
+    : m_handleSet(0)
+    , m_prev(0)
+    , m_next(0)
+{
+}
+
+inline HandleSlot HandleSet::Node::slot()
+{
+    return &m_value;
+}
+
+inline HandleSet* HandleSet::Node::handleSet()
+{
+    return m_handleSet;
+}
+
+inline void HandleSet::Node::setPrev(Node* prev)
+{
+    m_prev = prev;
+}
+
+inline HandleSet::Node* HandleSet::Node::prev()
+{
+    return m_prev;
+}
+
+inline void HandleSet::Node::setNext(Node* next)
+{
+    m_next = next;
+}
+
+inline HandleSet::Node* HandleSet::Node::next()
+{
+    return m_next;
+}
+
+template<typename Functor> void HandleSet::forEachStrongHandle(Functor& functor, const HashCountedSet<JSCell*>& skipSet)
+{
+    Node* end = m_strongList.end();
+    for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
+        JSValue value = *node->slot();
+        if (!value || !value.isCell())
+            continue;
+        if (skipSet.contains(value.asCell()))
+            continue;
+        functor(value.asCell());
+    }
+}
+
+}
+
+#endif
index ada4f9927831730cee57900991364b3f76ba6d89..42eb326a5950e3e246609276fe74f29a962ec919 100644 (file)
  */
 
 #include "config.h"
  */
 
 #include "config.h"
-
 #include "HandleStack.h"
 
 #include "HandleStack.h"
 
-#include "MarkStack.h"
+#include "HeapRootVisitor.h"
+#include "JSValueInlineMethods.h"
+#include "JSObject.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -39,7 +40,7 @@ HandleStack::HandleStack()
     grow();
 }
 
     grow();
 }
 
-void HandleStack::mark(HeapRootVisitor& heapRootMarker)
+void HandleStack::visit(HeapRootVisitor& heapRootVisitor)
 {
     const Vector<HandleSlot>& blocks = m_blockStack.blocks();
     size_t blockLength = m_blockStack.blockLength;
 {
     const Vector<HandleSlot>& blocks = m_blockStack.blocks();
     size_t blockLength = m_blockStack.blockLength;
@@ -47,10 +48,10 @@ void HandleStack::mark(HeapRootVisitor& heapRootMarker)
     int end = blocks.size() - 1;
     for (int i = 0; i < end; ++i) {
         HandleSlot block = blocks[i];
     int end = blocks.size() - 1;
     for (int i = 0; i < end; ++i) {
         HandleSlot block = blocks[i];
-        heapRootMarker.mark(block, blockLength);
+        heapRootVisitor.visit(block, blockLength);
     }
     HandleSlot block = blocks[end];
     }
     HandleSlot block = blocks[end];
-    heapRootMarker.mark(block, m_frame.m_next - block);
+    heapRootVisitor.visit(block, m_frame.m_next - block);
 }
 
 void HandleStack::grow()
 }
 
 void HandleStack::grow()
index 115784a87b3f3a5871d59f3b4d422fc9d3c0331d..858ebf23fc4a6ae71fc1d5462351f1c3f8d8e200 100644 (file)
@@ -26,8 +26,8 @@
 #ifndef HandleStack_h
 #define HandleStack_h
 
 #ifndef HandleStack_h
 #define HandleStack_h
 
-#include "Assertions.h"
-#include "BlockStack.h"
+#include <wtf/Assertions.h>
+#include <wtf/BlockStack.h>
 #include "Handle.h"
 
 #include <wtf/UnusedParam.h>
 #include "Handle.h"
 
 #include <wtf/UnusedParam.h>
@@ -52,7 +52,7 @@ public:
 
     HandleSlot push();
 
 
     HandleSlot push();
 
-    void mark(HeapRootVisitor&);
+    void visit(HeapRootVisitor&);
 
 private:
     void grow();
 
 private:
     void grow();
index 780ab85cdd5422aa3769b5aa3a412907f6e8e370..bdfbcfda312949c3dfe55dde91474cc7a92e88f3 100644 (file)
@@ -35,7 +35,7 @@ typedef JSValue* HandleSlot;
 
 template<typename T> struct HandleTypes {
     typedef T* ExternalType;
 
 template<typename T> struct HandleTypes {
     typedef T* ExternalType;
-    static ExternalType getFromSlot(HandleSlot slot) { return (slot && *slot) ? reinterpret_cast<ExternalType>(slot->asCell()) : 0; }
+    static ExternalType getFromSlot(HandleSlot slot) { return (slot && *slot) ? reinterpret_cast<ExternalType>(static_cast<void*>(slot->asCell())) : 0; }
     static JSValue toJSValue(T* cell) { return reinterpret_cast<JSCell*>(cell); }
     template<typename U> static void validateUpcast() { T* temp; temp = (U*)0; }
 };
     static JSValue toJSValue(T* cell) { return reinterpret_cast<JSCell*>(cell); }
     template<typename U> static void validateUpcast() { T* temp; temp = (U*)0; }
 };
index e93bfb44fa971aa389503bad691bdd9163647f4f..e967edc974656a6f5688eebb2c4f2bb30829755a 100644 (file)
 #include "config.h"
 #include "Heap.h"
 
 #include "config.h"
 #include "Heap.h"
 
+#include "CopiedSpace.h"
+#include "CopiedSpaceInlineMethods.h"
 #include "CodeBlock.h"
 #include "ConservativeRoots.h"
 #include "GCActivityCallback.h"
 #include "CodeBlock.h"
 #include "ConservativeRoots.h"
 #include "GCActivityCallback.h"
+#include "HeapRootVisitor.h"
 #include "Interpreter.h"
 #include "JSGlobalData.h"
 #include "JSGlobalObject.h"
 #include "JSLock.h"
 #include "JSONObject.h"
 #include "Tracing.h"
 #include "Interpreter.h"
 #include "JSGlobalData.h"
 #include "JSGlobalObject.h"
 #include "JSLock.h"
 #include "JSONObject.h"
 #include "Tracing.h"
+#include "WeakSetInlines.h"
 #include <algorithm>
 #include <algorithm>
+#include <wtf/CurrentTime.h>
 
 
-#define COLLECT_ON_EVERY_SLOW_ALLOCATION 0
 
 using namespace std;
 
 using namespace std;
+using namespace JSC;
 
 namespace JSC {
 
 
 namespace JSC {
 
-const size_t minBytesPerCycle = 512 * 1024;
+namespace { 
 
 
-Heap::Heap(JSGlobalData* globalData)
-    : m_operationInProgress(NoOperation)
-    , m_markedSpace(globalData)
+#if CPU(X86) || CPU(X86_64)
+static const size_t largeHeapSize = 16 * 1024 * 1024;
+#else
+static const size_t largeHeapSize = 8 * 1024 * 1024;
+#endif
+static const size_t smallHeapSize = 512 * 1024;
+
+#if ENABLE(GC_LOGGING)
+#if COMPILER(CLANG)
+#define DEFINE_GC_LOGGING_GLOBAL(type, name, arguments) \
+_Pragma("clang diagnostic push") \
+_Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \
+_Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \
+static type name arguments; \
+_Pragma("clang diagnostic pop")
+#else
+#define DEFINE_GC_LOGGING_GLOBAL(type, name, arguments) \
+static type name arguments;
+#endif // COMPILER(CLANG)
+
+struct GCTimer {
+    GCTimer(const char* name)
+        : m_time(0)
+        , m_min(100000000)
+        , m_max(0)
+        , m_count(0)
+        , m_name(name)
+    {
+    }
+    ~GCTimer()
+    {
+        dataLog("%s: %.2lfms (avg. %.2lf, min. %.2lf, max. %.2lf)\n", m_name, m_time * 1000, m_time * 1000 / m_count, m_min*1000, m_max*1000);
+    }
+    double m_time;
+    double m_min;
+    double m_max;
+    size_t m_count;
+    const char* m_name;
+};
+
+struct GCTimerScope {
+    GCTimerScope(GCTimer* timer)
+        : m_timer(timer)
+        , m_start(WTF::currentTime())
+    {
+    }
+    ~GCTimerScope()
+    {
+        double delta = WTF::currentTime() - m_start;
+        if (delta < m_timer->m_min)
+            m_timer->m_min = delta;
+        if (delta > m_timer->m_max)
+            m_timer->m_max = delta;
+        m_timer->m_count++;
+        m_timer->m_time += delta;
+    }
+    GCTimer* m_timer;
+    double m_start;
+};
+
+struct GCCounter {
+    GCCounter(const char* name)
+        : m_name(name)
+        , m_count(0)
+        , m_total(0)
+        , m_min(10000000)
+        , m_max(0)
+    {
+    }
+    
+    void count(size_t amount)
+    {
+        m_count++;
+        m_total += amount;
+        if (amount < m_min)
+            m_min = amount;
+        if (amount > m_max)
+            m_max = amount;
+    }
+    ~GCCounter()
+    {
+        dataLog("%s: %zu values (avg. %zu, min. %zu, max. %zu)\n", m_name, m_total, m_total / m_count, m_min, m_max);
+    }
+    const char* m_name;
+    size_t m_count;
+    size_t m_total;
+    size_t m_min;
+    size_t m_max;
+};
+
+#define GCPHASE(name) DEFINE_GC_LOGGING_GLOBAL(GCTimer, name##Timer, (#name)); GCTimerScope name##TimerScope(&name##Timer)
+#define COND_GCPHASE(cond, name1, name2) DEFINE_GC_LOGGING_GLOBAL(GCTimer, name1##Timer, (#name1)); DEFINE_GC_LOGGING_GLOBAL(GCTimer, name2##Timer, (#name2)); GCTimerScope name1##CondTimerScope(cond ? &name1##Timer : &name2##Timer)
+#define GCCOUNTER(name, value) do { DEFINE_GC_LOGGING_GLOBAL(GCCounter, name##Counter, (#name)); name##Counter.count(value); } while (false)
+    
+#else
+
+#define GCPHASE(name) do { } while (false)
+#define COND_GCPHASE(cond, name1, name2) do { } while (false)
+#define GCCOUNTER(name, value) do { } while (false)
+#endif
+
+static size_t heapSizeForHint(HeapSize heapSize)
+{
+    if (heapSize == LargeHeap)
+        return largeHeapSize;
+    ASSERT(heapSize == SmallHeap);
+    return smallHeapSize;
+}
+
+static inline bool isValidSharedInstanceThreadState(JSGlobalData* globalData)
+{
+    return globalData->apiLock().currentThreadIsHoldingLock();
+}
+
+static inline bool isValidThreadState(JSGlobalData* globalData)
+{
+    if (globalData->identifierTable != wtfThreadData().currentIdentifierTable())
+        return false;
+
+    if (globalData->isSharedInstance() && !isValidSharedInstanceThreadState(globalData))
+        return false;
+
+    return true;
+}
+
+class CountFunctor {
+public:
+    typedef size_t ReturnType;
+
+    CountFunctor();
+    void count(size_t);
+    ReturnType returnValue();
+
+private:
+    ReturnType m_count;
+};
+
+inline CountFunctor::CountFunctor()
+    : m_count(0)
+{
+}
+
+inline void CountFunctor::count(size_t count)
+{
+    m_count += count;
+}
+
+inline CountFunctor::ReturnType CountFunctor::returnValue()
+{
+    return m_count;
+}
+
+struct ClearMarks : MarkedBlock::VoidFunctor {
+    void operator()(MarkedBlock*);
+};
+
+inline void ClearMarks::operator()(MarkedBlock* block)
+{
+    block->clearMarks();
+}
+
+struct Sweep : MarkedBlock::VoidFunctor {
+    void operator()(MarkedBlock*);
+};
+
+inline void Sweep::operator()(MarkedBlock* block)
+{
+    block->sweep();
+}
+
+struct MarkCount : CountFunctor {
+    void operator()(MarkedBlock*);
+};
+
+inline void MarkCount::operator()(MarkedBlock* block)
+{
+    count(block->markCount());
+}
+
+struct Size : CountFunctor {
+    void operator()(MarkedBlock*);
+};
+
+inline void Size::operator()(MarkedBlock* block)
+{
+    count(block->markCount() * block->cellSize());
+}
+
+struct Capacity : CountFunctor {
+    void operator()(MarkedBlock*);
+};
+
+inline void Capacity::operator()(MarkedBlock* block)
+{
+    count(block->capacity());
+}
+
+struct Count : public CountFunctor {
+    void operator()(JSCell*);
+};
+
+inline void Count::operator()(JSCell*)
+{
+    count(1);
+}
+
+struct CountIfGlobalObject : CountFunctor {
+    void operator()(JSCell*);
+};
+
+inline void CountIfGlobalObject::operator()(JSCell* cell)
+{
+    if (!cell->isObject())
+        return;
+    if (!asObject(cell)->isGlobalObject())
+        return;
+    count(1);
+}
+
+class RecordType {
+public:
+    typedef PassOwnPtr<TypeCountSet> ReturnType;
+
+    RecordType();
+    void operator()(JSCell*);
+    ReturnType returnValue();
+
+private:
+    const char* typeName(JSCell*);
+    OwnPtr<TypeCountSet> m_typeCountSet;
+};
+
+inline RecordType::RecordType()
+    : m_typeCountSet(adoptPtr(new TypeCountSet))
+{
+}
+
+inline const char* RecordType::typeName(JSCell* cell)
+{
+    const ClassInfo* info = cell->classInfo();
+    if (!info || !info->className)
+        return "[unknown]";
+    return info->className;
+}
+
+inline void RecordType::operator()(JSCell* cell)
+{
+    m_typeCountSet->add(typeName(cell));
+}
+
+inline PassOwnPtr<TypeCountSet> RecordType::returnValue()
+{
+    return m_typeCountSet.release();
+}
+
+} // anonymous namespace
+
+Heap::Heap(JSGlobalData* globalData, HeapSize heapSize)
+    : m_heapSize(heapSize)
+    , m_minBytesPerCycle(heapSizeForHint(heapSize))
+    , m_sizeAfterLastCollect(0)
+    , m_bytesAllocatedLimit(m_minBytesPerCycle)
+    , m_bytesAllocated(0)
+    , m_bytesAbandoned(0)
+    , m_operationInProgress(NoOperation)
+    , m_objectSpace(this)
+    , m_storageSpace(this)
     , m_markListSet(0)
     , m_markListSet(0)
-    , m_activityCallback(DefaultGCActivityCallback::create(this))
-    , m_globalData(globalData)
     , m_machineThreads(this)
     , m_machineThreads(this)
-    , m_markStack(globalData->jsArrayVPtr)
-    , m_handleHeap(globalData)
-    , m_extraCost(0)
+    , m_sharedData(globalData)
+    , m_slotVisitor(m_sharedData)
+    , m_weakSet(this)
+    , m_handleSet(globalData)
+    , m_isSafeToCollect(false)
+    , m_globalData(globalData)
+    , m_lastGCLength(0)
+    , m_lastCodeDiscardTime(WTF::currentTime())
+    , m_activityCallback(DefaultGCActivityCallback::create(this))
 {
 {
-    m_markedSpace.setHighWaterMark(minBytesPerCycle);
-    (*m_activityCallback)();
+    m_storageSpace.init();
 }
 
 Heap::~Heap()
 {
 }
 
 Heap::~Heap()
 {
-    // The destroy function must already have been called, so assert this.
-    ASSERT(!m_globalData);
+    delete m_markListSet;
+
+    m_objectSpace.shrink();
+    m_storageSpace.freeAllBlocks();
+
+    ASSERT(!size());
+    ASSERT(!capacity());
 }
 
 }
 
-void Heap::destroy()
+bool Heap::isPagedOut(double deadline)
 {
 {
-    JSLock lock(SilenceAssertionsOnly);
-
-    if (!m_globalData)
-        return;
+    return m_objectSpace.isPagedOut(deadline) || m_storageSpace.isPagedOut(deadline);
+}
 
 
+// The JSGlobalData is being destroyed and the collector will never run again.
+// Run all pending finalizers now because we won't get another chance.
+void Heap::lastChanceToFinalize()
+{
     ASSERT(!m_globalData->dynamicGlobalObject);
     ASSERT(m_operationInProgress == NoOperation);
     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
+    // FIXME: Make this a release-mode crash once we're sure no one's doing this.
+    if (size_t size = m_protectedValues.size())
+        WTFLogAlways("ERROR: JavaScriptCore heap deallocated while %ld values were still protected", static_cast<unsigned long>(size));
 
 
-    delete m_markListSet;
-    m_markListSet = 0;
-    m_markedSpace.clearMarks();
-    m_handleHeap.finalizeWeakHandles();
-    m_markedSpace.destroy();
+    m_weakSet.finalizeAll();
+    canonicalizeCellLivenessData();
+    clearMarks();
+    sweep();
+    m_globalData->smallStrings.finalizeSmallStrings();
 
 
-    m_globalData = 0;
+#if ENABLE(SIMPLE_HEAP_PROFILING)
+    m_slotVisitor.m_visitedTypeCounts.dump(WTF::dataFile(), "Visited Type Counts");
+    m_destroyedTypeCounts.dump(WTF::dataFile(), "Destroyed Type Counts");
+#endif
 }
 
 void Heap::reportExtraMemoryCostSlowCase(size_t cost)
 }
 
 void Heap::reportExtraMemoryCostSlowCase(size_t cost)
@@ -101,38 +379,35 @@ void Heap::reportExtraMemoryCostSlowCase(size_t cost)
     // if a large value survives one garbage collection, there is not much point to
     // collecting more frequently as long as it stays alive.
 
     // 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;
+    didAllocate(cost);
+    if (shouldCollect())
+        collect(DoNotSweep);
 }
 
 }
 
-void* Heap::allocateSlowCase(size_t bytes)
+void Heap::reportAbandonedObjectGraph()
 {
 {
-    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;
+    // Our clients don't know exactly how much memory they
+    // are abandoning so we just guess for them.
+    double abandonedBytes = 0.10 * m_sizeAfterLastCollect;
+
+    // We want to accelerate the next collection. Because memory has just 
+    // been abandoned, the next collection has the potential to 
+    // be more profitable. Since allocation is the trigger for collection, 
+    // we hasten the next collection by pretending that we've allocated more memory. 
+    didAbandon(abandonedBytes);
+}
 
 
-    ASSERT(result);
-    return result;
+void Heap::didAbandon(size_t bytes)
+{
+    if (m_activityCallback)
+        m_activityCallback->didAllocate(m_bytesAllocated + m_bytesAbandoned);
+    m_bytesAbandoned += bytes;
 }
 
 void Heap::protect(JSValue k)
 {
     ASSERT(k);
 }
 
 void Heap::protect(JSValue k)
 {
     ASSERT(k);
-    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
+    ASSERT(m_globalData->apiLock().currentThreadIsHoldingLock());
 
     if (!k.isCell())
         return;
 
     if (!k.isCell())
         return;
@@ -143,7 +418,7 @@ void Heap::protect(JSValue k)
 bool Heap::unprotect(JSValue k)
 {
     ASSERT(k);
 bool Heap::unprotect(JSValue k)
 {
     ASSERT(k);
-    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
+    ASSERT(m_globalData->apiLock().currentThreadIsHoldingLock());
 
     if (!k.isCell())
         return false;
 
     if (!k.isCell())
         return false;
@@ -151,11 +426,16 @@ bool Heap::unprotect(JSValue k)
     return m_protectedValues.remove(k.asCell());
 }
 
     return m_protectedValues.remove(k.asCell());
 }
 
-void Heap::markProtectedObjects(HeapRootVisitor& heapRootMarker)
+void Heap::jettisonDFGCodeBlock(PassOwnPtr<CodeBlock> codeBlock)
+{
+    m_dfgCodeBlocks.jettison(codeBlock);
+}
+
+void Heap::markProtectedObjects(HeapRootVisitor& heapRootVisitor)
 {
     ProtectCountSet::iterator end = m_protectedValues.end();
     for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
 {
     ProtectCountSet::iterator end = m_protectedValues.end();
     for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
-        heapRootMarker.mark(&it->first);
+        heapRootVisitor.visit(&it->first);
 }
 
 void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector)
 }
 
 void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector)
@@ -168,8 +448,8 @@ void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector)
     ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last());
     m_tempSortingVectors.removeLast();
 }
     ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last());
     m_tempSortingVectors.removeLast();
 }
-    
-void Heap::markTempSortVectors(HeapRootVisitor& heapRootMarker)
+
+void Heap::markTempSortVectors(HeapRootVisitor& heapRootVisitor)
 {
     typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors;
 
 {
     typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors;
 
@@ -180,11 +460,21 @@ void Heap::markTempSortVectors(HeapRootVisitor& heapRootMarker)
         Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end();
         for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) {
             if (vectorIt->first)
         Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end();
         for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) {
             if (vectorIt->first)
-                heapRootMarker.mark(&vectorIt->first);
+                heapRootVisitor.visit(&vectorIt->first);
         }
     }
 }
 
         }
     }
 }
 
+void Heap::harvestWeakReferences()
+{
+    m_slotVisitor.harvestWeakReferences();
+}
+
+void Heap::finalizeUnconditionalFinalizers()
+{
+    m_slotVisitor.finalizeUnconditionalFinalizers();
+}
+
 inline RegisterFile& Heap::registerFile()
 {
     return m_globalData->interpreter->registerFile();
 inline RegisterFile& Heap::registerFile()
 {
     return m_globalData->interpreter->registerFile();
@@ -192,16 +482,8 @@ inline RegisterFile& Heap::registerFile()
 
 void Heap::getConservativeRegisterRoots(HashSet<JSCell*>& roots)
 {
 
 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);
+    ASSERT(isValidThreadState(m_globalData));
+    ConservativeRoots registerFileRoots(&m_objectSpace.blocks(), &m_storageSpace);
     registerFile().gatherConservativeRoots(registerFileRoots);
     size_t registerFileRootCount = registerFileRoots.size();
     JSCell** registerRoots = registerFileRoots.roots();
     registerFile().gatherConservativeRoots(registerFileRoots);
     size_t registerFileRootCount = registerFileRoots.size();
     JSCell** registerRoots = registerFileRoots.roots();
@@ -209,247 +491,398 @@ void Heap::getConservativeRegisterRoots(HashSet<JSCell*>& roots)
         setMarked(registerRoots[i]);
         roots.add(registerRoots[i]);
     }
         setMarked(registerRoots[i]);
         roots.add(registerRoots[i]);
     }
-    m_operationInProgress = NoOperation;
 }
 
 }
 
-void Heap::markRoots()
+void Heap::markRoots(bool fullGC)
 {
 {
-#ifndef NDEBUG
-    if (m_globalData->isSharedInstance()) {
-        ASSERT(JSLock::lockCount() > 0);
-        ASSERT(JSLock::currentThreadIsHoldingLock());
-    }
-#endif
+    SamplingRegion samplingRegion("Garbage Collection: Tracing");
 
 
-    void* dummy;
-
-    ASSERT(m_operationInProgress == NoOperation);
-    if (m_operationInProgress != NoOperation)
-        CRASH();
+    COND_GCPHASE(fullGC, MarkFullRoots, MarkYoungRoots);
+    UNUSED_PARAM(fullGC);
+    ASSERT(isValidThreadState(m_globalData));
 
 
-    m_operationInProgress = Collection;
-
-    MarkStack& visitor = m_markStack;
-    HeapRootVisitor heapRootMarker(visitor);
+    void* dummy;
     
     
-    // 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);
+    // We gather conservative roots before clearing mark bits because conservative
+    // gathering uses the mark bits to determine whether a reference is valid.
+    ConservativeRoots machineThreadRoots(&m_objectSpace.blocks(), &m_storageSpace);
+    {
+        GCPHASE(GatherConservativeRoots);
+        m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy);
+    }
 
 
-    ConservativeRoots registerFileRoots(this);
-    registerFile().gatherConservativeRoots(registerFileRoots);
+    ConservativeRoots registerFileRoots(&m_objectSpace.blocks(), &m_storageSpace);
+    m_dfgCodeBlocks.clearMarks();
+    {
+        GCPHASE(GatherRegisterFileRoots);
+        registerFile().gatherConservativeRoots(registerFileRoots, m_dfgCodeBlocks);
+    }
 
 
-    m_markedSpace.clearMarks();
+#if ENABLE(DFG_JIT)
+    ConservativeRoots scratchBufferRoots(&m_objectSpace.blocks(), &m_storageSpace);
+    {
+        GCPHASE(GatherScratchBufferRoots);
+        m_globalData->gatherConservativeRoots(scratchBufferRoots);
+    }
+#endif
 
 
-    visitor.append(machineThreadRoots);
-    visitor.drain();
+#if ENABLE(GGC)
+    MarkedBlock::DirtyCellVector dirtyCells;
+    if (!fullGC) {
+        GCPHASE(GatheringDirtyCells);
+        m_objectSpace.gatherDirtyCells(dirtyCells);
+    } else
+#endif
+    {
+        GCPHASE(clearMarks);
+        clearMarks();
+    }
 
 
-    visitor.append(registerFileRoots);
-    visitor.drain();
+    m_storageSpace.startedCopying();
+    SlotVisitor& visitor = m_slotVisitor;
+    HeapRootVisitor heapRootVisitor(visitor);
+
+    {
+        ParallelModeEnabler enabler(visitor);
+#if ENABLE(GGC)
+        {
+            size_t dirtyCellCount = dirtyCells.size();
+            GCPHASE(VisitDirtyCells);
+            GCCOUNTER(DirtyCellCount, dirtyCellCount);
+            for (size_t i = 0; i < dirtyCellCount; i++) {
+                heapRootVisitor.visitChildren(dirtyCells[i]);
+                visitor.donateAndDrain();
+            }
+        }
+#endif
+    
+        if (m_globalData->codeBlocksBeingCompiled.size()) {
+            GCPHASE(VisitActiveCodeBlock);
+            for (size_t i = 0; i < m_globalData->codeBlocksBeingCompiled.size(); i++)
+                m_globalData->codeBlocksBeingCompiled[i]->visitAggregate(visitor);
+        }
+    
+        {
+            GCPHASE(VisitMachineRoots);
+            visitor.append(machineThreadRoots);
+            visitor.donateAndDrain();
+        }
+        {
+            GCPHASE(VisitRegisterFileRoots);
+            visitor.append(registerFileRoots);
+            visitor.donateAndDrain();
+        }
+#if ENABLE(DFG_JIT)
+        {
+            GCPHASE(VisitScratchBufferRoots);
+            visitor.append(scratchBufferRoots);
+            visitor.donateAndDrain();
+        }
+#endif
+        {
+            GCPHASE(VisitProtectedObjects);
+            markProtectedObjects(heapRootVisitor);
+            visitor.donateAndDrain();
+        }
+        {
+            GCPHASE(VisitTempSortVectors);
+            markTempSortVectors(heapRootVisitor);
+            visitor.donateAndDrain();
+        }
 
 
-    markProtectedObjects(heapRootMarker);
-    visitor.drain();
+        {
+            GCPHASE(MarkingArgumentBuffers);
+            if (m_markListSet && m_markListSet->size()) {
+                MarkedArgumentBuffer::markLists(heapRootVisitor, *m_markListSet);
+                visitor.donateAndDrain();
+            }
+        }
+        if (m_globalData->exception) {
+            GCPHASE(MarkingException);
+            heapRootVisitor.visit(&m_globalData->exception);
+            visitor.donateAndDrain();
+        }
     
     
-    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();
+        {
+            GCPHASE(VisitStrongHandles);
+            m_handleSet.visitStrongHandles(heapRootVisitor);
+            visitor.donateAndDrain();
+        }
     
     
-    // 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());
+        {
+            GCPHASE(HandleStack);
+            m_handleStack.visit(heapRootVisitor);
+            visitor.donateAndDrain();
+        }
+    
+        {
+            GCPHASE(TraceCodeBlocks);
+            m_dfgCodeBlocks.traceMarkedCodeBlocks(visitor);
+            visitor.donateAndDrain();
+        }
+    
+#if ENABLE(PARALLEL_GC)
+        {
+            GCPHASE(Convergence);
+            visitor.drainFromShared(SlotVisitor::MasterDrain);
+        }
+#endif
+    }
 
 
-    visitor.reset();
+    // Weak references must be marked last because their liveness depends on
+    // the liveness of the rest of the object graph.
+    {
+        GCPHASE(VisitingLiveWeakHandles);
+        while (true) {
+            m_weakSet.visitLiveWeakImpls(heapRootVisitor);
+            harvestWeakReferences();
+            if (visitor.isEmpty())
+                break;
+            {
+                ParallelModeEnabler enabler(visitor);
+                visitor.donateAndDrain();
+#if ENABLE(PARALLEL_GC)
+                visitor.drainFromShared(SlotVisitor::MasterDrain);
+#endif
+            }
+        }
+    }
 
 
-    m_operationInProgress = NoOperation;
-}
+    {
+        GCPHASE(VisitingDeadWeakHandles);
+        m_weakSet.visitDeadWeakImpls(heapRootVisitor);
+    }
 
 
-size_t Heap::objectCount() const
-{
-    return m_markedSpace.objectCount();
-}
+    GCCOUNTER(VisitedValueCount, visitor.visitCount());
+
+    visitor.doneCopying();
+    visitor.reset();
+    m_sharedData.reset();
+    m_storageSpace.doneCopying();
 
 
-size_t Heap::size() const
-{
-    return m_markedSpace.size();
 }
 
 }
 
-size_t Heap::capacity() const
+void Heap::clearMarks()
 {
 {
-    return m_markedSpace.capacity();
+    m_objectSpace.forEachBlock<ClearMarks>();
 }
 
 }
 
-size_t Heap::globalObjectCount()
+void Heap::sweep()
 {
 {
-    return m_globalData->globalObjectCount;
+    m_objectSpace.forEachBlock<Sweep>();
 }
 
 }
 
-size_t Heap::protectedGlobalObjectCount()
+size_t Heap::objectCount()
 {
 {
-    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;
+    return m_objectSpace.forEachBlock<MarkCount>();
 }
 
 }
 
-size_t Heap::protectedObjectCount()
+size_t Heap::size()
 {
 {
-    return m_protectedValues.size();
+    return m_objectSpace.forEachBlock<Size>() + m_storageSpace.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))
+size_t Heap::capacity()
 {
 {
+    return m_objectSpace.forEachBlock<Capacity>() + m_storageSpace.capacity();
 }
 
 }
 
-inline const char* TypeCounter::typeName(JSCell* cell)
+size_t Heap::protectedGlobalObjectCount()
 {
 {
-    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";
+    return forEachProtectedCell<CountIfGlobalObject>();
 }
 
 }
 
-inline void TypeCounter::operator()(JSCell* cell)
+size_t Heap::globalObjectCount()
 {
 {
-    if (!m_cells.add(cell).second)
-        return;
-    m_typeCountSet->add(typeName(cell));
+    return m_objectSpace.forEachCell<CountIfGlobalObject>();
 }
 
 }
 
-inline PassOwnPtr<TypeCountSet> TypeCounter::take()
+size_t Heap::protectedObjectCount()
 {
 {
-    return m_typeCountSet.release();
+    return forEachProtectedCell<Count>();
 }
 
 PassOwnPtr<TypeCountSet> Heap::protectedObjectTypeCounts()
 {
 }
 
 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();
+    return forEachProtectedCell<RecordType>();
 }
 
 }
 
-void HandleHeap::protectedObjectTypeCounts(TypeCounter& typeCounter)
+PassOwnPtr<TypeCountSet> Heap::objectTypeCounts()
 {
 {
-    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());
-    }
+    return m_objectSpace.forEachCell<RecordType>();
 }
 
 }
 
-PassOwnPtr<TypeCountSet> Heap::objectTypeCounts()
+void Heap::discardAllCompiledCode()
 {
 {
-    TypeCounter typeCounter;
-    forEach(typeCounter);
-    return typeCounter.take();
+    // If JavaScript is running, it's not safe to recompile, since we'll end
+    // up throwing away code that is live on the stack.
+    if (m_globalData->dynamicGlobalObject)
+        return;
+
+    for (FunctionExecutable* current = m_functions.head(); current; current = current->next())
+        current->discardCode();
 }
 
 void Heap::collectAllGarbage()
 {
 }
 
 void Heap::collectAllGarbage()
 {
-    m_markStack.setShouldUnlinkCalls(true);
-    reset(DoSweep);
-    m_markStack.setShouldUnlinkCalls(false);
+    if (!m_isSafeToCollect)
+        return;
+
+    collect(DoSweep);
 }
 
 }
 
-void Heap::reset(SweepToggle sweepToggle)
+static double minute = 60.0;
+
+void Heap::collect(SweepToggle sweepToggle)
 {
 {
+    SamplingRegion samplingRegion("Garbage Collection");
+    
+    GCPHASE(Collect);
+    ASSERT(globalData()->apiLock().currentThreadIsHoldingLock());
     ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
     ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
+    ASSERT(m_isSafeToCollect);
     JAVASCRIPTCORE_GC_BEGIN();
     JAVASCRIPTCORE_GC_BEGIN();
+    if (m_operationInProgress != NoOperation)
+        CRASH();
+    m_operationInProgress = Collection;
 
 
-    markRoots();
-    m_handleHeap.finalizeWeakHandles();
-
-    JAVASCRIPTCORE_GC_MARKED();
+    if (m_activityCallback)
+        m_activityCallback->willCollect();
 
 
-    m_markedSpace.reset();
-    m_extraCost = 0;
+    double lastGCStartTime = WTF::currentTime();
+    if (lastGCStartTime - m_lastCodeDiscardTime > minute) {
+        discardAllCompiledCode();
+        m_lastCodeDiscardTime = WTF::currentTime();
+    }
 
 
-#if ENABLE(JSC_ZOMBIES)
-    sweepToggle = DoSweep;
+#if ENABLE(GGC)
+    bool fullGC = sweepToggle == DoSweep;
+    if (!fullGC)
+        fullGC = (capacity() > 4 * m_sizeAfterLastCollect);  
+#else
+    bool fullGC = true;
 #endif
 #endif
+    {
+        GCPHASE(Canonicalize);
+        canonicalizeCellLivenessData();
+    }
+
+    markRoots(fullGC);
+    
+    {
+        GCPHASE(FinalizeUnconditionalFinalizers);
+        finalizeUnconditionalFinalizers();
+    }
+        
+    {
+        GCPHASE(FinalizeWeakHandles);
+        m_weakSet.sweep();
+        m_globalData->smallStrings.finalizeSmallStrings();
+    }
+    
+    JAVASCRIPTCORE_GC_MARKED();
+
+    {
+        GCPHASE(ResetAllocator);
+        resetAllocators();
+    }
+    
+    {
+        GCPHASE(DeleteCodeBlocks);
+        m_dfgCodeBlocks.deleteUnmarkedJettisonedCodeBlocks();
+    }
 
     if (sweepToggle == DoSweep) {
 
     if (sweepToggle == DoSweep) {
-        m_markedSpace.sweep();
-        m_markedSpace.shrink();
+        SamplingRegion samplingRegion("Garbage Collection: Sweeping");
+        GCPHASE(Sweeping);
+        sweep();
+        m_objectSpace.shrink();
+        m_weakSet.shrink();
+        m_bytesAbandoned = 0;
     }
 
     }
 
-    // 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 :
+    // To avoid pathological GC churn in large heaps, we set the new allocation 
+    // limit to be the current size of the heap. This heuristic 
+    // is a bit arbitrary. Using the current size of the heap after this 
+    // collection gives us a 2X multiplier, which is a 1:1 (heap size :
     // new bytes allocated) proportion, and seems to work well in benchmarks.
     // new bytes allocated) proportion, and seems to work well in benchmarks.
-    size_t proportionalBytes = 2 * m_markedSpace.size();
-    m_markedSpace.setHighWaterMark(max(proportionalBytes, minBytesPerCycle));
-
+    size_t newSize = size();
+    if (fullGC) {
+        m_sizeAfterLastCollect = newSize;
+        m_bytesAllocatedLimit = max(newSize, m_minBytesPerCycle);
+    }
+    m_bytesAllocated = 0;
+    double lastGCEndTime = WTF::currentTime();
+    m_lastGCLength = lastGCEndTime - lastGCStartTime;
+    if (m_operationInProgress != Collection)
+        CRASH();
+    m_operationInProgress = NoOperation;
     JAVASCRIPTCORE_GC_END();
     JAVASCRIPTCORE_GC_END();
+}
+
+void Heap::canonicalizeCellLivenessData()
+{
+    m_objectSpace.canonicalizeCellLivenessData();
+}
 
 
-    (*m_activityCallback)();
+void Heap::resetAllocators()
+{
+    m_objectSpace.resetAllocators();
+    m_weakSet.resetAllocator();
 }
 
 }
 
-void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback)
+void Heap::setActivityCallback(GCActivityCallback* activityCallback)
 {
     m_activityCallback = activityCallback;
 }
 
 GCActivityCallback* Heap::activityCallback()
 {
 {
     m_activityCallback = activityCallback;
 }
 
 GCActivityCallback* Heap::activityCallback()
 {
-    return m_activityCallback.get();
+    return m_activityCallback;
+}
+
+void Heap::didAllocate(size_t bytes)
+{
+    if (m_activityCallback)
+        m_activityCallback->didAllocate(m_bytesAllocated + m_bytesAbandoned);
+    m_bytesAllocated += bytes;
+}
+
+bool Heap::isValidAllocation(size_t bytes)
+{
+    if (!isValidThreadState(m_globalData))
+        return false;
+
+    if (bytes > MarkedSpace::maxCellSize)
+        return false;
+
+    if (m_operationInProgress != NoOperation)
+        return false;
+    
+    return true;
+}
+
+void Heap::addFinalizer(JSCell* cell, Finalizer finalizer)
+{
+    WeakSet::allocate(cell, &m_finalizerOwner, reinterpret_cast<void*>(finalizer)); // Balanced by FinalizerOwner::finalize().
+}
+
+void Heap::FinalizerOwner::finalize(Handle<Unknown> handle, void* context)
+{
+    HandleSlot slot = handle.slot();
+    Finalizer finalizer = reinterpret_cast<Finalizer>(context);
+    finalizer(slot->asCell());
+    WeakSet::deallocate(WeakImpl::asWeakImpl(slot));
+}
+
+void Heap::addFunctionExecutable(FunctionExecutable* executable)
+{
+    m_functions.append(executable);
+}
+
+void Heap::removeFunctionExecutable(FunctionExecutable* executable)
+{
+    m_functions.remove(executable);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index feba1cfccf22f383dc2adc122e22860098fdeab2..4b9d073f7c6450d6efcf5bf22fe43ae10c686681 100644 (file)
 #ifndef Heap_h
 #define Heap_h
 
 #ifndef Heap_h
 #define Heap_h
 
-#include "HandleHeap.h"
+#include "BlockAllocator.h"
+#include "DFGCodeBlocks.h"
+#include "HandleSet.h"
 #include "HandleStack.h"
 #include "HandleStack.h"
-#include "MarkStack.h"
+#include "MarkedAllocator.h"
+#include "MarkedBlock.h"
+#include "MarkedBlockSet.h"
 #include "MarkedSpace.h"
 #include "MarkedSpace.h"
-#include <wtf/Forward.h>
+#include "SlotVisitor.h"
+#include "WeakHandleOwner.h"
+#include "WeakSet.h"
+#include "WriteBarrierSupport.h"
 #include <wtf/HashCountedSet.h>
 #include <wtf/HashSet.h>
 
 #include <wtf/HashCountedSet.h>
 #include <wtf/HashSet.h>
 
+#define COLLECT_ON_EVERY_ALLOCATION 0
+
 namespace JSC {
 
 namespace JSC {
 
+    class CopiedSpace;
+    class CodeBlock;
+    class FunctionExecutable;
     class GCActivityCallback;
     class GlobalCodeBlock;
     class GCActivityCallback;
     class GlobalCodeBlock;
+    class Heap;
     class HeapRootVisitor;
     class JSCell;
     class JSGlobalData;
     class JSValue;
     class LiveObjectIterator;
     class HeapRootVisitor;
     class JSCell;
     class JSGlobalData;
     class JSValue;
     class LiveObjectIterator;
-    class MarkStack;
+    class LLIntOffsetsExtractor;
     class MarkedArgumentBuffer;
     class RegisterFile;
     class UString;
     class WeakGCHandlePool;
     class MarkedArgumentBuffer;
     class RegisterFile;
     class UString;
     class WeakGCHandlePool;
-    typedef MarkStack SlotVisitor;
+    class SlotVisitor;
 
     typedef std::pair<JSValue, UString> ValueStringPair;
     typedef HashCountedSet<JSCell*> ProtectCountSet;
 
     typedef std::pair<JSValue, UString> ValueStringPair;
     typedef HashCountedSet<JSCell*> ProtectCountSet;
@@ -52,135 +65,266 @@ namespace JSC {
 
     enum OperationInProgress { NoOperation, Allocation, Collection };
 
 
     enum OperationInProgress { NoOperation, Allocation, Collection };
 
+    // Heap size hint.
+    enum HeapSize { SmallHeap, LargeHeap };
+
     class Heap {
         WTF_MAKE_NONCOPYABLE(Heap);
     public:
     class Heap {
         WTF_MAKE_NONCOPYABLE(Heap);
     public:
-        static Heap* heap(JSValue); // 0 for immediate values
-        static Heap* heap(JSCell*);
+        friend class JIT;
+        friend class MarkStackThreadSharedData;
+        static Heap* heap(const JSValue); // 0 for immediate values
+        static Heap* heap(const JSCell*);
+
+        // This constant determines how many blocks we iterate between checks of our 
+        // deadline when calling Heap::isPagedOut. Decreasing it will cause us to detect 
+        // overstepping our deadline more quickly, while increasing it will cause 
+        // our scan to run faster. 
+        static const unsigned s_timeCheckResolution = 16;
 
 
-        static bool isMarked(const JSCell*);
-        static bool testAndSetMarked(const JSCell*);
-        static void setMarked(JSCell*);
+        static bool isMarked(const void*);
+        static bool testAndSetMarked(const void*);
+        static void setMarked(const void*);
 
         static void writeBarrier(const JSCell*, JSValue);
         static void writeBarrier(const JSCell*, JSCell*);
 
         static void writeBarrier(const JSCell*, JSValue);
         static void writeBarrier(const JSCell*, JSCell*);
+        static uint8_t* addressOfCardFor(JSCell*);
 
 
-        Heap(JSGlobalData*);
+        Heap(JSGlobalData*, HeapSize);
         ~Heap();
         ~Heap();
-        void destroy(); // JSGlobalData must call destroy() before ~Heap().
+        JS_EXPORT_PRIVATE void lastChanceToFinalize();
 
         JSGlobalData* globalData() const { return m_globalData; }
 
         JSGlobalData* globalData() const { return m_globalData; }
-        MarkedSpace& markedSpace() { return m_markedSpace; }
+        MarkedSpace& objectSpace() { return m_objectSpace; }
         MachineThreads& machineThreads() { return m_machineThreads; }
 
         MachineThreads& machineThreads() { return m_machineThreads; }
 
-        GCActivityCallback* activityCallback();
-        void setActivityCallback(PassOwnPtr<GCActivityCallback>);
+        JS_EXPORT_PRIVATE GCActivityCallback* activityCallback();
+        JS_EXPORT_PRIVATE void setActivityCallback(GCActivityCallback*);
 
         // true if an allocation or collection is in progress
         inline bool isBusy();
 
         // true if an allocation or collection is in progress
         inline bool isBusy();
+        
+        MarkedAllocator& firstAllocatorWithoutDestructors() { return m_objectSpace.firstAllocator(); }
+        MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
+        MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); }
+        CopiedAllocator& storageAllocator() { return m_storageSpace.allocator(); }
+        CheckedBoolean tryAllocateStorage(size_t, void**);
+        CheckedBoolean tryReallocateStorage(void**, size_t, size_t);
 
 
-        void* allocate(size_t);
-        void collectAllGarbage();
+        typedef void (*Finalizer)(JSCell*);
+        JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
+        void addFunctionExecutable(FunctionExecutable*);
+        void removeFunctionExecutable(FunctionExecutable*);
 
 
-        void reportExtraMemoryCost(size_t cost);
+        void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
 
 
-        void protect(JSValue);
-        bool unprotect(JSValue); // True when the protect count drops to 0.
+        JS_EXPORT_PRIVATE void collectAllGarbage();
+        enum SweepToggle { DoNotSweep, DoSweep };
+        bool shouldCollect();
+        void collect(SweepToggle);
+
+        void reportExtraMemoryCost(size_t cost);
+        JS_EXPORT_PRIVATE void reportAbandonedObjectGraph();
 
 
-        bool contains(void*);
+        JS_EXPORT_PRIVATE void protect(JSValue);
+        JS_EXPORT_PRIVATE bool unprotect(JSValue); // True when the protect count drops to 0.
+        
+        void jettisonDFGCodeBlock(PassOwnPtr<CodeBlock>);
 
 
-        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();
+        JS_EXPORT_PRIVATE size_t size();
+        JS_EXPORT_PRIVATE size_t capacity();
+        JS_EXPORT_PRIVATE size_t objectCount();
+        JS_EXPORT_PRIVATE size_t globalObjectCount();
+        JS_EXPORT_PRIVATE size_t protectedObjectCount();
+        JS_EXPORT_PRIVATE size_t protectedGlobalObjectCount();
+        JS_EXPORT_PRIVATE PassOwnPtr<TypeCountSet> protectedObjectTypeCounts();
+        JS_EXPORT_PRIVATE 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; }
         
 
         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(); }
+        template<typename Functor> typename Functor::ReturnType forEachProtectedCell(Functor&);
+        template<typename Functor> typename Functor::ReturnType forEachProtectedCell();
 
 
+        WeakSet* weakSet() { return &m_weakSet; }
+        HandleSet* handleSet() { return &m_handleSet; }
         HandleStack* handleStack() { return &m_handleStack; }
         HandleStack* handleStack() { return &m_handleStack; }
+
         void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
 
         void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
 
+        double lastGCLength() { return m_lastGCLength; }
+        void increaseLastGCLength(double amount) { m_lastGCLength += amount; }
+
+        JS_EXPORT_PRIVATE void discardAllCompiledCode();
+
+        void didAllocate(size_t);
+        void didAbandon(size_t);
+
+        bool isPagedOut(double deadline);
+
     private:
     private:
-        friend class JSGlobalData;
+        friend class CodeBlock;
+        friend class LLIntOffsetsExtractor;
+        friend class MarkedSpace;
+        friend class MarkedAllocator;
+        friend class MarkedBlock;
+        friend class CopiedSpace;
+        friend class SlotVisitor;
+        template<typename T> friend void* allocateCell(Heap&);
+
+        void* allocateWithDestructor(size_t);
+        void* allocateWithoutDestructor(size_t);
 
         static const size_t minExtraCost = 256;
         static const size_t maxExtraCost = 1024 * 1024;
 
         static const size_t minExtraCost = 256;
         static const size_t maxExtraCost = 1024 * 1024;
+        
+        class FinalizerOwner : public WeakHandleOwner {
+            virtual void finalize(Handle<Unknown>, void* context);
+        };
+
+        JS_EXPORT_PRIVATE bool isValidAllocation(size_t);
+        JS_EXPORT_PRIVATE void reportExtraMemoryCostSlowCase(size_t);
+
+        // Call this function before any operation that needs to know which cells
+        // in the heap are live. (For example, call this function before
+        // conservative marking, eager sweeping, or iterating the cells in a MarkedBlock.)
+        void canonicalizeCellLivenessData();
 
 
-        void* allocateSlowCase(size_t);
-        void reportExtraMemoryCostSlowCase(size_t);
+        void resetAllocators();
 
 
-        void markRoots();
+        void clearMarks();
+        void markRoots(bool fullGC);
         void markProtectedObjects(HeapRootVisitor&);
         void markTempSortVectors(HeapRootVisitor&);
         void markProtectedObjects(HeapRootVisitor&);
         void markTempSortVectors(HeapRootVisitor&);
-
-        enum SweepToggle { DoNotSweep, DoSweep };
-        void reset(SweepToggle);
+        void harvestWeakReferences();
+        void finalizeUnconditionalFinalizers();
+        
+        void sweep();
 
         RegisterFile& registerFile();
 
         RegisterFile& registerFile();
+        BlockAllocator& blockAllocator();
 
 
+        const HeapSize m_heapSize;
+        const size_t m_minBytesPerCycle;
+        size_t m_sizeAfterLastCollect;
+
+        size_t m_bytesAllocatedLimit;
+        size_t m_bytesAllocated;
+        size_t m_bytesAbandoned;
+        
         OperationInProgress m_operationInProgress;
         OperationInProgress m_operationInProgress;
-        MarkedSpace m_markedSpace;
+        MarkedSpace m_objectSpace;
+        CopiedSpace m_storageSpace;
+
+        BlockAllocator m_blockAllocator;
+
+#if ENABLE(SIMPLE_HEAP_PROFILING)
+        VTableSpectrum m_destroyedTypeCounts;
+#endif
 
         ProtectCountSet m_protectedValues;
         Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
 
         ProtectCountSet m_protectedValues;
         Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
-
         HashSet<MarkedArgumentBuffer*>* m_markListSet;
 
         HashSet<MarkedArgumentBuffer*>* m_markListSet;
 
-        OwnPtr<GCActivityCallback> m_activityCallback;
-
-        JSGlobalData* m_globalData;
-        
         MachineThreads m_machineThreads;
         MachineThreads m_machineThreads;
-        MarkStack m_markStack;
-        HandleHeap m_handleHeap;
+        
+        MarkStackThreadSharedData m_sharedData;
+        SlotVisitor m_slotVisitor;
+
+        WeakSet m_weakSet;
+        HandleSet m_handleSet;
         HandleStack m_handleStack;
         HandleStack m_handleStack;
+        DFGCodeBlocks m_dfgCodeBlocks;
+        FinalizerOwner m_finalizerOwner;
+        
+        bool m_isSafeToCollect;
 
 
-        size_t m_extraCost;
+        JSGlobalData* m_globalData;
+        double m_lastGCLength;
+        double m_lastCodeDiscardTime;
+
+        DoublyLinkedList<FunctionExecutable> m_functions;
+        
+        GCActivityCallback* m_activityCallback;
     };
 
     };
 
+    inline bool Heap::shouldCollect()
+    {
+#if ENABLE(GGC)
+        return m_objectSpace.nurseryWaterMark() >= m_minBytesPerCycle && m_isSafeToCollect && m_operationInProgress == NoOperation;
+#else
+        return m_bytesAllocated > m_bytesAllocatedLimit && m_isSafeToCollect && m_operationInProgress == NoOperation;
+#endif
+    }
+
     bool Heap::isBusy()
     {
         return m_operationInProgress != NoOperation;
     }
 
     bool Heap::isBusy()
     {
         return m_operationInProgress != NoOperation;
     }
 
-    inline bool Heap::isMarked(const JSCell* cell)
+    inline Heap* Heap::heap(const JSCell* cell)
     {
     {
-        return MarkedSpace::isMarked(cell);
+        return MarkedBlock::blockFor(cell)->heap();
     }
 
     }
 
-    inline bool Heap::testAndSetMarked(const JSCell* cell)
+    inline Heap* Heap::heap(const JSValue v)
     {
     {
-        return MarkedSpace::testAndSetMarked(cell);
+        if (!v.isCell())
+            return 0;
+        return heap(v.asCell());
     }
 
     }
 
-    inline void Heap::setMarked(JSCell* cell)
+    inline bool Heap::isMarked(const void* cell)
     {
     {
-        MarkedSpace::setMarked(cell);
+        return MarkedBlock::blockFor(cell)->isMarked(cell);
     }
 
     }
 
-    inline void Heap::writeBarrier(const JSCell*, JSValue)
+    inline bool Heap::testAndSetMarked(const void* cell)
+    {
+        return MarkedBlock::blockFor(cell)->testAndSetMarked(cell);
+    }
+
+    inline void Heap::setMarked(const void* cell)
+    {
+        MarkedBlock::blockFor(cell)->setMarked(cell);
+    }
+
+#if ENABLE(GGC)
+    inline uint8_t* Heap::addressOfCardFor(JSCell* cell)
     {
     {
+        return MarkedBlock::blockFor(cell)->addressOfCardFor(cell);
     }
 
     }
 
+    inline void Heap::writeBarrier(const JSCell* owner, JSCell*)
+    {
+        WriteBarrierCounters::countWriteBarrier();
+        MarkedBlock* block = MarkedBlock::blockFor(owner);
+        if (block->isMarked(owner))
+            block->setDirtyObject(owner);
+    }
+
+    inline void Heap::writeBarrier(const JSCell* owner, JSValue value)
+    {
+        if (!value)
+            return;
+        if (!value.isCell())
+            return;
+        writeBarrier(owner, value.asCell());
+    }
+#else
+
     inline void Heap::writeBarrier(const JSCell*, JSCell*)
     {
     inline void Heap::writeBarrier(const JSCell*, JSCell*)
     {
+        WriteBarrierCounters::countWriteBarrier();
     }
 
     }
 
-    inline bool Heap::contains(void* p)
+    inline void Heap::writeBarrier(const JSCell*, JSValue)
     {
     {
-        return m_markedSpace.contains(p);
+        WriteBarrierCounters::countWriteBarrier();
     }
     }
+#endif
 
     inline void Heap::reportExtraMemoryCost(size_t cost)
     {
 
     inline void Heap::reportExtraMemoryCost(size_t cost)
     {
@@ -188,9 +332,47 @@ namespace JSC {
             reportExtraMemoryCostSlowCase(cost);
     }
 
             reportExtraMemoryCostSlowCase(cost);
     }
 
-    template <typename Functor> inline void Heap::forEach(Functor& functor)
+    template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell(Functor& functor)
+    {
+        ProtectCountSet::iterator end = m_protectedValues.end();
+        for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
+            functor(it->first);
+        m_handleSet.forEachStrongHandle(functor, m_protectedValues);
+
+        return functor.returnValue();
+    }
+
+    template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell()
+    {
+        Functor functor;
+        return forEachProtectedCell(functor);
+    }
+
+    inline void* Heap::allocateWithDestructor(size_t bytes)
+    {
+        ASSERT(isValidAllocation(bytes));
+        return m_objectSpace.allocateWithDestructor(bytes);
+    }
+    
+    inline void* Heap::allocateWithoutDestructor(size_t bytes)
+    {
+        ASSERT(isValidAllocation(bytes));
+        return m_objectSpace.allocateWithoutDestructor(bytes);
+    }
+    
+    inline CheckedBoolean Heap::tryAllocateStorage(size_t bytes, void** outPtr)
+    {
+        return m_storageSpace.tryAllocate(bytes, outPtr);
+    }
+    
+    inline CheckedBoolean Heap::tryReallocateStorage(void** ptr, size_t oldSize, size_t newSize)
+    {
+        return m_storageSpace.tryReallocate(ptr, oldSize, newSize);
+    }
+
+    inline BlockAllocator& Heap::blockAllocator()
     {
     {
-        m_markedSpace.forEach(functor);
+        return m_blockAllocator;
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
diff --git a/heap/HeapBlock.h b/heap/HeapBlock.h
new file mode 100644 (file)
index 0000000..591520d
--- /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 HeapBlock_h
+#define HeapBlock_h
+
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/PageAllocationAligned.h>
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+enum AllocationEffort { AllocationCanFail, AllocationMustSucceed };
+
+class HeapBlock : public DoublyLinkedListNode<HeapBlock> {
+public:
+    HeapBlock(PageAllocationAligned& allocation)
+        : DoublyLinkedListNode<HeapBlock>()
+        , m_prev(0)
+        , m_next(0)
+        , m_allocation(allocation)
+    {
+        ASSERT(allocation);
+    }
+
+    HeapBlock* m_prev;
+    HeapBlock* m_next;
+    PageAllocationAligned m_allocation;
+    
+    static const size_t s_blockSize = 64 * KB;
+};
+
+} // namespace JSC
+
+#endif    
diff --git a/heap/HeapRootVisitor.h b/heap/HeapRootVisitor.h
new file mode 100644 (file)
index 0000000..76c9729
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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 HeapRootVisitor_h
+#define HeapRootVisitor_h
+
+#include "SlotVisitor.h"
+
+namespace JSC {
+
+    // 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.
+    class HeapRootVisitor {
+    private:
+        friend class Heap;
+        HeapRootVisitor(SlotVisitor&);
+
+    public:
+        void visit(JSValue*);
+        void visit(JSValue*, size_t);
+        void visit(JSString**);
+        void visit(JSCell**);
+
+        SlotVisitor& visitor();
+
+    private:
+        SlotVisitor& m_visitor;
+    };
+
+    inline HeapRootVisitor::HeapRootVisitor(SlotVisitor& visitor)
+        : m_visitor(visitor)
+    {
+    }
+
+    inline void HeapRootVisitor::visit(JSValue* slot)
+    {
+        m_visitor.append(slot);
+    }
+
+    inline void HeapRootVisitor::visit(JSValue* slot, size_t count)
+    {
+        m_visitor.append(slot, count);
+    }
+
+    inline void HeapRootVisitor::visit(JSString** slot)
+    {
+        m_visitor.append(reinterpret_cast<JSCell**>(slot));
+    }
+
+    inline void HeapRootVisitor::visit(JSCell** slot)
+    {
+        m_visitor.append(slot);
+    }
+
+    inline SlotVisitor& HeapRootVisitor::visitor()
+    {
+        return m_visitor;
+    }
+
+} // namespace JSC
+
+#endif // HeapRootVisitor_h
diff --git a/heap/ListableHandler.h b/heap/ListableHandler.h
new file mode 100644 (file)
index 0000000..41f18fb
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *  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 ListableHandler_h
+#define ListableHandler_h
+
+#include <stdint.h>
+#include <wtf/Locker.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/ThreadingPrimitives.h>
+
+namespace JSC {
+
+class MarkStack;
+class MarkStackThreadSharedData;
+class SlotVisitor;
+
+template<typename T>
+class ListableHandler {
+    WTF_MAKE_NONCOPYABLE(ListableHandler);
+    
+protected:
+    ListableHandler()
+        : m_nextAndFlag(0)
+    {
+    }
+    
+    virtual ~ListableHandler() { }
+    
+    T* next() const
+    {
+        return reinterpret_cast<T*>(m_nextAndFlag & ~1);
+    }
+
+private:
+    // Allow these classes to use ListableHandler::List.
+    friend class MarkStack;
+    friend class MarkStackThreadSharedData;
+    friend class SlotVisitor;
+    
+    class List {
+        WTF_MAKE_NONCOPYABLE(List);
+    public:
+        List()
+            : m_first(0)
+        {
+        }
+        
+        void addThreadSafe(T* handler)
+        {
+            // NOTE: If we ever want this to be faster, we could turn it into
+            // a CAS loop, since this is a singly-linked-list that, in parallel
+            // tracing mode, can only grow. I.e. we don't have to worry about
+            // any ABA problems.
+            MutexLocker locker(m_lock);
+            addNotThreadSafe(handler);
+        }
+        
+        bool hasNext()
+        {
+            return !!m_first;
+        }
+        
+        T* head()
+        {
+            return m_first;
+        }
+        
+        T* removeNext()
+        {
+            T* current = m_first;
+            T* next = current->next();
+            current->m_nextAndFlag = 0;
+            m_first = next;
+            return current;
+        }
+        
+        void removeAll()
+        {
+            while (hasNext())
+                removeNext();
+        }
+        
+    private:
+        void addNotThreadSafe(T* handler)
+        {
+            if (handler->m_nextAndFlag & 1)
+                return;
+            handler->m_nextAndFlag = reinterpret_cast<uintptr_t>(m_first) | 1;
+            m_first = handler;
+        }
+        
+        Mutex m_lock;
+        T* m_first;
+    };
+    
+    uintptr_t m_nextAndFlag;
+};
+
+} // namespace JSC
+
+#endif // ListableHandler_h
index ac7d13696a1d261f51957a7627181bc972a3b956..5d1f064391317f004f395ec6fb8312b214a9fc32 100644 (file)
@@ -57,13 +57,13 @@ private:
 };
 
 template <typename T> inline Local<T>::Local(JSGlobalData& globalData, ExternalType value)
 };
 
 template <typename T> inline Local<T>::Local(JSGlobalData& globalData, ExternalType value)
-    : Handle<T>(globalData.allocateLocalHandle())
+    : Handle<T>(globalData.heap.handleStack()->push())
 {
     set(value);
 }
 
 template <typename T> inline Local<T>::Local(JSGlobalData& globalData, Handle<T> other)
 {
     set(value);
 }
 
 template <typename T> inline Local<T>::Local(JSGlobalData& globalData, Handle<T> other)
-    : Handle<T>(globalData.allocateLocalHandle())
+    : Handle<T>(globalData.heap.handleStack()->push())
 {
     set(other.get());
 }
 {
     set(other.get());
 }
@@ -94,7 +94,6 @@ template <typename T> inline Local<T>& Local<T>::operator=(Handle<T> other)
 template <typename T> inline void Local<T>::set(ExternalType externalType)
 {
     ASSERT(slot());
 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;
 }
 
     *slot() = externalType;
 }
 
@@ -103,7 +102,7 @@ template <typename T, unsigned inlineCapacity = 0> class LocalStack {
     typedef typename Handle<T>::ExternalType ExternalType;
 public:
     LocalStack(JSGlobalData& globalData)
     typedef typename Handle<T>::ExternalType ExternalType;
 public:
     LocalStack(JSGlobalData& globalData)
-        : m_globalData(&globalData)
+        : m_globalData(globalData)
         , m_count(0)
     {
     }
         , m_count(0)
     {
     }
@@ -123,7 +122,7 @@ public:
     void push(ExternalType value)
     {
         if (m_count == m_stack.size())
     void push(ExternalType value)
     {
         if (m_count == m_stack.size())
-            m_stack.append(Local<T>(*m_globalData, value));
+            m_stack.append(Local<T>(m_globalData, value));
         else
             m_stack[m_count] = value;
         m_count++;
         else
             m_stack[m_count] = value;
         m_count++;
@@ -133,7 +132,7 @@ public:
     unsigned size() const { return m_count; }
 
 private:
     unsigned size() const { return m_count; }
 
 private:
-    RefPtr<JSGlobalData> m_globalData;
+    JSGlobalData& m_globalData;
     Vector<Local<T>, inlineCapacity> m_stack;
     unsigned m_count;
 };
     Vector<Local<T>, inlineCapacity> m_stack;
     unsigned m_count;
 };
index 73a3db6778d2c4d2553dff142fe3241a1c3b2b81..30915eaf8b7aa7ed2f0fb3bf1940bd90cf9aeb58 100644 (file)
 #include <stdlib.h>
 #include <wtf/StdLibExtras.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>
 #if OS(DARWIN)
 
 #include <mach/mach_init.h>
 #include <windows.h>
 #include <malloc.h>
 
 #include <windows.h>
 #include <malloc.h>
 
-#elif OS(HAIKU)
-
-#include <OS.h>
-
 #elif OS(UNIX)
 
 #include <stdlib.h>
 #elif OS(UNIX)
 
 #include <stdlib.h>
-#if !OS(HAIKU)
 #include <sys/mman.h>
 #include <sys/mman.h>
-#endif
 #include <unistd.h>
 
 #if OS(SOLARIS)
 #include <unistd.h>
 
 #if OS(SOLARIS)
@@ -78,9 +68,6 @@
 
 #if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
 #include <signal.h>
 
 #if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
 #include <signal.h>
-#ifndef SA_RESTART
-#error MachineThreads requires SA_RESTART
-#endif
 #endif
 
 #endif
 #endif
 
 #endif
@@ -101,8 +88,6 @@ UNUSED_PARAM(end);
 #endif
 }
 
 #endif
 }
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
 #if OS(DARWIN)
 typedef mach_port_t PlatformThread;
 #elif OS(WINDOWS)
 #if OS(DARWIN)
 typedef mach_port_t PlatformThread;
 #elif OS(WINDOWS)
@@ -111,6 +96,7 @@ typedef HANDLE PlatformThread;
 typedef pthread_t PlatformThread;
 static const int SigThreadSuspendResume = SIGUSR2;
 
 typedef pthread_t PlatformThread;
 static const int SigThreadSuspendResume = SIGUSR2;
 
+#if defined(SA_RESTART)
 static void pthreadSignalHandlerSuspendResume(int signo)
 {
     sigset_t signalSet;
 static void pthreadSignalHandlerSuspendResume(int signo)
 {
     sigset_t signalSet;
@@ -119,15 +105,16 @@ static void pthreadSignalHandlerSuspendResume(int signo)
     sigsuspend(&signalSet);
 }
 #endif
     sigsuspend(&signalSet);
 }
 #endif
+#endif
 
 class MachineThreads::Thread {
 public:
 
 class MachineThreads::Thread {
 public:
-    Thread(pthread_t pthread, const PlatformThread& platThread, void* base) 
-        : posixThread(pthread)
-        , platformThread(platThread)
+    Thread(const PlatformThread& platThread, void* base)
+        : platformThread(platThread)
         , stackBase(base)
     {
         , stackBase(base)
     {
-#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
+#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) && defined(SA_RESTART)
+        // if we have SA_RESTART, enable SIGUSR2 debugging mechanism
         struct sigaction action;
         action.sa_handler = pthreadSignalHandlerSuspendResume;
         sigemptyset(&action.sa_mask);
         struct sigaction action;
         action.sa_handler = pthreadSignalHandlerSuspendResume;
         sigemptyset(&action.sa_mask);
@@ -142,25 +129,19 @@ public:
     }
 
     Thread* next;
     }
 
     Thread* next;
-    pthread_t posixThread;
     PlatformThread platformThread;
     void* stackBase;
 };
 
     PlatformThread platformThread;
     void* stackBase;
 };
 
-#endif
-
 MachineThreads::MachineThreads(Heap* heap)
     : m_heap(heap)
 MachineThreads::MachineThreads(Heap* heap)
     : m_heap(heap)
-#if ENABLE(JSC_MULTIPLE_THREADS)
     , m_registeredThreads(0)
     , m_threadSpecific(0)
     , m_registeredThreads(0)
     , m_threadSpecific(0)
-#endif
 {
 }
 
 MachineThreads::~MachineThreads()
 {
 {
 }
 
 MachineThreads::~MachineThreads()
 {
-#if ENABLE(JSC_MULTIPLE_THREADS)
     if (m_threadSpecific) {
         int error = pthread_key_delete(m_threadSpecific);
         ASSERT_UNUSED(error, !error);
     if (m_threadSpecific) {
         int error = pthread_key_delete(m_threadSpecific);
         ASSERT_UNUSED(error, !error);
@@ -172,22 +153,30 @@ MachineThreads::~MachineThreads()
         delete t;
         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)
 static inline PlatformThread getCurrentPlatformThread()
 {
 #if OS(DARWIN)
     return pthread_mach_thread_np(pthread_self());
 #elif OS(WINDOWS)
-    return pthread_getw32threadhandle_np(pthread_self());
+    return GetCurrentThread();
 #elif USE(PTHREADS)
     return pthread_self();
 #endif
 }
 
 #elif USE(PTHREADS)
     return pthread_self();
 #endif
 }
 
+static inline bool equalThread(const PlatformThread& first, const PlatformThread& second)
+{
+#if OS(DARWIN) || OS(WINDOWS)
+    return first == second;
+#elif USE(PTHREADS)
+    return !!pthread_equal(first, second);
+#else
+#error Need a way to compare threads on this platform
+#endif
+}
+
 void MachineThreads::makeUsableFromMultipleThreads()
 {
     if (m_threadSpecific)
 void MachineThreads::makeUsableFromMultipleThreads()
 {
     if (m_threadSpecific)
@@ -206,7 +195,7 @@ void MachineThreads::addCurrentThread()
         return;
 
     pthread_setspecific(m_threadSpecific, this);
         return;
 
     pthread_setspecific(m_threadSpecific, this);
-    Thread* thread = new Thread(pthread_self(), getCurrentPlatformThread(), m_heap->globalData()->stack().origin());
+    Thread* thread = new Thread(getCurrentPlatformThread(), wtfThreadData().stack().origin());
 
     MutexLocker lock(m_registeredThreadsMutex);
 
 
     MutexLocker lock(m_registeredThreadsMutex);
 
@@ -222,11 +211,11 @@ void MachineThreads::removeThread(void* p)
 
 void MachineThreads::removeCurrentThread()
 {
 
 void MachineThreads::removeCurrentThread()
 {
-    pthread_t currentPosixThread = pthread_self();
+    PlatformThread currentPlatformThread = getCurrentPlatformThread();
 
     MutexLocker lock(m_registeredThreadsMutex);
 
 
     MutexLocker lock(m_registeredThreadsMutex);
 
-    if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) {
+    if (equalThread(currentPlatformThread, m_registeredThreads->platformThread)) {
         Thread* t = m_registeredThreads;
         m_registeredThreads = m_registeredThreads->next;
         delete t;
         Thread* t = m_registeredThreads;
         m_registeredThreads = m_registeredThreads->next;
         delete t;
@@ -234,7 +223,7 @@ void MachineThreads::removeCurrentThread()
         Thread* last = m_registeredThreads;
         Thread* t;
         for (t = m_registeredThreads->next; t; t = t->next) {
         Thread* last = m_registeredThreads;
         Thread* t;
         for (t = m_registeredThreads->next; t; t = t->next) {
-            if (pthread_equal(t->posixThread, currentPosixThread)) {
+            if (equalThread(t->platformThread, currentPlatformThread)) {
                 last->next = t->next;
                 break;
             }
                 last->next = t->next;
                 break;
             }
@@ -245,8 +234,6 @@ void MachineThreads::removeCurrentThread()
     }
 }
 
     }
 }
 
-#endif
-
 #if COMPILER(GCC)
 #define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
 #else
 #if COMPILER(GCC)
 #define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
 #else
@@ -272,13 +259,11 @@ void MachineThreads::gatherFromCurrentThread(ConservativeRoots& conservativeRoot
     conservativeRoots.add(registersBegin, registersEnd);
 
     void* stackBegin = stackCurrent;
     conservativeRoots.add(registersBegin, registersEnd);
 
     void* stackBegin = stackCurrent;
-    void* stackEnd = m_heap->globalData()->stack().origin();
+    void* stackEnd = wtfThreadData().stack().origin();
     swapIfBackwards(stackBegin, stackEnd);
     conservativeRoots.add(stackBegin, stackEnd);
 }
 
     swapIfBackwards(stackBegin, stackEnd);
     conservativeRoots.add(stackBegin, stackEnd);
 }
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
 static inline void suspendThread(const PlatformThread& platformThread)
 {
 #if OS(DARWIN)
 static inline void suspendThread(const PlatformThread& platformThread)
 {
 #if OS(DARWIN)
@@ -325,6 +310,8 @@ typedef arm_thread_state_t PlatformThreadRegisters;
 
 #elif OS(WINDOWS)
 typedef CONTEXT PlatformThreadRegisters;
 
 #elif OS(WINDOWS)
 typedef CONTEXT PlatformThreadRegisters;
+#elif OS(QNX)
+typedef struct _debug_thread_info PlatformThreadRegisters;
 #elif USE(PTHREADS)
 typedef pthread_attr_t PlatformThreadRegisters;
 #else
 #elif USE(PTHREADS)
 typedef pthread_attr_t PlatformThreadRegisters;
 #else
@@ -364,9 +351,19 @@ static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, P
 // end OS(DARWIN)
 
 #elif OS(WINDOWS)
 // end OS(DARWIN)
 
 #elif OS(WINDOWS)
-    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
+    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
     GetThreadContext(platformThread, &regs);
     return sizeof(CONTEXT);
     GetThreadContext(platformThread, &regs);
     return sizeof(CONTEXT);
+#elif OS(QNX)
+    memset(&regs, 0, sizeof(regs));
+    regs.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, &regs, sizeof(regs), 0);
+    close(fd);
 #elif USE(PTHREADS)
     pthread_attr_init(&regs);
 #if HAVE(PTHREAD_NP_H) || OS(NETBSD)
 #elif USE(PTHREADS)
     pthread_attr_init(&regs);
 #if HAVE(PTHREAD_NP_H) || OS(NETBSD)
@@ -415,10 +412,23 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
 #endif // __DARWIN_UNIX03
 
 // end OS(DARWIN)
 #endif // __DARWIN_UNIX03
 
 // end OS(DARWIN)
-#elif CPU(X86) && OS(WINDOWS)
+#elif OS(WINDOWS)
+
+#if CPU(ARM)
+    return reinterpret_cast<void*>((uintptr_t) regs.Sp);
+#elif CPU(MIPS)
+    return reinterpret_cast<void*>((uintptr_t) regs.IntSp);
+#elif CPU(X86)
     return reinterpret_cast<void*>((uintptr_t) regs.Esp);
     return reinterpret_cast<void*>((uintptr_t) regs.Esp);
-#elif CPU(X86_64) && OS(WINDOWS)
+#elif CPU(X86_64)
     return reinterpret_cast<void*>((uintptr_t) regs.Rsp);
     return reinterpret_cast<void*>((uintptr_t) regs.Rsp);
+#else
+#error Unknown Architecture
+#endif
+
+#elif OS(QNX)
+    return reinterpret_cast<void*>((uintptr_t) regs.sp);
+
 #elif USE(PTHREADS)
     void* stackBase = 0;
     size_t stackSize = 0;
 #elif USE(PTHREADS)
     void* stackBase = 0;
     size_t stackSize = 0;
@@ -433,7 +443,7 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
 
 static void freePlatformThreadRegisters(PlatformThreadRegisters& regs)
 {
 
 static void freePlatformThreadRegisters(PlatformThreadRegisters& regs)
 {
-#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
+#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) && !OS(QNX)
     pthread_attr_destroy(&regs);
 #else
     UNUSED_PARAM(regs);
     pthread_attr_destroy(&regs);
 #else
     UNUSED_PARAM(regs);
@@ -459,15 +469,12 @@ void MachineThreads::gatherFromOtherThread(ConservativeRoots& conservativeRoots,
     freePlatformThreadRegisters(regs);
 }
 
     freePlatformThreadRegisters(regs);
 }
 
-#endif
-
 void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, void* stackCurrent)
 {
     gatherFromCurrentThread(conservativeRoots, stackCurrent);
 
 void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, void* stackCurrent)
 {
     gatherFromCurrentThread(conservativeRoots, stackCurrent);
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
     if (m_threadSpecific) {
     if (m_threadSpecific) {
+        PlatformThread currentPlatformThread = getCurrentPlatformThread();
 
         MutexLocker lock(m_registeredThreadsMutex);
 
 
         MutexLocker lock(m_registeredThreadsMutex);
 
@@ -480,14 +487,13 @@ void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoot
         // 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) {
         // 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()))
+            if (!equalThread(thread->platformThread, currentPlatformThread))
                 gatherFromOtherThread(conservativeRoots, thread);
         }
 #ifndef NDEBUG
         fastMallocAllow();
 #endif
     }
                 gatherFromOtherThread(conservativeRoots, thread);
         }
 #ifndef NDEBUG
         fastMallocAllow();
 #endif
     }
-#endif
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index c814ac5510e9d95f3a36c8eda42494f47443605f..eeb7db9a2480f0dfdfc5a5861042a6806ec909b0 100644 (file)
 #ifndef MachineThreads_h
 #define MachineThreads_h
 
 #ifndef MachineThreads_h
 #define MachineThreads_h
 
+#include <pthread.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/ThreadingPrimitives.h>
 
 #include <wtf/Noncopyable.h>
 #include <wtf/ThreadingPrimitives.h>
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-#include <pthread.h>
-#endif
-
 namespace JSC {
 
     class Heap;
 namespace JSC {
 
     class Heap;
@@ -42,30 +39,23 @@ namespace JSC {
 
         void gatherConservativeRoots(ConservativeRoots&, void* stackCurrent);
 
 
         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
+        JS_EXPORT_PRIVATE void makeUsableFromMultipleThreads();
+        JS_EXPORT_PRIVATE void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
 
     private:
         void gatherFromCurrentThread(ConservativeRoots&, void* stackCurrent);
 
 
     private:
         void gatherFromCurrentThread(ConservativeRoots&, void* stackCurrent);
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
         class Thread;
 
         static void removeThread(void*);
         void removeCurrentThread();
 
         void gatherFromOtherThread(ConservativeRoots&, Thread*);
         class Thread;
 
         static void removeThread(void*);
         void removeCurrentThread();
 
         void gatherFromOtherThread(ConservativeRoots&, Thread*);
-#endif
 
         Heap* m_heap;
 
         Heap* m_heap;
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
         Mutex m_registeredThreadsMutex;
         Thread* m_registeredThreads;
         pthread_key_t m_threadSpecific;
         Mutex m_registeredThreadsMutex;
         Thread* m_registeredThreads;
         pthread_key_t m_threadSpecific;
-#endif
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index d3adfdceb0becb2dcf47ffb178780c43ef1cdc41..cf6e3513ce2caeb08aff4d3f7c1611875212267e 100644 (file)
 #include "config.h"
 #include "MarkStack.h"
 
 #include "config.h"
 #include "MarkStack.h"
 
+#include "CopiedSpace.h"
+#include "CopiedSpaceInlineMethods.h"
 #include "ConservativeRoots.h"
 #include "Heap.h"
 #include "ConservativeRoots.h"
 #include "Heap.h"
+#include "Options.h"
 #include "JSArray.h"
 #include "JSCell.h"
 #include "JSObject.h"
 #include "ScopeChain.h"
 #include "Structure.h"
 #include "JSArray.h"
 #include "JSCell.h"
 #include "JSObject.h"
 #include "ScopeChain.h"
 #include "Structure.h"
+#include "WriteBarrier.h"
+#include <wtf/MainThread.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
-size_t MarkStack::s_pageSize = 0;
+MarkStackSegmentAllocator::MarkStackSegmentAllocator()
+    : m_nextFreeSegment(0)
+{
+}
+
+MarkStackSegmentAllocator::~MarkStackSegmentAllocator()
+{
+    shrinkReserve();
+}
+
+MarkStackSegment* MarkStackSegmentAllocator::allocate()
+{
+    {
+        MutexLocker locker(m_lock);
+        if (m_nextFreeSegment) {
+            MarkStackSegment* result = m_nextFreeSegment;
+            m_nextFreeSegment = result->m_previous;
+            return result;
+        }
+    }
+
+    return static_cast<MarkStackSegment*>(OSAllocator::reserveAndCommit(Options::gcMarkStackSegmentSize));
+}
+
+void MarkStackSegmentAllocator::release(MarkStackSegment* segment)
+{
+    MutexLocker locker(m_lock);
+    segment->m_previous = m_nextFreeSegment;
+    m_nextFreeSegment = segment;
+}
+
+void MarkStackSegmentAllocator::shrinkReserve()
+{
+    MarkStackSegment* segments;
+    {
+        MutexLocker locker(m_lock);
+        segments = m_nextFreeSegment;
+        m_nextFreeSegment = 0;
+    }
+    while (segments) {
+        MarkStackSegment* toFree = segments;
+        segments = segments->m_previous;
+        OSAllocator::decommitAndRelease(toFree, Options::gcMarkStackSegmentSize);
+    }
+}
+
+MarkStackArray::MarkStackArray(MarkStackSegmentAllocator& allocator)
+    : m_allocator(allocator)
+    , m_segmentCapacity(MarkStackSegment::capacityFromSize(Options::gcMarkStackSegmentSize))
+    , m_top(0)
+    , m_numberOfPreviousSegments(0)
+{
+    m_topSegment = m_allocator.allocate();
+#if !ASSERT_DISABLED
+    m_topSegment->m_top = 0;
+#endif
+    m_topSegment->m_previous = 0;
+}
+
+MarkStackArray::~MarkStackArray()
+{
+    ASSERT(!m_topSegment->m_previous);
+    m_allocator.release(m_topSegment);
+}
+
+void MarkStackArray::expand()
+{
+    ASSERT(m_topSegment->m_top == m_segmentCapacity);
+    
+    m_numberOfPreviousSegments++;
+    
+    MarkStackSegment* nextSegment = m_allocator.allocate();
+#if !ASSERT_DISABLED
+    nextSegment->m_top = 0;
+#endif
+    nextSegment->m_previous = m_topSegment;
+    m_topSegment = nextSegment;
+    setTopForEmptySegment();
+    validatePrevious();
+}
+
+bool MarkStackArray::refill()
+{
+    validatePrevious();
+    if (top())
+        return true;
+    MarkStackSegment* toFree = m_topSegment;
+    MarkStackSegment* previous = m_topSegment->m_previous;
+    if (!previous)
+        return false;
+    ASSERT(m_numberOfPreviousSegments);
+    m_numberOfPreviousSegments--;
+    m_topSegment = previous;
+    m_allocator.release(toFree);
+    setTopForFullSegment();
+    validatePrevious();
+    return true;
+}
+
+bool MarkStackArray::donateSomeCellsTo(MarkStackArray& other)
+{
+    ASSERT(m_segmentCapacity == other.m_segmentCapacity);
+    validatePrevious();
+    other.validatePrevious();
+        
+    // Fast check: see if the other mark stack already has enough segments.
+    if (other.m_numberOfPreviousSegments + 1 >= Options::maximumNumberOfSharedSegments)
+        return false;
+        
+    size_t numberOfCellsToKeep = Options::minimumNumberOfCellsToKeep;
+    ASSERT(m_top > numberOfCellsToKeep || m_topSegment->m_previous);
+        
+    // Looks like we should donate! Give the other mark stack all of our
+    // previous segments, and then top it off.
+    MarkStackSegment* previous = m_topSegment->m_previous;
+    while (previous) {
+        ASSERT(m_numberOfPreviousSegments);
+
+        MarkStackSegment* current = previous;
+        previous = current->m_previous;
+            
+        current->m_previous = other.m_topSegment->m_previous;
+        other.m_topSegment->m_previous = current;
+            
+        m_numberOfPreviousSegments--;
+        other.m_numberOfPreviousSegments++;
+    }
+    ASSERT(!m_numberOfPreviousSegments);
+    m_topSegment->m_previous = 0;
+    validatePrevious();
+    other.validatePrevious();
+        
+    // Now top off. We want to keep at a minimum numberOfCellsToKeep, but if
+    // we really have a lot of work, we give up half.
+    if (m_top > numberOfCellsToKeep * 2)
+        numberOfCellsToKeep = m_top / 2;
+    while (m_top > numberOfCellsToKeep)
+        other.append(removeLast());
+        
+    return true;
+}
+
+void MarkStackArray::stealSomeCellsFrom(MarkStackArray& other)
+{
+    ASSERT(m_segmentCapacity == other.m_segmentCapacity);
+    validatePrevious();
+    other.validatePrevious();
+        
+    // If other has an entire segment, steal it and return.
+    if (other.m_topSegment->m_previous) {
+        ASSERT(other.m_topSegment->m_previous->m_top == m_segmentCapacity);
+            
+        // First remove a segment from other.
+        MarkStackSegment* current = other.m_topSegment->m_previous;
+        other.m_topSegment->m_previous = current->m_previous;
+        other.m_numberOfPreviousSegments--;
+            
+        ASSERT(!!other.m_numberOfPreviousSegments == !!other.m_topSegment->m_previous);
+            
+        // Now add it to this.
+        current->m_previous = m_topSegment->m_previous;
+        m_topSegment->m_previous = current;
+        m_numberOfPreviousSegments++;
+            
+        validatePrevious();
+        other.validatePrevious();
+        return;
+    }
+        
+    // Otherwise drain 1/Nth of the shared array where N is the number of
+    // workers, or Options::minimumNumberOfCellsToKeep, whichever is bigger.
+    size_t numberOfCellsToSteal = std::max((size_t)Options::minimumNumberOfCellsToKeep, other.size() / Options::numberOfGCMarkers);
+    while (numberOfCellsToSteal-- > 0 && other.canRemoveLast())
+        append(other.removeLast());
+}
+
+#if ENABLE(PARALLEL_GC)
+void MarkStackThreadSharedData::markingThreadMain()
+{
+    WTF::registerGCThread();
+    SlotVisitor slotVisitor(*this);
+    ParallelModeEnabler enabler(slotVisitor);
+    slotVisitor.drainFromShared(SlotVisitor::SlaveDrain);
+}
+
+void MarkStackThreadSharedData::markingThreadStartFunc(void* shared)
+{
+    static_cast<MarkStackThreadSharedData*>(shared)->markingThreadMain();
+}
+#endif
+
+MarkStackThreadSharedData::MarkStackThreadSharedData(JSGlobalData* globalData)
+    : m_globalData(globalData)
+    , m_copiedSpace(&globalData->heap.m_storageSpace)
+    , m_sharedMarkStack(m_segmentAllocator)
+    , m_numberOfActiveParallelMarkers(0)
+    , m_parallelMarkersShouldExit(false)
+{
+#if ENABLE(PARALLEL_GC)
+    for (unsigned i = 1; i < Options::numberOfGCMarkers; ++i) {
+        m_markingThreads.append(createThread(markingThreadStartFunc, this, "JavaScriptCore::Marking"));
+        ASSERT(m_markingThreads.last());
+    }
+#endif
+}
+
+MarkStackThreadSharedData::~MarkStackThreadSharedData()
+{
+#if ENABLE(PARALLEL_GC)    
+    // Destroy our marking threads.
+    {
+        MutexLocker locker(m_markingLock);
+        m_parallelMarkersShouldExit = true;
+        m_markingCondition.broadcast();
+    }
+    for (unsigned i = 0; i < m_markingThreads.size(); ++i)
+        waitForThreadCompletion(m_markingThreads[i]);
+#endif
+}
+    
+void MarkStackThreadSharedData::reset()
+{
+    ASSERT(!m_numberOfActiveParallelMarkers);
+    ASSERT(!m_parallelMarkersShouldExit);
+    ASSERT(m_sharedMarkStack.isEmpty());
+    
+#if ENABLE(PARALLEL_GC)
+    m_segmentAllocator.shrinkReserve();
+    m_opaqueRoots.clear();
+#else
+    ASSERT(m_opaqueRoots.isEmpty());
+#endif
+    
+    m_weakReferenceHarvesters.removeAll();
+}
 
 void MarkStack::reset()
 {
 
 void MarkStack::reset()
 {
-    ASSERT(s_pageSize);
-    m_values.shrinkAllocation(s_pageSize);
-    m_markSets.shrinkAllocation(s_pageSize);
+    m_visitCount = 0;
+    ASSERT(m_stack.isEmpty());
+#if ENABLE(PARALLEL_GC)
+    ASSERT(m_opaqueRoots.isEmpty()); // Should have merged by now.
+#else
     m_opaqueRoots.clear();
     m_opaqueRoots.clear();
+#endif
 }
 
 void MarkStack::append(ConservativeRoots& conservativeRoots)
 }
 
 void MarkStack::append(ConservativeRoots& conservativeRoots)
@@ -54,100 +296,243 @@ void MarkStack::append(ConservativeRoots& conservativeRoots)
         internalAppend(roots[i]);
 }
 
         internalAppend(roots[i]);
 }
 
-inline void MarkStack::visitChildren(JSCell* cell)
+ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell)
 {
 {
+#if ENABLE(SIMPLE_HEAP_PROFILING)
+    m_visitedTypeCounts.count(cell);
+#endif
+
     ASSERT(Heap::isMarked(cell));
     ASSERT(Heap::isMarked(cell));
-    if (cell->structure()->typeInfo().type() < CompoundType) {
-        cell->JSCell::visitChildren(*this);
+    
+    if (isJSString(cell)) {
+        JSString::visitChildren(const_cast<JSCell*>(cell), visitor);
         return;
     }
 
         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
+    if (isJSFinalObject(cell)) {
+        JSObject::visitChildren(const_cast<JSCell*>(cell), visitor);
         return;
     }
         return;
     }
-    if (cell->vptr() == m_jsArrayVPtr) {
-        asArray(cell)->visitChildrenDirect(*this);
+
+    if (isJSArray(cell)) {
+        JSArray::visitChildren(const_cast<JSCell*>(cell), visitor);
         return;
     }
         return;
     }
-    cell->visitChildren(*this);
+
+    cell->methodTable()->visitChildren(const_cast<JSCell*>(cell), visitor);
 }
 
 }
 
-void MarkStack::drain()
+void SlotVisitor::donateSlow()
 {
 {
-#if !ASSERT_DISABLED
-    ASSERT(!m_isDraining);
-    m_isDraining = true;
+    // Refuse to donate if shared has more entries than I do.
+    if (m_shared.m_sharedMarkStack.size() > m_stack.size())
+        return;
+    MutexLocker locker(m_shared.m_markingLock);
+    if (m_stack.donateSomeCellsTo(m_shared.m_sharedMarkStack)) {
+        // Only wake up threads if the shared stack is big enough; otherwise assume that
+        // it's more profitable for us to just scan this ourselves later.
+        if (m_shared.m_sharedMarkStack.size() >= Options::sharedStackWakeupThreshold)
+            m_shared.m_markingCondition.broadcast();
+    }
+}
+
+void SlotVisitor::drain()
+{
+    ASSERT(m_isInParallelMode);
+   
+#if ENABLE(PARALLEL_GC)
+    if (Options::numberOfGCMarkers > 1) {
+        while (!m_stack.isEmpty()) {
+            m_stack.refill();
+            for (unsigned countdown = Options::minimumNumberOfScansBetweenRebalance; m_stack.canRemoveLast() && countdown--;)
+                visitChildren(*this, m_stack.removeLast());
+            donateKnownParallel();
+        }
+        
+        mergeOpaqueRootsIfNecessary();
+        return;
+    }
 #endif
 #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;
-            }
+    
+    while (!m_stack.isEmpty()) {
+        m_stack.refill();
+        while (m_stack.canRemoveLast())
+            visitChildren(*this, m_stack.removeLast());
+    }
+}
 
 
-            if (cell->structure()->typeInfo().type() < CompoundType) {
-                cell->JSCell::visitChildren(*this);
-                if (current.m_values == end) {
-                    m_markSets.removeLast();
-                    continue;
-                }
-                goto findNextUnmarkedNullValue;
-            }
+void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode)
+{
+    ASSERT(m_isInParallelMode);
+    
+    ASSERT(Options::numberOfGCMarkers);
+    
+    bool shouldBeParallel;
 
 
-            if (current.m_values == end)
-                m_markSets.removeLast();
+#if ENABLE(PARALLEL_GC)
+    shouldBeParallel = Options::numberOfGCMarkers > 1;
+#else
+    ASSERT(Options::numberOfGCMarkers == 1);
+    shouldBeParallel = false;
+#endif
+    
+    if (!shouldBeParallel) {
+        // This call should be a no-op.
+        ASSERT_UNUSED(sharedDrainMode, sharedDrainMode == MasterDrain);
+        ASSERT(m_stack.isEmpty());
+        ASSERT(m_shared.m_sharedMarkStack.isEmpty());
+        return;
+    }
+    
+#if ENABLE(PARALLEL_GC)
+    {
+        MutexLocker locker(m_shared.m_markingLock);
+        m_shared.m_numberOfActiveParallelMarkers++;
+    }
+    while (true) {
+        {
+            MutexLocker locker(m_shared.m_markingLock);
+            m_shared.m_numberOfActiveParallelMarkers--;
 
 
-            visitChildren(cell);
+            // How we wait differs depending on drain mode.
+            if (sharedDrainMode == MasterDrain) {
+                // Wait until either termination is reached, or until there is some work
+                // for us to do.
+                while (true) {
+                    // Did we reach termination?
+                    if (!m_shared.m_numberOfActiveParallelMarkers && m_shared.m_sharedMarkStack.isEmpty()) {
+                        // Let any sleeping slaves know it's time for them to give their private CopiedBlocks back
+                        m_shared.m_markingCondition.broadcast();
+                        return;
+                    }
+                    
+                    // Is there work to be done?
+                    if (!m_shared.m_sharedMarkStack.isEmpty())
+                        break;
+                    
+                    // Otherwise wait.
+                    m_shared.m_markingCondition.wait(m_shared.m_markingLock);
+                }
+            } else {
+                ASSERT(sharedDrainMode == SlaveDrain);
+                
+                // Did we detect termination? If so, let the master know.
+                if (!m_shared.m_numberOfActiveParallelMarkers && m_shared.m_sharedMarkStack.isEmpty())
+                    m_shared.m_markingCondition.broadcast();
+                
+                while (m_shared.m_sharedMarkStack.isEmpty() && !m_shared.m_parallelMarkersShouldExit) {
+                    if (!m_shared.m_numberOfActiveParallelMarkers && m_shared.m_sharedMarkStack.isEmpty())
+                        doneCopying();
+                    m_shared.m_markingCondition.wait(m_shared.m_markingLock);
+                }
+                
+                // Is the VM exiting? If so, exit this thread.
+                if (m_shared.m_parallelMarkersShouldExit) {
+                    doneCopying();
+                    return;
+                }
+            }
+           
+            m_stack.stealSomeCellsFrom(m_shared.m_sharedMarkStack);
+            m_shared.m_numberOfActiveParallelMarkers++;
         }
         }
-        while (!m_values.isEmpty())
-            visitChildren(m_values.removeLast());
+        
+        drain();
     }
     }
-#if !ASSERT_DISABLED
-    m_isDraining = false;
 #endif
 }
 
 #endif
 }
 
-#if ENABLE(GC_VALIDATION)
-void MarkStack::validateSet(JSValue* values, size_t count)
+void MarkStack::mergeOpaqueRoots()
 {
 {
-    for (size_t i = 0; i < count; i++) {
-        if (values[i])
-            validateValue(values[i]);
+    ASSERT(!m_opaqueRoots.isEmpty()); // Should only be called when opaque roots are non-empty.
+    {
+        MutexLocker locker(m_shared.m_opaqueRootsLock);
+        HashSet<void*>::iterator begin = m_opaqueRoots.begin();
+        HashSet<void*>::iterator end = m_opaqueRoots.end();
+        for (HashSet<void*>::iterator iter = begin; iter != end; ++iter)
+            m_shared.m_opaqueRoots.add(*iter);
     }
     }
+    m_opaqueRoots.clear();
 }
 
 }
 
-void MarkStack::validateValue(JSValue value)
+void SlotVisitor::startCopying()
 {
 {
-    if (!value)
+    ASSERT(!m_copyBlock);
+    if (!m_shared.m_copiedSpace->borrowBlock(&m_copyBlock))
         CRASH();
         CRASH();
-    if (!value.isCell())
+}    
+
+void* SlotVisitor::allocateNewSpace(void* ptr, size_t bytes)
+{
+    if (CopiedSpace::isOversize(bytes)) {
+        m_shared.m_copiedSpace->pin(CopiedSpace::oversizeBlockFor(ptr));
+        return 0;
+    }
+
+    if (m_shared.m_copiedSpace->isPinned(ptr))
+        return 0;
+
+    // The only time it's possible to have a null copy block is if we have just started copying.
+    if (!m_copyBlock)
+        startCopying();
+
+    if (!CopiedSpace::fitsInBlock(m_copyBlock, bytes)) {
+        // We don't need to lock across these two calls because the master thread won't 
+        // call doneCopying() because this thread is considered active.
+        m_shared.m_copiedSpace->doneFillingBlock(m_copyBlock);
+        if (!m_shared.m_copiedSpace->borrowBlock(&m_copyBlock))
+            CRASH();
+    }
+    return CopiedSpace::allocateFromBlock(m_copyBlock, bytes);
+}
+
+void SlotVisitor::copyAndAppend(void** ptr, size_t bytes, JSValue* values, unsigned length)
+{
+    void* oldPtr = *ptr;
+    void* newPtr = allocateNewSpace(oldPtr, bytes);
+    if (newPtr) {
+        size_t jsValuesOffset = static_cast<size_t>(reinterpret_cast<char*>(values) - static_cast<char*>(oldPtr));
+
+        JSValue* newValues = reinterpret_cast_ptr<JSValue*>(static_cast<char*>(newPtr) + jsValuesOffset);
+        for (unsigned i = 0; i < length; i++) {
+            JSValue& value = values[i];
+            newValues[i] = value;
+            if (!value)
+                continue;
+            internalAppend(value);
+        }
+
+        memcpy(newPtr, oldPtr, jsValuesOffset);
+        *ptr = newPtr;
+    } else
+        append(values, length);
+}
+    
+void SlotVisitor::doneCopying()
+{
+    if (!m_copyBlock)
         return;
         return;
-    JSCell* cell = value.asCell();
+
+    m_shared.m_copiedSpace->doneFillingBlock(m_copyBlock);
+
+    m_copyBlock = 0;
+}
+
+void SlotVisitor::harvestWeakReferences()
+{
+    for (WeakReferenceHarvester* current = m_shared.m_weakReferenceHarvesters.head(); current; current = current->next())
+        current->visitWeakReferences(*this);
+}
+
+void SlotVisitor::finalizeUnconditionalFinalizers()
+{
+    while (m_shared.m_unconditionalFinalizers.hasNext())
+        m_shared.m_unconditionalFinalizers.removeNext()->finalizeUnconditionally();
+}
+
+#if ENABLE(GC_VALIDATION)
+void MarkStack::validate(JSCell* cell)
+{
     if (!cell)
         CRASH();
 
     if (!cell)
         CRASH();
 
@@ -159,6 +544,10 @@ void MarkStack::validateValue(JSValue value)
     if (cell->structure()->structure()->JSCell::classInfo() != cell->structure()->JSCell::classInfo())
         CRASH();
 }
     if (cell->structure()->structure()->JSCell::classInfo() != cell->structure()->JSCell::classInfo())
         CRASH();
 }
+#else
+void MarkStack::validate(JSCell*)
+{
+}
 #endif
 
 } // namespace JSC
 #endif
 
 } // namespace JSC
index f269fd208caaeb3b4a3675b2dcaaa58d78331567..0695b1b32278342613c164ff1f2a3c44dbc4d97d 100644 (file)
 #ifndef MarkStack_h
 #define MarkStack_h
 
 #ifndef MarkStack_h
 #define MarkStack_h
 
+#include "CopiedSpace.h"
 #include "HandleTypes.h"
 #include "HandleTypes.h"
+#include "Options.h"
 #include "JSValue.h"
 #include "Register.h"
 #include "JSValue.h"
 #include "Register.h"
+#include "UnconditionalFinalizer.h"
+#include "VTableSpectrum.h"
+#include "WeakReferenceHarvester.h"
+#include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/Vector.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/OSAllocator.h>
 #include <wtf/HashSet.h>
 #include <wtf/Vector.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/OSAllocator.h>
+#include <wtf/PageBlock.h>
 
 namespace JSC {
 
     class ConservativeRoots;
     class JSGlobalData;
 
 namespace JSC {
 
     class ConservativeRoots;
     class JSGlobalData;
+    class MarkStack;
+    class ParallelModeEnabler;
     class Register;
     class Register;
+    class SlotVisitor;
     template<typename T> class WriteBarrierBase;
     template<typename T> class JITWriteBarrier;
     
     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)
+    struct MarkStackSegment {
+        MarkStackSegment* m_previous;
 #if !ASSERT_DISABLED
 #if !ASSERT_DISABLED
-            , m_isCheckingForDefaultMarkViolation(false)
-            , m_isDraining(false)
+        size_t m_top;
 #endif
 #endif
+        
+        const JSCell** data()
         {
         {
+            return bitwise_cast<const JSCell**>(this + 1);
         }
         }
-
-        ~MarkStack()
+        
+        static size_t capacityFromSize(size_t size)
+        {
+            return (size - sizeof(MarkStackSegment)) / sizeof(const JSCell*);
+        }
+        
+        static size_t sizeFromCapacity(size_t capacity)
         {
         {
-            ASSERT(m_markSets.isEmpty());
-            ASSERT(m_values.isEmpty());
+            return sizeof(MarkStackSegment) + capacity * sizeof(const JSCell*);
         }
         }
+    };
 
 
-        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);
+    class MarkStackSegmentAllocator {
+    public:
+        MarkStackSegmentAllocator();
+        ~MarkStackSegmentAllocator();
         
         
-        void append(ConservativeRoots&);
+        MarkStackSegment* allocate();
+        void release(MarkStackSegment*);
+        
+        void shrinkReserve();
+        
+    private:
+        Mutex m_lock;
+        MarkStackSegment* m_nextFreeSegment;
+    };
 
 
-        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(); }
+    class MarkStackArray {
+    public:
+        MarkStackArray(MarkStackSegmentAllocator&);
+        ~MarkStackArray();
 
 
-        void drain();
-        void reset();
+        void append(const JSCell*);
 
 
-        bool shouldUnlinkCalls() const { return m_shouldUnlinkCalls; }
-        void setShouldUnlinkCalls(bool shouldUnlinkCalls) { m_shouldUnlinkCalls = shouldUnlinkCalls; }
+        bool canRemoveLast();
+        const JSCell* removeLast();
+        bool refill();
+        
+        bool isEmpty();
+        
+        bool canDonateSomeCells(); // Returns false if you should definitely not call doanteSomeCellsTo().
+        bool donateSomeCellsTo(MarkStackArray& other); // Returns true if some cells were donated.
+        
+        void stealSomeCellsFrom(MarkStackArray& other);
+
+        size_t size();
+
+    private:
+        MarkStackSegment* m_topSegment;
+        
+        JS_EXPORT_PRIVATE void expand();
+        
+        MarkStackSegmentAllocator& m_allocator;
+
+        size_t m_segmentCapacity;
+        size_t m_top;
+        size_t m_numberOfPreviousSegments;
+        
+        size_t postIncTop()
+        {
+            size_t result = m_top++;
+            ASSERT(result == m_topSegment->m_top++);
+            return result;
+        }
+        
+        size_t preDecTop()
+        {
+            size_t result = --m_top;
+            ASSERT(result == --m_topSegment->m_top);
+            return result;
+        }
+        
+        void setTopForFullSegment()
+        {
+            ASSERT(m_topSegment->m_top == m_segmentCapacity);
+            m_top = m_segmentCapacity;
+        }
+        
+        void setTopForEmptySegment()
+        {
+            ASSERT(!m_topSegment->m_top);
+            m_top = 0;
+        }
+        
+        size_t top()
+        {
+            ASSERT(m_top == m_topSegment->m_top);
+            return m_top;
+        }
+        
+#if ASSERT_DISABLED
+        void validatePrevious() { }
+#else
+        void validatePrevious()
+        {
+            unsigned count = 0;
+            for (MarkStackSegment* current = m_topSegment->m_previous; current; current = current->m_previous)
+                count++;
+            ASSERT(count == m_numberOfPreviousSegments);
+        }
+#endif
+    };
 
 
+    class MarkStackThreadSharedData {
+    public:
+        MarkStackThreadSharedData(JSGlobalData*);
+        ~MarkStackThreadSharedData();
+        
+        void reset();
+    
     private:
     private:
+        friend class MarkStack;
+        friend class SlotVisitor;
+
+#if ENABLE(PARALLEL_GC)
+        void markingThreadMain();
+        static void markingThreadStartFunc(void* heap);
+#endif
+
+        JSGlobalData* m_globalData;
+        CopiedSpace* m_copiedSpace;
+        
+        MarkStackSegmentAllocator m_segmentAllocator;
+        
+        Vector<ThreadIdentifier> m_markingThreads;
+        
+        Mutex m_markingLock;
+        ThreadCondition m_markingCondition;
+        MarkStackArray m_sharedMarkStack;
+        unsigned m_numberOfActiveParallelMarkers;
+        bool m_parallelMarkersShouldExit;
+
+        Mutex m_opaqueRootsLock;
+        HashSet<void*> m_opaqueRoots;
+
+        ListableHandler<WeakReferenceHarvester>::List m_weakReferenceHarvesters;
+        ListableHandler<UnconditionalFinalizer>::List m_unconditionalFinalizers;
+    };
+
+    class MarkStack {
+        WTF_MAKE_NONCOPYABLE(MarkStack);
         friend class HeapRootVisitor; // Allowed to mark a JSValue* or JSCell** directly.
 
         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);
+    public:
+        MarkStack(MarkStackThreadSharedData&);
+        ~MarkStack();
+
+        void append(ConservativeRoots&);
+        
+        template<typename T> void append(JITWriteBarrier<T>*);
+        template<typename T> void append(WriteBarrierBase<T>*);
+        void appendValues(WriteBarrierBase<Unknown>*, size_t count);
+        
+        template<typename T>
+        void appendUnbarrieredPointer(T**);
+        
+        void addOpaqueRoot(void*);
+        bool containsOpaqueRoot(void*);
+        int opaqueRootCount();
+        
+        bool isEmpty() { return m_stack.isEmpty(); }
+
+        void reset();
+
+        size_t visitCount() const { return m_visitCount; }
+
+#if ENABLE(SIMPLE_HEAP_PROFILING)
+        VTableSpectrum m_visitedTypeCounts;
 #endif
 
 #endif
 
+        void addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester)
+        {
+            m_shared.m_weakReferenceHarvesters.addThreadSafe(weakReferenceHarvester);
+        }
+        
+        void addUnconditionalFinalizer(UnconditionalFinalizer* unconditionalFinalizer)
+        {
+            m_shared.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer);
+        }
+
+    protected:
+        JS_EXPORT_PRIVATE static void validate(JSCell*);
+
         void append(JSValue*);
         void append(JSValue*, size_t count);
         void append(JSCell**);
 
         void internalAppend(JSCell*);
         void internalAppend(JSValue);
         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()
+        
+        JS_EXPORT_PRIVATE void mergeOpaqueRoots();
+        
+        void mergeOpaqueRootsIfNecessary()
         {
         {
-            if (!s_pageSize)
-                initializePagesize();
-            return s_pageSize;
+            if (m_opaqueRoots.isEmpty())
+                return;
+            mergeOpaqueRoots();
         }
         }
-
-        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;
+        
+        void mergeOpaqueRootsIfProfitable()
+        {
+            if (static_cast<unsigned>(m_opaqueRoots.size()) < Options::opaqueRootMergeThreshold)
+                return;
+            mergeOpaqueRoots();
+        }
+        
+        MarkStackArray m_stack;
         HashSet<void*> m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector.
         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
 #if !ASSERT_DISABLED
     public:
         bool m_isCheckingForDefaultMarkViolation;
         bool m_isDraining;
 #endif
+    protected:
+        friend class ParallelModeEnabler;
+        
+        size_t m_visitCount;
+        bool m_isInParallelMode;
+        
+        MarkStackThreadSharedData& m_shared;
     };
 
     };
 
-    typedef MarkStack SlotVisitor;
+    inline MarkStack::MarkStack(MarkStackThreadSharedData& shared)
+        : m_stack(shared.m_segmentAllocator)
+#if !ASSERT_DISABLED
+        , m_isCheckingForDefaultMarkViolation(false)
+        , m_isDraining(false)
+#endif
+        , m_visitCount(0)
+        , m_isInParallelMode(false)
+        , m_shared(shared)
+    {
+    }
+
+    inline MarkStack::~MarkStack()
+    {
+        ASSERT(m_stack.isEmpty());
+    }
 
 
-    inline void MarkStack::append(JSValue* slot, size_t count)
+    inline void MarkStack::addOpaqueRoot(void* root)
     {
     {
-        if (!count)
+#if ENABLE(PARALLEL_GC)
+        if (Options::numberOfGCMarkers == 1) {
+            // Put directly into the shared HashSet.
+            m_shared.m_opaqueRoots.add(root);
             return;
             return;
-#if ENABLE(GC_VALIDATION)
-        validateSet(slot, count);
+        }
+        // Put into the local set, but merge with the shared one every once in
+        // a while to make sure that the local sets don't grow too large.
+        mergeOpaqueRootsIfProfitable();
+        m_opaqueRoots.add(root);
+#else
+        m_opaqueRoots.add(root);
 #endif
 #endif
-        m_markSets.append(MarkSet(slot, slot + count, NoNullValues));
     }
     }
-    
-    ALWAYS_INLINE void MarkStack::append(JSValue* value)
+
+    inline bool MarkStack::containsOpaqueRoot(void* root)
     {
     {
-        ASSERT(value);
-        internalAppend(*value);
+        ASSERT(!m_isInParallelMode);
+#if ENABLE(PARALLEL_GC)
+        ASSERT(m_opaqueRoots.isEmpty());
+        return m_shared.m_opaqueRoots.contains(root);
+#else
+        return m_opaqueRoots.contains(root);
+#endif
     }
 
     }
 
-    ALWAYS_INLINE void MarkStack::append(JSCell** value)
+    inline int MarkStack::opaqueRootCount()
     {
     {
-        ASSERT(value);
-        internalAppend(*value);
+        ASSERT(!m_isInParallelMode);
+#if ENABLE(PARALLEL_GC)
+        ASSERT(m_opaqueRoots.isEmpty());
+        return m_shared.m_opaqueRoots.size();
+#else
+        return m_opaqueRoots.size();
+#endif
     }
 
     }
 
-    ALWAYS_INLINE void MarkStack::internalAppend(JSValue value)
+    inline void MarkStackArray::append(const JSCell* cell)
     {
     {
-        ASSERT(value);
-#if ENABLE(GC_VALIDATION)
-        validateValue(value);
-#endif
-        if (value.isCell())
-            internalAppend(value.asCell());
+        if (m_top == m_segmentCapacity)
+            expand();
+        m_topSegment->data()[postIncTop()] = cell;
     }
 
     }
 
-    // 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();
+    inline bool MarkStackArray::canRemoveLast()
+    {
+        return !!m_top;
+    }
 
 
-    private:
-        SlotVisitor& m_visitor;
-    };
+    inline const JSCell* MarkStackArray::removeLast()
+    {
+        return m_topSegment->data()[preDecTop()];
+    }
 
 
-    inline HeapRootVisitor::HeapRootVisitor(SlotVisitor& visitor)
-        : m_visitor(visitor)
+    inline bool MarkStackArray::isEmpty()
     {
     {
+        if (m_top)
+            return false;
+        if (m_topSegment->m_previous) {
+            ASSERT(m_topSegment->m_previous->m_top == m_segmentCapacity);
+            return false;
+        }
+        return true;
     }
 
     }
 
-    inline void HeapRootVisitor::mark(JSValue* slot)
+    inline bool MarkStackArray::canDonateSomeCells()
     {
     {
-        m_visitor.append(slot);
+        size_t numberOfCellsToKeep = Options::minimumNumberOfCellsToKeep;
+        // Another check: see if we have enough cells to warrant donation.
+        if (m_top <= numberOfCellsToKeep) {
+            // This indicates that we might not want to donate anything; check if we have
+            // another full segment. If not, then don't donate.
+            if (!m_topSegment->m_previous)
+                return false;
+            
+            ASSERT(m_topSegment->m_previous->m_top == m_segmentCapacity);
+        }
+        
+        return true;
     }
 
     }
 
-    inline void HeapRootVisitor::mark(JSValue* slot, size_t count)
+    inline size_t MarkStackArray::size()
     {
     {
-        m_visitor.append(slot, count);
+        return m_top + m_segmentCapacity * m_numberOfPreviousSegments;
     }
 
     }
 
-    inline void HeapRootVisitor::mark(JSString** slot)
+    ALWAYS_INLINE void MarkStack::append(JSValue* slot, size_t count)
     {
     {
-        m_visitor.append(reinterpret_cast<JSCell**>(slot));
+        for (size_t i = 0; i < count; ++i) {
+            JSValue& value = slot[i];
+            if (!value)
+                continue;
+            internalAppend(value);
+        }
     }
 
     }
 
-    inline void HeapRootVisitor::mark(JSCell** slot)
+    template<typename T>
+    inline void MarkStack::appendUnbarrieredPointer(T** slot)
     {
     {
-        m_visitor.append(slot);
+        ASSERT(slot);
+        JSCell* cell = *slot;
+        if (cell)
+            internalAppend(cell);
+    }
+    
+    ALWAYS_INLINE void MarkStack::append(JSValue* slot)
+    {
+        ASSERT(slot);
+        internalAppend(*slot);
     }
 
     }
 
-    inline SlotVisitor& HeapRootVisitor::visitor()
+    ALWAYS_INLINE void MarkStack::append(JSCell** slot)
     {
     {
-        return m_visitor;
+        ASSERT(slot);
+        internalAppend(*slot);
     }
 
     }
 
+    ALWAYS_INLINE void MarkStack::internalAppend(JSValue value)
+    {
+        ASSERT(value);
+        if (!value.isCell())
+            return;
+        internalAppend(value.asCell());
+    }
+
+    class ParallelModeEnabler {
+    public:
+        ParallelModeEnabler(MarkStack& stack)
+            : m_stack(stack)
+        {
+            ASSERT(!m_stack.m_isInParallelMode);
+            m_stack.m_isInParallelMode = true;
+        }
+        
+        ~ParallelModeEnabler()
+        {
+            ASSERT(m_stack.m_isInParallelMode);
+            m_stack.m_isInParallelMode = false;
+        }
+        
+    private:
+        MarkStack& m_stack;
+    };
+
 } // namespace JSC
 
 #endif
 } // namespace JSC
 
 #endif
diff --git a/heap/MarkStackPosix.cpp b/heap/MarkStackPosix.cpp
deleted file mode 100644 (file)
index 2a5b298..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. 
- */
-
-#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
deleted file mode 100644 (file)
index a3893d7..0000000
+++ /dev/null
@@ -1,38 +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;
-}
-
-}
-
-#endif
diff --git a/heap/MarkStackWin.cpp b/heap/MarkStackWin.cpp
deleted file mode 100644 (file)
index 2d2a1b3..0000000
+++ /dev/null
@@ -1,44 +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;
-}
-
-}
-
-#endif
diff --git a/heap/MarkedAllocator.cpp b/heap/MarkedAllocator.cpp
new file mode 100644 (file)
index 0000000..2135e99
--- /dev/null
@@ -0,0 +1,123 @@
+#include "config.h"
+#include "MarkedAllocator.h"
+
+#include "GCActivityCallback.h"
+#include "Heap.h"
+#include "JSGlobalData.h"
+#include <wtf/CurrentTime.h>
+
+namespace JSC {
+
+bool MarkedAllocator::isPagedOut(double deadline)
+{
+    unsigned itersSinceLastTimeCheck = 0;
+    HeapBlock* block = m_blockList.head();
+    while (block) {
+        block = block->next();
+        ++itersSinceLastTimeCheck;
+        if (itersSinceLastTimeCheck >= Heap::s_timeCheckResolution) {
+            double currentTime = WTF::monotonicallyIncreasingTime();
+            if (currentTime > deadline)
+                return true;
+            itersSinceLastTimeCheck = 0;
+        }
+    }
+
+    return false;
+}
+
+inline void* MarkedAllocator::tryAllocateHelper()
+{
+    if (!m_freeList.head) {
+        for (MarkedBlock*& block = m_currentBlock; block; block = static_cast<MarkedBlock*>(block->next())) {
+            m_freeList = block->sweep(MarkedBlock::SweepToFreeList);
+            if (m_freeList.head)
+                break;
+            block->didConsumeFreeList();
+        }
+        
+        if (!m_freeList.head)
+            return 0;
+    }
+    
+    MarkedBlock::FreeCell* head = m_freeList.head;
+    m_freeList.head = head->next;
+    ASSERT(head);
+    return head;
+}
+    
+inline void* MarkedAllocator::tryAllocate()
+{
+    ASSERT(!m_heap->isBusy());
+    m_heap->m_operationInProgress = Allocation;
+    void* result = tryAllocateHelper();
+    m_heap->m_operationInProgress = NoOperation;
+    return result;
+}
+    
+void* MarkedAllocator::allocateSlowCase()
+{
+    ASSERT(m_heap->globalData()->apiLock().currentThreadIsHoldingLock());
+#if COLLECT_ON_EVERY_ALLOCATION
+    m_heap->collectAllGarbage();
+    ASSERT(m_heap->m_operationInProgress == NoOperation);
+#endif
+    
+    ASSERT(!m_freeList.head);
+    m_heap->didAllocate(m_freeList.bytes);
+    
+    void* result = tryAllocate();
+    
+    if (LIKELY(result != 0))
+        return result;
+    
+    if (m_heap->shouldCollect()) {
+        m_heap->collect(Heap::DoNotSweep);
+
+        result = tryAllocate();
+        if (result)
+            return result;
+    }
+
+    ASSERT(!m_heap->shouldCollect());
+    
+    MarkedBlock* block = allocateBlock();
+    ASSERT(block);
+    addBlock(block);
+        
+    result = tryAllocate();
+    ASSERT(result);
+    return result;
+}
+    
+MarkedBlock* MarkedAllocator::allocateBlock()
+{
+    MarkedBlock* block = static_cast<MarkedBlock*>(m_heap->blockAllocator().allocate());
+    if (block)
+        block = MarkedBlock::recycle(block, m_heap, m_cellSize, m_cellsNeedDestruction);
+    else
+        block = MarkedBlock::create(m_heap, m_cellSize, m_cellsNeedDestruction);
+    
+    m_markedSpace->didAddBlock(block);
+    
+    return block;
+}
+
+void MarkedAllocator::addBlock(MarkedBlock* block)
+{
+    ASSERT(!m_currentBlock);
+    ASSERT(!m_freeList.head);
+    
+    m_blockList.append(block);
+    m_currentBlock = block;
+    m_freeList = block->sweep(MarkedBlock::SweepToFreeList);
+}
+
+void MarkedAllocator::removeBlock(MarkedBlock* block)
+{
+    if (m_currentBlock == block)
+        m_currentBlock = 0;
+    m_blockList.remove(block);
+}
+
+} // namespace JSC
diff --git a/heap/MarkedAllocator.h b/heap/MarkedAllocator.h
new file mode 100644 (file)
index 0000000..8b3620f
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef MarkedAllocator_h
+#define MarkedAllocator_h
+
+#include "MarkedBlock.h"
+#include <wtf/DoublyLinkedList.h>
+
+namespace JSC {
+
+class Heap;
+class MarkedSpace;
+class LLIntOffsetsExtractor;
+
+namespace DFG {
+class SpeculativeJIT;
+}
+
+class MarkedAllocator {
+    friend class JIT;
+    friend class DFG::SpeculativeJIT;
+
+public:
+    MarkedAllocator();
+    void reset();
+    void zapFreeList();
+    size_t cellSize() { return m_cellSize; }
+    bool cellsNeedDestruction() { return m_cellsNeedDestruction; }
+    void* allocate();
+    Heap* heap() { return m_heap; }
+    
+    template<typename Functor> void forEachBlock(Functor&);
+    
+    void addBlock(MarkedBlock*);
+    void removeBlock(MarkedBlock*);
+    void init(Heap*, MarkedSpace*, size_t cellSize, bool cellsNeedDestruction);
+
+    bool isPagedOut(double deadline);
+   
+private:
+    friend class LLIntOffsetsExtractor;
+    
+    JS_EXPORT_PRIVATE void* allocateSlowCase();
+    void* tryAllocate();
+    void* tryAllocateHelper();
+    MarkedBlock* allocateBlock();
+    
+    MarkedBlock::FreeList m_freeList;
+    MarkedBlock* m_currentBlock;
+    DoublyLinkedList<HeapBlock> m_blockList;
+    size_t m_cellSize;
+    bool m_cellsNeedDestruction;
+    Heap* m_heap;
+    MarkedSpace* m_markedSpace;
+};
+
+inline MarkedAllocator::MarkedAllocator()
+    : m_currentBlock(0)
+    , m_cellSize(0)
+    , m_cellsNeedDestruction(true)
+    , m_heap(0)
+    , m_markedSpace(0)
+{
+}
+
+inline void MarkedAllocator::init(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, bool cellsNeedDestruction)
+{
+    m_heap = heap;
+    m_markedSpace = markedSpace;
+    m_cellSize = cellSize;
+    m_cellsNeedDestruction = cellsNeedDestruction;
+}
+
+inline void* MarkedAllocator::allocate()
+{
+    MarkedBlock::FreeCell* head = m_freeList.head;
+    // This is a light-weight fast path to cover the most common case.
+    if (UNLIKELY(!head))
+        return allocateSlowCase();
+    
+    m_freeList.head = head->next;
+    return head;
+}
+
+inline void MarkedAllocator::reset()
+{
+    m_currentBlock = static_cast<MarkedBlock*>(m_blockList.head());
+}
+
+inline void MarkedAllocator::zapFreeList()
+{
+    if (!m_currentBlock) {
+        ASSERT(!m_freeList.head);
+        return;
+    }
+    
+    m_currentBlock->zapFreeList(m_freeList);
+    m_freeList = MarkedBlock::FreeList();
+}
+
+template <typename Functor> inline void MarkedAllocator::forEachBlock(Functor& functor)
+{
+    HeapBlock* next;
+    for (HeapBlock* block = m_blockList.head(); block; block = next) {
+        next = block->next();
+        functor(static_cast<MarkedBlock*>(block));
+    }
+}
+    
+} // namespace JSC
+
+#endif
index f1f630ceaa30ff123eb6d6c4d2ac2db154c961da..3a58b5a42dc7fb0a9cf8bd3a1a8f0e811faf2214 100644 (file)
 
 #include "JSCell.h"
 #include "JSObject.h"
 
 #include "JSCell.h"
 #include "JSObject.h"
-#include "JSZombie.h"
 #include "ScopeChain.h"
 
 namespace JSC {
 
 #include "ScopeChain.h"
 
 namespace JSC {
 
-MarkedBlock* MarkedBlock::create(JSGlobalData* globalData, size_t cellSize)
+MarkedBlock* MarkedBlock::create(Heap* heap, size_t cellSize, bool cellsNeedDestruction)
 {
     PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, blockSize, OSAllocator::JSGCHeapPages);
     if (!static_cast<bool>(allocation))
         CRASH();
 {
     PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, blockSize, OSAllocator::JSGCHeapPages);
     if (!static_cast<bool>(allocation))
         CRASH();
-    return new (allocation.base()) MarkedBlock(allocation, globalData, cellSize);
+    return new (NotNull, allocation.base()) MarkedBlock(allocation, heap, cellSize, cellsNeedDestruction);
+}
+
+MarkedBlock* MarkedBlock::recycle(MarkedBlock* block, Heap* heap, size_t cellSize, bool cellsNeedDestruction)
+{
+    return new (NotNull, block) MarkedBlock(block->m_allocation, heap, cellSize, cellsNeedDestruction);
 }
 
 void MarkedBlock::destroy(MarkedBlock* block)
 {
 }
 
 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();
 }
 
     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)
+MarkedBlock::MarkedBlock(PageAllocationAligned& allocation, Heap* heap, size_t cellSize, bool cellsNeedDestruction)
+    : HeapBlock(allocation)
+    , m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
+    , m_endAtom(atomsPerBlock - m_atomsPerCell + 1)
+    , m_cellsNeedDestruction(cellsNeedDestruction)
+    , m_state(New) // All cells start out unmarked.
+    , m_heap(heap)
+{
+    ASSERT(heap);
+    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
+}
+
+inline void MarkedBlock::callDestructor(JSCell* cell)
 {
 {
-    m_atomsPerCell = (cellSize + atomSize - 1) / atomSize;
-    m_endAtom = atomsPerBlock - m_atomsPerCell + 1;
+    // A previous eager sweep may already have run cell's destructor.
+    if (cell->isZapped())
+        return;
+
+#if ENABLE(SIMPLE_HEAP_PROFILING)
+    m_heap->m_destroyedTypeCounts.countVPtr(vptr);
+#endif
+    cell->methodTable()->destroy(cell);
 
 
-    Structure* dummyMarkableCellStructure = globalData->dummyMarkableCellStructure.get();
-    for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell)
-        new (&atoms()[i]) JSCell(*globalData, dummyMarkableCellStructure, JSCell::CreatingEarlyCell);
+    cell->zap();
 }
 
 }
 
-void MarkedBlock::sweep()
+template<MarkedBlock::BlockState blockState, MarkedBlock::SweepMode sweepMode, bool destructorCallNeeded>
+MarkedBlock::FreeList MarkedBlock::specializedSweep()
 {
 {
-    Structure* dummyMarkableCellStructure = m_heap->globalData()->dummyMarkableCellStructure.get();
+    ASSERT(blockState != Allocated && blockState != FreeListed);
+    ASSERT(destructorCallNeeded || sweepMode != SweepOnly);
 
 
+    // This produces a free list that is ordered in reverse through the block.
+    // This is fine, since the allocation code makes no assumptions about the
+    // order of the free list.
+    FreeCell* head = 0;
+    size_t count = 0;
     for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
     for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
-        if (m_marks.get(i))
+        if (blockState == Marked && m_marks.get(i))
             continue;
 
             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);
+        JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]);
+        if (blockState == Zapped && !cell->isZapped())
+            continue;
+
+        if (destructorCallNeeded && blockState != New)
+            callDestructor(cell);
+
+        if (sweepMode == SweepToFreeList) {
+            FreeCell* freeCell = reinterpret_cast<FreeCell*>(cell);
+            freeCell->next = head;
+            head = freeCell;
+            ++count;
         }
         }
-#else
-        cell->~JSCell();
-        new (cell) JSCell(*m_heap->globalData(), dummyMarkableCellStructure);
-#endif
     }
     }
+
+    m_state = ((sweepMode == SweepToFreeList) ? FreeListed : Zapped);
+    return FreeList(head, count * cellSize());
+}
+
+MarkedBlock::FreeList MarkedBlock::sweep(SweepMode sweepMode)
+{
+    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
+
+    if (sweepMode == SweepOnly && !m_cellsNeedDestruction)
+        return FreeList();
+
+    if (m_cellsNeedDestruction)
+        return sweepHelper<true>(sweepMode);
+    return sweepHelper<false>(sweepMode);
+}
+
+template<bool destructorCallNeeded>
+MarkedBlock::FreeList MarkedBlock::sweepHelper(SweepMode sweepMode)
+{
+    switch (m_state) {
+    case New:
+        ASSERT(sweepMode == SweepToFreeList);
+        return specializedSweep<New, SweepToFreeList, destructorCallNeeded>();
+    case FreeListed:
+        // Happens when a block transitions to fully allocated.
+        ASSERT(sweepMode == SweepToFreeList);
+        return FreeList();
+    case Allocated:
+        ASSERT_NOT_REACHED();
+        return FreeList();
+    case Marked:
+        return sweepMode == SweepToFreeList
+            ? specializedSweep<Marked, SweepToFreeList, destructorCallNeeded>()
+            : specializedSweep<Marked, SweepOnly, destructorCallNeeded>();
+    case Zapped:
+        return sweepMode == SweepToFreeList
+            ? specializedSweep<Zapped, SweepToFreeList, destructorCallNeeded>()
+            : specializedSweep<Zapped, SweepOnly, destructorCallNeeded>();
+    }
+
+    ASSERT_NOT_REACHED();
+    return FreeList();
+}
+
+void MarkedBlock::zapFreeList(const FreeList& freeList)
+{
+    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
+    FreeCell* head = freeList.head;
+
+    if (m_state == Marked) {
+        // If the block is in the Marked state then we know that:
+        // 1) It was not used for allocation during the previous allocation cycle.
+        // 2) It may have dead objects, and we only know them to be dead by the
+        //    fact that their mark bits are unset.
+        // Hence if the block is Marked we need to leave it Marked.
+        
+        ASSERT(!head);
+        
+        return;
+    }
+    
+    if (m_state == Zapped) {
+        // If the block is in the Zapped state then we know that someone already
+        // zapped it for us. This could not have happened during a GC, but might
+        // be the result of someone having done a GC scan to perform some operation
+        // over all live objects (or all live blocks). It also means that somebody
+        // had allocated in this block since the last GC, swept all dead objects
+        // onto the free list, left the block in the FreeListed state, then the heap
+        // scan happened, and canonicalized the block, leading to all dead objects
+        // being zapped. Therefore, it is safe for us to simply do nothing, since
+        // dead objects will have 0 in their vtables and live objects will have
+        // non-zero vtables, which is consistent with the block being zapped.
+        
+        ASSERT(!head);
+        
+        return;
+    }
+    
+    ASSERT(m_state == FreeListed);
+    
+    // Roll back to a coherent state for Heap introspection. Cells newly
+    // allocated from our free list are not currently marked, so we need another
+    // way to tell what's live vs dead. We use zapping for that.
+    
+    FreeCell* next;
+    for (FreeCell* current = head; current; current = next) {
+        next = current->next;
+        reinterpret_cast<JSCell*>(current)->zap();
+    }
+    
+    m_state = Zapped;
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index c567502be74b2ec92cbfb733f8634141ab2da464..429b7c08e15131361ac6b3ce699a5a01c4efa526 100644 (file)
 #ifndef MarkedBlock_h
 #define MarkedBlock_h
 
 #ifndef MarkedBlock_h
 #define MarkedBlock_h
 
+#include "CardSet.h"
+#include "HeapBlock.h"
+
 #include <wtf/Bitmap.h>
 #include <wtf/Bitmap.h>
+#include <wtf/DataLog.h>
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/HashFunctions.h>
 #include <wtf/PageAllocationAligned.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/PageAllocationAligned.h>
 #include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+// Set to log state transitions of blocks.
+#define HEAP_LOG_BLOCK_STATE_TRANSITIONS 0
+
+#if HEAP_LOG_BLOCK_STATE_TRANSITIONS
+#define HEAP_LOG_BLOCK_STATE_TRANSITION(block) do {                     \
+        dataLog(                                                    \
+            "%s:%d %s: block %s = %p, %d\n",                            \
+            __FILE__, __LINE__, __FUNCTION__,                           \
+            #block, (block), (block)->m_state);                         \
+    } while (false)
+#else
+#define HEAP_LOG_BLOCK_STATE_TRANSITION(block) ((void)0)
+#endif
 
 namespace JSC {
 
 namespace JSC {
-
+    
     class Heap;
     class JSCell;
     class Heap;
     class JSCell;
-    class JSGlobalData;
 
     typedef uintptr_t Bits;
 
 
     typedef uintptr_t Bits;
 
-    static const size_t KB = 1024;
-
-    class MarkedBlock {
+    static const size_t MB = 1024 * 1024;
+    
+    bool isZapped(const JSCell*);
+    
+    // A marked block is a page-aligned container for heap-allocated objects.
+    // Objects are allocated within cells of the marked block. For a given
+    // marked block, all cells have the same size. Objects smaller than the
+    // cell size may be allocated in the marked block, in which case the
+    // allocation suffers from internal fragmentation: wasted space whose
+    // size is equal to the difference between the cell size and the object
+    // size.
+
+    class MarkedBlock : public HeapBlock {
+        friend class WTF::DoublyLinkedListNode<MarkedBlock>;
     public:
     public:
-        static const size_t atomSize = sizeof(double); // Ensures natural alignment for all built-in types.
+        // Ensure natural alignment for native types whilst recognizing that the smallest
+        // object the heap will commonly allocate is four words.
+        static const size_t atomSize = 4 * sizeof(void*);
+        static const size_t atomShift = 5;
+        static const size_t blockSize = 64 * KB;
+        static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two.
 
 
-        static MarkedBlock* create(JSGlobalData*, size_t cellSize);
+        static const size_t atomsPerBlock = blockSize / atomSize; // ~0.4% overhead
+        static const size_t atomMask = atomsPerBlock - 1;
+        static const int cardShift = 8; // This is log2 of bytes per card.
+        static const size_t bytesPerCard = 1 << cardShift;
+        static const int cardCount = blockSize / bytesPerCard;
+        static const int cardMask = cardCount - 1;
+
+        struct FreeCell {
+            FreeCell* next;
+        };
+        
+        struct FreeList {
+            FreeCell* head;
+            size_t bytes;
+
+            FreeList();
+            FreeList(FreeCell*, size_t);
+        };
+
+        struct VoidFunctor {
+            typedef void ReturnType;
+            void returnValue() { }
+        };
+
+        static MarkedBlock* create(Heap*, size_t cellSize, bool cellsNeedDestruction);
+        static MarkedBlock* recycle(MarkedBlock*, Heap*, size_t cellSize, bool cellsNeedDestruction);
         static void destroy(MarkedBlock*);
 
         static bool isAtomAligned(const void*);
         static void destroy(MarkedBlock*);
 
         static bool isAtomAligned(const void*);
@@ -48,57 +109,106 @@ namespace JSC {
         static size_t firstAtom();
         
         Heap* heap() const;
         static size_t firstAtom();
         
         Heap* heap() const;
-
-        void setPrev(MarkedBlock*);
-        void setNext(MarkedBlock*);
-        MarkedBlock* prev() const;
-        MarkedBlock* next() const;
         
         void* allocate();
         
         void* allocate();
-        void reset();
-        void sweep();
-        
-        bool isEmpty();
+
+        enum SweepMode { SweepOnly, SweepToFreeList };
+        FreeList sweep(SweepMode = SweepOnly);
+
+        // While allocating from a free list, MarkedBlock temporarily has bogus
+        // cell liveness data. To restore accurate cell liveness data, call one
+        // of these functions:
+        void didConsumeFreeList(); // Call this once you've allocated all the items in the free list.
+        void zapFreeList(const FreeList&); // Call this to undo the free list.
 
         void clearMarks();
         size_t markCount();
 
         void clearMarks();
         size_t markCount();
+        bool markCountIsZero(); // Faster than markCount().
 
         size_t cellSize();
 
         size_t cellSize();
+        bool cellsNeedDestruction();
 
         size_t size();
         size_t capacity();
 
 
         size_t size();
         size_t capacity();
 
-        bool contains(const void*);
-        size_t atomNumber(const void*);
         bool isMarked(const void*);
         bool testAndSetMarked(const void*);
         bool isMarked(const void*);
         bool testAndSetMarked(const void*);
+        bool isLive(const JSCell*);
+        bool isLiveCell(const void*);
         void setMarked(const void*);
         
         void setMarked(const void*);
         
-        template <typename Functor> void forEach(Functor&);
+#if ENABLE(GGC)
+        void setDirtyObject(const void* atom)
+        {
+            ASSERT(MarkedBlock::blockFor(atom) == this);
+            m_cards.markCardForAtom(atom);
+        }
+
+        uint8_t* addressOfCardFor(const void* atom)
+        {
+            ASSERT(MarkedBlock::blockFor(atom) == this);
+            return &m_cards.cardForAtom(atom);
+        }
+
+        static inline size_t offsetOfCards()
+        {
+            return OBJECT_OFFSETOF(MarkedBlock, m_cards);
+        }
+
+        static inline size_t offsetOfMarks()
+        {
+            return OBJECT_OFFSETOF(MarkedBlock, m_marks);
+        }
+
+        typedef Vector<JSCell*, 32> DirtyCellVector;
+        inline void gatherDirtyCells(DirtyCellVector&);
+        template <int size> inline void gatherDirtyCellsWithSize(DirtyCellVector&);
+#endif
+
+        template <typename Functor> void forEachCell(Functor&);
 
     private:
 
     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 atomAlignmentMask = atomSize - 1; // atomSize 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;
+        enum BlockState { New, FreeListed, Allocated, Marked, Zapped };
+        template<bool destructorCallNeeded> FreeList sweepHelper(SweepMode = SweepOnly);
 
         typedef char Atom[atomSize];
 
 
         typedef char Atom[atomSize];
 
-        MarkedBlock(const PageAllocationAligned&, JSGlobalData*, size_t cellSize);
+        MarkedBlock(PageAllocationAligned&, Heap*, size_t cellSize, bool cellsNeedDestruction);
         Atom* atoms();
         Atom* atoms();
+        size_t atomNumber(const void*);
+        void callDestructor(JSCell*);
+        template<BlockState, SweepMode, bool destructorCallNeeded> FreeList specializedSweep();
+        
+#if ENABLE(GGC)
+        CardSet<bytesPerCard, blockSize> m_cards;
+#endif
 
 
-        size_t m_nextAtom;
-        size_t m_endAtom; // This is a fuzzy end. Always test for < m_endAtom.
         size_t m_atomsPerCell;
         size_t m_atomsPerCell;
-        WTF::Bitmap<blockSize / atomSize> m_marks;
-        PageAllocationAligned m_allocation;
+        size_t m_endAtom; // This is a fuzzy end. Always test for < m_endAtom.
+#if ENABLE(PARALLEL_GC)
+        WTF::Bitmap<atomsPerBlock, WTF::BitmapAtomic> m_marks;
+#else
+        WTF::Bitmap<atomsPerBlock, WTF::BitmapNotAtomic> m_marks;
+#endif
+        bool m_cellsNeedDestruction;
+        BlockState m_state;
         Heap* m_heap;
         Heap* m_heap;
-        MarkedBlock* m_prev;
-        MarkedBlock* m_next;
     };
 
     };
 
+    inline MarkedBlock::FreeList::FreeList()
+        : head(0)
+        , bytes(0)
+    {
+    }
+
+    inline MarkedBlock::FreeList::FreeList(FreeCell* head, size_t bytes)
+        : head(head)
+        , bytes(bytes)
+    {
+    }
+
     inline size_t MarkedBlock::firstAtom()
     {
         return WTF::roundUpToMultipleOf<atomSize>(sizeof(MarkedBlock)) / atomSize;
     inline size_t MarkedBlock::firstAtom()
     {
         return WTF::roundUpToMultipleOf<atomSize>(sizeof(MarkedBlock)) / atomSize;
@@ -111,12 +221,12 @@ namespace JSC {
 
     inline bool MarkedBlock::isAtomAligned(const void* p)
     {
 
     inline bool MarkedBlock::isAtomAligned(const void* p)
     {
-        return !((intptr_t)(p) & ~atomMask);
+        return !(reinterpret_cast<Bits>(p) & atomAlignmentMask);
     }
 
     inline MarkedBlock* MarkedBlock::blockFor(const void* p)
     {
     }
 
     inline MarkedBlock* MarkedBlock::blockFor(const void* p)
     {
-        return reinterpret_cast<MarkedBlock*>(reinterpret_cast<uintptr_t>(p) & blockMask);
+        return reinterpret_cast<MarkedBlock*>(reinterpret_cast<Bits>(p) & blockMask);
     }
 
     inline Heap* MarkedBlock::heap() const
     }
 
     inline Heap* MarkedBlock::heap() const
@@ -124,49 +234,44 @@ namespace JSC {
         return m_heap;
     }
 
         return m_heap;
     }
 
-    inline void MarkedBlock::setPrev(MarkedBlock* prev)
+    inline void MarkedBlock::didConsumeFreeList()
     {
     {
-        m_prev = prev;
-    }
+        HEAP_LOG_BLOCK_STATE_TRANSITION(this);
 
 
-    inline void MarkedBlock::setNext(MarkedBlock* next)
-    {
-        m_next = next;
+        ASSERT(m_state == FreeListed);
+        m_state = Allocated;
     }
 
     }
 
-    inline MarkedBlock* MarkedBlock::prev() const
+    inline void MarkedBlock::clearMarks()
     {
     {
-        return m_prev;
-    }
+        HEAP_LOG_BLOCK_STATE_TRANSITION(this);
 
 
-    inline MarkedBlock* MarkedBlock::next() const
-    {
-        return m_next;
+        ASSERT(m_state != New && m_state != FreeListed);
+        m_marks.clearAll();
+
+        // This will become true at the end of the mark phase. We set it now to
+        // avoid an extra pass to do so later.
+        m_state = Marked;
     }
 
     }
 
-    inline void MarkedBlock::reset()
+    inline size_t MarkedBlock::markCount()
     {
     {
-        m_nextAtom = firstAtom();
+        return m_marks.count();
     }
 
     }
 
-    inline bool MarkedBlock::isEmpty()
+    inline bool MarkedBlock::markCountIsZero()
     {
         return m_marks.isEmpty();
     }
 
     {
         return m_marks.isEmpty();
     }
 
-    inline void MarkedBlock::clearMarks()
-    {
-        m_marks.clearAll();
-    }
-    
-    inline size_t MarkedBlock::markCount()
+    inline size_t MarkedBlock::cellSize()
     {
     {
-        return m_marks.count();
+        return m_atomsPerCell * atomSize;
     }
 
     }
 
-    inline size_t MarkedBlock::cellSize()
+    inline bool MarkedBlock::cellsNeedDestruction()
     {
     {
-        return m_atomsPerCell * atomSize;
+        return m_cellsNeedDestruction; 
     }
 
     inline size_t MarkedBlock::size()
     }
 
     inline size_t MarkedBlock::size()
@@ -179,19 +284,9 @@ namespace JSC {
         return m_allocation.size();
     }
 
         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)
     {
     inline size_t MarkedBlock::atomNumber(const void* p)
     {
-        return (reinterpret_cast<uintptr_t>(p) - reinterpret_cast<uintptr_t>(this)) / atomSize;
+        return (reinterpret_cast<Bits>(p) - reinterpret_cast<Bits>(this)) / atomSize;
     }
 
     inline bool MarkedBlock::isMarked(const void* p)
     }
 
     inline bool MarkedBlock::isMarked(const void* p)
@@ -201,7 +296,7 @@ namespace JSC {
 
     inline bool MarkedBlock::testAndSetMarked(const void* p)
     {
 
     inline bool MarkedBlock::testAndSetMarked(const void* p)
     {
-        return m_marks.testAndSet(atomNumber(p));
+        return m_marks.concurrentTestAndSet(atomNumber(p));
     }
 
     inline void MarkedBlock::setMarked(const void* p)
     }
 
     inline void MarkedBlock::setMarked(const void* p)
@@ -209,15 +304,159 @@ namespace JSC {
         m_marks.set(atomNumber(p));
     }
 
         m_marks.set(atomNumber(p));
     }
 
-    template <typename Functor> inline void MarkedBlock::forEach(Functor& functor)
+    inline bool MarkedBlock::isLive(const JSCell* cell)
+    {
+        switch (m_state) {
+        case Allocated:
+            return true;
+        case Zapped:
+            if (isZapped(cell)) {
+                // Object dead in previous collection, not allocated since previous collection: mark bit should not be set.
+                ASSERT(!m_marks.get(atomNumber(cell)));
+                return false;
+            }
+            
+            // Newly allocated objects: mark bit not set.
+            // Objects that survived prior collection: mark bit set.
+            return true;
+        case Marked:
+            return m_marks.get(atomNumber(cell));
+
+        case New:
+        case FreeListed:
+            ASSERT_NOT_REACHED();
+            return false;
+        }
+
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    inline bool MarkedBlock::isLiveCell(const void* p)
+    {
+        ASSERT(MarkedBlock::isAtomAligned(p));
+        size_t atomNumber = this->atomNumber(p);
+        size_t firstAtom = this->firstAtom();
+        if (atomNumber < firstAtom) // Filters pointers into MarkedBlock metadata.
+            return false;
+        if ((atomNumber - firstAtom) % m_atomsPerCell) // Filters pointers into cell middles.
+            return false;
+        if (atomNumber >= m_endAtom) // Filters pointers into invalid cells out of the range.
+            return false;
+
+        return isLive(static_cast<const JSCell*>(p));
+    }
+
+    template <typename Functor> inline void MarkedBlock::forEachCell(Functor& functor)
     {
         for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
     {
         for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
-            if (!m_marks.get(i))
+            JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]);
+            if (!isLive(cell))
                 continue;
                 continue;
-            functor(reinterpret_cast<JSCell*>(&atoms()[i]));
+
+            functor(cell);
         }
     }
 
         }
     }
 
+#if ENABLE(GGC)
+template <int _cellSize> void MarkedBlock::gatherDirtyCellsWithSize(DirtyCellVector& dirtyCells)
+{
+    if (m_cards.testAndClear(0)) {
+        char* ptr = reinterpret_cast<char*>(&atoms()[firstAtom()]);
+        const char* end = reinterpret_cast<char*>(this) + bytesPerCard;
+        while (ptr < end) {
+            JSCell* cell = reinterpret_cast<JSCell*>(ptr);
+            if (isMarked(cell))
+                dirtyCells.append(cell);
+            ptr += _cellSize;
+        }
+    }
+    
+    const size_t cellOffset = firstAtom() * atomSize % _cellSize;
+    for (size_t i = 1; i < m_cards.cardCount; i++) {
+        if (!m_cards.testAndClear(i))
+            continue;
+        char* ptr = reinterpret_cast<char*>(this) + i * bytesPerCard + cellOffset;
+        char* end = reinterpret_cast<char*>(this) + (i + 1) * bytesPerCard;
+        
+        while (ptr < end) {
+            JSCell* cell = reinterpret_cast<JSCell*>(ptr);
+            if (isMarked(cell))
+                dirtyCells.append(cell);
+            ptr += _cellSize;
+        }
+    }
+}
+
+void MarkedBlock::gatherDirtyCells(DirtyCellVector& dirtyCells)
+{
+    COMPILE_ASSERT((int)m_cards.cardCount == (int)cardCount, MarkedBlockCardCountsMatch);
+
+    ASSERT(m_state != New && m_state != FreeListed);
+    
+    // This is an optimisation to avoid having to walk the set of marked
+    // blocks twice during GC.
+    m_state = Marked;
+    
+    if (markCountIsZero())
+        return;
+    
+    size_t cellSize = this->cellSize();
+    if (cellSize == 32) {
+        gatherDirtyCellsWithSize<32>(dirtyCells);
+        return;
+    }
+    if (cellSize == 64) {
+        gatherDirtyCellsWithSize<64>(dirtyCells);
+        return;
+    }
+
+    const size_t firstCellOffset = firstAtom() * atomSize % cellSize;
+    
+    if (m_cards.testAndClear(0)) {
+        char* ptr = reinterpret_cast<char*>(this) + firstAtom() * atomSize;
+        char* end = reinterpret_cast<char*>(this) + bytesPerCard;
+        while (ptr < end) {
+            JSCell* cell = reinterpret_cast<JSCell*>(ptr);
+            if (isMarked(cell))
+                dirtyCells.append(cell);
+            ptr += cellSize;
+        }
+    }
+    for (size_t i = 1; i < m_cards.cardCount; i++) {
+        if (!m_cards.testAndClear(i))
+            continue;
+        char* ptr = reinterpret_cast<char*>(this) + firstCellOffset + cellSize * ((i * bytesPerCard + cellSize - 1 - firstCellOffset) / cellSize);
+        char* end = reinterpret_cast<char*>(this) + std::min((i + 1) * bytesPerCard, m_endAtom * atomSize);
+        
+        while (ptr < end) {
+            JSCell* cell = reinterpret_cast<JSCell*>(ptr);
+            if (isMarked(cell))
+                dirtyCells.append(cell);
+            ptr += cellSize;
+        }
+    }
+}
+#endif
+
 } // namespace JSC
 
 } // namespace JSC
 
-#endif // MarkedSpace_h
+namespace WTF {
+
+    struct MarkedBlockHash : PtrHash<JSC::MarkedBlock*> {
+        static unsigned hash(JSC::MarkedBlock* const& key)
+        {
+            // Aligned VM regions tend to be monotonically increasing integers,
+            // which is a great hash function, but we have to remove the low bits,
+            // since they're always zero, which is a terrible hash function!
+            return reinterpret_cast<JSC::Bits>(key) / JSC::MarkedBlock::blockSize;
+        }
+    };
+
+    template<> struct DefaultHash<JSC::MarkedBlock*> {
+        typedef MarkedBlockHash Hash;
+    };
+
+} // namespace WTF
+
+#endif // MarkedBlock_h
diff --git a/heap/MarkedBlockSet.h b/heap/MarkedBlockSet.h
new file mode 100644 (file)
index 0000000..022a173
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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 MarkedBlockSet_h
+#define MarkedBlockSet_h
+
+#include "MarkedBlock.h"
+#include "TinyBloomFilter.h"
+#include <wtf/HashSet.h>
+
+namespace JSC {
+
+class MarkedBlock;
+
+class MarkedBlockSet {
+public:
+    void add(MarkedBlock*);
+    void remove(MarkedBlock*);
+
+    TinyBloomFilter filter() const;
+    const HashSet<MarkedBlock*>& set() const;
+
+private:
+    void recomputeFilter();
+
+    TinyBloomFilter m_filter;
+    HashSet<MarkedBlock*> m_set;
+};
+
+inline void MarkedBlockSet::add(MarkedBlock* block)
+{
+    m_filter.add(reinterpret_cast<Bits>(block));
+    m_set.add(block);
+}
+
+inline void MarkedBlockSet::remove(MarkedBlock* block)
+{
+    int oldCapacity = m_set.capacity();
+    m_set.remove(block);
+    if (m_set.capacity() != oldCapacity) // Indicates we've removed a lot of blocks.
+        recomputeFilter();
+}
+
+inline void MarkedBlockSet::recomputeFilter()
+{
+    TinyBloomFilter filter;
+    for (HashSet<MarkedBlock*>::iterator it = m_set.begin(); it != m_set.end(); ++it)
+        filter.add(reinterpret_cast<Bits>(*it));
+    m_filter = filter;
+}
+
+inline TinyBloomFilter MarkedBlockSet::filter() const
+{
+    return m_filter;
+}
+
+inline const HashSet<MarkedBlock*>& MarkedBlockSet::set() const
+{
+    return m_set;
+}
+
+} // namespace JSC
+
+#endif // MarkedBlockSet_h
index 77f6e523aa6f7cbacc03de8c7d89d336cb5d1f64..405ed571a08bfa4e52d43e63fdb4911226e9eb82 100644 (file)
@@ -22,8 +22,6 @@
 #include "MarkedSpace.h"
 
 #include "JSGlobalObject.h"
 #include "MarkedSpace.h"
 
 #include "JSGlobalObject.h"
-#include "JSCell.h"
-#include "JSGlobalData.h"
 #include "JSLock.h"
 #include "JSObject.h"
 #include "ScopeChain.h"
 #include "JSLock.h"
 #include "JSObject.h"
 #include "ScopeChain.h"
@@ -32,136 +30,142 @@ namespace JSC {
 
 class Structure;
 
 
 class Structure;
 
-MarkedSpace::MarkedSpace(JSGlobalData* globalData)
-    : m_waterMark(0)
-    , m_highWaterMark(0)
-    , m_globalData(globalData)
+MarkedSpace::MarkedSpace(Heap* heap)
+    : m_heap(heap)
 {
 {
-    for (size_t cellSize = preciseStep; cellSize < preciseCutoff; cellSize += preciseStep)
-        sizeClassFor(cellSize).cellSize = cellSize;
+    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
+        allocatorFor(cellSize).init(heap, this, cellSize, false);
+        destructorAllocatorFor(cellSize).init(heap, this, cellSize, true);
+    }
 
 
-    for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep)
-        sizeClassFor(cellSize).cellSize = cellSize;
+    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
+        allocatorFor(cellSize).init(heap, this, cellSize, false);
+        destructorAllocatorFor(cellSize).init(heap, this, cellSize, true);
+    }
 }
 
 }
 
-void MarkedSpace::destroy()
+void MarkedSpace::resetAllocators()
 {
 {
-    clearMarks();
-    shrink();
-    ASSERT(!size());
+    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
+        allocatorFor(cellSize).reset();
+        destructorAllocatorFor(cellSize).reset();
+    }
+
+    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
+        allocatorFor(cellSize).reset();
+        destructorAllocatorFor(cellSize).reset();
+    }
 }
 
 }
 
-MarkedBlock* MarkedSpace::allocateBlock(SizeClass& sizeClass)
+void MarkedSpace::canonicalizeCellLivenessData()
 {
 {
-    MarkedBlock* block = MarkedBlock::create(globalData(), sizeClass.cellSize);
-    sizeClass.blockList.append(block);
-    sizeClass.nextBlock = block;
-    m_blocks.add(block);
+    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
+        allocatorFor(cellSize).zapFreeList();
+        destructorAllocatorFor(cellSize).zapFreeList();
+    }
 
 
-    return block;
+    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
+        allocatorFor(cellSize).zapFreeList();
+        destructorAllocatorFor(cellSize).zapFreeList();
+    }
 }
 
 }
 
-void MarkedSpace::freeBlocks(DoublyLinkedList<MarkedBlock>& blocks)
+bool MarkedSpace::isPagedOut(double deadline)
 {
 {
-    MarkedBlock* next;
-    for (MarkedBlock* block = blocks.head(); block; block = next) {
-        next = block->next();
+    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
+        if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
+            return true;
+    }
 
 
-        blocks.remove(block);
-        m_blocks.remove(block);
-        MarkedBlock::destroy(block);
+    for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) {
+        if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline))
+            return true;
     }
     }
+
+    return false;
 }
 
 }
 
-void* MarkedSpace::allocateFromSizeClass(SizeClass& sizeClass)
+void MarkedSpace::freeBlocks(MarkedBlock* head)
 {
 {
-    for (MarkedBlock*& block = sizeClass.nextBlock ; block; block = block->next()) {
-        if (void* result = block->allocate())
-            return result;
+    MarkedBlock* next;
+    for (MarkedBlock* block = head; block; block = next) {
+        next = static_cast<MarkedBlock*>(block->next());
+        
+        m_blocks.remove(block);
+        block->sweep();
 
 
-        m_waterMark += block->capacity();
+        m_heap->blockAllocator().deallocate(block);
     }
     }
+}
 
 
-    if (m_waterMark < m_highWaterMark)
-        return allocateBlock(sizeClass)->allocate();
+class TakeIfUnmarked {
+public:
+    typedef MarkedBlock* ReturnType;
+    
+    TakeIfUnmarked(MarkedSpace*);
+    void operator()(MarkedBlock*);
+    ReturnType returnValue();
+    
+private:
+    MarkedSpace* m_markedSpace;
+    DoublyLinkedList<MarkedBlock> m_empties;
+};
 
 
-    return 0;
+inline TakeIfUnmarked::TakeIfUnmarked(MarkedSpace* newSpace)
+    : m_markedSpace(newSpace)
+{
 }
 
 }
 
-void MarkedSpace::shrink()
+inline void TakeIfUnmarked::operator()(MarkedBlock* block)
 {
 {
-    // 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);
-        }
-    }
+    if (!block->markCountIsZero())
+        return;
     
     
-    freeBlocks(empties);
-    ASSERT(empties.isEmpty());
+    m_markedSpace->allocatorFor(block).removeBlock(block);
+    m_empties.append(block);
 }
 
 }
 
-void MarkedSpace::clearMarks()
+inline TakeIfUnmarked::ReturnType TakeIfUnmarked::returnValue()
 {
 {
-    BlockIterator end = m_blocks.end();
-    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
-        (*it)->clearMarks();
+    return m_empties.head();
 }
 
 }
 
-void MarkedSpace::sweep()
+void MarkedSpace::shrink()
 {
 {
-    BlockIterator end = m_blocks.end();
-    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
-        (*it)->sweep();
+    // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
+    TakeIfUnmarked takeIfUnmarked(this);
+    freeBlocks(forEachBlock(takeIfUnmarked));
 }
 
 }
 
-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;
-}
+#if ENABLE(GGC)
+class GatherDirtyCells {
+    WTF_MAKE_NONCOPYABLE(GatherDirtyCells);
+public:
+    typedef void* ReturnType;
+    
+    explicit GatherDirtyCells(MarkedBlock::DirtyCellVector*);
+    void operator()(MarkedBlock*);
+    ReturnType returnValue() { return 0; }
+    
+private:
+    MarkedBlock::DirtyCellVector* m_dirtyCells;
+};
 
 
-size_t MarkedSpace::size() const
+inline GatherDirtyCells::GatherDirtyCells(MarkedBlock::DirtyCellVector* dirtyCells)
+    : m_dirtyCells(dirtyCells)
 {
 {
-    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
+inline void GatherDirtyCells::operator()(MarkedBlock* block)
 {
 {
-    size_t result = 0;
-    BlockIterator end = m_blocks.end();
-    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
-        result += (*it)->capacity();
-    return result;
+    block->gatherDirtyCells(*m_dirtyCells);
 }
 
 }
 
-void MarkedSpace::reset()
+void MarkedSpace::gatherDirtyCells(MarkedBlock::DirtyCellVector& dirtyCells)
 {
 {
-    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();
+    GatherDirtyCells gatherDirtyCells(&dirtyCells);
+    forEachBlock(gatherDirtyCells);
 }
 }
+#endif
 
 } // namespace JSC
 
 } // namespace JSC
index a49e5f0118c248fedff2f6fe81a44ba8dcd9e80d..19061a12b9678e3228383d95adcffe9b8c7e017f 100644 (file)
 #define MarkedSpace_h
 
 #include "MachineStackMarker.h"
 #define MarkedSpace_h
 
 #include "MachineStackMarker.h"
+#include "MarkedAllocator.h"
 #include "MarkedBlock.h"
 #include "MarkedBlock.h"
-#include "PageAllocationAligned.h"
+#include "MarkedBlockSet.h"
+#include <wtf/PageAllocationAligned.h>
 #include <wtf/Bitmap.h>
 #include <wtf/DoublyLinkedList.h>
 #include <wtf/FixedArray.h>
 #include <wtf/Bitmap.h>
 #include <wtf/DoublyLinkedList.h>
 #include <wtf/FixedArray.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/Vector.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)
+#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= MarkedSpace::maxCellSize, class_fits_in_cell)
 
 namespace JSC {
 
 
 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;
+class Heap;
+class JSCell;
+class LiveObjectIterator;
+class LLIntOffsetsExtractor;
+class WeakGCHandle;
+class SlotVisitor;
+
+class MarkedSpace {
+    WTF_MAKE_NONCOPYABLE(MarkedSpace);
+public:
+    static const size_t maxCellSize = 2048;
+
+    MarkedSpace(Heap*);
+
+    MarkedAllocator& firstAllocator();
+    MarkedAllocator& allocatorFor(size_t);
+    MarkedAllocator& allocatorFor(MarkedBlock*);
+    MarkedAllocator& destructorAllocatorFor(size_t);
+    void* allocateWithDestructor(size_t);
+    void* allocateWithoutDestructor(size_t);
+    
+    void resetAllocators();
+
+    MarkedBlockSet& blocks() { return m_blocks; }
+    
+    void canonicalizeCellLivenessData();
+
+    typedef HashSet<MarkedBlock*>::iterator BlockIterator;
+    
+    template<typename Functor> typename Functor::ReturnType forEachCell(Functor&);
+    template<typename Functor> typename Functor::ReturnType forEachCell();
+    template<typename Functor> typename Functor::ReturnType forEachBlock(Functor&);
+    template<typename Functor> typename Functor::ReturnType forEachBlock();
+    
+    void shrink();
+    void freeBlocks(MarkedBlock* head);
+
+    void didAddBlock(MarkedBlock*);
+    void didConsumeFreeList(MarkedBlock*);
+
+    bool isPagedOut(double deadline);
+
+private:
+    friend class LLIntOffsetsExtractor;
+    
+    // [ 32... 256 ]
+    static const size_t preciseStep = MarkedBlock::atomSize;
+    static const size_t preciseCutoff = 256;
+    static const size_t preciseCount = preciseCutoff / preciseStep;
+
+    // [ 512... 2048 ]
+    static const size_t impreciseStep = preciseCutoff;
+    static const size_t impreciseCutoff = maxCellSize;
+    static const size_t impreciseCount = impreciseCutoff / impreciseStep;
+
+    struct Subspace {
+        FixedArray<MarkedAllocator, preciseCount> preciseAllocators;
+        FixedArray<MarkedAllocator, impreciseCount> impreciseAllocators;
     };
 
     };
 
-    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);
+    Subspace m_destructorSpace;
+    Subspace m_normalSpace;
+
+    Heap* m_heap;
+    MarkedBlockSet m_blocks;
+};
+
+template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachCell(Functor& functor)
+{
+    canonicalizeCellLivenessData();
+
+    BlockIterator end = m_blocks.set().end();
+    for (BlockIterator it = m_blocks.set().begin(); it != end; ++it)
+        (*it)->forEachCell(functor);
+    return functor.returnValue();
+}
+
+template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachCell()
+{
+    Functor functor;
+    return forEachCell(functor);
+}
+
+inline MarkedAllocator& MarkedSpace::firstAllocator()
+{
+    return m_normalSpace.preciseAllocators[0];
+}
+
+inline MarkedAllocator& MarkedSpace::allocatorFor(size_t bytes)
+{
+    ASSERT(bytes && bytes <= maxCellSize);
+    if (bytes <= preciseCutoff)
+        return m_normalSpace.preciseAllocators[(bytes - 1) / preciseStep];
+    return m_normalSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
+}
+
+inline MarkedAllocator& MarkedSpace::allocatorFor(MarkedBlock* block)
+{
+    if (block->cellsNeedDestruction())
+        return destructorAllocatorFor(block->cellSize());
+    return allocatorFor(block->cellSize());
+}
+
+inline MarkedAllocator& MarkedSpace::destructorAllocatorFor(size_t bytes)
+{
+    ASSERT(bytes && bytes <= maxCellSize);
+    if (bytes <= preciseCutoff)
+        return m_destructorSpace.preciseAllocators[(bytes - 1) / preciseStep];
+    return m_destructorSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
+}
+
+inline void* MarkedSpace::allocateWithoutDestructor(size_t bytes)
+{
+    return allocatorFor(bytes).allocate();
+}
+
+inline void* MarkedSpace::allocateWithDestructor(size_t bytes)
+{
+    return destructorAllocatorFor(bytes).allocate();
+}
+
+template <typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachBlock(Functor& functor)
+{
+    for (size_t i = 0; i < preciseCount; ++i) {
+        m_normalSpace.preciseAllocators[i].forEachBlock(functor);
+        m_destructorSpace.preciseAllocators[i].forEachBlock(functor);
     }
 
     }
 
-    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);
+    for (size_t i = 0; i < impreciseCount; ++i) {
+        m_normalSpace.impreciseAllocators[i].forEachBlock(functor);
+        m_destructorSpace.impreciseAllocators[i].forEachBlock(functor);
     }
 
     }
 
-    inline JSGlobalData* MarkedSpace::globalData()
-    {
-        return m_globalData;
-    }
+    return functor.returnValue();
+}
 
 
-    inline size_t MarkedSpace::highWaterMark()
-    {
-        return m_highWaterMark;
-    }
+template <typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachBlock()
+{
+    Functor functor;
+    return forEachBlock(functor);
+}
 
 
-    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();
-    }
+inline void MarkedSpace::didAddBlock(MarkedBlock* block)
+{
+    m_blocks.add(block);
+}
 
 } // namespace JSC
 
 
 } // namespace JSC
 
diff --git a/heap/PassWeak.h b/heap/PassWeak.h
new file mode 100644 (file)
index 0000000..8c6364e
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef PassWeak_h
+#define PassWeak_h
+
+#include "JSCell.h"
+#include "WeakSetInlines.h"
+#include <wtf/Assertions.h>
+#include <wtf/NullPtr.h>
+#include <wtf/TypeTraits.h>
+
+namespace JSC {
+
+template<typename T> class Weak;
+template<typename T> class PassWeak;
+template<typename T> PassWeak<T> adoptWeak(WeakImpl*);
+
+template<typename Base, typename T> class WeakImplAccessor {
+public:
+    typedef T* GetType;
+
+    T* operator->() const;
+    T& operator*() const;
+    GetType get() const;
+
+#if !ASSERT_DISABLED
+    bool was(GetType) const;
+#endif
+};
+
+template<typename T> class PassWeak : public WeakImplAccessor<PassWeak<T>, T> {
+public:
+    friend class WeakImplAccessor<PassWeak<T>, T>;
+    typedef typename WeakImplAccessor<PassWeak<T>, T>::GetType GetType;
+
+    PassWeak();
+    PassWeak(std::nullptr_t);
+    PassWeak(GetType, WeakHandleOwner* = 0, void* context = 0);
+
+    // It somewhat breaks the type system to allow transfer of ownership out of
+    // a const PassWeak. However, it makes it much easier to work with PassWeak
+    // temporaries, and we don't have a need to use real const PassWeaks anyway.
+    PassWeak(const PassWeak&);
+    template<typename U> PassWeak(const PassWeak<U>&);
+
+    ~PassWeak();
+
+    bool operator!() const;
+
+    // This conversion operator allows implicit conversion to bool but not to other integer types.
+    typedef JSValue (PassWeak::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const;
+
+    WeakImpl* leakImpl() const WARN_UNUSED_RETURN;
+
+private:
+    friend PassWeak adoptWeak<T>(WeakImpl*);
+    explicit PassWeak(WeakImpl*);
+
+    WeakImpl* m_impl;
+};
+
+template<typename Base, typename T> inline T* WeakImplAccessor<Base, T>::operator->() const
+{
+    ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live);
+    return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell());
+}
+
+template<typename Base, typename T> inline T& WeakImplAccessor<Base, T>::operator*() const
+{
+    ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live);
+    return *jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell());
+}
+
+template<typename Base, typename T> inline typename WeakImplAccessor<Base, T>::GetType WeakImplAccessor<Base, T>::get() const
+{
+    if (!static_cast<const Base*>(this)->m_impl || static_cast<const Base*>(this)->m_impl->state() != WeakImpl::Live)
+        return GetType();
+    return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell());
+}
+
+#if !ASSERT_DISABLED
+template<typename Base, typename T> inline bool WeakImplAccessor<Base, T>::was(typename WeakImplAccessor<Base, T>::GetType other) const
+{
+    return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell()) == other;
+}
+#endif
+
+template<typename T> inline PassWeak<T>::PassWeak()
+    : m_impl(0)
+{
+}
+
+template<typename T> inline PassWeak<T>::PassWeak(std::nullptr_t)
+    : m_impl(0)
+{
+}
+
+template<typename T> inline PassWeak<T>::PassWeak(typename PassWeak<T>::GetType getType, WeakHandleOwner* weakOwner, void* context)
+    : m_impl(getType ? WeakSet::allocate(getType, weakOwner, context) : 0)
+{
+}
+
+template<typename T> inline PassWeak<T>::PassWeak(const PassWeak& o)
+    : m_impl(o.leakImpl())
+{
+}
+
+template<typename T> template<typename U> inline PassWeak<T>::PassWeak(const PassWeak<U>& o)
+    : m_impl(o.leakImpl())
+{
+}
+
+template<typename T> inline PassWeak<T>::~PassWeak()
+{
+    if (!m_impl)
+        return;
+    WeakSet::deallocate(m_impl);
+}
+
+template<typename T> inline bool PassWeak<T>::operator!() const
+{
+    return !m_impl || m_impl->state() != WeakImpl::Live || !m_impl->jsValue();
+}
+
+template<typename T> inline PassWeak<T>::operator UnspecifiedBoolType*() const
+{
+    return reinterpret_cast<UnspecifiedBoolType*>(!!*this);
+}
+
+template<typename T> inline PassWeak<T>::PassWeak(WeakImpl* impl)
+: m_impl(impl)
+{
+}
+
+template<typename T> inline WeakImpl* PassWeak<T>::leakImpl() const
+{
+    WeakImpl* tmp = 0;
+    std::swap(tmp, const_cast<WeakImpl*&>(m_impl));
+    return tmp;
+}
+
+template<typename T> PassWeak<T> inline adoptWeak(WeakImpl* impl)
+{
+    return PassWeak<T>(impl);
+}
+
+template<typename T, typename U> inline bool operator==(const PassWeak<T>& a, const PassWeak<U>& b) 
+{
+    return a.get() == b.get(); 
+}
+
+template<typename T, typename U> inline bool operator==(const PassWeak<T>& a, const Weak<U>& b) 
+{
+    return a.get() == b.get(); 
+}
+
+template<typename T, typename U> inline bool operator==(const Weak<T>& a, const PassWeak<U>& b) 
+{
+    return a.get() == b.get(); 
+}
+
+template<typename T, typename U> inline bool operator==(const PassWeak<T>& a, U* b) 
+{
+    return a.get() == b; 
+}
+
+template<typename T, typename U> inline bool operator==(T* a, const PassWeak<U>& b) 
+{
+    return a == b.get(); 
+}
+
+template<typename T, typename U> inline bool operator!=(const PassWeak<T>& a, const PassWeak<U>& b) 
+{
+    return a.get() != b.get(); 
+}
+
+template<typename T, typename U> inline bool operator!=(const PassWeak<T>& a, const Weak<U>& b) 
+{
+    return a.get() != b.get(); 
+}
+
+template<typename T, typename U> inline bool operator!=(const Weak<T>& a, const PassWeak<U>& b) 
+{
+    return a.get() != b.get(); 
+}
+
+template<typename T, typename U> inline bool operator!=(const PassWeak<T>& a, U* b)
+{
+    return a.get() != b; 
+}
+
+template<typename T, typename U> inline bool operator!=(T* a, const PassWeak<U>& b) 
+{
+    return a != b.get(); 
+}
+
+} // namespace JSC
+
+#endif // PassWeak_h
diff --git a/heap/SlotVisitor.h b/heap/SlotVisitor.h
new file mode 100644 (file)
index 0000000..01eb219
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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 SlotVisitor_h
+#define SlotVisitor_h
+
+#include "CopiedSpace.h"
+#include "MarkStack.h"
+
+namespace JSC {
+
+class Heap;
+
+class SlotVisitor : public MarkStack {
+    friend class HeapRootVisitor;
+public:
+    SlotVisitor(MarkStackThreadSharedData&);
+
+    void donate()
+    {
+        ASSERT(m_isInParallelMode);
+        if (Options::numberOfGCMarkers == 1)
+            return;
+        
+        donateKnownParallel();
+    }
+    
+    void drain();
+    
+    void donateAndDrain()
+    {
+        donate();
+        drain();
+    }
+    
+    enum SharedDrainMode { SlaveDrain, MasterDrain };
+    void drainFromShared(SharedDrainMode);
+
+    void harvestWeakReferences();
+    void finalizeUnconditionalFinalizers();
+
+    void startCopying();
+    void copyAndAppend(void**, size_t, JSValue*, unsigned);
+    void doneCopying(); 
+        
+private:
+    void* allocateNewSpace(void*, size_t);
+
+    void donateSlow();
+    
+    void donateKnownParallel()
+    {
+        if (!m_stack.canDonateSomeCells())
+            return;
+        donateSlow();
+    }
+    
+    CopiedBlock* m_copyBlock;
+};
+
+inline SlotVisitor::SlotVisitor(MarkStackThreadSharedData& shared)
+    : MarkStack(shared)
+    , m_copyBlock(0)
+{
+}
+
+} // namespace JSC
+
+#endif // SlotVisitor_h
index 9f2aa05e25e0a9a5f738cac8307d56ba8a7eb26a..7fafaeab56008338663aae74585cd237cc1ebec3 100644 (file)
 #ifndef Strong_h
 #define Strong_h
 
 #ifndef Strong_h
 #define Strong_h
 
-#include "Assertions.h"
+#include <wtf/Assertions.h>
 #include "Handle.h"
 #include "Handle.h"
-#include "HandleHeap.h"
+#include "HandleSet.h"
 
 namespace JSC {
 
 class JSGlobalData;
 
 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> {
 
 // A strongly referenced handle that prevents the object it points to from being garbage collected.
 template <typename T> class Strong : public Handle<T> {
@@ -48,24 +47,16 @@ public:
     {
     }
     
     {
     }
     
-    Strong(JSGlobalData& globalData, ExternalType value = ExternalType())
-        : Handle<T>(allocateGlobalHandle(globalData))
-    {
-        set(value);
-    }
+    Strong(JSGlobalData&, ExternalType = ExternalType());
 
 
-    Strong(JSGlobalData& globalData, Handle<T> handle)
-        : Handle<T>(allocateGlobalHandle(globalData))
-    {
-        set(handle.get());
-    }
+    Strong(JSGlobalData&, Handle<T>);
     
     Strong(const Strong& other)
         : Handle<T>()
     {
         if (!other.slot())
             return;
     
     Strong(const Strong& other)
         : Handle<T>()
     {
         if (!other.slot())
             return;
-        setSlot(HandleHeap::heapFor(other.slot())->allocate());
+        setSlot(HandleSet::heapFor(other.slot())->allocate());
         set(other.get());
     }
 
         set(other.get());
     }
 
@@ -74,7 +65,7 @@ public:
     {
         if (!other.slot())
             return;
     {
         if (!other.slot())
             return;
-        setSlot(HandleHeap::heapFor(other.slot())->allocate());
+        setSlot(HandleSet::heapFor(other.slot())->allocate());
         set(other.get());
     }
     
         set(other.get());
     }
     
@@ -90,17 +81,20 @@ public:
         clear();
     }
 
         clear();
     }
 
+    bool operator!() const { return !slot() || !*slot(); }
+
+    // This conversion operator allows implicit conversion to bool but not to other integer types.
+    typedef JSValue (HandleBase::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const { return !!*this ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+
     void swap(Strong& other)
     {
         Handle<T>::swap(other);
     }
 
     void swap(Strong& other)
     {
         Handle<T>::swap(other);
     }
 
-    void set(JSGlobalData& globalData, ExternalType value)
-    {
-        if (!slot())
-            setSlot(allocateGlobalHandle(globalData));
-        set(value);
-    }
+    ExternalType get() const { return HandleTypes<T>::getFromSlot(this->slot()); }
+
+    void set(JSGlobalData&, ExternalType);
 
     template <typename U> Strong& operator=(const Strong<U>& other)
     {
 
     template <typename U> Strong& operator=(const Strong<U>& other)
     {
@@ -109,7 +103,7 @@ public:
             return *this;
         }
 
             return *this;
         }
 
-        set(*HandleHeap::heapFor(other.slot())->globalData(), other.get());
+        set(*HandleSet::heapFor(other.slot())->globalData(), other.get());
         return *this;
     }
     
         return *this;
     }
     
@@ -120,7 +114,7 @@ public:
             return *this;
         }
 
             return *this;
         }
 
-        set(*HandleHeap::heapFor(other.slot())->globalData(), other.get());
+        set(*HandleSet::heapFor(other.slot())->globalData(), other.get());
         return *this;
     }
 
         return *this;
     }
 
@@ -128,7 +122,7 @@ public:
     {
         if (!slot())
             return;
     {
         if (!slot())
             return;
-        HandleHeap::heapFor(slot())->deallocate(slot());
+        HandleSet::heapFor(slot())->deallocate(slot());
         setSlot(0);
     }
 
         setSlot(0);
     }
 
@@ -139,7 +133,7 @@ private:
     {
         ASSERT(slot());
         JSValue value = HandleTypes<T>::toJSValue(externalType);
     {
         ASSERT(slot());
         JSValue value = HandleTypes<T>::toJSValue(externalType);
-        HandleHeap::heapFor(slot())->writeBarrier(slot(), value);
+        HandleSet::heapFor(slot())->writeBarrier(slot(), value);
         *slot() = value;
     }
 };
         *slot() = value;
     }
 };
diff --git a/heap/StrongInlines.h b/heap/StrongInlines.h
new file mode 100644 (file)
index 0000000..2308bf6
--- /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. 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 StrongInlines_h
+#define StrongInlines_h
+
+#include "JSGlobalData.h"
+
+namespace JSC {
+
+template <typename T>
+inline Strong<T>::Strong(JSGlobalData& globalData, ExternalType value)
+    : Handle<T>(globalData.heap.handleSet()->allocate())
+{
+    set(value);
+}
+
+template <typename T>
+inline Strong<T>::Strong(JSGlobalData& globalData, Handle<T> handle)
+    : Handle<T>(globalData.heap.handleSet()->allocate())
+{
+    set(handle.get());
+}
+
+template <typename T>
+inline void Strong<T>::set(JSGlobalData& globalData, ExternalType value)
+{
+    if (!slot())
+        setSlot(globalData.heap.handleSet()->allocate());
+    set(value);
+}
+
+} // namespace JSC
+    
+#endif // StrongInlines_h
diff --git a/heap/TinyBloomFilter.h b/heap/TinyBloomFilter.h
new file mode 100644 (file)
index 0000000..a75ce8c
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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 TinyBloomFilter_h
+#define TinyBloomFilter_h
+
+namespace JSC {
+
+typedef uintptr_t Bits;
+
+class TinyBloomFilter {
+public:
+    TinyBloomFilter();
+
+    void add(Bits);
+    bool ruleOut(Bits) const; // True for 0.
+    void reset();
+
+private:
+    Bits m_bits;
+};
+
+inline TinyBloomFilter::TinyBloomFilter()
+    : m_bits(0)
+{
+}
+
+inline void TinyBloomFilter::add(Bits bits)
+{
+    m_bits |= bits;
+}
+
+inline bool TinyBloomFilter::ruleOut(Bits bits) const
+{
+    if (!bits)
+        return true;
+
+    if ((bits & m_bits) != bits)
+        return true;
+
+    return false;
+}
+
+inline void TinyBloomFilter::reset()
+{
+    m_bits = 0;
+}
+
+} // namespace JSC
+
+#endif // TinyBloomFilter_h
diff --git a/heap/UnconditionalFinalizer.h b/heap/UnconditionalFinalizer.h
new file mode 100644 (file)
index 0000000..26029d0
--- /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 UnconditionalFinalizer_h
+#define UnconditionalFinalizer_h
+
+#include "ListableHandler.h"
+
+namespace JSC {
+
+// An unconditional finalizer is useful for caches that you would like to
+// destroy on each GC. This is currently used for the bytecode stream
+// associated with each CodeBlock.
+
+class UnconditionalFinalizer : public ListableHandler<UnconditionalFinalizer> {
+public:    
+    virtual void finalizeUnconditionally() = 0;
+
+protected:
+    virtual ~UnconditionalFinalizer() { }
+};
+
+}
+
+#endif // UltraWeakFinalizer_h
diff --git a/heap/VTableSpectrum.cpp b/heap/VTableSpectrum.cpp
new file mode 100644 (file)
index 0000000..acb4940
--- /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. 
+ */
+
+#include "config.h"
+#include "VTableSpectrum.h"
+
+#include "JSObject.h"
+#include "Structure.h"
+#include <algorithm>
+#include <stdio.h>
+#include <wtf/Platform.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(MAC)
+#include <dlfcn.h>
+#endif
+
+namespace JSC {
+
+VTableSpectrum::VTableSpectrum()
+{
+}
+
+VTableSpectrum::~VTableSpectrum()
+{
+}
+
+void VTableSpectrum::countVPtr(void* vTablePointer)
+{
+    add(vTablePointer);
+}
+
+void VTableSpectrum::count(JSCell* cell)
+{
+    // FIXME: we need to change this class to count ClassInfos rather than vptrs
+    UNUSED_PARAM(cell);
+}
+
+void VTableSpectrum::dump(FILE* output, const char* comment)
+{
+    fprintf(output, "%s:\n", comment);
+    
+    Vector<KeyAndCount> list = buildList();
+    
+    for (size_t index = list.size(); index-- > 0;) {
+        KeyAndCount item = list.at(index);
+#if PLATFORM(MAC)
+        Dl_info info;
+        if (dladdr(item.key, &info)) {
+            char* findResult = strrchr(info.dli_fname, '/');
+            const char* strippedFileName;
+            
+            if (findResult)
+                strippedFileName = findResult + 1;
+            else
+                strippedFileName = info.dli_fname;
+            
+            fprintf(output, "    %s:%s(%p): %lu\n", strippedFileName, info.dli_sname, item.key, item.count);
+            continue;
+        }
+#endif
+        fprintf(output, "    %p: %lu\n", item.key, item.count);
+    }
+    
+    fflush(output);
+}
+
+} // namespace JSC
diff --git a/heap/VTableSpectrum.h b/heap/VTableSpectrum.h
new file mode 100644 (file)
index 0000000..a50a04f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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 VTableSpectrum_h
+#define VTableSpectrum_h
+
+#include <stdio.h>
+#include <wtf/Spectrum.h>
+
+namespace JSC {
+
+class JSCell;
+
+class VTableSpectrum : Spectrum<void*> {
+public:
+    VTableSpectrum();
+    ~VTableSpectrum();
+    
+    void countVPtr(void*);
+    JS_EXPORT_PRIVATE void count(JSCell*);
+    
+    void dump(FILE* output, const char* comment);
+};
+
+} // namespace JSC
+
+#endif // VTableSpectrum_h
index a235a570b820a371cf541ee213e01013a683efd5..0938249b8b0223247d4824e2c06aedab1bd9c671 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2012 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef Weak_h
 #define Weak_h
 
 #ifndef Weak_h
 #define Weak_h
 
-#include "Assertions.h"
-#include "Handle.h"
-#include "HandleHeap.h"
-#include "JSGlobalData.h"
+#include <wtf/Assertions.h>
+#include "PassWeak.h"
+#include "WeakSetInlines.h"
 
 namespace JSC {
 
 
 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;
-
+template<typename T> class Weak : public WeakImplAccessor<Weak<T>, T> {
+    WTF_MAKE_NONCOPYABLE(Weak);
 public:
 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()));
-    }
-    
+    friend class WeakImplAccessor<Weak<T>, T>;
+    typedef typename WeakImplAccessor<Weak<T>, T>::GetType GetType;
+
+    Weak();
+    Weak(std::nullptr_t);
+    Weak(GetType, WeakHandleOwner* = 0, void* context = 0);
+
     enum HashTableDeletedValueTag { HashTableDeletedValue };
     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;
-    }
+    bool isHashTableDeletedValue() const;
+    Weak(HashTableDeletedValueTag);
+
+    template<typename U> Weak(const PassWeak<U>&);
+
+    ~Weak();
+
+    void swap(Weak&);
+    Weak& operator=(const PassWeak<T>&);
     
     
-    HandleSlot leakHandle()
-    {
-        ASSERT(HandleHeap::heapFor(slot())->hasFinalizer(slot()));
-        HandleSlot result = slot();
-        setSlot(0);
-        return result;
-    }
+    bool operator!() const;
 
 
+    // This conversion operator allows implicit conversion to bool but not to other integer types.
+    typedef JSValue (HandleBase::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const;
+
+    PassWeak<T> release();
+    void clear();
+    
 private:
 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;
-    }
+    static WeakImpl* hashTableDeletedValue();
+
+    WeakImpl* m_impl;
 };
 
 };
 
+template<typename T> inline Weak<T>::Weak()
+    : m_impl(0)
+{
+}
+
+template<typename T> inline Weak<T>::Weak(std::nullptr_t)
+    : m_impl(0)
+{
+}
+
+template<typename T> inline Weak<T>::Weak(typename Weak<T>::GetType getType, WeakHandleOwner* weakOwner, void* context)
+    : m_impl(getType ? WeakSet::allocate(getType, weakOwner, context) : 0)
+{
+}
+
+template<typename T> inline bool Weak<T>::isHashTableDeletedValue() const
+{
+    return m_impl == hashTableDeletedValue();
+}
+
+template<typename T> inline Weak<T>::Weak(typename Weak<T>::HashTableDeletedValueTag)
+    : m_impl(hashTableDeletedValue())
+{
+}
+
+template<typename T> template<typename U>  inline Weak<T>::Weak(const PassWeak<U>& other)
+    : m_impl(other.leakImpl())
+{
+}
+
+template<typename T> inline Weak<T>::~Weak()
+{
+    clear();
+}
+
 template<class T> inline void swap(Weak<T>& a, Weak<T>& b)
 {
     a.swap(b);
 }
 
 template<class T> inline void swap(Weak<T>& a, Weak<T>& b)
 {
     a.swap(b);
 }
 
+template<typename T> inline void Weak<T>::swap(Weak& other)
+{
+    std::swap(m_impl, other.m_impl);
+}
+
+template<typename T> inline Weak<T>& Weak<T>::operator=(const PassWeak<T>& o)
+{
+    clear();
+    m_impl = o.leakImpl();
+    return *this;
+}
+
+template<typename T> inline bool Weak<T>::operator!() const
+{
+    return !m_impl || !m_impl->jsValue() || m_impl->state() != WeakImpl::Live;
+}
+
+template<typename T> inline Weak<T>::operator UnspecifiedBoolType*() const
+{
+    return reinterpret_cast<UnspecifiedBoolType*>(!!*this);
+}
+
+template<typename T> inline PassWeak<T> Weak<T>::release()
+{
+    PassWeak<T> tmp = adoptWeak<T>(m_impl);
+    m_impl = 0;
+    return tmp;
+}
+
+template<typename T> inline void Weak<T>::clear()
+{
+    if (!m_impl)
+        return;
+    WeakSet::deallocate(m_impl);
+    m_impl = 0;
+}
+    
+template<typename T> inline WeakImpl* Weak<T>::hashTableDeletedValue()
+{
+    return reinterpret_cast<WeakImpl*>(-1);
+}
+
 } // namespace JSC
 
 namespace WTF {
 } // namespace JSC
 
 namespace WTF {
@@ -163,7 +158,23 @@ template<typename T> struct VectorTraits<JSC::Weak<T> > : SimpleClassVectorTrait
     static const bool canCompareWithMemcmp = false;
 };
 
     static const bool canCompareWithMemcmp = false;
 };
 
-template<typename P> struct HashTraits<JSC::Weak<P> > : SimpleClassHashTraits<JSC::Weak<P> > { };
+template<typename T> struct HashTraits<JSC::Weak<T> > : SimpleClassHashTraits<JSC::Weak<T> > {
+    typedef JSC::Weak<T> StorageType;
+
+    typedef std::nullptr_t EmptyValueType;
+    static EmptyValueType emptyValue() { return nullptr; }
+
+    typedef JSC::PassWeak<T> PassInType;
+    static void store(PassInType value, StorageType& storage) { storage = value; }
+
+    typedef JSC::PassWeak<T> PassOutType;
+    static PassOutType passOut(StorageType& value) { return value.release(); }
+    static PassOutType passOut(EmptyValueType) { return PassOutType(); }
+
+    typedef typename StorageType::GetType PeekType;
+    static PeekType peek(const StorageType& value) { return value.get(); }
+    static PeekType peek(EmptyValueType) { return PeekType(); }
+};
 
 }
 
 
 }
 
diff --git a/heap/WeakBlock.cpp b/heap/WeakBlock.cpp
new file mode 100644 (file)
index 0000000..7ba778b
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 "WeakBlock.h"
+
+#include "Heap.h"
+#include "HeapRootVisitor.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
+#include "Structure.h"
+
+namespace JSC {
+
+WeakBlock* WeakBlock::create()
+{
+    PageAllocation allocation = PageAllocation::allocate(blockSize, OSAllocator::JSGCHeapPages);
+    if (!static_cast<bool>(allocation))
+        CRASH();
+    return new (NotNull, allocation.base()) WeakBlock(allocation);
+}
+
+void WeakBlock::destroy(WeakBlock* block)
+{
+    block->m_allocation.deallocate();
+}
+
+WeakBlock::WeakBlock(PageAllocation& allocation)
+    : m_allocation(allocation)
+{
+    for (size_t i = 0; i < weakImplCount(); ++i) {
+        WeakImpl* weakImpl = &weakImpls()[i];
+        new (NotNull, weakImpl) WeakImpl;
+        addToFreeList(&m_sweepResult.freeList, weakImpl);
+    }
+
+    ASSERT(!m_sweepResult.isNull() && m_sweepResult.blockIsFree);
+}
+
+void WeakBlock::finalizeAll()
+{
+    for (size_t i = 0; i < weakImplCount(); ++i) {
+        WeakImpl* weakImpl = &weakImpls()[i];
+        if (weakImpl->state() >= WeakImpl::Finalized)
+            continue;
+        weakImpl->setState(WeakImpl::Dead);
+        finalize(weakImpl);
+    }
+}
+
+void WeakBlock::sweep()
+{
+    if (!m_sweepResult.isNull())
+        return;
+
+    SweepResult sweepResult;
+    for (size_t i = 0; i < weakImplCount(); ++i) {
+        WeakImpl* weakImpl = &weakImpls()[i];
+        if (weakImpl->state() == WeakImpl::Dead)
+            finalize(weakImpl);
+        if (weakImpl->state() == WeakImpl::Deallocated)
+            addToFreeList(&sweepResult.freeList, weakImpl);
+        else
+            sweepResult.blockIsFree = false;
+    }
+
+    m_sweepResult = sweepResult;
+    ASSERT(!m_sweepResult.isNull());
+}
+
+void WeakBlock::visitLiveWeakImpls(HeapRootVisitor& heapRootVisitor)
+{
+    // If a block is completely empty, a visit won't have any effect.
+    if (!m_sweepResult.isNull() && m_sweepResult.blockIsFree)
+        return;
+
+    SlotVisitor& visitor = heapRootVisitor.visitor();
+
+    for (size_t i = 0; i < weakImplCount(); ++i) {
+        WeakImpl* weakImpl = &weakImpls()[i];
+        if (weakImpl->state() != WeakImpl::Live)
+            continue;
+
+        const JSValue& jsValue = weakImpl->jsValue();
+        if (Heap::isMarked(jsValue.asCell()))
+            continue;
+
+        WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner();
+        if (!weakHandleOwner)
+            continue;
+
+        if (!weakHandleOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(jsValue)), weakImpl->context(), visitor))
+            continue;
+
+        heapRootVisitor.visit(&const_cast<JSValue&>(jsValue));
+    }
+}
+
+void WeakBlock::visitDeadWeakImpls(HeapRootVisitor&)
+{
+    // If a block is completely empty, a visit won't have any effect.
+    if (!m_sweepResult.isNull() && m_sweepResult.blockIsFree)
+        return;
+
+    for (size_t i = 0; i < weakImplCount(); ++i) {
+        WeakImpl* weakImpl = &weakImpls()[i];
+        if (weakImpl->state() > WeakImpl::Dead)
+            continue;
+
+        if (Heap::isMarked(weakImpl->jsValue().asCell())) {
+            ASSERT(weakImpl->state() == WeakImpl::Live);
+            continue;
+        }
+
+        weakImpl->setState(WeakImpl::Dead);
+    }
+}
+
+} // namespace JSC
diff --git a/heap/WeakBlock.h b/heap/WeakBlock.h
new file mode 100644 (file)
index 0000000..9e546ea
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 WeakBlock_h
+#define WeakBlock_h
+
+#include "HeapBlock.h"
+#include "WeakHandleOwner.h"
+#include "WeakImpl.h"
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/PageAllocation.h>
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+class HeapRootVisitor;
+class JSValue;
+class WeakHandleOwner;
+
+class WeakBlock : public DoublyLinkedListNode<WeakBlock> {
+public:
+    friend class WTF::DoublyLinkedListNode<WeakBlock>;
+    static const size_t blockSize = 4 * KB;
+
+    struct FreeCell {
+        FreeCell* next;
+    };
+
+    struct SweepResult {
+        SweepResult();
+        bool isNull() const;
+
+        bool blockIsFree;
+        FreeCell* freeList;
+    };
+
+    static WeakBlock* create();
+    static void destroy(WeakBlock*);
+
+    static WeakImpl* asWeakImpl(FreeCell*);
+
+    void sweep();
+    const SweepResult& sweepResult();
+    SweepResult takeSweepResult();
+
+    void visitLiveWeakImpls(HeapRootVisitor&);
+    void visitDeadWeakImpls(HeapRootVisitor&);
+
+    void finalizeAll();
+
+private:
+    static FreeCell* asFreeCell(WeakImpl*);
+
+    WeakBlock(PageAllocation&);
+    WeakImpl* firstWeakImpl();
+    void finalize(WeakImpl*);
+    WeakImpl* weakImpls();
+    size_t weakImplCount();
+    void addToFreeList(FreeCell**, WeakImpl*);
+
+    PageAllocation m_allocation;
+    WeakBlock* m_prev;
+    WeakBlock* m_next;
+    SweepResult m_sweepResult;
+};
+
+inline WeakBlock::SweepResult::SweepResult()
+    : blockIsFree(true)
+    , freeList(0)
+{
+    ASSERT(isNull());
+}
+
+inline bool WeakBlock::SweepResult::isNull() const
+{
+    return blockIsFree && !freeList; // This state is impossible, so we can use it to mean null.
+}
+
+inline WeakImpl* WeakBlock::asWeakImpl(FreeCell* freeCell)
+{
+    return reinterpret_cast<WeakImpl*>(freeCell);
+}
+
+inline WeakBlock::SweepResult WeakBlock::takeSweepResult()
+{
+    SweepResult tmp;
+    std::swap(tmp, m_sweepResult);
+    ASSERT(m_sweepResult.isNull());
+    return tmp;
+}
+
+inline const WeakBlock::SweepResult& WeakBlock::sweepResult()
+{
+    return m_sweepResult;
+}
+
+inline WeakBlock::FreeCell* WeakBlock::asFreeCell(WeakImpl* weakImpl)
+{
+    return reinterpret_cast<FreeCell*>(weakImpl);
+}
+
+inline void WeakBlock::finalize(WeakImpl* weakImpl)
+{
+    ASSERT(weakImpl->state() == WeakImpl::Dead);
+    weakImpl->setState(WeakImpl::Finalized);
+    WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner();
+    if (!weakHandleOwner)
+        return;
+    weakHandleOwner->finalize(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(weakImpl->jsValue())), weakImpl->context());
+}
+
+inline WeakImpl* WeakBlock::weakImpls()
+{
+    return reinterpret_cast<WeakImpl*>(this) + ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl));
+}
+
+inline size_t WeakBlock::weakImplCount()
+{
+    return (blockSize / sizeof(WeakImpl)) - ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl));
+}
+
+inline void WeakBlock::addToFreeList(FreeCell** freeList, WeakImpl* weakImpl)
+{
+    ASSERT(weakImpl->state() == WeakImpl::Deallocated);
+    FreeCell* freeCell = asFreeCell(weakImpl);
+    ASSERT(!*freeList || ((char*)*freeList > (char*)this && (char*)*freeList < (char*)this + blockSize));
+    ASSERT((char*)freeCell > (char*)this && (char*)freeCell < (char*)this + blockSize);
+    freeCell->next = *freeList;
+    *freeList = freeCell;
+}
+
+} // namespace JSC
+
+#endif // WeakBlock_h
diff --git a/heap/WeakHandleOwner.cpp b/heap/WeakHandleOwner.cpp
new file mode 100644 (file)
index 0000000..67e1774
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 "WeakHandleOwner.h"
+
+namespace JSC {
+
+class SlotVisitor;
+template<typename T> class Handle;
+
+WeakHandleOwner::~WeakHandleOwner()
+{
+}
+
+bool WeakHandleOwner::isReachableFromOpaqueRoots(Handle<Unknown>, void*, SlotVisitor&)
+{
+    return false;
+}
+
+void WeakHandleOwner::finalize(Handle<Unknown>, void*)
+{
+}
+
+} // namespace JSC
diff --git a/heap/WeakHandleOwner.h b/heap/WeakHandleOwner.h
new file mode 100644 (file)
index 0000000..6304dd2
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 WeakHandleOwner_h
+#define WeakHandleOwner_h
+
+#include "Handle.h"
+
+namespace JSC {
+
+class SlotVisitor;
+
+class JS_EXPORT_PRIVATE WeakHandleOwner {
+public:
+    virtual ~WeakHandleOwner();
+    virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, SlotVisitor&);
+    virtual void finalize(Handle<Unknown>, void* context);
+};
+
+} // namespace JSC
+
+#endif // WeakHandleOwner_h
diff --git a/heap/WeakImpl.h b/heap/WeakImpl.h
new file mode 100644 (file)
index 0000000..9924923
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 WeakImpl_h
+#define WeakImpl_h
+
+#include "JSValue.h"
+
+namespace JSC {
+
+class WeakHandleOwner;
+
+class WeakImpl {
+public:
+    enum State {
+        Live        = 0x0,
+        Dead        = 0x1,
+        Finalized   = 0x2,
+        Deallocated = 0x3
+    };
+
+    enum {
+        StateMask   = 0x3
+    };
+
+    WeakImpl();
+    WeakImpl(JSValue, WeakHandleOwner*, void* context);
+
+    State state();
+    void setState(State);
+
+    const JSValue& jsValue();
+    WeakHandleOwner* weakHandleOwner();
+    void* context();
+
+    static WeakImpl* asWeakImpl(JSValue*);
+
+private:
+    const JSValue m_jsValue;
+    WeakHandleOwner* m_weakHandleOwner;
+    void* m_context;
+};
+
+inline WeakImpl::WeakImpl()
+    : m_weakHandleOwner(0)
+    , m_context(0)
+{
+    setState(Deallocated);
+}
+
+inline WeakImpl::WeakImpl(JSValue jsValue, WeakHandleOwner* weakHandleOwner, void* context)
+    : m_jsValue(jsValue)
+    , m_weakHandleOwner(weakHandleOwner)
+    , m_context(context)
+{
+    ASSERT(state() == Live);
+    ASSERT(m_jsValue && m_jsValue.isCell());
+}
+
+inline WeakImpl::State WeakImpl::state()
+{
+    return static_cast<State>(reinterpret_cast<uintptr_t>(m_weakHandleOwner) & StateMask);
+}
+
+inline void WeakImpl::setState(WeakImpl::State state)
+{
+    ASSERT(state >= this->state());
+    m_weakHandleOwner = reinterpret_cast<WeakHandleOwner*>((reinterpret_cast<uintptr_t>(m_weakHandleOwner) & ~StateMask) | state);
+}
+
+inline const JSValue& WeakImpl::jsValue()
+{
+    return m_jsValue;
+}
+
+inline WeakHandleOwner* WeakImpl::weakHandleOwner()
+{
+    return reinterpret_cast<WeakHandleOwner*>((reinterpret_cast<uintptr_t>(m_weakHandleOwner) & ~StateMask));
+}
+
+inline void* WeakImpl::context()
+{
+    return m_context;
+}
+
+inline WeakImpl* WeakImpl::asWeakImpl(JSValue* slot)
+{
+    return reinterpret_cast<WeakImpl*>(reinterpret_cast<char*>(slot) + OBJECT_OFFSETOF(WeakImpl, m_jsValue));
+}
+
+} // namespace JSC
+
+#endif // WeakImpl_h
diff --git a/heap/WeakReferenceHarvester.h b/heap/WeakReferenceHarvester.h
new file mode 100644 (file)
index 0000000..90b4dee
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  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 WeakReferenceHarvester_h
+#define WeakReferenceHarvester_h
+
+#include "ListableHandler.h"
+
+namespace JSC {
+
+class MarkStack;
+class MarkStackSharedData;
+class SlotVisitor;
+
+class WeakReferenceHarvester : public ListableHandler<WeakReferenceHarvester> {
+public:
+    virtual void visitWeakReferences(SlotVisitor&) = 0;
+    
+protected:
+    WeakReferenceHarvester()
+    {
+    }
+    
+    virtual ~WeakReferenceHarvester() { }
+};
+
+} // namespace JSC
+
+#endif // WeakReferenceHarvester_h
diff --git a/heap/WeakSet.cpp b/heap/WeakSet.cpp
new file mode 100644 (file)
index 0000000..d9c773c
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 "WeakSet.h"
+
+#include "Heap.h"
+
+namespace JSC {
+
+WeakSet::~WeakSet()
+{
+    WeakBlock* next = 0;
+    for (WeakBlock* block = m_blocks.head(); block; block = next) {
+        next = block->next();
+        WeakBlock::destroy(block);
+    }
+    m_blocks.clear();
+}
+
+void WeakSet::finalizeAll()
+{
+    for (WeakBlock* block = m_blocks.head(); block; block = block->next())
+        block->finalizeAll();
+}
+
+void WeakSet::visitLiveWeakImpls(HeapRootVisitor& visitor)
+{
+    for (WeakBlock* block = m_blocks.head(); block; block = block->next())
+        block->visitLiveWeakImpls(visitor);
+}
+
+void WeakSet::visitDeadWeakImpls(HeapRootVisitor& visitor)
+{
+    for (WeakBlock* block = m_blocks.head(); block; block = block->next())
+        block->visitDeadWeakImpls(visitor);
+}
+
+void WeakSet::sweep()
+{
+    WeakBlock* next;
+    for (WeakBlock* block = m_blocks.head(); block; block = next) {
+        next = block->next();
+
+        // If a block is completely empty, a new sweep won't have any effect.
+        if (!block->sweepResult().isNull() && block->sweepResult().blockIsFree)
+            continue;
+
+        block->takeSweepResult(); // Force a new sweep by discarding the last sweep.
+        block->sweep();
+    }
+}
+
+void WeakSet::shrink()
+{
+    WeakBlock* next;
+    for (WeakBlock* block = m_blocks.head(); block; block = next) {
+        next = block->next();
+
+        if (!block->sweepResult().isNull() && block->sweepResult().blockIsFree)
+            removeAllocator(block);
+    }
+}
+
+void WeakSet::resetAllocator()
+{
+    m_allocator = 0;
+    m_nextAllocator = m_blocks.head();
+}
+
+WeakBlock::FreeCell* WeakSet::findAllocator()
+{
+    if (WeakBlock::FreeCell* allocator = tryFindAllocator())
+        return allocator;
+
+    return addAllocator();
+}
+
+WeakBlock::FreeCell* WeakSet::tryFindAllocator()
+{
+    while (m_nextAllocator) {
+        WeakBlock* block = m_nextAllocator;
+        m_nextAllocator = m_nextAllocator->next();
+
+        block->sweep();
+        WeakBlock::SweepResult sweepResult = block->takeSweepResult();
+        if (sweepResult.freeList)
+            return sweepResult.freeList;
+    }
+
+    return 0;
+}
+
+WeakBlock::FreeCell* WeakSet::addAllocator()
+{
+    WeakBlock* block = WeakBlock::create();
+    m_heap->didAllocate(WeakBlock::blockSize);
+    m_blocks.append(block);
+    WeakBlock::SweepResult sweepResult = block->takeSweepResult();
+    ASSERT(!sweepResult.isNull() && sweepResult.freeList);
+    return sweepResult.freeList;
+}
+
+void WeakSet::removeAllocator(WeakBlock* block)
+{
+    m_blocks.remove(block);
+    WeakBlock::destroy(block);
+}
+
+} // namespace JSC
diff --git a/heap/WeakSet.h b/heap/WeakSet.h
new file mode 100644 (file)
index 0000000..0a683bd
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 WeakSet_h
+#define WeakSet_h
+
+#include "WeakBlock.h"
+
+namespace JSC {
+
+class Heap;
+class WeakImpl;
+
+class WeakSet {
+public:
+    WeakSet(Heap*);
+    void finalizeAll();
+    ~WeakSet();
+
+    static WeakImpl* allocate(JSValue, WeakHandleOwner* = 0, void* context = 0);
+    static void deallocate(WeakImpl*);
+
+    void visitLiveWeakImpls(HeapRootVisitor&);
+    void visitDeadWeakImpls(HeapRootVisitor&);
+
+    void sweep();
+    void resetAllocator();
+
+    void shrink();
+
+private:
+    JS_EXPORT_PRIVATE WeakBlock::FreeCell* findAllocator();
+    WeakBlock::FreeCell* tryFindAllocator();
+    WeakBlock::FreeCell* addAllocator();
+    void removeAllocator(WeakBlock*);
+
+    WeakBlock::FreeCell* m_allocator;
+    WeakBlock* m_nextAllocator;
+    DoublyLinkedList<WeakBlock> m_blocks;
+    Heap* m_heap;
+};
+
+inline WeakSet::WeakSet(Heap* heap)
+    : m_allocator(0)
+    , m_nextAllocator(0)
+    , m_heap(heap)
+{
+}
+
+inline void WeakSet::deallocate(WeakImpl* weakImpl)
+{
+    weakImpl->setState(WeakImpl::Deallocated);
+}
+
+} // namespace JSC
+
+#endif // WeakSet_h
diff --git a/heap/WeakSetInlines.h b/heap/WeakSetInlines.h
new file mode 100644 (file)
index 0000000..0515904
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 WeakSetInlines_h
+#define WeakSetInlines_h
+
+#include "WeakSet.h"
+
+namespace JSC {
+
+inline WeakImpl* WeakSet::allocate(JSValue jsValue, WeakHandleOwner* weakHandleOwner, void* context)
+{
+    WeakSet& weakSet = *Heap::heap(jsValue.asCell())->weakSet();
+    WeakBlock::FreeCell* allocator = weakSet.m_allocator;
+    if (UNLIKELY(!allocator))
+        allocator = weakSet.findAllocator();
+    weakSet.m_allocator = allocator->next;
+
+    WeakImpl* weakImpl = WeakBlock::asWeakImpl(allocator);
+    return new (NotNull, weakImpl) WeakImpl(jsValue, weakHandleOwner, context);
+}
+
+} // namespace JSC
+
+#endif // WeakSetInlines_h
diff --git a/heap/WriteBarrierSupport.cpp b/heap/WriteBarrierSupport.cpp
new file mode 100644 (file)
index 0000000..5ca33c8
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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 "WriteBarrierSupport.h"
+
+namespace JSC {
+
+#if ENABLE(WRITE_BARRIER_PROFILING)
+GlobalSamplingCounter WriteBarrierCounters::usesWithBarrierFromCpp;
+GlobalSamplingCounter WriteBarrierCounters::usesWithoutBarrierFromCpp;
+GlobalSamplingCounter WriteBarrierCounters::usesWithBarrierFromJit;
+GlobalSamplingCounter WriteBarrierCounters::usesForPropertiesFromJit;
+GlobalSamplingCounter WriteBarrierCounters::usesForVariablesFromJit;
+GlobalSamplingCounter WriteBarrierCounters::usesWithoutBarrierFromJit;
+
+void WriteBarrierCounters::initialize()
+{
+    usesWithBarrierFromCpp.name("WithBarrierFromCpp");
+    usesWithoutBarrierFromCpp.name("WithoutBarrierFromCpp");
+    usesWithBarrierFromJit.name("WithBarrierFromJit");
+    usesForPropertiesFromJit.name("WriteForPropertiesFromJit");
+    usesForVariablesFromJit.name("WriteForVariablesFromJit");
+    usesWithoutBarrierFromJit.name("WithoutBarrierFromJit");
+}
+#else
+char WriteBarrierCounters::usesWithBarrierFromCpp;
+char WriteBarrierCounters::usesWithoutBarrierFromCpp;
+#endif
+
+} // namespace JSC
+
diff --git a/heap/WriteBarrierSupport.h b/heap/WriteBarrierSupport.h
new file mode 100644 (file)
index 0000000..5d7d2f6
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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 WriteBarrierSupport_h
+#define WriteBarrierSupport_h
+
+#include "SamplingCounter.h"
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+// This allows the JIT to distinguish between uses of the barrier for different
+// kinds of writes. This is used by the JIT for profiling, and may be appropriate
+// for allowing the GC implementation to specialize the JIT's write barrier code
+// for different kinds of target objects.
+enum WriteBarrierUseKind {
+    // This allows specialization for access to the property storage (either
+    // array element or property), but not for any other kind of property
+    // accesses (such as writes that are a consequence of setter execution).
+    WriteBarrierForPropertyAccess,
+    
+    // This allows specialization for variable accesses (such as global or
+    // scoped variables).
+    WriteBarrierForVariableAccess,
+    
+    // This captures all other forms of write barriers. It should always be
+    // correct to use a generic access write barrier, even when storing to
+    // properties. Hence, if optimization is not necessary, it is preferable
+    // to just use a generic access.
+    WriteBarrierForGenericAccess
+};
+
+class WriteBarrierCounters {
+private:
+    WriteBarrierCounters() { }
+
+public:
+#if ENABLE(WRITE_BARRIER_PROFILING)
+    static GlobalSamplingCounter usesWithBarrierFromCpp;
+    static GlobalSamplingCounter usesWithoutBarrierFromCpp;
+    static GlobalSamplingCounter usesWithBarrierFromJit;
+    static GlobalSamplingCounter usesForPropertiesFromJit;
+    static GlobalSamplingCounter usesForVariablesFromJit;
+    static GlobalSamplingCounter usesWithoutBarrierFromJit;
+    
+    static void initialize();
+    
+    static GlobalSamplingCounter& jitCounterFor(WriteBarrierUseKind useKind)
+    {
+        switch (useKind) {
+        case WriteBarrierForPropertyAccess:
+            return usesForPropertiesFromJit;
+        case WriteBarrierForVariableAccess:
+            return usesForVariablesFromJit;
+        default:
+            ASSERT(useKind == WriteBarrierForGenericAccess);
+            return usesWithBarrierFromJit;
+        }
+    }
+#else
+    // These are necessary to work around not having conditional exports.
+    JS_EXPORTDATA static char usesWithBarrierFromCpp;
+    JS_EXPORTDATA static char usesWithoutBarrierFromCpp;
+#endif // ENABLE(WRITE_BARRIER_PROFILING)
+
+    static void countWriteBarrier()
+    {
+#if ENABLE(WRITE_BARRIER_PROFILING)
+        WriteBarrierCounters::usesWithBarrierFromCpp.count();
+#endif
+    }
+};
+
+} // namespace JSC
+
+#endif // WriteBarrierSupport_h
+
diff --git a/icu/unicode/uscript.h b/icu/unicode/uscript.h
new file mode 100644 (file)
index 0000000..1637544
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+**********************************************************************
+*   Copyright (C) 1997-2006, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+**********************************************************************
+*
+* File USCRIPT.H
+*
+* Modification History:
+*
+*   Date        Name        Description
+*   07/06/2001    Ram         Creation.
+******************************************************************************
+*/
+#ifndef USCRIPT_H
+#define USCRIPT_H
+#include "unicode/utypes.h"
+
+/**
+ * \file
+ * \brief C API: Unicode Script Information
+ */
+/**
+ * Constants for ISO 15924 script codes.
+ *
+ * Many of these script codes - those from Unicode's ScriptNames.txt -
+ * are character property values for Unicode's Script property.
+ * See UAX #24 Script Names (http://www.unicode.org/reports/tr24/).
+ *
+ * Starting with ICU 3.6, constants for most ISO 15924 script codes
+ * are included (currently excluding private-use codes Qaaa..Qabx).
+ * For scripts for which there are codes in ISO 15924 but which are not
+ * used in the Unicode Character Database (UCD), there are no Unicode characters
+ * associated with those scripts.
+ *
+ * For example, there are no characters that have a UCD script code of
+ * Hans or Hant. All Han ideographs have the Hani script code.
+ * The Hans and Hant script codes are used with CLDR data.
+ *
+ * ISO 15924 script codes are included for use with CLDR and similar.
+ *
+ * @stable ICU 2.2
+ */
+typedef enum UScriptCode {
+      USCRIPT_INVALID_CODE = -1,
+      USCRIPT_COMMON       =  0 , /* Zyyy */
+      USCRIPT_INHERITED    =  1,  /* Qaai */
+      USCRIPT_ARABIC       =  2,  /* Arab */
+      USCRIPT_ARMENIAN     =  3,  /* Armn */
+      USCRIPT_BENGALI      =  4,  /* Beng */
+      USCRIPT_BOPOMOFO     =  5,  /* Bopo */
+      USCRIPT_CHEROKEE     =  6,  /* Cher */
+      USCRIPT_COPTIC       =  7,  /* Copt */
+      USCRIPT_CYRILLIC     =  8,  /* Cyrl */
+      USCRIPT_DESERET      =  9,  /* Dsrt */
+      USCRIPT_DEVANAGARI   = 10,  /* Deva */
+      USCRIPT_ETHIOPIC     = 11,  /* Ethi */
+      USCRIPT_GEORGIAN     = 12,  /* Geor */
+      USCRIPT_GOTHIC       = 13,  /* Goth */
+      USCRIPT_GREEK        = 14,  /* Grek */
+      USCRIPT_GUJARATI     = 15,  /* Gujr */
+      USCRIPT_GURMUKHI     = 16,  /* Guru */
+      USCRIPT_HAN          = 17,  /* Hani */
+      USCRIPT_HANGUL       = 18,  /* Hang */
+      USCRIPT_HEBREW       = 19,  /* Hebr */
+      USCRIPT_HIRAGANA     = 20,  /* Hira */
+      USCRIPT_KANNADA      = 21,  /* Knda */
+      USCRIPT_KATAKANA     = 22,  /* Kana */
+      USCRIPT_KHMER        = 23,  /* Khmr */
+      USCRIPT_LAO          = 24,  /* Laoo */
+      USCRIPT_LATIN        = 25,  /* Latn */
+      USCRIPT_MALAYALAM    = 26,  /* Mlym */
+      USCRIPT_MONGOLIAN    = 27,  /* Mong */
+      USCRIPT_MYANMAR      = 28,  /* Mymr */
+      USCRIPT_OGHAM        = 29,  /* Ogam */
+      USCRIPT_OLD_ITALIC   = 30,  /* Ital */
+      USCRIPT_ORIYA        = 31,  /* Orya */
+      USCRIPT_RUNIC        = 32,  /* Runr */
+      USCRIPT_SINHALA      = 33,  /* Sinh */
+      USCRIPT_SYRIAC       = 34,  /* Syrc */
+      USCRIPT_TAMIL        = 35,  /* Taml */
+      USCRIPT_TELUGU       = 36,  /* Telu */
+      USCRIPT_THAANA       = 37,  /* Thaa */
+      USCRIPT_THAI         = 38,  /* Thai */
+      USCRIPT_TIBETAN      = 39,  /* Tibt */
+      /** Canadian_Aboriginal script. @stable ICU 2.6 */
+      USCRIPT_CANADIAN_ABORIGINAL = 40,  /* Cans */
+      /** Canadian_Aboriginal script (alias). @stable ICU 2.2 */
+      USCRIPT_UCAS         = USCRIPT_CANADIAN_ABORIGINAL,
+      USCRIPT_YI           = 41,  /* Yiii */
+      USCRIPT_TAGALOG      = 42,  /* Tglg */
+      USCRIPT_HANUNOO      = 43,  /* Hano */
+      USCRIPT_BUHID        = 44,  /* Buhd */
+      USCRIPT_TAGBANWA     = 45,  /* Tagb */
+
+      /* New scripts in Unicode 4 @stable ICU 2.6 */
+      USCRIPT_BRAILLE      = 46,  /* Brai */
+      USCRIPT_CYPRIOT      = 47,  /* Cprt */
+      USCRIPT_LIMBU        = 48,  /* Limb */
+      USCRIPT_LINEAR_B     = 49,  /* Linb */
+      USCRIPT_OSMANYA      = 50,  /* Osma */
+      USCRIPT_SHAVIAN      = 51,  /* Shaw */
+      USCRIPT_TAI_LE       = 52,  /* Tale */
+      USCRIPT_UGARITIC     = 53,  /* Ugar */
+
+      /** New script code in Unicode 4.0.1 @stable ICU 3.0 */
+      USCRIPT_KATAKANA_OR_HIRAGANA = 54,/*Hrkt */
+      
+#ifndef U_HIDE_DRAFT_API
+      /* New scripts in Unicode 4.1 @draft ICU 3.4 */
+      USCRIPT_BUGINESE      = 55, /* Bugi */
+      USCRIPT_GLAGOLITIC    = 56, /* Glag */
+      USCRIPT_KHAROSHTHI    = 57, /* Khar */
+      USCRIPT_SYLOTI_NAGRI  = 58, /* Sylo */
+      USCRIPT_NEW_TAI_LUE   = 59, /* Talu */
+      USCRIPT_TIFINAGH      = 60, /* Tfng */
+      USCRIPT_OLD_PERSIAN   = 61, /* Xpeo */
+
+      /* New script codes from ISO 15924 @draft ICU 3.6 */
+      USCRIPT_BALINESE                      = 62, /* Bali */
+      USCRIPT_BATAK                         = 63, /* Batk */
+      USCRIPT_BLISSYMBOLS                   = 64, /* Blis */
+      USCRIPT_BRAHMI                        = 65, /* Brah */
+      USCRIPT_CHAM                          = 66, /* Cham */
+      USCRIPT_CIRTH                         = 67, /* Cirt */
+      USCRIPT_OLD_CHURCH_SLAVONIC_CYRILLIC  = 68, /* Cyrs */
+      USCRIPT_DEMOTIC_EGYPTIAN              = 69, /* Egyd */
+      USCRIPT_HIERATIC_EGYPTIAN             = 70, /* Egyh */
+      USCRIPT_EGYPTIAN_HIEROGLYPHS          = 71, /* Egyp */
+      USCRIPT_KHUTSURI                      = 72, /* Geok */
+      USCRIPT_SIMPLIFIED_HAN                = 73, /* Hans */
+      USCRIPT_TRADITIONAL_HAN               = 74, /* Hant */
+      USCRIPT_PAHAWH_HMONG                  = 75, /* Hmng */
+      USCRIPT_OLD_HUNGARIAN                 = 76, /* Hung */
+      USCRIPT_HARAPPAN_INDUS                = 77, /* Inds */
+      USCRIPT_JAVANESE                      = 78, /* Java */
+      USCRIPT_KAYAH_LI                      = 79, /* Kali */
+      USCRIPT_LATIN_FRAKTUR                 = 80, /* Latf */
+      USCRIPT_LATIN_GAELIC                  = 81, /* Latg */
+      USCRIPT_LEPCHA                        = 82, /* Lepc */
+      USCRIPT_LINEAR_A                      = 83, /* Lina */
+      USCRIPT_MANDAEAN                      = 84, /* Mand */
+      USCRIPT_MAYAN_HIEROGLYPHS             = 85, /* Maya */
+      USCRIPT_MEROITIC                      = 86, /* Mero */
+      USCRIPT_NKO                           = 87, /* Nkoo */
+      USCRIPT_ORKHON                        = 88, /* Orkh */
+      USCRIPT_OLD_PERMIC                    = 89, /* Perm */
+      USCRIPT_PHAGS_PA                      = 90, /* Phag */
+      USCRIPT_PHOENICIAN                    = 91, /* Phnx */
+      USCRIPT_PHONETIC_POLLARD              = 92, /* Plrd */
+      USCRIPT_RONGORONGO                    = 93, /* Roro */
+      USCRIPT_SARATI                        = 94, /* Sara */
+      USCRIPT_ESTRANGELO_SYRIAC             = 95, /* Syre */
+      USCRIPT_WESTERN_SYRIAC                = 96, /* Syrj */
+      USCRIPT_EASTERN_SYRIAC                = 97, /* Syrn */
+      USCRIPT_TENGWAR                       = 98, /* Teng */
+      USCRIPT_VAI                           = 99, /* Vaii */
+      USCRIPT_VISIBLE_SPEECH                = 100, /* Visp */
+      USCRIPT_CUNEIFORM                     = 101,/* Xsux */
+      USCRIPT_UNWRITTEN_LANGUAGES           = 102,/* Zxxx */
+      USCRIPT_UNKNOWN                       = 103,/* Zzzz */ /* Unknown="Code for uncoded script", for unassigned code points */
+      /* Private use codes from Qaaa - Qabx are not supported*/
+#endif /* U_HIDE_DRAFT_API */
+      USCRIPT_CODE_LIMIT    = 104
+} UScriptCode;
+
+/**
+ * Gets script codes associated with the given locale or ISO 15924 abbreviation or name. 
+ * Fills in USCRIPT_MALAYALAM given "Malayam" OR "Mlym".
+ * Fills in USCRIPT_LATIN given "en" OR "en_US" 
+ * If required capacity is greater than capacity of the destination buffer then the error code
+ * is set to U_BUFFER_OVERFLOW_ERROR and the required capacity is returned
+ *
+ * <p>Note: To search by short or long script alias only, use
+ * u_getPropertyValueEnum(UCHAR_SCRIPT, alias) instead.  This does
+ * a fast lookup with no access of the locale data.
+ * @param nameOrAbbrOrLocale name of the script, as given in
+ * PropertyValueAliases.txt, or ISO 15924 code or locale
+ * @param fillIn the UScriptCode buffer to fill in the script code
+ * @param capacity the capacity (size) fo UScriptCode buffer passed in.
+ * @param err the error status code.
+ * @return The number of script codes filled in the buffer passed in 
+ * @stable ICU 2.4
+ */
+U_STABLE int32_t  U_EXPORT2 
+uscript_getCode(const char* nameOrAbbrOrLocale,UScriptCode* fillIn,int32_t capacity,UErrorCode *err);
+
+/**
+ * Gets a script name associated with the given script code. 
+ * Returns  "Malayam" given USCRIPT_MALAYALAM
+ * @param scriptCode UScriptCode enum
+ * @return script long name as given in
+ * PropertyValueAliases.txt, or NULL if scriptCode is invalid
+ * @stable ICU 2.4
+ */
+U_STABLE const char*  U_EXPORT2 
+uscript_getName(UScriptCode scriptCode);
+
+/**
+ * Gets a script name associated with the given script code. 
+ * Returns  "Mlym" given USCRIPT_MALAYALAM
+ * @param scriptCode UScriptCode enum
+ * @return script abbreviated name as given in
+ * PropertyValueAliases.txt, or NULL if scriptCode is invalid
+ * @stable ICU 2.4
+ */
+U_STABLE const char*  U_EXPORT2 
+uscript_getShortName(UScriptCode scriptCode);
+
+/** 
+ * Gets the script code associated with the given codepoint.
+ * Returns USCRIPT_MALAYALAM given 0x0D02 
+ * @param codepoint UChar32 codepoint
+ * @param err the error status code.
+ * @return The UScriptCode, or 0 if codepoint is invalid 
+ * @stable ICU 2.4
+ */
+U_STABLE UScriptCode  U_EXPORT2 
+uscript_getScript(UChar32 codepoint, UErrorCode *err);
+
+#endif
diff --git a/interpreter/AbstractPC.cpp b/interpreter/AbstractPC.cpp
new file mode 100644 (file)
index 0000000..755a0e3
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "AbstractPC.h"
+
+#include "CallFrame.h"
+#include "JSGlobalData.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
+
+namespace JSC {
+
+AbstractPC::AbstractPC(JSGlobalData& globalData, ExecState* exec)
+{
+    UNUSED_PARAM(globalData);
+    
+#if ENABLE(JIT)
+    if (globalData.canUseJIT()) {
+        m_pointer = exec->returnPC().value();
+        m_mode = JIT;
+        return;
+    }
+#endif
+    
+#if ENABLE(CLASSIC_INTERPRETER)
+    UNUSED_PARAM(globalData);
+    m_pointer = exec->returnVPC();
+    m_mode = Interpreter;
+#endif
+}
+
+} // namespace JSC
+
diff --git a/interpreter/AbstractPC.h b/interpreter/AbstractPC.h
new file mode 100644 (file)
index 0000000..5ed7447
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef AbstractPC_h
+#define AbstractPC_h
+
+#include "MacroAssemblerCodeRef.h"
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+class JSGlobalData;
+class ExecState;
+struct Instruction;
+
+class AbstractPC {
+public:
+    AbstractPC()
+        : m_pointer(0)
+        , m_mode(None)
+    {
+    }
+    
+    AbstractPC(JSGlobalData&, ExecState*);
+    
+#if ENABLE(JIT)
+    AbstractPC(ReturnAddressPtr ptr)
+        : m_pointer(ptr.value())
+        , m_mode(JIT)
+    {
+    }
+    
+    bool hasJITReturnAddress() const { return m_mode == JIT; }
+    ReturnAddressPtr jitReturnAddress() const
+    {
+        ASSERT(hasJITReturnAddress());
+        return ReturnAddressPtr(m_pointer);
+    }
+#endif
+
+#if ENABLE(CLASSIC_INTERPRETER)
+    AbstractPC(Instruction* vPC)
+        : m_pointer(vPC)
+        , m_mode(Interpreter)
+    {
+    }
+    
+    bool hasInterpreterReturnAddress() const { return m_mode == Interpreter; }
+    Instruction* interpreterReturnAddress() const
+    {
+        ASSERT(hasInterpreterReturnAddress());
+        return static_cast<Instruction*>(m_pointer);
+    }
+#endif
+    
+    bool isSet() const { return m_mode != None; }
+    bool operator!() const { return !isSet(); }
+
+private:
+    void* m_pointer;
+    
+    enum Mode { None, JIT, Interpreter };
+    Mode m_mode;
+};
+
+} // namespace JSC
+
+#endif // AbstractPC_h
+
index 04f2210755730040c7e6441dcdc1717337594a6f..ea55d90e580fbb65623726baf02575b8a09b98b8 100644 (file)
@@ -35,13 +35,13 @@ namespace JSC {
     class CachedCall {
         WTF_MAKE_NONCOPYABLE(CachedCall); WTF_MAKE_FAST_ALLOCATED;
     public:
     class CachedCall {
         WTF_MAKE_NONCOPYABLE(CachedCall); WTF_MAKE_FAST_ALLOCATED;
     public:
-        CachedCall(CallFrame* callFrame, JSFunction* function, int argCount)
+        CachedCall(CallFrame* callFrame, JSFunction* function, int argumentCount)
             : m_valid(false)
             , m_interpreter(callFrame->interpreter())
             , m_globalObjectScope(callFrame->globalData(), function->scope()->globalObject.get())
         {
             ASSERT(!function->isHostFunction());
             : m_valid(false)
             , m_interpreter(callFrame->interpreter())
             , m_globalObjectScope(callFrame->globalData(), function->scope()->globalObject.get())
         {
             ASSERT(!function->isHostFunction());
-            m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argCount, function->scope());
+            m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argumentCount + 1, function->scope());
             m_valid = !callFrame->hadException();
         }
         
             m_valid = !callFrame->hadException();
         }
         
@@ -50,8 +50,8 @@ namespace JSC {
             ASSERT(m_valid);
             return m_interpreter->execute(m_closure);
         }
             ASSERT(m_valid);
             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.setThis(v); }
+        void setArgument(int n, JSValue v) { m_closure.setArgument(n, v); }
 
         CallFrame* newCallFrame(ExecState* exec)
         {
 
         CallFrame* newCallFrame(ExecState* exec)
         {
index 5819875150b0f8327a9f683e4927693eaba9392d..a5ffaee8d61499f4d696575623ac8d3d3093a48c 100644 (file)
@@ -40,7 +40,7 @@ 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.utf8().data(), signedLineNumber);
+    dataLog("Callpoint => %s:%d\n", urlString.utf8().data(), signedLineNumber);
 }
 
 RegisterFile* CallFrame::registerFile()
 }
 
 RegisterFile* CallFrame::registerFile()
@@ -50,4 +50,144 @@ RegisterFile* CallFrame::registerFile()
 
 #endif
 
 
 #endif
 
+#if USE(JSVALUE32_64)
+unsigned CallFrame::bytecodeOffsetForNonDFGCode() const
+{
+    ASSERT(codeBlock());
+    return currentVPC() - codeBlock()->instructions().begin();
+}
+
+void CallFrame::setBytecodeOffsetForNonDFGCode(unsigned offset)
+{
+    ASSERT(codeBlock());
+    setCurrentVPC(codeBlock()->instructions().begin() + offset);
+}
+#else
+Instruction* CallFrame::currentVPC() const
+{
+    return codeBlock()->instructions().begin() + bytecodeOffsetForNonDFGCode();
+}
+void CallFrame::setCurrentVPC(Instruction* vpc)
+{
+    setBytecodeOffsetForNonDFGCode(vpc - codeBlock()->instructions().begin());
+}
+#endif
+    
+#if ENABLE(DFG_JIT)
+bool CallFrame::isInlineCallFrameSlow()
+{
+    if (!callee())
+        return false;
+    JSCell* calleeAsFunctionCell = getJSFunction(callee());
+    if (!calleeAsFunctionCell)
+        return false;
+    JSFunction* calleeAsFunction = jsCast<JSFunction*>(calleeAsFunctionCell);
+    return calleeAsFunction->executable() != codeBlock()->ownerExecutable();
+}
+
+CallFrame* CallFrame::trueCallFrame(AbstractPC pc)
+{
+    // Am I an inline call frame? If so, we're done.
+    if (isInlineCallFrame())
+        return this;
+    
+    // If I don't have a code block, then I'm not DFG code, so I'm the true call frame.
+    CodeBlock* machineCodeBlock = codeBlock();
+    if (!machineCodeBlock)
+        return this;
+    
+    // If the code block does not have any code origins, then there was no inlining, so
+    // I'm done.
+    if (!machineCodeBlock->hasCodeOrigins())
+        return this;
+    
+    // At this point the PC must be due either to the DFG, or it must be unset.
+    ASSERT(pc.hasJITReturnAddress() || !pc);
+    
+    // Try to determine the CodeOrigin. If we don't have a pc set then the only way
+    // that this makes sense is if the CodeOrigin index was set in the call frame.
+    // FIXME: Note that you will see "Not currently in inlined code" comments below.
+    // Currently, we do not record code origins for code that is not inlined, because
+    // the only thing that we use code origins for is determining the inline stack.
+    // But in the future, we'll want to use this same functionality (having a code
+    // origin mapping for any calls out of JIT code) to determine the PC at any point
+    // in the stack even if not in inlined code. When that happens, the code below
+    // will have to change the way it detects the presence of inlining: it will always
+    // get a code origin, but sometimes, that code origin will not have an inline call
+    // frame. In that case, this method should bail and return this.
+    CodeOrigin codeOrigin;
+    if (pc.isSet()) {
+        ReturnAddressPtr currentReturnPC = pc.jitReturnAddress();
+        
+        bool hasCodeOrigin = machineCodeBlock->codeOriginForReturn(currentReturnPC, codeOrigin);
+        ASSERT_UNUSED(hasCodeOrigin, hasCodeOrigin);
+    } else {
+        unsigned index = codeOriginIndexForDFG();
+        codeOrigin = machineCodeBlock->codeOrigin(index);
+    }
+
+    if (!codeOrigin.inlineCallFrame)
+        return this; // Not currently in inlined code.
+    
+    for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) {
+        InlineCallFrame* nextInlineCallFrame = inlineCallFrame->caller.inlineCallFrame;
+        
+        CallFrame* inlinedCaller = this + inlineCallFrame->stackOffset;
+        
+        JSFunction* calleeAsFunction = inlineCallFrame->callee.get();
+        
+        // Fill in the inlinedCaller
+        inlinedCaller->setCodeBlock(machineCodeBlock);
+        
+        inlinedCaller->setScopeChain(calleeAsFunction->scope());
+        if (nextInlineCallFrame)
+            inlinedCaller->setCallerFrame(this + nextInlineCallFrame->stackOffset);
+        else
+            inlinedCaller->setCallerFrame(this);
+        
+        inlinedCaller->setInlineCallFrame(inlineCallFrame);
+        inlinedCaller->setArgumentCountIncludingThis(inlineCallFrame->arguments.size());
+        inlinedCaller->setCallee(calleeAsFunction);
+        
+        inlineCallFrame = nextInlineCallFrame;
+    }
+    
+    return this + codeOrigin.inlineCallFrame->stackOffset;
+}
+        
+CallFrame* CallFrame::trueCallerFrame()
+{
+    // this -> The callee; this is either an inlined callee in which case it already has
+    //    a pointer to the true caller. Otherwise it contains current PC in the machine
+    //    caller.
+    //
+    // machineCaller -> The caller according to the machine, which may be zero or
+    //    more frames above the true caller due to inlining.
+
+    // Am I an inline call frame? If so, we're done.
+    if (isInlineCallFrame())
+        return callerFrame()->removeHostCallFrameFlag();
+    
+    // I am a machine call frame, so the question is: is my caller a machine call frame
+    // that has inlines or a machine call frame that doesn't?
+    CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag();
+    if (!machineCaller)
+        return 0;
+    ASSERT(!machineCaller->isInlineCallFrame());
+    
+    // Figure out how we want to get the current code location.
+    if (!hasReturnPC() || returnAddressIsInCtiTrampoline(returnPC()))
+        return machineCaller->trueCallFrameFromVMCode()->removeHostCallFrameFlag();
+    
+    return machineCaller->trueCallFrame(returnPC())->removeHostCallFrameFlag();
+}
+#endif
+
+Register* CallFrame::frameExtentInternal()
+{
+    CodeBlock* codeBlock = this->codeBlock();
+    ASSERT(codeBlock);
+    return registers() + codeBlock->m_numCalleeRegisters;
+}
+
 }
 }
index 57b24ef8e3983c39e2d1a729867bae3e1ecc5150..4ec3de7f3d6f1e065a31fe26ed93f76cc09e62fb 100644 (file)
@@ -23,6 +23,7 @@
 #ifndef CallFrame_h
 #define CallFrame_h
 
 #ifndef CallFrame_h
 #define CallFrame_h
 
+#include "AbstractPC.h"
 #include "JSGlobalData.h"
 #include "MacroAssemblerCodeRef.h"
 #include "RegisterFile.h"
 #include "JSGlobalData.h"
 #include "MacroAssemblerCodeRef.h"
 #include "RegisterFile.h"
@@ -38,6 +39,7 @@ namespace JSC  {
     // Passed as the first argument to most functions.
     class ExecState : private Register {
     public:
     // Passed as the first argument to most functions.
     class ExecState : private Register {
     public:
+        JSValue calleeAsValue() const { return this[RegisterFile::Callee].jsValue(); }
         JSObject* callee() const { return this[RegisterFile::Callee].function(); }
         CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); }
         ScopeChainNode* scopeChain() const
         JSObject* callee() const { return this[RegisterFile::Callee].function(); }
         CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); }
         ScopeChainNode* scopeChain() const
@@ -102,10 +104,65 @@ namespace JSC  {
         CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
 #if ENABLE(JIT)
         ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); }
         CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
 #if ENABLE(JIT)
         ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); }
+        bool hasReturnPC() const { return !!this[RegisterFile::ReturnPC].vPC(); }
+        void clearReturnPC() { registers()[RegisterFile::ReturnPC] = static_cast<Instruction*>(0); }
 #endif
 #endif
-#if ENABLE(INTERPRETER)
+        AbstractPC abstractReturnPC(JSGlobalData& globalData) { return AbstractPC(globalData, this); }
+#if USE(JSVALUE32_64)
+        unsigned bytecodeOffsetForNonDFGCode() const;
+        void setBytecodeOffsetForNonDFGCode(unsigned offset);
+#else
+        unsigned bytecodeOffsetForNonDFGCode() const
+        {
+            ASSERT(codeBlock());
+            return this[RegisterFile::ArgumentCount].tag();
+        }
+        
+        void setBytecodeOffsetForNonDFGCode(unsigned offset)
+        {
+            ASSERT(codeBlock());
+            this[RegisterFile::ArgumentCount].tag() = static_cast<int32_t>(offset);
+        }
+#endif
+
+        Register* frameExtent()
+        {
+            if (!codeBlock())
+                return registers();
+            return frameExtentInternal();
+        }
+    
+        Register* frameExtentInternal();
+    
+#if ENABLE(DFG_JIT)
+        InlineCallFrame* inlineCallFrame() const { return this[RegisterFile::ReturnPC].asInlineCallFrame(); }
+        unsigned codeOriginIndexForDFG() const { return this[RegisterFile::ArgumentCount].tag(); }
+#else
+        // This will never be called if !ENABLE(DFG_JIT) since all calls should be guarded by
+        // isInlineCallFrame(). But to make it easier to write code without having a bunch of
+        // #if's, we make a dummy implementation available anyway.
+        InlineCallFrame* inlineCallFrame() const
+        {
+            ASSERT_NOT_REACHED();
+            return 0;
+        }
+#endif
+#if ENABLE(CLASSIC_INTERPRETER)
         Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); }
 #endif
         Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); }
 #endif
+#if USE(JSVALUE32_64)
+        Instruction* currentVPC() const
+        {
+            return bitwise_cast<Instruction*>(this[RegisterFile::ArgumentCount].tag());
+        }
+        void setCurrentVPC(Instruction* vpc)
+        {
+            this[RegisterFile::ArgumentCount].tag() = bitwise_cast<int32_t>(vpc);
+        }
+#else
+        Instruction* currentVPC() const;
+        void setCurrentVPC(Instruction* vpc);
+#endif
 
         void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
         void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; }
 
         void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
         void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; }
@@ -130,33 +187,83 @@ namespace JSC  {
         inline Register& uncheckedR(int);
 
         // Access to arguments.
         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 argumentCount() const { return argumentCountIncludingThis() - 1; }
-        size_t argumentCountIncludingThis() const { return this[RegisterFile::ArgumentCount].i(); }
-        JSValue argument(int argumentNumber)
+        size_t argumentCountIncludingThis() const { return this[RegisterFile::ArgumentCount].payload(); }
+        static int argumentOffset(size_t argument) { return s_firstArgumentOffset - argument; }
+        static int argumentOffsetIncludingThis(size_t argument) { return s_thisArgumentOffset - argument; }
+
+        JSValue argument(size_t argument)
+        {
+            if (argument >= argumentCount())
+                 return jsUndefined();
+            return this[argumentOffset(argument)].jsValue();
+        }
+        void setArgument(size_t argument, JSValue value)
         {
         {
-            int argumentIndex = -RegisterFile::CallFrameHeaderSize - this[RegisterFile::ArgumentCount].i() + argumentNumber + 1;
-            if (argumentIndex >= -RegisterFile::CallFrameHeaderSize)
-                return jsUndefined();
-            return this[argumentIndex].jsValue();
+            this[argumentOffset(argument)] = value;
         }
 
         }
 
+        static int thisArgumentOffset() { return argumentOffsetIncludingThis(0); }
+        JSValue thisValue() { return this[thisArgumentOffset()].jsValue(); }
+        void setThisValue(JSValue value) { this[thisArgumentOffset()] = value; }
+
+        static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize; }
+
+        // FIXME: Remove these.
+        int hostThisRegister() { return thisArgumentOffset(); }
+        JSValue hostThisValue() { return thisValue(); }
+
         static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(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); }
 
         static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(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); }
 
-        void setArgumentCountIncludingThis(int count) { static_cast<Register*>(this)[RegisterFile::ArgumentCount] = Register::withInt(count); }
+        void setArgumentCountIncludingThis(int count) { static_cast<Register*>(this)[RegisterFile::ArgumentCount].payload() = count; }
         void setCallee(JSObject* callee) { static_cast<Register*>(this)[RegisterFile::Callee] = Register::withCallee(callee); }
         void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[RegisterFile::CodeBlock] = codeBlock; }
         void setReturnPC(void* value) { static_cast<Register*>(this)[RegisterFile::ReturnPC] = (Instruction*)value; }
         void setCallee(JSObject* callee) { static_cast<Register*>(this)[RegisterFile::Callee] = Register::withCallee(callee); }
         void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[RegisterFile::CodeBlock] = codeBlock; }
         void setReturnPC(void* value) { static_cast<Register*>(this)[RegisterFile::ReturnPC] = (Instruction*)value; }
+        
+#if ENABLE(DFG_JIT)
+        bool isInlineCallFrame();
+        
+        void setInlineCallFrame(InlineCallFrame* inlineCallFrame) { static_cast<Register*>(this)[RegisterFile::ReturnPC] = inlineCallFrame; }
+        
+        // Call this to get the semantically correct JS CallFrame* for the
+        // currently executing function.
+        CallFrame* trueCallFrame(AbstractPC);
+        
+        // Call this to get the semantically correct JS CallFrame* corresponding
+        // to the caller. This resolves issues surrounding inlining and the
+        // HostCallFrameFlag stuff.
+        CallFrame* trueCallerFrame();
+#else
+        bool isInlineCallFrame() { return false; }
+        
+        CallFrame* trueCallFrame(AbstractPC) { return this; }
+        CallFrame* trueCallerFrame() { return callerFrame()->removeHostCallFrameFlag(); }
+#endif
+        
+        // Call this to get the true call frame (accounted for inlining and any
+        // other optimizations), when you have entered into VM code through one
+        // of the "blessed" entrypoints (JITStubs or DFGOperations). This means
+        // that if you're pretty much anywhere in the VM you can safely call this;
+        // though if you were to magically get an ExecState* by, say, interrupting
+        // a thread that is running JS code and brutishly scraped the call frame
+        // register, calling this method would probably lead to horrible things
+        // happening.
+        CallFrame* trueCallFrameFromVMCode() { return trueCallFrame(AbstractPC()); }
 
     private:
         static const intptr_t HostCallFrameFlag = 1;
 
     private:
         static const intptr_t HostCallFrameFlag = 1;
+        static const int s_thisArgumentOffset = -1 - RegisterFile::CallFrameHeaderSize;
+        static const int s_firstArgumentOffset = s_thisArgumentOffset - 1;
+
 #ifndef NDEBUG
         RegisterFile* registerFile();
 #ifndef NDEBUG
         RegisterFile* registerFile();
+#endif
+#if ENABLE(DFG_JIT)
+        bool isInlineCallFrameSlow();
 #endif
         ExecState();
         ~ExecState();
 #endif
         ExecState();
         ~ExecState();
index b4b7efd45baa8019ff86ac2f62422716e60aa636..2a841511a9d40f7a7d422f2f22685efbf1003606 100644 (file)
@@ -36,22 +36,24 @@ struct CallFrameClosure {
     JSGlobalData* globalData;
     Register* oldEnd;
     ScopeChainNode* scopeChain;
     JSGlobalData* globalData;
     Register* oldEnd;
     ScopeChainNode* scopeChain;
-    int expectedParams;
-    int providedParams;
+    int parameterCountIncludingThis;
+    int argumentCountIncludingThis;
     
     
-    void setArgument(int arg, JSValue value)
+    void setThis(JSValue value)
     {
     {
-        if (arg < expectedParams)
-            newCallFrame[arg - RegisterFile::CallFrameHeaderSize - expectedParams] = value;
-        else
-            newCallFrame[arg - RegisterFile::CallFrameHeaderSize - expectedParams - providedParams] = value;
+        newCallFrame->setThisValue(value);
+    }
+
+    void setArgument(int argument, JSValue value)
+    {
+        newCallFrame->setArgument(argument, value);
     }
 
     void resetCallFrame()
     {
         newCallFrame->setScopeChain(scopeChain);
     }
 
     void resetCallFrame()
     {
         newCallFrame->setScopeChain(scopeChain);
-        for (int i = providedParams; i < expectedParams; ++i)
-            newCallFrame[i - RegisterFile::CallFrameHeaderSize - expectedParams] = jsUndefined();
+        for (int i = argumentCountIncludingThis; i < parameterCountIncludingThis; ++i)
+            newCallFrame->setArgument(i, jsUndefined());
     }
 };
 
     }
 };
 
index 1514933f90b332b38941d7dcb955ac4c7536726d..6c43adf886f44b05c5c6b7de9d0beade4b575749 100644 (file)
@@ -44,8 +44,7 @@
 #include "GetterSetter.h"
 #include "JSActivation.h"
 #include "JSArray.h"
 #include "GetterSetter.h"
 #include "JSActivation.h"
 #include "JSArray.h"
-#include "JSByteArray.h"
-#include "JSFunction.h"
+#include "JSBoundFunction.h"
 #include "JSNotAnObject.h"
 #include "JSPropertyNameIterator.h"
 #include "LiteralParser.h"
 #include "JSNotAnObject.h"
 #include "JSPropertyNameIterator.h"
 #include "LiteralParser.h"
 #include "Register.h"
 #include "SamplingTool.h"
 #include "StrictEvalActivation.h"
 #include "Register.h"
 #include "SamplingTool.h"
 #include "StrictEvalActivation.h"
+#include "StrongInlines.h"
 #include "UStringConcatenate.h"
 #include <limits.h>
 #include <stdio.h>
 #include <wtf/Threading.h>
 #include "UStringConcatenate.h"
 #include <limits.h>
 #include <stdio.h>
 #include <wtf/Threading.h>
+#include <wtf/text/StringBuilder.h>
 
 #if ENABLE(JIT)
 #include "JIT.h"
 #endif
 
 
 #if ENABLE(JIT)
 #include "JIT.h"
 #endif
 
-#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND (ENABLE(COMPUTED_GOTO_INTERPRETER) && !defined(__llvm__))
+#define WTF_USE_GCC_COMPUTED_GOTO_WORKAROUND ((ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)) && !defined(__llvm__))
 
 using namespace std;
 
 
 using namespace std;
 
@@ -83,7 +84,7 @@ static int depth(CodeBlock* codeBlock, ScopeChainNode* sc)
     return sc->localDepth();
 }
 
     return sc->localDepth();
 }
 
-#if ENABLE(INTERPRETER) 
+#if ENABLE(CLASSIC_INTERPRETER) 
 static NEVER_INLINE JSValue concatenateStrings(ExecState* exec, Register* strings, unsigned count)
 {
     return jsString(exec, strings, count);
 static NEVER_INLINE JSValue concatenateStrings(ExecState* exec, Register* strings, unsigned count)
 {
     return jsString(exec, strings, count);
@@ -321,46 +322,80 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst
     return false;
 }
 
     return false;
 }
 
-#endif // ENABLE(INTERPRETER)
-
-ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
+NEVER_INLINE bool Interpreter::resolveThisAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
 {
 {
-    Register* r = callFrame->registers();
-    Register* newEnd = r + registerOffset + newCodeBlock->m_numCalleeRegisters;
+    int thisDst = vPC[1].u.operand;
+    int propDst = vPC[2].u.operand;
+    int property = vPC[3].u.operand;
 
 
-    if (LIKELY(argc == newCodeBlock->m_numParameters)) { // correct number of arguments
-        if (UNLIKELY(!registerFile->grow(newEnd)))
-            return 0;
-        r += registerOffset;
-    } else if (argc < newCodeBlock->m_numParameters) { // too few arguments -- fill in the blanks
-        size_t omittedArgCount = newCodeBlock->m_numParameters - argc;
-        registerOffset += omittedArgCount;
-        newEnd += omittedArgCount;
-        if (!registerFile->grow(newEnd))
-            return 0;
-        r += registerOffset;
+    ScopeChainNode* scopeChain = callFrame->scopeChain();
+    ScopeChainIterator iter = scopeChain->begin();
+    ScopeChainIterator end = scopeChain->end();
 
 
-        Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
-        for (size_t i = 0; i < omittedArgCount; ++i)
-            argv[i] = jsUndefined();
-    } else { // too many arguments -- copy expected arguments, leaving the extra arguments behind
-        size_t numParameters = newCodeBlock->m_numParameters;
-        registerOffset += numParameters;
-        newEnd += numParameters;
+    // FIXME: add scopeDepthIsZero optimization
 
 
-        if (!registerFile->grow(newEnd))
-            return 0;
-        r += registerOffset;
+    ASSERT(iter != end);
+
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    Identifier& ident = codeBlock->identifier(property);
+    JSObject* base;
+    do {
+        base = iter->get();
+        ++iter;
+        PropertySlot slot(base);
+        if (base->getPropertySlot(callFrame, ident, slot)) {
+            JSValue result = slot.getValue(callFrame, ident);
+            exceptionValue = callFrame->globalData().exception;
+            if (exceptionValue)
+                return false;
+            callFrame->uncheckedR(propDst) = JSValue(result);
+            // All entries on the scope chain should be EnvironmentRecords (activations etc),
+            // other then 'with' object, which are directly referenced from the scope chain,
+            // and the global object. If we hit either an EnvironmentRecord or a global
+            // object at the end of the scope chain, this is undefined. If we hit a non-
+            // EnvironmentRecord within the scope chain, pass the base as the this value.
+            if (iter == end || base->structure()->typeInfo().isEnvironmentRecord())
+                callFrame->uncheckedR(thisDst) = jsUndefined();
+            else
+                callFrame->uncheckedR(thisDst) = JSValue(base);
+            return true;
+        }
+    } while (iter != end);
+
+    exceptionValue = createUndefinedVariableError(callFrame, ident);
+    return false;
+}
+
+#endif // ENABLE(CLASSIC_INTERPRETER)
+
+ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argumentCountIncludingThis)
+{
+    // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
+    if (!registerFile->grow(callFrame->registers() + registerOffset + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters))
+        return 0;
 
 
-        Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argc;
-        for (size_t i = 0; i < numParameters; ++i)
-            argv[i + argc] = argv[i];
+    if (argumentCountIncludingThis >= newCodeBlock->numParameters()) {
+        Register* newCallFrame = callFrame->registers() + registerOffset;
+        return CallFrame::create(newCallFrame);
     }
 
     }
 
-    return CallFrame::create(r);
+    // Too few arguments -- copy arguments, then fill in missing arguments with undefined.
+    size_t delta = newCodeBlock->numParameters() - argumentCountIncludingThis;
+    CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset + delta);
+
+    Register* dst = &newCallFrame->uncheckedR(CallFrame::thisArgumentOffset());
+    Register* end = dst - argumentCountIncludingThis;
+    for ( ; dst != end; --dst)
+        *dst = *(dst - delta);
+
+    end -= delta;
+    for ( ; dst != end; --dst)
+        *dst = jsUndefined();
+
+    return newCallFrame;
 }
 
 }
 
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
 static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, JSValue value, JSValue& exceptionData)
 {
     if (value.isObject())
 static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, JSValue value, JSValue& exceptionData)
 {
     if (value.isObject())
@@ -378,51 +413,192 @@ static NEVER_INLINE bool isInvalidParamForInstanceOf(CallFrame* callFrame, JSVal
 }
 #endif
 
 }
 #endif
 
-NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset)
+JSValue eval(CallFrame* callFrame)
 {
 {
-    if (argc < 2)
+    if (!callFrame->argumentCount())
         return jsUndefined();
 
         return jsUndefined();
 
-    JSValue program = argv[1].jsValue();
-
+    JSValue program = callFrame->argument(0);
     if (!program.isString())
         return program;
     if (!program.isString())
         return program;
-
+    
+    TopCallFrameSetter topCallFrame(callFrame->globalData(), callFrame);
     UString programSource = asString(program)->value(callFrame);
     if (callFrame->hadException())
         return JSValue();
     
     UString programSource = asString(program)->value(callFrame);
     if (callFrame->hadException())
         return JSValue();
     
-    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;
+    CallFrame* callerFrame = callFrame->callerFrame();
+    CodeBlock* callerCodeBlock = callerFrame->codeBlock();
+    ScopeChainNode* callerScopeChain = callerFrame->scopeChain();
+    EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, callerScopeChain);
+
+    if (!eval) {
+        if (!callerCodeBlock->isStrictMode()) {
+            // FIXME: We can use the preparser in strict mode, we just need additional logic
+            // to prevent duplicates.
+            if (programSource.is8Bit()) {
+                LiteralParser<LChar> preparser(callFrame, programSource.characters8(), programSource.length(), NonStrictJSON);
+                if (JSValue parsedObject = preparser.tryLiteralParse())
+                    return parsedObject;
+            } else {
+                LiteralParser<UChar> preparser(callFrame, programSource.characters16(), programSource.length(), NonStrictJSON);
+                if (JSValue parsedObject = preparser.tryLiteralParse())
+                    return parsedObject;                
+            }
+        }
+
+        JSValue exceptionValue;
+        eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), programSource, callerScopeChain, exceptionValue);
+        
+        ASSERT(!eval == exceptionValue);
+        if (UNLIKELY(!eval))
+            return throwError(callFrame, exceptionValue);
     }
 
     }
 
-    ScopeChainNode* scopeChain = callFrame->scopeChain();
-    JSValue exceptionValue;
-    EvalExecutable* eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->ownerExecutable(), codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue);
+    JSValue thisValue = callerFrame->thisValue();
+    ASSERT(isValidThisObject(thisValue, callFrame));
+    Interpreter* interpreter = callFrame->globalData().interpreter;
+    return interpreter->execute(eval, callFrame, thisValue, callerScopeChain, callFrame->registers() - interpreter->registerFile().begin() + 1 + RegisterFile::CallFrameHeaderSize);
+}
+
+CallFrame* loadVarargs(CallFrame* callFrame, RegisterFile* registerFile, JSValue thisValue, JSValue arguments, int firstFreeRegister)
+{
+    if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
+        unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
+        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize);
+        if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !registerFile->grow(newCallFrame->registers())) {
+            callFrame->globalData().exception = createStackOverflowError(callFrame);
+            return 0;
+        }
+
+        newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis);
+        newCallFrame->setThisValue(thisValue);
+        for (size_t i = 0; i < callFrame->argumentCount(); ++i)
+            newCallFrame->setArgument(i, callFrame->argument(i));
+        return newCallFrame;
+    }
+
+    if (arguments.isUndefinedOrNull()) {
+        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + 1 + RegisterFile::CallFrameHeaderSize);
+        if (!registerFile->grow(newCallFrame->registers())) {
+            callFrame->globalData().exception = createStackOverflowError(callFrame);
+            return 0;
+        }
+        newCallFrame->setArgumentCountIncludingThis(1);
+        newCallFrame->setThisValue(thisValue);
+        return newCallFrame;
+    }
+
+    if (!arguments.isObject()) {
+        callFrame->globalData().exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
+        return 0;
+    }
 
 
-    ASSERT(!eval == exceptionValue);
-    if (UNLIKELY(!eval))
-        return throwError(callFrame, exceptionValue);
+    if (asObject(arguments)->classInfo() == &Arguments::s_info) {
+        Arguments* argsObject = asArguments(arguments);
+        unsigned argCount = argsObject->length(callFrame);
+        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
+        if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) {
+            callFrame->globalData().exception = createStackOverflowError(callFrame);
+            return 0;
+        }
+        newCallFrame->setArgumentCountIncludingThis(argCount + 1);
+        newCallFrame->setThisValue(thisValue);
+        argsObject->copyToArguments(callFrame, newCallFrame, argCount);
+        return newCallFrame;
+    }
+
+    if (isJSArray(arguments)) {
+        JSArray* array = asArray(arguments);
+        unsigned argCount = array->length();
+        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
+        if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) {
+            callFrame->globalData().exception = createStackOverflowError(callFrame);
+            return 0;
+        }
+        newCallFrame->setArgumentCountIncludingThis(argCount + 1);
+        newCallFrame->setThisValue(thisValue);
+        array->copyToArguments(callFrame, newCallFrame, argCount);
+        return newCallFrame;
+    }
 
 
-    return callFrame->globalData().interpreter->execute(eval, callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain);
+    JSObject* argObject = asObject(arguments);
+    unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
+    CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
+    if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) {
+        callFrame->globalData().exception = createStackOverflowError(callFrame);
+        return 0;
+    }
+    newCallFrame->setArgumentCountIncludingThis(argCount + 1);
+    newCallFrame->setThisValue(thisValue);
+    for (size_t i = 0; i < argCount; ++i) {
+        newCallFrame->setArgument(i, asObject(arguments)->get(callFrame, i));
+        if (UNLIKELY(callFrame->globalData().exception))
+            return 0;
+    }
+    return newCallFrame;
 }
 
 }
 
-Interpreter::Interpreter(JSGlobalData& globalData)
+Interpreter::Interpreter()
     : m_sampleEntryDepth(0)
     , m_reentryDepth(0)
     : m_sampleEntryDepth(0)
     , m_reentryDepth(0)
-    , m_registerFile(globalData)
+#if !ASSERT_DISABLED
+    , m_initialized(false)
+#endif
+    , m_classicEnabled(false)
 {
 {
-#if ENABLE(COMPUTED_GOTO_INTERPRETER)
-    privateExecute(InitializeAndReturn, 0, 0);
+}
+
+Interpreter::~Interpreter()
+{
+#if ENABLE(LLINT)
+    if (m_classicEnabled)
+        delete[] m_opcodeTable;
+#endif
+}
+
+void Interpreter::initialize(LLInt::Data* llintData, bool canUseJIT)
+{
+    UNUSED_PARAM(llintData);
+    UNUSED_PARAM(canUseJIT);
+
+    // If we have LLInt, then we shouldn't be building any kind of classic interpreter.
+#if ENABLE(LLINT) && ENABLE(CLASSIC_INTERPRETER)
+#error "Building both LLInt and the Classic Interpreter is not supported because it doesn't make sense."
+#endif
 
 
+#if ENABLE(LLINT)
+    m_opcodeTable = llintData->opcodeMap();
     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));
-#endif // ENABLE(COMPUTED_GOTO_INTERPRETER)
+    m_classicEnabled = false;
+#elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+    if (canUseJIT) {
+        // If the JIT is present, don't use jump destinations for opcodes.
+        
+        for (int i = 0; i < numOpcodeIDs; ++i) {
+            Opcode opcode = bitwise_cast<void*>(static_cast<uintptr_t>(i));
+            m_opcodeTable[i] = opcode;
+        }
+        m_classicEnabled = false;
+    } else {
+        privateExecute(InitializeAndReturn, 0, 0);
+        
+        for (int i = 0; i < numOpcodeIDs; ++i)
+            m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
+        
+        m_classicEnabled = true;
+    }
+#else
+#if ENABLE(CLASSIC_INTERPRETER)
+    m_classicEnabled = true;
+#else
+    m_classicEnabled = false;
+#endif
+#endif // ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+#if !ASSERT_DISABLED
+    m_initialized = true;
+#endif
 
 #if ENABLE(OPCODE_SAMPLING)
     enableSampler();
 
 #if ENABLE(OPCODE_SAMPLING)
     enableSampler();
@@ -439,59 +615,43 @@ void Interpreter::dumpCallFrame(CallFrame* callFrame)
 
 void Interpreter::dumpRegisters(CallFrame* callFrame)
 {
 
 void Interpreter::dumpRegisters(CallFrame* callFrame)
 {
-    printf("Register frame: \n\n");
-    printf("-----------------------------------------------------------------------------\n");
-    printf("            use            |   address  |                value               \n");
-    printf("-----------------------------------------------------------------------------\n");
+    dataLog("Register frame: \n\n");
+    dataLog("-----------------------------------------------------------------------------\n");
+    dataLog("            use            |   address  |                value               \n");
+    dataLog("-----------------------------------------------------------------------------\n");
 
     CodeBlock* codeBlock = callFrame->codeBlock();
 
     CodeBlock* codeBlock = callFrame->codeBlock();
-    RegisterFile* registerFile = &callFrame->scopeChain()->globalObject->globalData().interpreter->registerFile();
     const Register* it;
     const Register* end;
     JSValue v;
 
     const Register* it;
     const Register* end;
     JSValue v;
 
-    if (codeBlock->codeType() == GlobalCode) {
-        it = registerFile->lastGlobal();
-        end = it + registerFile->numGlobals();
-        while (it != end) {
-            v = (*it).jsValue();
-#if USE(JSVALUE32_64)
-            printf("[global var]               | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
-#else
-            printf("[global var]               | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
-#endif
-            ++it;
-        }
-        printf("-----------------------------------------------------------------------------\n");
-    }
-    
-    it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters;
+    it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->numParameters();
     v = (*it).jsValue();
 #if USE(JSVALUE32_64)
     v = (*it).jsValue();
 #if USE(JSVALUE32_64)
-    printf("[this]                     | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); ++it;
+    dataLog("[this]                     | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); ++it;
 #else
 #else
-    printf("[this]                     | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); ++it;
+    dataLog("[this]                     | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); ++it;
 #endif
 #endif
-    end = it + max(codeBlock->m_numParameters - 1, 0); // - 1 to skip "this"
+    end = it + max(codeBlock->numParameters() - 1, 0); // - 1 to skip "this"
     if (it != end) {
         do {
             v = (*it).jsValue();
 #if USE(JSVALUE32_64)
     if (it != end) {
         do {
             v = (*it).jsValue();
 #if USE(JSVALUE32_64)
-            printf("[param]                    | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
+            dataLog("[param]                    | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
 #else
 #else
-            printf("[param]                    | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
+            dataLog("[param]                    | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
 #endif
             ++it;
         } while (it != end);
     }
 #endif
             ++it;
         } while (it != end);
     }
-    printf("-----------------------------------------------------------------------------\n");
-    printf("[CodeBlock]                | %10p | %p \n", it, (*it).codeBlock()); ++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("[ArgumentCount]            | %10p | %d \n", it, (*it).i()); ++it;
-    printf("[Callee]                   | %10p | %p \n", it, (*it).function()); ++it;
-    printf("-----------------------------------------------------------------------------\n");
+    dataLog("-----------------------------------------------------------------------------\n");
+    dataLog("[CodeBlock]                | %10p | %p \n", it, (*it).codeBlock()); ++it;
+    dataLog("[ScopeChain]               | %10p | %p \n", it, (*it).scopeChain()); ++it;
+    dataLog("[CallerRegisters]          | %10p | %d \n", it, (*it).i()); ++it;
+    dataLog("[ReturnPC]                 | %10p | %p \n", it, (*it).vPC()); ++it;
+    dataLog("[ArgumentCount]            | %10p | %d \n", it, (*it).i()); ++it;
+    dataLog("[Callee]                   | %10p | %p \n", it, (*it).function()); ++it;
+    dataLog("-----------------------------------------------------------------------------\n");
 
     int registerCount = 0;
 
 
     int registerCount = 0;
 
@@ -500,37 +660,41 @@ void Interpreter::dumpRegisters(CallFrame* callFrame)
         do {
             v = (*it).jsValue();
 #if USE(JSVALUE32_64)
         do {
             v = (*it).jsValue();
 #if USE(JSVALUE32_64)
-            printf("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
+            dataLog("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
 #else
 #else
-            printf("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
+            dataLog("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
 #endif
             ++it;
             ++registerCount;
         } while (it != end);
     }
 #endif
             ++it;
             ++registerCount;
         } while (it != end);
     }
-    printf("-----------------------------------------------------------------------------\n");
+    dataLog("-----------------------------------------------------------------------------\n");
 
     end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
     if (it != end) {
         do {
             v = (*it).jsValue();
 #if USE(JSVALUE32_64)
 
     end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
     if (it != end) {
         do {
             v = (*it).jsValue();
 #if USE(JSVALUE32_64)
-            printf("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
+            dataLog("[r%2d]                      | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
 #else
 #else
-            printf("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
+            dataLog("[r%2d]                      | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
 #endif
             ++it;
             ++registerCount;
         } while (it != end);
     }
 #endif
             ++it;
             ++registerCount;
         } while (it != end);
     }
-    printf("-----------------------------------------------------------------------------\n");
+    dataLog("-----------------------------------------------------------------------------\n");
 }
 
 #endif
 
 bool Interpreter::isOpcode(Opcode opcode)
 {
 }
 
 #endif
 
 bool Interpreter::isOpcode(Opcode opcode)
 {
-#if ENABLE(COMPUTED_GOTO_INTERPRETER)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
+#if !ENABLE(LLINT)
+    if (!m_classicEnabled)
+        return opcode >= 0 && static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode)) <= op_end;
+#endif
     return opcode != HashTraits<Opcode>::emptyValue()
         && !HashTraits<Opcode>::isDeletedValue(opcode)
         && m_opcodeIDTable.contains(opcode);
     return opcode != HashTraits<Opcode>::emptyValue()
         && !HashTraits<Opcode>::isDeletedValue(opcode)
         && m_opcodeIDTable.contains(opcode);
@@ -563,17 +727,16 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex
 
         callFrame->setScopeChain(scopeChain);
         JSActivation* activation = asActivation(scopeChain->object.get());
 
         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);
-        }
+        activation->tearOff(*scopeChain->globalData);
+        if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue())
+            asArguments(arguments)->didTearOffActivation(callFrame->globalData(), activation);
     } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) {
         if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue())
     } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) {
         if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue())
-            asArguments(arguments)->copyRegisters(callFrame->globalData());
+            asArguments(arguments)->tearOff(callFrame);
     }
 
     CallFrame* callerFrame = callFrame->callerFrame();
     }
 
     CallFrame* callerFrame = callFrame->callerFrame();
+    callFrame->globalData().topCallFrame = callerFrame;
     if (callerFrame->hasHostCallFrameFlag())
         return false;
 
     if (callerFrame->hasHostCallFrameFlag())
         return false;
 
@@ -586,13 +749,13 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex
     // the beginning of next instruction to execute. To get an offset
     // inside the call instruction that triggered the exception we
     // have to subtract 1.
     // 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 ENABLE(JIT) && ENABLE(CLASSIC_INTERPRETER)
     if (callerFrame->globalData().canUseJIT())
     if (callerFrame->globalData().canUseJIT())
-        bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
+        bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
     else
         bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
 #elif ENABLE(JIT)
     else
         bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
 #elif ENABLE(JIT)
-    bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
+    bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
 #else
     bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
 #endif
 #else
     bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
 #endif
@@ -632,19 +795,19 @@ static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception,
         message =  makeUString(message, " (evaluating '", codeBlock->source()->getRange(expressionStart, expressionStop), "')");
     else {
         // No range information, so give a few characters of context
         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();
+        const StringImpl* 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.
         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')
+        while (start > 0 && (expressionStart - start < 20) && (*data)[start - 1] != '\n')
             start--;
             start--;
-        while (start < (expressionStart - 1) && isStrWhiteSpace(data[start]))
+        while (start < (expressionStart - 1) && isStrWhiteSpace((*data)[start]))
             start++;
             start++;
-        while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n')
+        while (stop < dataLength && (stop - expressionStart < 20) && (*data)[stop] != '\n')
             stop++;
             stop++;
-        while (stop > expressionStart && isStrWhiteSpace(data[stop - 1]))
+        while (stop > expressionStart && isStrWhiteSpace((*data)[stop - 1]))
             stop--;
         message = makeUString(message, " (near '...", codeBlock->source()->getRange(start, stop), "...')");
     }
             stop--;
         message = makeUString(message, " (near '...", codeBlock->source()->getRange(start, stop), "...')");
     }
@@ -652,11 +815,207 @@ static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception,
     exception->putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
 }
 
     exception->putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
 }
 
+static int getLineNumberForCallFrame(JSGlobalData* globalData, CallFrame* callFrame)
+{
+    UNUSED_PARAM(globalData);
+    callFrame = callFrame->removeHostCallFrameFlag();
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    if (!codeBlock)
+        return -1;
+#if ENABLE(CLASSIC_INTERPRETER)
+    if (!globalData->canUseJIT())
+        return codeBlock->lineNumberForBytecodeOffset(callFrame->bytecodeOffsetForNonDFGCode() - 1);
+#endif
+#if ENABLE(JIT)
+#if ENABLE(DFG_JIT)
+    if (codeBlock->getJITType() == JITCode::DFGJIT)
+        return codeBlock->lineNumberForBytecodeOffset(codeBlock->codeOrigin(callFrame->codeOriginIndexForDFG()).bytecodeIndex);
+#endif
+    return codeBlock->lineNumberForBytecodeOffset(callFrame->bytecodeOffsetForNonDFGCode());
+#else
+    return -1;
+#endif
+}
+
+static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber)
+{
+    UNUSED_PARAM(globalData);
+    unsigned bytecodeOffset = 0;
+    lineNumber = -1;
+    ASSERT(!callFrame->hasHostCallFrameFlag());
+    CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : callFrame->callerFrame()->removeHostCallFrameFlag();
+    bool callframeIsHost = callerFrame->addHostCallFrameFlag() == callFrame->callerFrame();
+    ASSERT(!callerFrame->hasHostCallFrameFlag());
+
+    if (callerFrame == CallFrame::noCaller() || !callerFrame || !callerFrame->codeBlock())
+        return callerFrame;
+    
+    CodeBlock* callerCodeBlock = callerFrame->codeBlock();
+    
+#if ENABLE(JIT)
+    if (!callFrame->hasReturnPC())
+        callframeIsHost = true;
+#endif
+#if ENABLE(DFG_JIT)
+    if (callFrame->isInlineCallFrame())
+        callframeIsHost = false;
+#endif
+
+    if (callframeIsHost) {
+        // Don't need to deal with inline callframes here as by definition we haven't
+        // inlined a call with an intervening native call frame.
+#if ENABLE(CLASSIC_INTERPRETER)
+        if (!globalData->canUseJIT()) {
+            bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode();
+            lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
+            return callerFrame;
+        }
+#endif
+#if ENABLE(JIT)
+#if ENABLE(DFG_JIT)
+        if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
+            unsigned codeOriginIndex = callerFrame->codeOriginIndexForDFG();
+            bytecodeOffset = callerCodeBlock->codeOrigin(codeOriginIndex).bytecodeIndex;
+        } else
+#endif
+            bytecodeOffset = callerFrame->bytecodeOffsetForNonDFGCode();
+#endif
+    } else {
+#if ENABLE(CLASSIC_INTERPRETER)
+        if (!globalData->canUseJIT()) {
+            bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
+            lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
+            return callerFrame;
+        }
+#endif
+#if ENABLE(JIT)
+    #if ENABLE(DFG_JIT)
+        if (callFrame->isInlineCallFrame()) {
+            InlineCallFrame* icf = callFrame->inlineCallFrame();
+            bytecodeOffset = icf->caller.bytecodeIndex;
+            if (InlineCallFrame* parentCallFrame = icf->caller.inlineCallFrame) {
+                FunctionExecutable* executable = static_cast<FunctionExecutable*>(parentCallFrame->executable.get());
+                CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(parentCallFrame->isCall ? CodeForCall : CodeForConstruct);
+                ASSERT(newCodeBlock);
+                ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
+                callerCodeBlock = newCodeBlock;
+            }
+        } else if (callerCodeBlock && callerCodeBlock->getJITType() == JITCode::DFGJIT) {
+            CodeOrigin origin;
+            if (!callerCodeBlock->codeOriginForReturn(callFrame->returnPC(), origin))
+                ASSERT_NOT_REACHED();
+            bytecodeOffset = origin.bytecodeIndex;
+            if (InlineCallFrame* icf = origin.inlineCallFrame) {
+                FunctionExecutable* executable = static_cast<FunctionExecutable*>(icf->executable.get());
+                CodeBlock* newCodeBlock = executable->baselineCodeBlockFor(icf->isCall ? CodeForCall : CodeForConstruct);
+                ASSERT(newCodeBlock);
+                ASSERT(newCodeBlock->instructionCount() > bytecodeOffset);
+                callerCodeBlock = newCodeBlock;
+            }
+        } else
+    #endif
+            bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+#endif
+    }
+
+    lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset);
+    return callerFrame;
+}
+
+static ALWAYS_INLINE const UString getSourceURLFromCallFrame(CallFrame* callFrame) 
+{
+    ASSERT(!callFrame->hasHostCallFrameFlag());
+#if ENABLE(CLASSIC_INTERPRETER)
+#if ENABLE(JIT)
+    if (callFrame->globalData().canUseJIT())
+        return callFrame->codeBlock()->ownerExecutable()->sourceURL();
+#endif
+    return callFrame->codeBlock()->source()->url();
+
+#else
+    return callFrame->codeBlock()->ownerExecutable()->sourceURL();
+#endif
+}
+
+static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame)
+{
+    ASSERT(!callFrame->hasHostCallFrameFlag());
+
+    switch (callFrame->codeBlock()->codeType()) {
+    case EvalCode:
+        return StackFrameEvalCode;
+    case FunctionCode:
+        return StackFrameFunctionCode;
+    case GlobalCode:
+        return StackFrameGlobalCode;
+    }
+    ASSERT_NOT_REACHED();
+    return StackFrameGlobalCode;
+}
+
+void Interpreter::getStackTrace(JSGlobalData* globalData, Vector<StackFrame>& results)
+{
+    CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag();
+    if (!callFrame || callFrame == CallFrame::noCaller()) 
+        return;
+    int line = getLineNumberForCallFrame(globalData, callFrame);
+
+    callFrame = callFrame->trueCallFrameFromVMCode();
+
+    while (callFrame && callFrame != CallFrame::noCaller()) {
+        UString sourceURL;
+        if (callFrame->codeBlock()) {
+            sourceURL = getSourceURLFromCallFrame(callFrame);
+            StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), getStackFrameCodeType(callFrame), Strong<ExecutableBase>(*globalData, callFrame->codeBlock()->ownerExecutable()), line, sourceURL};
+            results.append(s);
+        } else {
+            StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), -1, UString()};
+            results.append(s);
+        }
+        callFrame = getCallerInfo(globalData, callFrame, line);
+    }
+}
+
+void Interpreter::addStackTraceIfNecessary(CallFrame* callFrame, JSObject* error)
+{
+    JSGlobalData* globalData = &callFrame->globalData();
+    ASSERT(callFrame == globalData->topCallFrame || callFrame == callFrame->lexicalGlobalObject()->globalExec() || callFrame == callFrame->dynamicGlobalObject()->globalExec());
+    if (error->hasProperty(callFrame, globalData->propertyNames->stack))
+        return;
+
+    Vector<StackFrame> stackTrace;
+    getStackTrace(&callFrame->globalData(), stackTrace);
+    
+    if (stackTrace.isEmpty())
+        return;
+    
+    JSGlobalObject* globalObject = 0;
+    if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error))
+        globalObject = globalData->dynamicGlobalObject;
+    else
+        globalObject = error->globalObject();
+    StringBuilder builder;
+    for (unsigned i = 0; i < stackTrace.size(); i++) {
+        builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl()));
+        if (i != stackTrace.size() - 1)
+            builder.append('\n');
+    }
+    
+    error->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, UString(builder.toString().impl())), ReadOnly | DontDelete);
+}
+
 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
 {
     CodeBlock* codeBlock = callFrame->codeBlock();
     bool isInterrupt = false;
 
 NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
 {
     CodeBlock* codeBlock = callFrame->codeBlock();
     bool isInterrupt = false;
 
+    ASSERT(!exceptionValue.isEmpty());
+    ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
+    // This shouldn't be possible (hence the assertions), but we're already in the slowest of
+    // slow cases, so let's harden against it anyway to be safe.
+    if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
+        exceptionValue = jsNull();
+
     // Set up the exception object
     if (exceptionValue.isObject()) {
         JSObject* exception = asObject(exceptionValue);
     // Set up the exception object
     if (exceptionValue.isObject()) {
         JSObject* exception = asObject(exceptionValue);
@@ -664,17 +1023,13 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
         if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage())
             appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset);
 
         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());
-
+        if (!hasErrorInfo(callFrame, exception)) {
             // 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());
         }
 
             // 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;
+        isInterrupt = isInterruptedExecutionException(exception) || isTerminatedExecutionException(exception);
     }
 
     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
     }
 
     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
@@ -689,9 +1044,11 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
         if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
             if (Profiler* profiler = *Profiler::enabledProfilerReference())
                 profiler->exceptionUnwind(callFrame);
         if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
             if (Profiler* profiler = *Profiler::enabledProfilerReference())
                 profiler->exceptionUnwind(callFrame);
+            callFrame->globalData().topCallFrame = callFrame;
             return 0;
         }
     }
             return 0;
         }
     }
+    callFrame->globalData().topCallFrame = callFrame;
 
     if (Profiler* profiler = *Profiler::enabledProfilerReference())
         profiler->exceptionUnwind(callFrame);
 
     if (Profiler* profiler = *Profiler::enabledProfilerReference())
         profiler->exceptionUnwind(callFrame);
@@ -735,39 +1092,51 @@ static inline JSObject* checkedReturn(JSObject* returnValue)
 
 JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj)
 {
 
 JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj)
 {
+    ASSERT(isValidThisObject(thisObj, callFrame));
     ASSERT(!scopeChain->globalData->exception);
     ASSERT(!callFrame->globalData().isCollectorBusy());
     if (callFrame->globalData().isCollectorBusy())
     ASSERT(!scopeChain->globalData->exception);
     ASSERT(!callFrame->globalData().isCollectorBusy());
     if (callFrame->globalData().isCollectorBusy())
-        return jsNull();
+        CRASH();
 
     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
         return checkedReturn(throwStackOverflowError(callFrame));
 
     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
 
     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())) {
+    Vector<JSONPData> JSONPData;
+    bool parseResult;
+    const UString programSource = program->source().toString();
+    if (programSource.isNull())
+        return jsUndefined();
+    if (programSource.is8Bit()) {
+        LiteralParser<LChar> literalParser(callFrame, programSource.characters8(), programSource.length(), JSONP);
+        parseResult = literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get()));
+    } else {
+        LiteralParser<UChar> literalParser(callFrame, programSource.characters16(), programSource.length(), JSONP);
+        parseResult = literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->globalObjectMethodTable()->supportsRichSourceInfo(scopeChain->globalObject.get()));
+    }
+
+    if (parseResult) {
         JSGlobalObject* globalObject = scopeChain->globalObject.get();
         JSValue result;
         for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
         JSGlobalObject* globalObject = scopeChain->globalObject.get();
         JSValue result;
         for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
-            Vector<LiteralParser::JSONPPathEntry> JSONPPath;
+            Vector<JSONPPathEntry> JSONPPath;
             JSONPPath.swap(JSONPData[entry].m_path);
             JSValue JSONPValue = JSONPData[entry].m_value.get();
             JSONPPath.swap(JSONPData[entry].m_path);
             JSValue JSONPValue = JSONPData[entry].m_value.get();
-            if (JSONPPath.size() == 1 && JSONPPath[0].m_type == LiteralParser::JSONPPathEntryTypeDeclare) {
+            if (JSONPPath.size() == 1 && JSONPPath[0].m_type == JSONPPathEntryTypeDeclare) {
                 if (globalObject->hasProperty(callFrame, JSONPPath[0].m_pathEntryName)) {
                     PutPropertySlot slot;
                 if (globalObject->hasProperty(callFrame, JSONPPath[0].m_pathEntryName)) {
                     PutPropertySlot slot;
-                    globalObject->put(callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
+                    globalObject->methodTable()->put(globalObject, callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
                 } else
                 } else
-                    globalObject->putWithAttributes(callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, DontEnum | DontDelete);
+                    globalObject->methodTable()->putDirectVirtual(globalObject, 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++) {
                 // 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);
+                ASSERT(JSONPPath[i].m_type != JSONPPathEntryTypeDeclare);
                 switch (JSONPPath[i].m_type) {
                 switch (JSONPPath[i].m_type) {
-                case LiteralParser::JSONPPathEntryTypeDot: {
+                case JSONPPathEntryTypeDot: {
                     if (i == 0) {
                         PropertySlot slot(globalObject);
                         if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
                     if (i == 0) {
                         PropertySlot slot(globalObject);
                         if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
@@ -782,7 +1151,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
                         return jsUndefined();
                     continue;
                 }
                         return jsUndefined();
                     continue;
                 }
-                case LiteralParser::JSONPPathEntryTypeLookup: {
+                case JSONPPathEntryTypeLookup: {
                     baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
                     if (callFrame->hadException())
                         return jsUndefined();
                     baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
                     if (callFrame->hadException())
                         return jsUndefined();
@@ -795,7 +1164,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
             }
             PutPropertySlot slot;
             switch (JSONPPath.last().m_type) {
             }
             PutPropertySlot slot;
             switch (JSONPPath.last().m_type) {
-            case LiteralParser::JSONPPathEntryTypeCall: {
+            case JSONPPathEntryTypeCall: {
                 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
                 if (callFrame->hadException())
                     return jsUndefined();
                 JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
                 if (callFrame->hadException())
                     return jsUndefined();
@@ -811,14 +1180,14 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
                     return jsUndefined();
                 break;
             }
                     return jsUndefined();
                 break;
             }
-            case LiteralParser::JSONPPathEntryTypeDot: {
+            case JSONPPathEntryTypeDot: {
                 baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
                 if (callFrame->hadException())
                     return jsUndefined();
                 break;
             }
                 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);
+            case JSONPPathEntryTypeLookup: {
+                baseObject.putByIndex(callFrame, JSONPPath.last().m_pathIndex, JSONPValue, slot.isStrictMode());
                 if (callFrame->hadException())
                     return jsUndefined();
                 break;
                 if (callFrame->hadException())
                     return jsUndefined();
                 break;
@@ -838,18 +1207,15 @@ failedJSONP:
     CodeBlock* codeBlock = &program->generatedBytecode();
 
     Register* oldEnd = m_registerFile.end();
     CodeBlock* codeBlock = &program->generatedBytecode();
 
     Register* oldEnd = m_registerFile.end();
-    Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
+    Register* newEnd = oldEnd + codeBlock->numParameters() + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
     if (!m_registerFile.grow(newEnd))
         return checkedReturn(throwStackOverflowError(callFrame));
 
     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);
-    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);
+    CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->numParameters() + RegisterFile::CallFrameHeaderSize);
+    ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
+    newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), codeBlock->numParameters(), 0);
+    newCallFrame->setThisValue(thisObj);
+    TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
@@ -861,7 +1227,7 @@ failedJSONP:
 
         m_reentryDepth++;  
 #if ENABLE(JIT)
 
         m_reentryDepth++;  
 #if ENABLE(JIT)
-        if (callFrame->globalData().canUseJIT())
+        if (!classicEnabled())
             result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
         else
 #endif
             result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
         else
 #endif
@@ -873,9 +1239,6 @@ failedJSONP:
     if (*profiler)
         (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo());
 
     if (*profiler)
         (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo());
 
-    if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
-        lastGlobalObject->copyGlobalsTo(m_registerFile);
-
     m_registerFile.shrink(oldEnd);
 
     return checkedReturn(result);
     m_registerFile.shrink(oldEnd);
 
     return checkedReturn(result);
@@ -883,6 +1246,7 @@ failedJSONP:
 
 JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
 {
 
 JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
 {
+    ASSERT(isValidThisObject(thisValue, callFrame));
     ASSERT(!callFrame->hadException());
     ASSERT(!callFrame->globalData().isCollectorBusy());
     if (callFrame->globalData().isCollectorBusy())
     ASSERT(!callFrame->hadException());
     ASSERT(!callFrame->globalData().isCollectorBusy());
     if (callFrame->globalData().isCollectorBusy())
@@ -892,18 +1256,17 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
         return checkedReturn(throwStackOverflowError(callFrame));
 
     Register* oldEnd = m_registerFile.end();
         return checkedReturn(throwStackOverflowError(callFrame));
 
     Register* oldEnd = m_registerFile.end();
+    ASSERT(callFrame->frameExtent() <= oldEnd || callFrame == callFrame->scopeChain()->globalObject->globalExec());
     int argCount = 1 + args.size(); // implicit "this" parameter
     size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
 
     int argCount = 1 + args.size(); // implicit "this" parameter
     size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
 
-    if (!m_registerFile.grow(oldEnd + registerOffset))
+    CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset);
+    if (!m_registerFile.grow(newCallFrame->registers()))
         return checkedReturn(throwStackOverflowError(callFrame));
 
         return checkedReturn(throwStackOverflowError(callFrame));
 
-    CallFrame* newCallFrame = CallFrame::create(oldEnd);
-    size_t dst = 0;
-    newCallFrame->uncheckedR(0) = thisValue;
-    ArgList::const_iterator end = args.end();
-    for (ArgList::const_iterator it = args.begin(); it != end; ++it)
-        newCallFrame->uncheckedR(++dst) = *it;
+    newCallFrame->setThisValue(thisValue);
+    for (size_t i = 0; i < args.size(); ++i)
+        newCallFrame->setArgument(i, args.at(i));
 
     if (callType == CallTypeJS) {
         ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
 
     if (callType == CallTypeJS) {
         ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
@@ -917,7 +1280,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
         }
 
         CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
         }
 
         CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
-        newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
+        newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, 0, argCount);
         if (UNLIKELY(!newCallFrame)) {
             m_registerFile.shrink(oldEnd);
             return checkedReturn(throwStackOverflowError(callFrame));
         if (UNLIKELY(!newCallFrame)) {
             m_registerFile.shrink(oldEnd);
             return checkedReturn(throwStackOverflowError(callFrame));
@@ -925,6 +1288,8 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
 
         newCallFrame->init(newCodeBlock, 0, callDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
 
 
         newCallFrame->init(newCodeBlock, 0, callDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
 
+        TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
+
         Profiler** profiler = Profiler::enabledProfilerReference();
         if (*profiler)
             (*profiler)->willExecute(callFrame, function);
         Profiler** profiler = Profiler::enabledProfilerReference();
         if (*profiler)
             (*profiler)->willExecute(callFrame, function);
@@ -935,7 +1300,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
 
             m_reentryDepth++;  
 #if ENABLE(JIT)
 
             m_reentryDepth++;  
 #if ENABLE(JIT)
-            if (callFrame->globalData().canUseJIT())
+            if (!classicEnabled())
                 result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData);
             else
 #endif
                 result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData);
             else
 #endif
@@ -952,9 +1317,10 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
 
     ASSERT(callType == CallTypeHost);
     ScopeChainNode* scopeChain = callFrame->scopeChain();
 
     ASSERT(callType == CallTypeHost);
     ScopeChainNode* scopeChain = callFrame->scopeChain();
-    newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
     newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
 
     newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
 
+    TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
+
     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
 
     Profiler** profiler = Profiler::enabledProfilerReference();
@@ -993,11 +1359,10 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
     if (!m_registerFile.grow(oldEnd + registerOffset))
         return checkedReturn(throwStackOverflowError(callFrame));
 
     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;
+    CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset);
+    newCallFrame->setThisValue(jsUndefined());
+    for (size_t i = 0; i < args.size(); ++i)
+        newCallFrame->setArgument(i, args.at(i));
 
     if (constructType == ConstructTypeJS) {
         ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain;
 
     if (constructType == ConstructTypeJS) {
         ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain;
@@ -1011,7 +1376,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
         }
 
         CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
         }
 
         CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
-        newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
+        newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, 0, argCount);
         if (UNLIKELY(!newCallFrame)) {
             m_registerFile.shrink(oldEnd);
             return checkedReturn(throwStackOverflowError(callFrame));
         if (UNLIKELY(!newCallFrame)) {
             m_registerFile.shrink(oldEnd);
             return checkedReturn(throwStackOverflowError(callFrame));
@@ -1019,6 +1384,8 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
 
         newCallFrame->init(newCodeBlock, 0, constructDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
 
 
         newCallFrame->init(newCodeBlock, 0, constructDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
 
+        TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
+
         Profiler** profiler = Profiler::enabledProfilerReference();
         if (*profiler)
             (*profiler)->willExecute(callFrame, constructor);
         Profiler** profiler = Profiler::enabledProfilerReference();
         if (*profiler)
             (*profiler)->willExecute(callFrame, constructor);
@@ -1029,7 +1396,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
 
             m_reentryDepth++;  
 #if ENABLE(JIT)
 
             m_reentryDepth++;  
 #if ENABLE(JIT)
-            if (callFrame->globalData().canUseJIT())
+            if (!classicEnabled())
                 result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData);
             else
 #endif
                 result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData);
             else
 #endif
@@ -1049,9 +1416,10 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
 
     ASSERT(constructType == ConstructTypeHost);
     ScopeChainNode* scopeChain = callFrame->scopeChain();
 
     ASSERT(constructType == ConstructTypeHost);
     ScopeChainNode* scopeChain = callFrame->scopeChain();
-    newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
     newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
 
     newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
 
+    TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
+
     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
 
     Profiler** profiler = Profiler::enabledProfilerReference();
@@ -1074,47 +1442,44 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
     return checkedReturn(asObject(result));
 }
 
     return checkedReturn(asObject(result));
 }
 
-CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionExecutable, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain)
+CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, int argumentCountIncludingThis, ScopeChainNode* scopeChain)
 {
     ASSERT(!scopeChain->globalData->exception);
     
 {
     ASSERT(!scopeChain->globalData->exception);
     
-    if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
-        if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
-            throwStackOverflowError(callFrame);
-            return CallFrameClosure();
-        }
+    if (callFrame->globalData().isCollectorBusy())
+        return CallFrameClosure();
+
+    if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
+        throwStackOverflowError(callFrame);
+        return CallFrameClosure();
     }
     }
-    
+
     Register* oldEnd = m_registerFile.end();
     Register* oldEnd = m_registerFile.end();
-    int argc = 1 + argCount; // implicit "this" parameter
-    
-    if (!m_registerFile.grow(oldEnd + argc)) {
+    size_t registerOffset = argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize;
+
+    CallFrame* newCallFrame = CallFrame::create(oldEnd + registerOffset);
+    if (!m_registerFile.grow(newCallFrame->registers())) {
         throwStackOverflowError(callFrame);
         return CallFrameClosure();
     }
 
         throwStackOverflowError(callFrame);
         return CallFrameClosure();
     }
 
-    CallFrame* newCallFrame = CallFrame::create(oldEnd);
-    // We initialise |this| unnecessarily here for the sake of code clarity
-    size_t dst = 0;
-    for (int i = 0; i < argc; ++i)
-        newCallFrame->uncheckedR(dst++) = jsUndefined();
-    
-    JSObject* error = FunctionExecutable->compileForCall(callFrame, scopeChain);
+    JSObject* error = functionExecutable->compileForCall(callFrame, scopeChain);
     if (error) {
         throwError(callFrame, error);
         m_registerFile.shrink(oldEnd);
         return CallFrameClosure();
     }
     if (error) {
         throwError(callFrame, error);
         m_registerFile.shrink(oldEnd);
         return CallFrameClosure();
     }
-    CodeBlock* codeBlock = &FunctionExecutable->generatedBytecodeForCall();
+    CodeBlock* codeBlock = &functionExecutable->generatedBytecodeForCall();
 
 
-    newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
+    newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, 0, argumentCountIncludingThis);
     if (UNLIKELY(!newCallFrame)) {
         throwStackOverflowError(callFrame);
         m_registerFile.shrink(oldEnd);
         return CallFrameClosure();
     }
     if (UNLIKELY(!newCallFrame)) {
         throwStackOverflowError(callFrame);
         m_registerFile.shrink(oldEnd);
         return CallFrameClosure();
     }
-    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argc, function);  
-    CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
+    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argumentCountIncludingThis, function);  
+    scopeChain->globalData->topCallFrame = newCallFrame;
+    CallFrameClosure result = { callFrame, newCallFrame, function, functionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->numParameters(), argumentCountIncludingThis };
     return result;
 }
 
     return result;
 }
 
@@ -1127,27 +1492,29 @@ JSValue Interpreter::execute(CallFrameClosure& closure)
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
         (*profiler)->willExecute(closure.oldCallFrame, closure.function);
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
         (*profiler)->willExecute(closure.oldCallFrame, closure.function);
-    
+
+    TopCallFrameSetter topCallFrame(*closure.globalData, closure.newCallFrame);
+
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get());
         
         m_reentryDepth++;  
 #if ENABLE(JIT)
     JSValue result;
     {
         SamplingTool::CallRecord callRecord(m_sampler.get());
         
         m_reentryDepth++;  
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
         if (closure.newCallFrame->globalData().canUseJIT())
 #endif
             result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData);
         if (closure.newCallFrame->globalData().canUseJIT())
 #endif
             result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData);
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
         else
 #endif
 #endif
         else
 #endif
 #endif
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
             result = privateExecute(Normal, &m_registerFile, closure.newCallFrame);
 #endif
         m_reentryDepth--;
     }
             result = privateExecute(Normal, &m_registerFile, closure.newCallFrame);
 #endif
         m_reentryDepth--;
     }
-    
+
     if (*profiler)
         (*profiler)->didExecute(closure.oldCallFrame, closure.function);
     return checkedReturn(result);
     if (*profiler)
         (*profiler)->didExecute(closure.oldCallFrame, closure.function);
     return checkedReturn(result);
@@ -1155,19 +1522,13 @@ JSValue Interpreter::execute(CallFrameClosure& closure)
 
 void Interpreter::endRepeatCall(CallFrameClosure& closure)
 {
 
 void Interpreter::endRepeatCall(CallFrameClosure& closure)
 {
+    closure.globalData->topCallFrame = closure.oldCallFrame;
     m_registerFile.shrink(closure.oldEnd);
 }
 
     m_registerFile.shrink(closure.oldEnd);
 }
 
-JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain)
-{
-    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 Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, ScopeChainNode* scopeChain, int globalRegisterOffset)
 {
 {
+    ASSERT(isValidThisObject(thisValue, callFrame));
     ASSERT(!scopeChain->globalData->exception);
     ASSERT(!callFrame->globalData().isCollectorBusy());
     if (callFrame->globalData().isCollectorBusy())
     ASSERT(!scopeChain->globalData->exception);
     ASSERT(!callFrame->globalData().isCollectorBusy());
     if (callFrame->globalData().isCollectorBusy())
@@ -1186,8 +1547,8 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
     JSObject* variableObject;
     for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) {
         ASSERT(node);
     JSObject* variableObject;
     for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) {
         ASSERT(node);
-        if (node->object->isVariableObject()) {
-            variableObject = static_cast<JSVariableObject*>(node->object.get());
+        if (node->object->isVariableObject() && !node->object->isStaticScopeObject()) {
+            variableObject = jsCast<JSVariableObject*>(node->object.get());
             break;
         }
     }
             break;
         }
     }
@@ -1197,7 +1558,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
     bool pushedScope = false;
     if (numVariables || numFunctions) {
         if (codeBlock->isStrictMode()) {
     bool pushedScope = false;
     if (numVariables || numFunctions) {
         if (codeBlock->isStrictMode()) {
-            variableObject = new (callFrame) StrictEvalActivation(callFrame);
+            variableObject = StrictEvalActivation::create(callFrame);
             scopeChain = scopeChain->push(variableObject);
             pushedScope = true;
         }
             scopeChain = scopeChain->push(variableObject);
             pushedScope = true;
         }
@@ -1208,30 +1569,32 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
             const Identifier& ident = codeBlock->variable(i);
             if (!variableObject->hasProperty(callFrame, ident)) {
                 PutPropertySlot slot;
             const Identifier& ident = codeBlock->variable(i);
             if (!variableObject->hasProperty(callFrame, ident)) {
                 PutPropertySlot slot;
-                variableObject->put(callFrame, ident, jsUndefined(), slot);
+                variableObject->methodTable()->put(variableObject, callFrame, ident, jsUndefined(), slot);
             }
         }
 
         for (int i = 0; i < numFunctions; ++i) {
             FunctionExecutable* function = codeBlock->functionDecl(i);
             PutPropertySlot slot;
             }
         }
 
         for (int i = 0; i < numFunctions; ++i) {
             FunctionExecutable* function = codeBlock->functionDecl(i);
             PutPropertySlot slot;
-            variableObject->put(callFrame, function->name(), function->make(callFrame, scopeChain), slot);
+            variableObject->methodTable()->put(variableObject, callFrame, function->name(), function->make(callFrame, scopeChain), slot);
         }
     }
 
     Register* oldEnd = m_registerFile.end();
         }
     }
 
     Register* oldEnd = m_registerFile.end();
-    Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
+    Register* newEnd = m_registerFile.begin() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
     if (!m_registerFile.grow(newEnd)) {
         if (pushedScope)
             scopeChain->pop();
         return checkedReturn(throwStackOverflowError(callFrame));
     }
 
     if (!m_registerFile.grow(newEnd)) {
         if (pushedScope)
             scopeChain->pop();
         return checkedReturn(throwStackOverflowError(callFrame));
     }
 
-    CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
+    CallFrame* newCallFrame = CallFrame::create(m_registerFile.begin() + globalRegisterOffset);
+
+    ASSERT(codeBlock->numParameters() == 1); // 1 parameter for 'this'.
+    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), codeBlock->numParameters(), 0);
+    newCallFrame->setThisValue(thisValue);
 
 
-    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);
+    TopCallFrameSetter topCallFrame(callFrame->globalData(), newCallFrame);
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
@@ -1244,15 +1607,15 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
         m_reentryDepth++;
         
 #if ENABLE(JIT)
         m_reentryDepth++;
         
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
         if (callFrame->globalData().canUseJIT())
 #endif
             result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
         if (callFrame->globalData().canUseJIT())
 #endif
             result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
         else
 #endif
 #endif
         else
 #endif
 #endif
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
             result = privateExecute(Normal, &m_registerFile, newCallFrame);
 #endif
         m_reentryDepth--;
             result = privateExecute(Normal, &m_registerFile, newCallFrame);
 #endif
         m_reentryDepth--;
@@ -1295,14 +1658,14 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook
     }
 }
     
     }
 }
     
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
 NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
 {
     int dst = vPC[1].u.operand;
     CodeBlock* codeBlock = callFrame->codeBlock();
     Identifier& property = codeBlock->identifier(vPC[2].u.operand);
     JSValue value = callFrame->r(vPC[3].u.operand).jsValue();
 NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
 {
     int dst = vPC[1].u.operand;
     CodeBlock* codeBlock = callFrame->codeBlock();
     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);
+    JSObject* scope = JSStaticScopeObject::create(callFrame, property, value, DontDelete);
     callFrame->uncheckedR(dst) = JSValue(scope);
 
     return callFrame->scopeChain()->push(scope);
     callFrame->uncheckedR(dst) = JSValue(scope);
 
     return callFrame->scopeChain()->push(scope);
@@ -1399,13 +1762,12 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
         return;
     }
 
         return;
     }
 
-    JSGlobalData* globalData = &callFrame->globalData();
-    if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
+    if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
         vPC[0] = getOpcode(op_get_array_length);
         return;
     }
 
         vPC[0] = getOpcode(op_get_array_length);
         return;
     }
 
-    if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
+    if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
         vPC[0] = getOpcode(op_get_string_length);
         return;
     }
         vPC[0] = getOpcode(op_get_string_length);
         return;
     }
@@ -1503,6 +1865,7 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
     }
 
     
     }
 
     
+    StructureChain* prototypeChain = structure->prototypeChain(callFrame);
     switch (slot.cachedPropertyType()) {
     case PropertySlot::Getter:
         vPC[0] = getOpcode(op_get_by_id_getter_chain);
     switch (slot.cachedPropertyType()) {
     case PropertySlot::Getter:
         vPC[0] = getOpcode(op_get_by_id_getter_chain);
@@ -1518,7 +1881,7 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
         break;
     }
     vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
         break;
     }
     vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
-    vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure->prototypeChain(callFrame));
+    vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), prototypeChain);
     vPC[6] = count;
 }
 
     vPC[6] = count;
 }
 
@@ -1528,40 +1891,46 @@ NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock*, Instruction* vPC)
     vPC[4] = 0;
 }
 
     vPC[4] = 0;
 }
 
-#endif // ENABLE(INTERPRETER)
+#endif // ENABLE(CLASSIC_INTERPRETER)
 
 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.
     if (UNLIKELY(flag == InitializeAndReturn)) {
 
 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.
     if (UNLIKELY(flag == InitializeAndReturn)) {
-        #if ENABLE(COMPUTED_GOTO_INTERPRETER)
+        #if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
             #define LIST_OPCODE_LABEL(id, length) &&id,
                 static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) };
                 for (size_t i = 0; i < WTF_ARRAY_LENGTH(labels); ++i)
                     m_opcodeTable[i] = labels[i];
             #undef LIST_OPCODE_LABEL
             #define LIST_OPCODE_LABEL(id, length) &&id,
                 static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) };
                 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)
+        #endif // ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
         return JSValue();
     }
     
         return JSValue();
     }
     
+    ASSERT(m_initialized);
+    ASSERT(m_classicEnabled);
+    
 #if ENABLE(JIT)
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
     // Mixing Interpreter + JIT is not supported.
     if (callFrame->globalData().canUseJIT())
 #endif
         ASSERT_NOT_REACHED();
 #endif
 
     // Mixing Interpreter + JIT is not supported.
     if (callFrame->globalData().canUseJIT())
 #endif
         ASSERT_NOT_REACHED();
 #endif
 
-#if !ENABLE(INTERPRETER)
+#if !ENABLE(CLASSIC_INTERPRETER)
     UNUSED_PARAM(registerFile);
     UNUSED_PARAM(callFrame);
     return JSValue();
 #else
 
     UNUSED_PARAM(registerFile);
     UNUSED_PARAM(callFrame);
     return JSValue();
 #else
 
+    ASSERT(callFrame->globalData().topCallFrame == callFrame);
+
     JSGlobalData* globalData = &callFrame->globalData();
     JSValue exceptionValue;
     HandlerInfo* handler = 0;
     JSGlobalData* globalData = &callFrame->globalData();
     JSValue exceptionValue;
     HandlerInfo* handler = 0;
+    CallFrame** topCallFrameSlot = &globalData->topCallFrame;
 
     CodeBlock* codeBlock = callFrame->codeBlock();
     Instruction* vPC = codeBlock->instructions().begin();
 
     CodeBlock* codeBlock = callFrame->codeBlock();
     Instruction* vPC = codeBlock->instructions().begin();
@@ -1596,20 +1965,31 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
     #define SAMPLE(codeBlock, vPC)
 #endif
 
     #define SAMPLE(codeBlock, vPC)
 #endif
 
-#if ENABLE(COMPUTED_GOTO_INTERPRETER)
+#define UPDATE_BYTECODE_OFFSET() \
+    do {\
+        callFrame->setBytecodeOffsetForNonDFGCode(vPC - codeBlock->instructions().data() + 1);\
+    } while (0)
+
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
     #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto *vPC->u.opcode
 #if ENABLE(OPCODE_STATS)
     #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto *vPC->u.opcode
 #if ENABLE(OPCODE_STATS)
-    #define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
+    #define DEFINE_OPCODE(opcode) \
+        opcode:\
+            OpcodeStats::recordInstruction(opcode);\
+            UPDATE_BYTECODE_OFFSET();
 #else
 #else
-    #define DEFINE_OPCODE(opcode) opcode:
+    #define DEFINE_OPCODE(opcode) opcode: UPDATE_BYTECODE_OFFSET();
 #endif
     NEXT_INSTRUCTION();
 #else
     #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto interpreterLoopStart
 #if ENABLE(OPCODE_STATS)
 #endif
     NEXT_INSTRUCTION();
 #else
     #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto interpreterLoopStart
 #if ENABLE(OPCODE_STATS)
-    #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
+    #define DEFINE_OPCODE(opcode) \
+        case opcode:\
+            OpcodeStats::recordInstruction(opcode);\
+            UPDATE_BYTECODE_OFFSET();
 #else
 #else
-    #define DEFINE_OPCODE(opcode) case opcode:
+    #define DEFINE_OPCODE(opcode) case opcode: UPDATE_BYTECODE_OFFSET();
 #endif
     while (1) { // iterator loop begins
     interpreterLoopStart:;
 #endif
     while (1) { // iterator loop begins
     interpreterLoopStart:;
@@ -1639,8 +2019,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int dst = vPC[1].u.operand;
         int firstArg = vPC[2].u.operand;
         int argCount = vPC[3].u.operand;
         int dst = vPC[1].u.operand;
         int firstArg = vPC[2].u.operand;
         int argCount = vPC[3].u.operand;
-        ArgList args(callFrame->registers() + firstArg, argCount);
-        callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, args));
+        callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, reinterpret_cast<JSValue*>(&callFrame->registers()[firstArg]), argCount));
 
         vPC += OPCODE_LENGTH(op_new_array);
         NEXT_INSTRUCTION();
 
         vPC += OPCODE_LENGTH(op_new_array);
         NEXT_INSTRUCTION();
@@ -1655,8 +2034,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int dst = vPC[1].u.operand;
         int firstArg = vPC[2].u.operand;
         int argCount = vPC[3].u.operand;
         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));
+        callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, codeBlock->constantBuffer(firstArg), argCount));
         
         vPC += OPCODE_LENGTH(op_new_array);
         NEXT_INSTRUCTION();
         
         vPC += OPCODE_LENGTH(op_new_array);
         NEXT_INSTRUCTION();
@@ -1674,7 +2052,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             exceptionValue = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor.");
             goto vm_throw;
         }
             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));
+        callFrame->uncheckedR(dst) = JSValue(RegExpObject::create(*globalData, callFrame->lexicalGlobalObject(), callFrame->scopeChain()->globalObject->regExpStructure(), regExp));
 
         vPC += OPCODE_LENGTH(op_new_regexp);
         NEXT_INSTRUCTION();
 
         vPC += OPCODE_LENGTH(op_new_regexp);
         NEXT_INSTRUCTION();
@@ -1816,7 +2194,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int dst = vPC[1].u.operand;
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         int dst = vPC[1].u.operand;
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
-        JSValue result = jsBoolean(jsLess(callFrame, src1, src2));
+        JSValue result = jsBoolean(jsLess<true>(callFrame, src1, src2));
         CHECK_FOR_EXCEPTION();
         callFrame->uncheckedR(dst) = result;
 
         CHECK_FOR_EXCEPTION();
         callFrame->uncheckedR(dst) = result;
 
@@ -1833,13 +2211,47 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int dst = vPC[1].u.operand;
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         int dst = vPC[1].u.operand;
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
-        JSValue result = jsBoolean(jsLessEq(callFrame, src1, src2));
+        JSValue result = jsBoolean(jsLessEq<true>(callFrame, src1, src2));
         CHECK_FOR_EXCEPTION();
         callFrame->uncheckedR(dst) = result;
 
         vPC += OPCODE_LENGTH(op_lesseq);
         NEXT_INSTRUCTION();
     }
         CHECK_FOR_EXCEPTION();
         callFrame->uncheckedR(dst) = result;
 
         vPC += OPCODE_LENGTH(op_lesseq);
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_greater) {
+        /* greater dst(r) src1(r) src2(r)
+
+           Checks whether register src1 is greater than register src2, as
+           with the ECMAScript '>' operator, and puts the result as
+           a boolean in register dst.
+        */
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
+        JSValue result = jsBoolean(jsLess<false>(callFrame, src2, src1));
+        CHECK_FOR_EXCEPTION();
+        callFrame->uncheckedR(dst) = result;
+
+        vPC += OPCODE_LENGTH(op_greater);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_greatereq) {
+        /* greatereq dst(r) src1(r) src2(r)
+
+           Checks whether register src1 is greater than or equal to
+           register src2, as with the ECMAScript '>=' operator, and
+           puts the result as a boolean in register dst.
+        */
+        int dst = vPC[1].u.operand;
+        JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
+        JSValue result = jsBoolean(jsLessEq<false>(callFrame, src2, src1));
+        CHECK_FOR_EXCEPTION();
+        callFrame->uncheckedR(dst) = result;
+
+        vPC += OPCODE_LENGTH(op_greatereq);
+        NEXT_INSTRUCTION();
+    }
     DEFINE_OPCODE(op_pre_inc) {
         /* pre_inc srcDst(r)
 
     DEFINE_OPCODE(op_pre_inc) {
         /* pre_inc srcDst(r)
 
@@ -1892,10 +2304,10 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1);
             callFrame->uncheckedR(dst) = v;
         } else {
             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1);
             callFrame->uncheckedR(dst) = v;
         } else {
-            JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
+            double number = callFrame->r(srcDst).jsValue().toNumber(callFrame);
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->uncheckedR(srcDst) = jsNumber(number.uncheckedGetNumber() + 1);
-            callFrame->uncheckedR(dst) = number;
+            callFrame->uncheckedR(srcDst) = jsNumber(number + 1);
+            callFrame->uncheckedR(dst) = jsNumber(number);
         }
 
         vPC += OPCODE_LENGTH(op_post_inc);
         }
 
         vPC += OPCODE_LENGTH(op_post_inc);
@@ -1915,10 +2327,10 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1);
             callFrame->uncheckedR(dst) = v;
         } else {
             callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1);
             callFrame->uncheckedR(dst) = v;
         } else {
-            JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
+            double number = callFrame->r(srcDst).jsValue().toNumber(callFrame);
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->uncheckedR(srcDst) = jsNumber(number.uncheckedGetNumber() - 1);
-            callFrame->uncheckedR(dst) = number;
+            callFrame->uncheckedR(srcDst) = jsNumber(number - 1);
+            callFrame->uncheckedR(dst) = jsNumber(number);
         }
 
         vPC += OPCODE_LENGTH(op_post_dec);
         }
 
         vPC += OPCODE_LENGTH(op_post_dec);
@@ -1938,9 +2350,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         if (LIKELY(srcVal.isNumber()))
             callFrame->uncheckedR(dst) = callFrame->r(src);
         else {
         if (LIKELY(srcVal.isNumber()))
             callFrame->uncheckedR(dst) = callFrame->r(src);
         else {
-            JSValue result = srcVal.toJSNumber(callFrame);
+            double number = srcVal.toNumber(callFrame);
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->uncheckedR(dst) = result;
+            callFrame->uncheckedR(dst) = jsNumber(number);
         }
 
         vPC += OPCODE_LENGTH(op_to_jsnumber);
         }
 
         vPC += OPCODE_LENGTH(op_to_jsnumber);
@@ -1975,7 +2387,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int dst = vPC[1].u.operand;
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         int dst = vPC[1].u.operand;
         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
+        if (src1.isInt32() && src2.isInt32() && !((src1.asInt32() | src2.asInt32()) & 0xc0000000)) // no overflow
             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() + src2.asInt32());
         else {
             JSValue result = jsAdd(callFrame, src1, src2);
             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() + src2.asInt32());
         else {
             JSValue result = jsAdd(callFrame, src1, src2);
@@ -1994,7 +2406,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int dst = vPC[1].u.operand;
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         int dst = vPC[1].u.operand;
         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
+        if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32()) >> 15) // no overflow
                 callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() * src2.asInt32());
         else {
             JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
                 callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() * src2.asInt32());
         else {
             JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
@@ -2062,7 +2474,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int dst = vPC[1].u.operand;
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         int dst = vPC[1].u.operand;
         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
+        if (src1.isInt32() && src2.isInt32() && !((src1.asInt32() | src2.asInt32()) & 0xc0000000)) // no overflow
             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() - src2.asInt32());
         else {
             JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
             callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() - src2.asInt32());
         else {
             JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
@@ -2200,24 +2612,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         vPC += OPCODE_LENGTH(op_bitor);
         NEXT_INSTRUCTION();
     }
         vPC += OPCODE_LENGTH(op_bitor);
         NEXT_INSTRUCTION();
     }
-    DEFINE_OPCODE(op_bitnot) {
-        /* bitnot dst(r) src(r)
-
-           Computes bitwise NOT of register src1 (converted to int32),
-           and puts the result in register dst.
-        */
-        int dst = vPC[1].u.operand;
-        JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
-        if (src.isInt32())
-            callFrame->uncheckedR(dst) = jsNumber(~src.asInt32());
-        else {
-            JSValue result = jsNumber(~src.toInt32(callFrame));
-            CHECK_FOR_EXCEPTION();
-            callFrame->uncheckedR(dst) = result;
-        }
-        vPC += OPCODE_LENGTH(op_bitnot);
-        NEXT_INSTRUCTION();
-    }
     DEFINE_OPCODE(op_not) {
         /* not dst(r) src(r)
 
     DEFINE_OPCODE(op_not) {
         /* not dst(r) src(r)
 
@@ -2272,7 +2666,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         ASSERT(!isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue));
 
 
         ASSERT(!isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue));
 
-        bool result = asObject(baseVal)->hasInstance(callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
+        bool result = asObject(baseVal)->methodTable()->hasInstance(asObject(baseVal), callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
         CHECK_FOR_EXCEPTION();
         callFrame->uncheckedR(dst) = jsBoolean(result);
 
         CHECK_FOR_EXCEPTION();
         callFrame->uncheckedR(dst) = jsBoolean(result);
 
@@ -2402,7 +2796,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         if (propName.getUInt32(i))
             callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, i));
         else {
         if (propName.getUInt32(i))
             callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, i));
         else {
-            Identifier property(callFrame, propName.toString(callFrame));
+            Identifier property(callFrame, propName.toString(callFrame)->value(callFrame));
             CHECK_FOR_EXCEPTION();
             callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
         }
             CHECK_FOR_EXCEPTION();
             callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
         }
@@ -2511,20 +2905,20 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         ScopeChainNode* scopeChain = callFrame->scopeChain();
         ScopeChainIterator iter = scopeChain->begin();
         ScopeChainIterator end = scopeChain->end();
         ScopeChainNode* scopeChain = callFrame->scopeChain();
         ScopeChainIterator iter = scopeChain->begin();
         ScopeChainIterator end = scopeChain->end();
-        ASSERT(iter != end);
+        ASSERT_UNUSED(end, iter != end);
         ASSERT(codeBlock == callFrame->codeBlock());
         bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
         ASSERT(skip || !checkTopLevel);
         ASSERT(codeBlock == callFrame->codeBlock());
         bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
         ASSERT(skip || !checkTopLevel);
-    if (checkTopLevel && skip--) {
+        if (checkTopLevel && skip--) {
             if (callFrame->r(codeBlock->activationRegister()).jsValue())
                 ++iter;
         }
         while (skip--) {
             ++iter;
             if (callFrame->r(codeBlock->activationRegister()).jsValue())
                 ++iter;
         }
         while (skip--) {
             ++iter;
-            ASSERT(iter != end);
+            ASSERT_UNUSED(end, iter != end);
         }
         ASSERT((*iter)->isVariableObject());
         }
         ASSERT((*iter)->isVariableObject());
-        JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get());
+        JSVariableObject* scope = jsCast<JSVariableObject*>(iter->get());
         callFrame->uncheckedR(dst) = scope->registerAt(index).get();
         ASSERT(callFrame->r(dst).jsValue());
         vPC += OPCODE_LENGTH(op_get_scoped_var);
         callFrame->uncheckedR(dst) = scope->registerAt(index).get();
         ASSERT(callFrame->r(dst).jsValue());
         vPC += OPCODE_LENGTH(op_get_scoped_var);
@@ -2542,20 +2936,20 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         ScopeChainIterator iter = scopeChain->begin();
         ScopeChainIterator end = scopeChain->end();
         ASSERT(codeBlock == callFrame->codeBlock());
         ScopeChainIterator iter = scopeChain->begin();
         ScopeChainIterator end = scopeChain->end();
         ASSERT(codeBlock == callFrame->codeBlock());
-        ASSERT(iter != end);
+        ASSERT_UNUSED(end, iter != end);
         bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
         ASSERT(skip || !checkTopLevel);
         bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
         ASSERT(skip || !checkTopLevel);
-    if (checkTopLevel && skip--) {
+        if (checkTopLevel && skip--) {
             if (callFrame->r(codeBlock->activationRegister()).jsValue())
                 ++iter;
         }
         while (skip--) {
             ++iter;
             if (callFrame->r(codeBlock->activationRegister()).jsValue())
                 ++iter;
         }
         while (skip--) {
             ++iter;
-            ASSERT(iter != end);
+            ASSERT_UNUSED(end, iter != end);
         }
 
         ASSERT((*iter)->isVariableObject());
         }
 
         ASSERT((*iter)->isVariableObject());
-        JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get());
+        JSVariableObject* scope = jsCast<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);
         ASSERT(callFrame->r(value).jsValue());
         scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue());
         vPC += OPCODE_LENGTH(op_put_scoped_var);
@@ -2614,6 +3008,22 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         vPC += OPCODE_LENGTH(op_resolve_with_base);
         NEXT_INSTRUCTION();
     }
         vPC += OPCODE_LENGTH(op_resolve_with_base);
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_resolve_with_this) {
+        /* resolve_with_this thisDst(r) propDst(r) property(id)
+
+           Searches the scope chain for an object containing
+           identifier property, and if one is found, writes the
+           retrieved property value to register propDst, and the
+           this object to pass in a call to thisDst.
+
+           If the property is not found, raises an exception.
+        */
+        if (UNLIKELY(!resolveThisAndProperty(callFrame, vPC, exceptionValue)))
+            goto vm_throw;
+
+        vPC += OPCODE_LENGTH(op_resolve_with_this);
+        NEXT_INSTRUCTION();
+    }
     DEFINE_OPCODE(op_get_by_id) {
         /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n)
 
     DEFINE_OPCODE(op_get_by_id) {
         /* get_by_id dst(r) base(r) property(id) structure(sID) nop(n) nop(n) nop(n)
 
@@ -2731,7 +3141,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                     if (GetterSetter* getterSetter = asGetterSetter(protoObject->getDirectOffset(offset).asCell())) {
                         JSObject* getter = getterSetter->getter();
                         CallData callData;
                     if (GetterSetter* getterSetter = asGetterSetter(protoObject->getDirectOffset(offset).asCell())) {
                         JSObject* getter = getterSetter->getter();
                         CallData callData;
-                        CallType callType = getter->getCallData(callData);
+                        CallType callType = getter->methodTable()->getCallData(getter, callData);
                         JSValue result = call(callFrame, getter, callType, callData, asObject(baseCell), ArgList());
                         CHECK_FOR_EXCEPTION();
                         callFrame->uncheckedR(dst) = result;
                         JSValue result = call(callFrame, getter, callType, callData, asObject(baseCell), ArgList());
                         CHECK_FOR_EXCEPTION();
                         callFrame->uncheckedR(dst) = result;
@@ -2790,48 +3200,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
     skip_id_custom_proto:
 #endif
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
     skip_id_custom_proto:
 #endif
-    DEFINE_OPCODE(op_get_by_id_self_list) {
-        // Polymorphic self access caching currently only supported when JITting.
-        ASSERT_NOT_REACHED();
-        // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
-        vPC += OPCODE_LENGTH(op_get_by_id_self_list);
-        NEXT_INSTRUCTION();
-    }
-    DEFINE_OPCODE(op_get_by_id_proto_list) {
-        // Polymorphic prototype access caching currently only supported when JITting.
-        ASSERT_NOT_REACHED();
-        // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
-        vPC += OPCODE_LENGTH(op_get_by_id_proto_list);
-        NEXT_INSTRUCTION();
-    }
-    DEFINE_OPCODE(op_get_by_id_getter_self_list) {
-        // Polymorphic self access caching currently only supported when JITting.
-        ASSERT_NOT_REACHED();
-        // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
-        vPC += OPCODE_LENGTH(op_get_by_id_self_list);
-        NEXT_INSTRUCTION();
-    }
-    DEFINE_OPCODE(op_get_by_id_getter_proto_list) {
-        // Polymorphic prototype access caching currently only supported when JITting.
-        ASSERT_NOT_REACHED();
-        // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
-        vPC += OPCODE_LENGTH(op_get_by_id_proto_list);
-        NEXT_INSTRUCTION();
-    }
-    DEFINE_OPCODE(op_get_by_id_custom_self_list) {
-        // Polymorphic self access caching currently only supported when JITting.
-        ASSERT_NOT_REACHED();
-        // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
-        vPC += OPCODE_LENGTH(op_get_by_id_custom_self_list);
-        NEXT_INSTRUCTION();
-    }
-    DEFINE_OPCODE(op_get_by_id_custom_proto_list) {
-        // Polymorphic prototype access caching currently only supported when JITting.
-        ASSERT_NOT_REACHED();
-        // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
-        vPC += OPCODE_LENGTH(op_get_by_id_proto_list);
-        NEXT_INSTRUCTION();
-    }
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
     goto *(&&skip_get_by_id_chain);
 #endif
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
     goto *(&&skip_get_by_id_chain);
 #endif
@@ -2908,7 +3276,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                 if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
                     JSObject* getter = getterSetter->getter();
                     CallData callData;
                 if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
                     JSObject* getter = getterSetter->getter();
                     CallData callData;
-                    CallType callType = getter->getCallData(callData);
+                    CallType callType = getter->methodTable()->getCallData(getter, callData);
                     JSValue result = call(callFrame, getter, callType, callData, baseObject, ArgList());
                     CHECK_FOR_EXCEPTION();
                     callFrame->uncheckedR(dst) = result;
                     JSValue result = call(callFrame, getter, callType, callData, baseObject, ArgList());
                     CHECK_FOR_EXCEPTION();
                     callFrame->uncheckedR(dst) = result;
@@ -3016,7 +3384,7 @@ skip_id_custom_self:
                         if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
                             JSObject* getter = getterSetter->getter();
                             CallData callData;
                         if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
                             JSObject* getter = getterSetter->getter();
                             CallData callData;
-                            CallType callType = getter->getCallData(callData);
+                            CallType callType = getter->methodTable()->getCallData(getter, callData);
                             JSValue result = call(callFrame, getter, callType, callData, baseValue, ArgList());
                             CHECK_FOR_EXCEPTION();
                             callFrame->uncheckedR(dst) = result;
                             JSValue result = call(callFrame, getter, callType, callData, baseValue, ArgList());
                             CHECK_FOR_EXCEPTION();
                             callFrame->uncheckedR(dst) = result;
@@ -3100,7 +3468,7 @@ skip_id_custom_self:
 
         int base = vPC[2].u.operand;
         JSValue baseValue = callFrame->r(base).jsValue();
 
         int base = vPC[2].u.operand;
         JSValue baseValue = callFrame->r(base).jsValue();
-        if (LIKELY(isJSArray(globalData, baseValue))) {
+        if (LIKELY(isJSArray(baseValue))) {
             int dst = vPC[1].u.operand;
             callFrame->uncheckedR(dst) = jsNumber(asArray(baseValue)->length());
             vPC += OPCODE_LENGTH(op_get_array_length);
             int dst = vPC[1].u.operand;
             callFrame->uncheckedR(dst) = jsNumber(asArray(baseValue)->length());
             vPC += OPCODE_LENGTH(op_get_array_length);
@@ -3124,7 +3492,7 @@ skip_id_custom_self:
 
         int base = vPC[2].u.operand;
         JSValue baseValue = callFrame->r(base).jsValue();
 
         int base = vPC[2].u.operand;
         JSValue baseValue = callFrame->r(base).jsValue();
-        if (LIKELY(isJSString(globalData, baseValue))) {
+        if (LIKELY(isJSString(baseValue))) {
             int dst = vPC[1].u.operand;
             callFrame->uncheckedR(dst) = jsNumber(asString(baseValue)->length());
             vPC += OPCODE_LENGTH(op_get_string_length);
             int dst = vPC[1].u.operand;
             callFrame->uncheckedR(dst) = jsNumber(asString(baseValue)->length());
             vPC += OPCODE_LENGTH(op_get_string_length);
@@ -3160,8 +3528,8 @@ skip_id_custom_self:
         Identifier& ident = codeBlock->identifier(property);
         PutPropertySlot slot(codeBlock->isStrictMode());
         if (direct) {
         Identifier& ident = codeBlock->identifier(property);
         PutPropertySlot slot(codeBlock->isStrictMode());
         if (direct) {
-            baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
-            ASSERT(slot.base() == baseValue);
+            ASSERT(baseValue.isObject());
+            asObject(baseValue)->putDirect(*globalData, ident, callFrame->r(value).jsValue(), slot);
         } else
             baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
         CHECK_FOR_EXCEPTION();
         } else
             baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
         CHECK_FOR_EXCEPTION();
@@ -3174,6 +3542,8 @@ skip_id_custom_self:
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
       skip_put_by_id:
 #endif
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
       skip_put_by_id:
 #endif
+    DEFINE_OPCODE(op_put_by_id_transition_direct)
+    DEFINE_OPCODE(op_put_by_id_transition_normal)
     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)
          
@@ -3279,8 +3649,8 @@ skip_id_custom_self:
         Identifier& ident = codeBlock->identifier(property);
         PutPropertySlot slot(codeBlock->isStrictMode());
         if (direct) {
         Identifier& ident = codeBlock->identifier(property);
         PutPropertySlot slot(codeBlock->isStrictMode());
         if (direct) {
-            baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
-            ASSERT(slot.base() == baseValue);
+            ASSERT(baseValue.isObject());
+            asObject(baseValue)->putDirect(*globalData, ident, callFrame->r(value).jsValue(), slot);
         } else
             baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
         CHECK_FOR_EXCEPTION();
         } else
             baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
         CHECK_FOR_EXCEPTION();
@@ -3302,7 +3672,7 @@ skip_id_custom_self:
 
         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
         Identifier& ident = codeBlock->identifier(property);
 
         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
         Identifier& ident = codeBlock->identifier(property);
-        bool result = baseObj->deleteProperty(callFrame, ident);
+        bool result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, ident);
         if (!result && codeBlock->isStrictMode()) {
             exceptionValue = createTypeError(callFrame, "Unable to delete property.");
             goto vm_throw;
         if (!result && codeBlock->isStrictMode()) {
             exceptionValue = createTypeError(callFrame, "Unable to delete property.");
             goto vm_throw;
@@ -3333,7 +3703,7 @@ skip_id_custom_self:
             NEXT_INSTRUCTION();
         }
         {
             NEXT_INSTRUCTION();
         }
         {
-            Identifier propertyName(callFrame, subscript.toString(callFrame));
+            Identifier propertyName(callFrame, subscript.toString(callFrame)->value(callFrame));
             result = baseValue.get(callFrame, propertyName);
         }
         CHECK_FOR_EXCEPTION();
             result = baseValue.get(callFrame, propertyName);
         }
         CHECK_FOR_EXCEPTION();
@@ -3365,17 +3735,12 @@ skip_id_custom_self:
         JSValue arguments = callFrame->r(argumentsRegister).jsValue();
         JSValue subscript = callFrame->r(property).jsValue();
         if (!arguments && subscript.isUInt32() && subscript.asUInt32() < callFrame->argumentCount()) {
         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);
+            callFrame->uncheckedR(dst) = callFrame->argument(subscript.asUInt32());
             vPC += OPCODE_LENGTH(op_get_argument_by_val);
             NEXT_INSTRUCTION();
         }
         if (!arguments) {
             vPC += OPCODE_LENGTH(op_get_argument_by_val);
             NEXT_INSTRUCTION();
         }
         if (!arguments) {
-            Arguments* arguments = new (globalData) Arguments(callFrame);
+            Arguments* arguments = Arguments::create(*globalData, callFrame);
             callFrame->uncheckedR(argumentsRegister) = JSValue(arguments);
             callFrame->uncheckedR(unmodifiedArgumentsRegister(argumentsRegister)) = JSValue(arguments);
         }
             callFrame->uncheckedR(argumentsRegister) = JSValue(arguments);
             callFrame->uncheckedR(unmodifiedArgumentsRegister(argumentsRegister)) = JSValue(arguments);
         }
@@ -3400,20 +3765,18 @@ skip_id_custom_self:
 
         if (LIKELY(subscript.isUInt32())) {
             uint32_t i = subscript.asUInt32();
 
         if (LIKELY(subscript.isUInt32())) {
             uint32_t i = subscript.asUInt32();
-            if (isJSArray(globalData, baseValue)) {
+            if (isJSArray(baseValue)) {
                 JSArray* jsArray = asArray(baseValue);
                 if (jsArray->canGetIndex(i))
                     result = jsArray->getIndex(i);
                 else
                     result = jsArray->JSArray::get(callFrame, i);
                 JSArray* jsArray = asArray(baseValue);
                 if (jsArray->canGetIndex(i))
                     result = jsArray->getIndex(i);
                 else
                     result = jsArray->JSArray::get(callFrame, i);
-            } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
+            } else if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
                 result = asString(baseValue)->getIndex(callFrame, i);
                 result = asString(baseValue)->getIndex(callFrame, i);
-            else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i))
-                result = asByteArray(baseValue)->getIndex(callFrame, i);
             else
                 result = baseValue.get(callFrame, i);
         } else {
             else
                 result = baseValue.get(callFrame, i);
         } else {
-            Identifier property(callFrame, subscript.toString(callFrame));
+            Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
             result = baseValue.get(callFrame, property);
         }
 
             result = baseValue.get(callFrame, property);
         }
 
@@ -3442,26 +3805,16 @@ skip_id_custom_self:
 
         if (LIKELY(subscript.isUInt32())) {
             uint32_t i = subscript.asUInt32();
 
         if (LIKELY(subscript.isUInt32())) {
             uint32_t i = subscript.asUInt32();
-            if (isJSArray(globalData, baseValue)) {
+            if (isJSArray(baseValue)) {
                 JSArray* jsArray = asArray(baseValue);
                 if (jsArray->canSetIndex(i))
                     jsArray->setIndex(*globalData, i, callFrame->r(value).jsValue());
                 else
                 JSArray* jsArray = asArray(baseValue);
                 if (jsArray->canSetIndex(i))
                     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)) {
-                JSByteArray* jsByteArray = asByteArray(baseValue);
-                double dValue = 0;
-                JSValue jsValue = callFrame->r(value).jsValue();
-                if (jsValue.isInt32())
-                    jsByteArray->setIndex(i, jsValue.asInt32());
-                else if (jsValue.getNumber(dValue))
-                    jsByteArray->setIndex(i, dValue);
-                else
-                    baseValue.put(callFrame, i, jsValue);
+                    jsArray->JSArray::putByIndex(jsArray, callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode());
             } else
             } else
-                baseValue.put(callFrame, i, callFrame->r(value).jsValue());
+                baseValue.putByIndex(callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode());
         } else {
         } else {
-            Identifier property(callFrame, subscript.toString(callFrame));
+            Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
             if (!globalData->exception) { // Don't put to an object if toString threw an exception.
                 PutPropertySlot slot(codeBlock->isStrictMode());
                 baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot);
             if (!globalData->exception) { // Don't put to an object if toString threw an exception.
                 PutPropertySlot slot(codeBlock->isStrictMode());
                 baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot);
@@ -3490,12 +3843,12 @@ skip_id_custom_self:
         bool result;
         uint32_t i;
         if (subscript.getUInt32(i))
         bool result;
         uint32_t i;
         if (subscript.getUInt32(i))
-            result = baseObj->deleteProperty(callFrame, i);
+            result = baseObj->methodTable()->deletePropertyByIndex(baseObj, callFrame, i);
         else {
             CHECK_FOR_EXCEPTION();
         else {
             CHECK_FOR_EXCEPTION();
-            Identifier property(callFrame, subscript.toString(callFrame));
+            Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            result = baseObj->deleteProperty(callFrame, property);
+            result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, property);
         }
         if (!result && codeBlock->isStrictMode()) {
             exceptionValue = createTypeError(callFrame, "Unable to delete property.");
         }
         if (!result && codeBlock->isStrictMode()) {
             exceptionValue = createTypeError(callFrame, "Unable to delete property.");
@@ -3522,7 +3875,9 @@ skip_id_custom_self:
         unsigned property = vPC[2].u.operand;
         int value = vPC[3].u.operand;
 
         unsigned property = vPC[2].u.operand;
         int value = vPC[3].u.operand;
 
-        callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue());
+        JSValue arrayValue = callFrame->r(base).jsValue();
+        ASSERT(isJSArray(arrayValue));
+        asArray(arrayValue)->putDirectIndex(callFrame, property, callFrame->r(value).jsValue(), false);
 
         vPC += OPCODE_LENGTH(op_put_by_index);
         NEXT_INSTRUCTION();
 
         vPC += OPCODE_LENGTH(op_put_by_index);
         NEXT_INSTRUCTION();
@@ -3558,6 +3913,11 @@ skip_id_custom_self:
         vPC += target;
         NEXT_INSTRUCTION();
     }
         vPC += target;
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_loop_hint) {
+        // This is a no-op unless we intend on doing OSR from the interpreter.
+        vPC += OPCODE_LENGTH(op_loop_hint);
+        NEXT_INSTRUCTION();
+    }
     DEFINE_OPCODE(op_loop_if_true) {
         /* loop_if_true cond(r) target(offset)
          
     DEFINE_OPCODE(op_loop_if_true) {
         /* loop_if_true cond(r) target(offset)
          
@@ -3698,7 +4058,7 @@ skip_id_custom_self:
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
         
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
         
-        bool result = jsLess(callFrame, src1, src2);
+        bool result = jsLess<true>(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
         
         if (result) {
         CHECK_FOR_EXCEPTION();
         
         if (result) {
@@ -3725,7 +4085,7 @@ skip_id_custom_self:
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
         
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
         
-        bool result = jsLessEq(callFrame, src1, src2);
+        bool result = jsLessEq<true>(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
         
         if (result) {
         CHECK_FOR_EXCEPTION();
         
         if (result) {
@@ -3737,27 +4097,58 @@ skip_id_custom_self:
         vPC += OPCODE_LENGTH(op_loop_if_lesseq);
         NEXT_INSTRUCTION();
     }
         vPC += OPCODE_LENGTH(op_loop_if_lesseq);
         NEXT_INSTRUCTION();
     }
-    DEFINE_OPCODE(op_jnless) {
-        /* jnless src1(r) src2(r) target(offset)
+    DEFINE_OPCODE(op_loop_if_greater) {
+        /* loop_if_greater src1(r) src2(r) target(offset)
 
 
-           Checks whether register src1 is less than register src2, as
-           with the ECMAScript '<' operator, and then jumps to offset
+           Checks whether register src1 is greater than register src2, as
+           with the ECMAScript '>' operator, and then jumps to offset
            target from the current instruction, if and only if the 
            target from the current instruction, if and only if the 
-           result of the comparison is false.
-        */
+           result of the comparison is true.
+
+           Additionally this loop instruction may terminate JS execution is
+           the JS timeout is reached.
+         */
         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
-
-        bool result = jsLess(callFrame, src1, src2);
+        
+        bool result = jsLess<false>(callFrame, src2, src1);
         CHECK_FOR_EXCEPTION();
         
         CHECK_FOR_EXCEPTION();
         
-        if (!result) {
+        if (result) {
             vPC += target;
             vPC += target;
+            CHECK_FOR_TIMEOUT();
             NEXT_INSTRUCTION();
         }
             NEXT_INSTRUCTION();
         }
+        
+        vPC += OPCODE_LENGTH(op_loop_if_greater);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_loop_if_greatereq) {
+        /* loop_if_greatereq src1(r) src2(r) target(offset)
 
 
-        vPC += OPCODE_LENGTH(op_jnless);
+           Checks whether register src1 is greater than or equal to register
+           src2, as with the ECMAScript '>=' operator, and then jumps to
+           offset target from the current instruction, if and only if the 
+           result of the comparison is true.
+
+           Additionally this loop instruction may terminate JS execution is
+           the JS timeout is reached.
+        */
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
+        
+        bool result = jsLessEq<false>(callFrame, src2, src1);
+        CHECK_FOR_EXCEPTION();
+        
+        if (result) {
+            vPC += target;
+            CHECK_FOR_TIMEOUT();
+            NEXT_INSTRUCTION();
+        }
+        
+        vPC += OPCODE_LENGTH(op_loop_if_greatereq);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jless) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_jless) {
@@ -3772,7 +4163,7 @@ skip_id_custom_self:
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
 
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
 
-        bool result = jsLess(callFrame, src1, src2);
+        bool result = jsLess<true>(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
         
         if (result) {
         CHECK_FOR_EXCEPTION();
         
         if (result) {
@@ -3783,6 +4174,98 @@ skip_id_custom_self:
         vPC += OPCODE_LENGTH(op_jless);
         NEXT_INSTRUCTION();
     }
         vPC += OPCODE_LENGTH(op_jless);
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_jlesseq) {
+        /* jlesseq src1(r) src2(r) target(offset)
+         
+         Checks whether register src1 is less than or equal to
+         register src2, as with the ECMAScript '<=' operator,
+         and then jumps to offset target from the current instruction,
+         if and only if the result of the comparison is true.
+         */
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
+        
+        bool result = jsLessEq<true>(callFrame, src1, src2);
+        CHECK_FOR_EXCEPTION();
+        
+        if (result) {
+            vPC += target;
+            NEXT_INSTRUCTION();
+        }
+        
+        vPC += OPCODE_LENGTH(op_jlesseq);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_jgreater) {
+        /* jgreater src1(r) src2(r) target(offset)
+
+           Checks whether register src1 is greater than register src2, as
+           with the ECMAScript '>' operator, and then jumps to offset
+           target from the current instruction, if and only if the 
+           result of the comparison is true.
+        */
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
+
+        bool result = jsLess<false>(callFrame, src2, src1);
+        CHECK_FOR_EXCEPTION();
+        
+        if (result) {
+            vPC += target;
+            NEXT_INSTRUCTION();
+        }
+
+        vPC += OPCODE_LENGTH(op_jgreater);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_jgreatereq) {
+        /* jgreatereq src1(r) src2(r) target(offset)
+         
+         Checks whether register src1 is greater than or equal to
+         register src2, as with the ECMAScript '>=' operator,
+         and then jumps to offset target from the current instruction,
+         if and only if the result of the comparison is true.
+         */
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
+        
+        bool result = jsLessEq<false>(callFrame, src2, src1);
+        CHECK_FOR_EXCEPTION();
+        
+        if (result) {
+            vPC += target;
+            NEXT_INSTRUCTION();
+        }
+        
+        vPC += OPCODE_LENGTH(op_jgreatereq);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_jnless) {
+        /* jnless src1(r) src2(r) target(offset)
+
+           Checks whether register src1 is less than register src2, as
+           with the ECMAScript '<' operator, and then jumps to offset
+           target from the current instruction, if and only if the 
+           result of the comparison is false.
+        */
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
+
+        bool result = jsLess<true>(callFrame, src1, src2);
+        CHECK_FOR_EXCEPTION();
+        
+        if (!result) {
+            vPC += target;
+            NEXT_INSTRUCTION();
+        }
+
+        vPC += OPCODE_LENGTH(op_jnless);
+        NEXT_INSTRUCTION();
+    }
     DEFINE_OPCODE(op_jnlesseq) {
         /* jnlesseq src1(r) src2(r) target(offset)
 
     DEFINE_OPCODE(op_jnlesseq) {
         /* jnlesseq src1(r) src2(r) target(offset)
 
@@ -3795,7 +4278,7 @@ skip_id_custom_self:
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
 
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
 
-        bool result = jsLessEq(callFrame, src1, src2);
+        bool result = jsLessEq<true>(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
         
         if (!result) {
         CHECK_FOR_EXCEPTION();
         
         if (!result) {
@@ -3806,27 +4289,50 @@ skip_id_custom_self:
         vPC += OPCODE_LENGTH(op_jnlesseq);
         NEXT_INSTRUCTION();
     }
         vPC += OPCODE_LENGTH(op_jnlesseq);
         NEXT_INSTRUCTION();
     }
-    DEFINE_OPCODE(op_jlesseq) {
-        /* jlesseq src1(r) src2(r) target(offset)
-         
-         Checks whether register src1 is less than or equal to
-         register src2, as with the ECMAScript '<=' operator,
-         and then jumps to offset target from the current instruction,
-         if and only if the result of the comparison is true.
-         */
+    DEFINE_OPCODE(op_jngreater) {
+        /* jngreater src1(r) src2(r) target(offset)
+
+           Checks whether register src1 is greater than register src2, as
+           with the ECMAScript '>' operator, and then jumps to offset
+           target from the current instruction, if and only if the 
+           result of the comparison is false.
+        */
         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
         JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
         int target = vPC[3].u.operand;
-        
-        bool result = jsLessEq(callFrame, src1, src2);
+
+        bool result = jsLess<false>(callFrame, src2, src1);
         CHECK_FOR_EXCEPTION();
         
         CHECK_FOR_EXCEPTION();
         
-        if (result) {
+        if (!result) {
             vPC += target;
             NEXT_INSTRUCTION();
         }
             vPC += target;
             NEXT_INSTRUCTION();
         }
+
+        vPC += OPCODE_LENGTH(op_jngreater);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_jngreatereq) {
+        /* jngreatereq src1(r) src2(r) target(offset)
+
+           Checks whether register src1 is greater than or equal to
+           register src2, as with the ECMAScript '>=' operator,
+           and then jumps to offset target from the current instruction,
+           if and only if theresult of the comparison is false.
+        */
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
+
+        bool result = jsLessEq<false>(callFrame, src2, src1);
+        CHECK_FOR_EXCEPTION();
         
         
-        vPC += OPCODE_LENGTH(op_jlesseq);
+        if (!result) {
+            vPC += target;
+            NEXT_INSTRUCTION();
+        }
+
+        vPC += OPCODE_LENGTH(op_jngreatereq);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_switch_imm) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_switch_imm) {
@@ -3843,14 +4349,10 @@ skip_id_custom_self:
         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
         if (scrutinee.isInt32())
             vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset);
         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
         if (scrutinee.isInt32())
             vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset);
-        else {
-            double value;
-            int32_t intValue;
-            if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
-                vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(intValue, defaultOffset);
-            else
-                vPC += defaultOffset;
-        }
+        else if (scrutinee.isDouble() && scrutinee.asDouble() == static_cast<int32_t>(scrutinee.asDouble()))
+            vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(static_cast<int32_t>(scrutinee.asDouble()), defaultOffset);
+        else
+            vPC += defaultOffset;
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_switch_char) {
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_switch_char) {
@@ -3872,7 +4374,7 @@ skip_id_custom_self:
             if (value->length() != 1)
                 vPC += defaultOffset;
             else
             if (value->length() != 1)
                 vPC += defaultOffset;
             else
-                vPC += codeBlock->characterSwitchJumpTable(tableIndex).offsetForValue(value->characters()[0], defaultOffset);
+                vPC += codeBlock->characterSwitchJumpTable(tableIndex).offsetForValue((*value)[0], defaultOffset);
         }
         NEXT_INSTRUCTION();
     }
         }
         NEXT_INSTRUCTION();
     }
@@ -3935,7 +4437,7 @@ skip_id_custom_self:
             does not affect the scope enclosing the FunctionExpression.
          */
         if (!function->name().isNull()) {
             does not affect the scope enclosing the FunctionExpression.
          */
         if (!function->name().isNull()) {
-            JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
+            JSStaticScopeObject* functionScopeObject = JSStaticScopeObject::create(callFrame, function->name(), func, ReadOnly | DontDelete);
             func->setScope(*globalData, func->scope()->push(functionScopeObject));
         }
 
             func->setScope(*globalData, func->scope()->push(functionScopeObject));
         }
 
@@ -3963,13 +4465,11 @@ skip_id_custom_self:
         ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
         JSValue funcVal = callFrame->r(func).jsValue();
 
         ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
         JSValue funcVal = callFrame->r(func).jsValue();
 
-        Register* newCallFrame = callFrame->registers() + registerOffset;
-        Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
-        JSValue thisValue = argv[0].jsValue();
-        JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject.get();
+        if (isHostFunction(funcVal, globalFuncEval)) {
+            CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
+            newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_eval), callFrame->scopeChain(), callFrame, argCount, jsCast<JSFunction*>(funcVal));
 
 
-        if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
-            JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset);
+            JSValue result = eval(newCallFrame);
             if ((exceptionValue = globalData->exception))
                 goto vm_throw;
             functionReturnValue = result;
             if ((exceptionValue = globalData->exception))
                 goto vm_throw;
             functionReturnValue = result;
@@ -4020,9 +4520,10 @@ skip_id_custom_self:
                 goto vm_throw;
             }
 
                 goto vm_throw;
             }
 
-            callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
+            callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call), callDataScopeChain, previousCallFrame, argCount, jsCast<JSFunction*>(v));
             codeBlock = newCodeBlock;
             ASSERT(codeBlock == callFrame->codeBlock());
             codeBlock = newCodeBlock;
             ASSERT(codeBlock == callFrame->codeBlock());
+            *topCallFrameSlot = callFrame;
             vPC = newCodeBlock->instructions().begin();
 
 #if ENABLE(OPCODE_STATS)
             vPC = newCodeBlock->instructions().begin();
 
 #if ENABLE(OPCODE_STATS)
@@ -4035,17 +4536,13 @@ 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);
-            if (!registerFile->grow(newCallFrame->registers())) {
-                exceptionValue = createStackOverflowError(callFrame);
-                goto vm_throw;
-            }
-
             newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call), scopeChain, callFrame, argCount, asObject(v));
             newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call), scopeChain, callFrame, argCount, asObject(v));
-
             JSValue returnValue;
             {
             JSValue returnValue;
             {
+                *topCallFrameSlot = newCallFrame;
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = JSValue::decode(callData.native.function(newCallFrame));
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = JSValue::decode(callData.native.function(newCallFrame));
+                *topCallFrameSlot = callFrame;
             }
             CHECK_FOR_EXCEPTION();
 
             }
             CHECK_FOR_EXCEPTION();
 
@@ -4060,87 +4557,8 @@ skip_id_custom_self:
         exceptionValue = createNotAFunctionError(callFrame, v);
         goto vm_throw;
     }
         exceptionValue = createNotAFunctionError(callFrame, v);
         goto vm_throw;
     }
-    DEFINE_OPCODE(op_load_varargs) {
-        int argCountDst = vPC[1].u.operand;
-        int argsOffset = vPC[2].u.operand;
-        
-        JSValue arguments = callFrame->r(argsOffset).jsValue();
-        uint32_t argCount = 0;
-        if (!arguments) {
-            argCount = (uint32_t)(callFrame->argumentCount());
-            argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
-            int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
-            Register* newEnd = callFrame->registers() + sizeDelta;
-            if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
-                exceptionValue = createStackOverflowError(callFrame);
-                goto vm_throw;
-            }
-            ASSERT(!asFunction(callFrame->callee())->isHostFunction());
-            int32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
-            int32_t inplaceArgs = min(static_cast<int32_t>(argCount), expectedParams);
-            int32_t i = 0;
-            Register* argStore = callFrame->registers() + argsOffset;
-
-            // First step is to copy the "expected" parameters from their normal location relative to the callframe
-            for (; i < inplaceArgs; i++)
-                argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams];
-            // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
-            for (; i < static_cast<int32_t>(argCount); i++)
-                argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - static_cast<int32_t>(argCount) - 1];
-        } else if (!arguments.isUndefinedOrNull()) {
-            if (!arguments.isObject()) {
-                exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
-                goto vm_throw;
-            }
-            if (asObject(arguments)->classInfo() == &Arguments::s_info) {
-                Arguments* args = asArguments(arguments);
-                argCount = args->numProvidedArguments(callFrame);
-                argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
-                int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
-                Register* newEnd = callFrame->registers() + sizeDelta;
-                if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
-                    exceptionValue = createStackOverflowError(callFrame);
-                    goto vm_throw;
-                }
-                args->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
-            } else if (isJSArray(&callFrame->globalData(), arguments)) {
-                JSArray* array = asArray(arguments);
-                argCount = array->length();
-                argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
-                int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
-                Register* newEnd = callFrame->registers() + sizeDelta;
-                if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
-                    exceptionValue = createStackOverflowError(callFrame);
-                    goto vm_throw;
-                }
-                array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
-            } 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);
-                int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
-                Register* newEnd = callFrame->registers() + sizeDelta;
-                if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
-                    exceptionValue = createStackOverflowError(callFrame);
-                    goto vm_throw;
-                }
-                Register* argsBuffer = callFrame->registers() + argsOffset;
-                for (uint32_t i = 0; i < argCount; ++i) {
-                    argsBuffer[i] = asObject(arguments)->get(callFrame, i);
-                    CHECK_FOR_EXCEPTION();
-                }
-            } else {
-                exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
-                goto vm_throw;
-            }
-        }
-        CHECK_FOR_EXCEPTION();
-        callFrame->uncheckedR(argCountDst) = Register::withInt(argCount + 1);
-        vPC += OPCODE_LENGTH(op_load_varargs);
-        NEXT_INSTRUCTION();
-    }
     DEFINE_OPCODE(op_call_varargs) {
     DEFINE_OPCODE(op_call_varargs) {
-        /* call_varargs func(r) argCountReg(r) baseRegisterOffset(n)
+        /* call_varargs callee(r) thisValue(r) arguments(r) firstFreeRegister(n)
          
          Perform a function call with a dynamic set of arguments.
          
          
          Perform a function call with a dynamic set of arguments.
          
@@ -4151,13 +4569,16 @@ skip_id_custom_self:
          dst is where op_ret should store its result.
          */
         
          dst is where op_ret should store its result.
          */
         
-        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;
+        JSValue v = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue thisValue = callFrame->r(vPC[2].u.operand).jsValue();
+        JSValue arguments = callFrame->r(vPC[3].u.operand).jsValue();
+        int firstFreeRegister = vPC[4].u.operand;
+
+        CallFrame* newCallFrame = loadVarargs(callFrame, registerFile, thisValue, arguments, firstFreeRegister);
+        if ((exceptionValue = globalData->exception))
+            goto vm_throw;
+        int argCount = newCallFrame->argumentCountIncludingThis();
+
         CallData callData;
         CallType callType = getCallData(v, callData);
         
         CallData callData;
         CallType callType = getCallData(v, callData);
         
@@ -4170,20 +4591,20 @@ skip_id_custom_self:
                 goto vm_throw;
             }
 
                 goto vm_throw;
             }
 
-            CallFrame* previousCallFrame = callFrame;
             CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
             CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
-            callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
-            if (UNLIKELY(!callFrame)) {
-                callFrame = previousCallFrame;
+            newCallFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, newCallFrame, 0, argCount);
+            if (UNLIKELY(!newCallFrame)) {
                 exceptionValue = createStackOverflowError(callFrame);
                 goto vm_throw;
             }
 
                 exceptionValue = createStackOverflowError(callFrame);
                 goto vm_throw;
             }
 
-            callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
+            newCallFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, callFrame, argCount, jsCast<JSFunction*>(v));
             codeBlock = newCodeBlock;
             codeBlock = newCodeBlock;
+            callFrame = newCallFrame;
             ASSERT(codeBlock == callFrame->codeBlock());
             ASSERT(codeBlock == callFrame->codeBlock());
+            *topCallFrameSlot = callFrame;
             vPC = newCodeBlock->instructions().begin();
             vPC = newCodeBlock->instructions().begin();
-            
+
 #if ENABLE(OPCODE_STATS)
             OpcodeStats::resetLastInstruction();
 #endif
 #if ENABLE(OPCODE_STATS)
             OpcodeStats::resetLastInstruction();
 #endif
@@ -4193,17 +4614,14 @@ skip_id_custom_self:
         
         if (callType == CallTypeHost) {
             ScopeChainNode* scopeChain = callFrame->scopeChain();
         
         if (callType == CallTypeHost) {
             ScopeChainNode* scopeChain = callFrame->scopeChain();
-            CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
-            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;
             {
             newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_varargs), scopeChain, callFrame, argCount, asObject(v));
             
             JSValue returnValue;
             {
+                *topCallFrameSlot = newCallFrame;
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = JSValue::decode(callData.native.function(newCallFrame));
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = JSValue::decode(callData.native.function(newCallFrame));
+                *topCallFrameSlot = callFrame;
             }
             CHECK_FOR_EXCEPTION();
             
             }
             CHECK_FOR_EXCEPTION();
             
@@ -4234,15 +4652,13 @@ skip_id_custom_self:
         ASSERT(codeBlock->needsFullScopeChain());
         JSValue activationValue = callFrame->r(activation).jsValue();
         if (activationValue) {
         ASSERT(codeBlock->needsFullScopeChain());
         JSValue activationValue = callFrame->r(activation).jsValue();
         if (activationValue) {
-            asActivation(activationValue)->copyRegisters(*globalData);
+            asActivation(activationValue)->tearOff(*globalData);
 
 
-            if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
-                if (!codeBlock->isStrictMode())
-                    asArguments(argumentsValue)->setActivation(*globalData, asActivation(activationValue));
-            }
+            if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue())
+                asArguments(argumentsValue)->didTearOffActivation(*globalData, asActivation(activationValue));
         } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
             if (!codeBlock->isStrictMode())
         } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
             if (!codeBlock->isStrictMode())
-                asArguments(argumentsValue)->copyRegisters(*globalData);
+                asArguments(argumentsValue)->tearOff(callFrame);
         }
 
         vPC += OPCODE_LENGTH(op_tear_off_activation);
         }
 
         vPC += OPCODE_LENGTH(op_tear_off_activation);
@@ -4264,7 +4680,7 @@ skip_id_custom_self:
         ASSERT(!codeBlock->needsFullScopeChain() && codeBlock->ownerExecutable()->usesArguments());
 
         if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src1)).jsValue())
         ASSERT(!codeBlock->needsFullScopeChain() && codeBlock->ownerExecutable()->usesArguments());
 
         if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src1)).jsValue())
-            asArguments(arguments)->copyRegisters(*globalData);
+            asArguments(arguments)->tearOff(callFrame);
 
         vPC += OPCODE_LENGTH(op_tear_off_arguments);
         NEXT_INSTRUCTION();
 
         vPC += OPCODE_LENGTH(op_tear_off_arguments);
         NEXT_INSTRUCTION();
@@ -4285,10 +4701,11 @@ skip_id_custom_self:
 
         vPC = callFrame->returnVPC();
         callFrame = callFrame->callerFrame();
 
         vPC = callFrame->returnVPC();
         callFrame = callFrame->callerFrame();
-        
+
         if (callFrame->hasHostCallFrameFlag())
             return returnValue;
 
         if (callFrame->hasHostCallFrameFlag())
             return returnValue;
 
+        *topCallFrameSlot = callFrame;
         functionReturnValue = returnValue;
         codeBlock = callFrame->codeBlock();
         ASSERT(codeBlock == callFrame->codeBlock());
         functionReturnValue = returnValue;
         codeBlock = callFrame->codeBlock();
         ASSERT(codeBlock == callFrame->codeBlock());
@@ -4330,6 +4747,7 @@ skip_id_custom_self:
         if (callFrame->hasHostCallFrameFlag())
             return returnValue;
 
         if (callFrame->hasHostCallFrameFlag())
             return returnValue;
 
+        *topCallFrameSlot = callFrame;
         functionReturnValue = returnValue;
         codeBlock = callFrame->codeBlock();
         ASSERT(codeBlock == callFrame->codeBlock());
         functionReturnValue = returnValue;
         codeBlock = callFrame->codeBlock();
         ASSERT(codeBlock == callFrame->codeBlock());
@@ -4361,7 +4779,7 @@ skip_id_custom_self:
 
         int activationReg = vPC[1].u.operand;
         if (!callFrame->r(activationReg).jsValue()) {
 
         int activationReg = vPC[1].u.operand;
         if (!callFrame->r(activationReg).jsValue()) {
-            JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
+            JSActivation* activation = JSActivation::create(*globalData, callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
             callFrame->r(activationReg) = JSValue(activation);
             callFrame->setScopeChain(callFrame->scopeChain()->push(activation));
         }
             callFrame->r(activationReg) = JSValue(activation);
             callFrame->setScopeChain(callFrame->scopeChain()->push(activation));
         }
@@ -4391,10 +4809,10 @@ skip_id_custom_self:
         int thisRegister = vPC[1].u.operand;
         int protoRegister = vPC[2].u.operand;
 
         int thisRegister = vPC[1].u.operand;
         int protoRegister = vPC[2].u.operand;
 
-        JSFunction* constructor = asFunction(callFrame->callee());
+        JSFunction* constructor = jsCast<JSFunction*>(callFrame->callee());
 #if !ASSERT_DISABLED
         ConstructData constructData;
 #if !ASSERT_DISABLED
         ConstructData constructData;
-        ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
+        ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
 #endif
 
         Structure* structure;
 #endif
 
         Structure* structure;
@@ -4422,31 +4840,12 @@ skip_id_custom_self:
 
         int thisRegister = vPC[1].u.operand;
         JSValue thisVal = callFrame->r(thisRegister).jsValue();
 
         int thisRegister = vPC[1].u.operand;
         JSValue thisVal = callFrame->r(thisRegister).jsValue();
-        if (thisVal.needsThisConversion())
+        if (thisVal.isPrimitive())
             callFrame->uncheckedR(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
 
         vPC += OPCODE_LENGTH(op_convert_this);
         NEXT_INSTRUCTION();
     }
             callFrame->uncheckedR(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
 
         vPC += OPCODE_LENGTH(op_convert_this);
         NEXT_INSTRUCTION();
     }
-    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)
 
     DEFINE_OPCODE(op_init_lazy_reg) {
         /* init_lazy_reg dst(r)
 
@@ -4471,7 +4870,7 @@ skip_id_custom_self:
         int dst = vPC[1].u.operand;
 
         if (!callFrame->r(dst).jsValue()) {
         int dst = vPC[1].u.operand;
 
         if (!callFrame->r(dst).jsValue()) {
-            Arguments* arguments = new (globalData) Arguments(callFrame);
+            Arguments* arguments = Arguments::create(*globalData, callFrame);
             callFrame->uncheckedR(dst) = JSValue(arguments);
             callFrame->uncheckedR(unmodifiedArgumentsRegister(dst)) = JSValue(arguments);
         }
             callFrame->uncheckedR(dst) = JSValue(arguments);
             callFrame->uncheckedR(unmodifiedArgumentsRegister(dst)) = JSValue(arguments);
         }
@@ -4520,8 +4919,9 @@ skip_id_custom_self:
                 goto vm_throw;
             }
 
                 goto vm_throw;
             }
 
-            callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
+            callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, jsCast<JSFunction*>(v));
             codeBlock = newCodeBlock;
             codeBlock = newCodeBlock;
+            *topCallFrameSlot = callFrame;
             vPC = newCodeBlock->instructions().begin();
 #if ENABLE(OPCODE_STATS)
             OpcodeStats::resetLastInstruction();
             vPC = newCodeBlock->instructions().begin();
 #if ENABLE(OPCODE_STATS)
             OpcodeStats::resetLastInstruction();
@@ -4533,16 +4933,14 @@ skip_id_custom_self:
         if (constructType == ConstructTypeHost) {
             ScopeChainNode* scopeChain = callFrame->scopeChain();
             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
         if (constructType == ConstructTypeHost) {
             ScopeChainNode* scopeChain = callFrame->scopeChain();
             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
-            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;
             {
             newCallFrame->init(0, vPC + OPCODE_LENGTH(op_construct), scopeChain, callFrame, argCount, asObject(v));
 
             JSValue returnValue;
             {
+                *topCallFrameSlot = newCallFrame;
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = JSValue::decode(constructData.native.function(newCallFrame));
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
                 returnValue = JSValue::decode(constructData.native.function(newCallFrame));
+                *topCallFrameSlot = callFrame;
             }
             CHECK_FOR_EXCEPTION();
             functionReturnValue = returnValue;
             }
             CHECK_FOR_EXCEPTION();
             functionReturnValue = returnValue;
@@ -4693,7 +5091,7 @@ skip_id_custom_self:
         vPC += target;
         NEXT_INSTRUCTION();
     }
         vPC += target;
         NEXT_INSTRUCTION();
     }
-#if ENABLE(COMPUTED_GOTO_INTERPRETER)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
     // Appease GCC
     goto *(&&skip_new_scope);
 #endif
     // Appease GCC
     goto *(&&skip_new_scope);
 #endif
@@ -4709,7 +5107,7 @@ skip_id_custom_self:
         vPC += OPCODE_LENGTH(op_push_new_scope);
         NEXT_INSTRUCTION();
     }
         vPC += OPCODE_LENGTH(op_push_new_scope);
         NEXT_INSTRUCTION();
     }
-#if ENABLE(COMPUTED_GOTO_INTERPRETER)
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
     skip_new_scope:
 #endif
     DEFINE_OPCODE(op_catch) {
     skip_new_scope:
 #endif
     DEFINE_OPCODE(op_catch) {
@@ -4757,7 +5155,7 @@ skip_id_custom_self:
            original constructor, using constant message as the
            message string. The result is thrown.
         */
            original constructor, using constant message as the
            message string. The result is thrown.
         */
-        UString message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame);
+        UString message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame)->value(callFrame);
         exceptionValue = JSValue(createReferenceError(callFrame, message));
         goto vm_throw;
     }
         exceptionValue = JSValue(createReferenceError(callFrame, message));
         goto vm_throw;
     }
@@ -4771,82 +5169,47 @@ skip_id_custom_self:
         int result = vPC[1].u.operand;
         return callFrame->r(result).jsValue();
     }
         int result = vPC[1].u.operand;
         return callFrame->r(result).jsValue();
     }
-    DEFINE_OPCODE(op_put_getter) {
-        /* put_getter base(r) property(id) function(r)
+    DEFINE_OPCODE(op_put_getter_setter) {
+        /* put_getter_setter base(r) property(id) getter(r) setter(r)
 
 
-           Sets register function on register base as the getter named
-           by identifier property. Base and function are assumed to be
-           objects as this op should only be used for getters defined
-           in object literal form.
+           Puts accessor descriptor to register base as the named
+           identifier property. Base and function may be objects
+           or undefined, this op should only be used for accessors
+           defined in object literal form.
 
            Unlike many opcodes, this one does not write any output to
            the register file.
         */
         int base = vPC[1].u.operand;
         int property = vPC[2].u.operand;
 
            Unlike many opcodes, this one does not write any output to
            the register file.
         */
         int base = vPC[1].u.operand;
         int property = vPC[2].u.operand;
-        int function = vPC[3].u.operand;
+        int getterReg = vPC[3].u.operand;
+        int setterReg = vPC[4].u.operand;
 
         ASSERT(callFrame->r(base).jsValue().isObject());
         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
         Identifier& ident = codeBlock->identifier(property);
 
         ASSERT(callFrame->r(base).jsValue().isObject());
         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
         Identifier& ident = codeBlock->identifier(property);
-        ASSERT(callFrame->r(function).jsValue().isObject());
-        baseObj->defineGetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
 
 
-        vPC += OPCODE_LENGTH(op_put_getter);
-        NEXT_INSTRUCTION();
-    }
-    DEFINE_OPCODE(op_put_setter) {
-        /* put_setter base(r) property(id) function(r)
+        GetterSetter* accessor = GetterSetter::create(callFrame);
 
 
-           Sets register function on register base as the setter named
-           by identifier property. Base and function are assumed to be
-           objects as this op should only be used for setters defined
-           in object literal form.
+        JSValue getter = callFrame->r(getterReg).jsValue();
+        JSValue setter = callFrame->r(setterReg).jsValue();
+        ASSERT(getter.isObject() || getter.isUndefined());
+        ASSERT(setter.isObject() || setter.isUndefined());
+        ASSERT(getter.isObject() || setter.isObject());
 
 
-           Unlike many opcodes, this one does not write any output to
-           the register file.
-        */
-        int base = vPC[1].u.operand;
-        int property = vPC[2].u.operand;
-        int function = vPC[3].u.operand;
-
-        ASSERT(callFrame->r(base).jsValue().isObject());
-        JSObject* baseObj = asObject(callFrame->r(base).jsValue());
-        Identifier& ident = codeBlock->identifier(property);
-        ASSERT(callFrame->r(function).jsValue().isObject());
-        baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()), 0);
+        if (!getter.isUndefined())
+            accessor->setGetter(callFrame->globalData(), asObject(getter));
+        if (!setter.isUndefined())
+            accessor->setSetter(callFrame->globalData(), asObject(setter));
+        baseObj->putDirectAccessor(callFrame->globalData(), ident, accessor, Accessor);
 
 
-        vPC += OPCODE_LENGTH(op_put_setter);
+        vPC += OPCODE_LENGTH(op_put_getter_setter);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_method_check) {
         vPC++;
         NEXT_INSTRUCTION();
     }
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_method_check) {
         vPC++;
         NEXT_INSTRUCTION();
     }
-    DEFINE_OPCODE(op_jsr) {
-        /* jsr retAddrDst(r) target(offset)
-
-           Places the address of the next instruction into the retAddrDst
-           register and jumps to offset target from the current instruction.
-        */
-        int retAddrDst = vPC[1].u.operand;
-        int target = vPC[2].u.operand;
-        callFrame->r(retAddrDst) = vPC + OPCODE_LENGTH(op_jsr);
-
-        vPC += target;
-        NEXT_INSTRUCTION();
-    }
-    DEFINE_OPCODE(op_sret) {
-        /* sret retAddrSrc(r)
-
-         Jumps to the address stored in the retAddrSrc register. This
-         differs from op_jmp because the target address is stored in a
-         register, not as an immediate.
-        */
-        int retAddrSrc = vPC[1].u.operand;
-        vPC = callFrame->r(retAddrSrc).vPC();
-        NEXT_INSTRUCTION();
-    }
     DEFINE_OPCODE(op_debug) {
         /* debug debugHookID(n) firstLine(n) lastLine(n)
 
     DEFINE_OPCODE(op_debug) {
         /* debug debugHookID(n) firstLine(n) lastLine(n)
 
@@ -4910,19 +5273,19 @@ skip_id_custom_self:
         NEXT_INSTRUCTION();
     }
     }
         NEXT_INSTRUCTION();
     }
     }
-#if !ENABLE(COMPUTED_GOTO_INTERPRETER)
+#if !ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
     } // iterator loop ends
 #endif
     #undef NEXT_INSTRUCTION
     #undef DEFINE_OPCODE
     #undef CHECK_FOR_EXCEPTION
     #undef CHECK_FOR_TIMEOUT
     } // iterator loop ends
 #endif
     #undef NEXT_INSTRUCTION
     #undef DEFINE_OPCODE
     #undef CHECK_FOR_EXCEPTION
     #undef CHECK_FOR_TIMEOUT
-#endif // ENABLE(INTERPRETER)
+#endif // ENABLE(CLASSIC_INTERPRETER)
 }
 
 }
 
-JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
+JSValue Interpreter::retrieveArgumentsFromVMCode(CallFrame* callFrame, JSFunction* function) const
 {
 {
-    CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
+    CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
     if (!functionCallFrame)
         return jsNull();
 
     if (!functionCallFrame)
         return jsNull();
 
@@ -4933,31 +5296,43 @@ JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* functio
         int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
         if (JSValue arguments = functionCallFrame->uncheckedR(argumentsRegister).jsValue())
             return arguments;
         int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
         if (JSValue arguments = functionCallFrame->uncheckedR(argumentsRegister).jsValue())
             return arguments;
-        JSValue arguments = JSValue(new (callFrame) Arguments(functionCallFrame));
+        JSValue arguments = JSValue(Arguments::create(callFrame->globalData(), functionCallFrame));
         functionCallFrame->r(argumentsRegister) = arguments;
         functionCallFrame->r(realArgumentsRegister) = arguments;
         return arguments;
     }
 
         functionCallFrame->r(argumentsRegister) = arguments;
         functionCallFrame->r(realArgumentsRegister) = arguments;
         return arguments;
     }
 
-    Arguments* arguments = new (functionCallFrame) Arguments(functionCallFrame);
-    arguments->copyRegisters(functionCallFrame->globalData());
-    return arguments;
+    Arguments* arguments = Arguments::create(functionCallFrame->globalData(), functionCallFrame);
+    arguments->tearOff(functionCallFrame);
+    return JSValue(arguments);
 }
 
 }
 
-JSValue Interpreter::retrieveCaller(CallFrame* callFrame, JSFunction* function) const
+JSValue Interpreter::retrieveCallerFromVMCode(CallFrame* callFrame, JSFunction* function) const
 {
 {
-    CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
+    CallFrame* functionCallFrame = findFunctionCallFrameFromVMCode(callFrame, function);
+
     if (!functionCallFrame)
         return jsNull();
     if (!functionCallFrame)
         return jsNull();
-
-    CallFrame* callerFrame = functionCallFrame->callerFrame();
-    if (callerFrame->hasHostCallFrameFlag())
+    
+    int lineNumber;
+    CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber);
+    if (!callerFrame)
         return jsNull();
         return jsNull();
-
     JSValue caller = callerFrame->callee();
     if (!caller)
         return jsNull();
 
     JSValue caller = callerFrame->callee();
     if (!caller)
         return jsNull();
 
+    // Skip over function bindings.
+    ASSERT(caller.isObject());
+    while (asObject(caller)->inherits(&JSBoundFunction::s_info)) {
+        callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber);
+        if (!callerFrame)
+            return jsNull();
+        caller = callerFrame->callee();
+        if (!caller)
+            return jsNull();
+    }
+
     return caller;
 }
 
     return caller;
 }
 
@@ -4975,15 +5350,15 @@ void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intp
     if (!callerCodeBlock)
         return;
     unsigned bytecodeOffset = 0;
     if (!callerCodeBlock)
         return;
     unsigned bytecodeOffset = 0;
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
     if (!callerFrame->globalData().canUseJIT())
         bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
 #if ENABLE(JIT)
     else
     if (!callerFrame->globalData().canUseJIT())
         bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
 #if ENABLE(JIT)
     else
-        bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
+        bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
 #endif
 #else
 #endif
 #else
-    bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
+    bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
 #endif
     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
     sourceID = callerCodeBlock->ownerExecutable()->sourceID();
 #endif
     lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
     sourceID = callerCodeBlock->ownerExecutable()->sourceID();
@@ -4991,9 +5366,9 @@ void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intp
     function = callerFrame->callee();
 }
 
     function = callerFrame->callee();
 }
 
-CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, JSFunction* function)
+CallFrame* Interpreter::findFunctionCallFrameFromVMCode(CallFrame* callFrame, JSFunction* function)
 {
 {
-    for (CallFrame* candidate = callFrame; candidate; candidate = candidate->callerFrame()->removeHostCallFrameFlag()) {
+    for (CallFrame* candidate = callFrame->trueCallFrameFromVMCode(); candidate; candidate = candidate->trueCallerFrame()) {
         if (candidate->callee() == function)
             return candidate;
     }
         if (candidate->callee() == function)
             return candidate;
     }
@@ -5004,7 +5379,7 @@ void Interpreter::enableSampler()
 {
 #if ENABLE(OPCODE_SAMPLING)
     if (!m_sampler) {
 {
 #if ENABLE(OPCODE_SAMPLING)
     if (!m_sampler) {
-        m_sampler.set(new SamplingTool(this));
+        m_sampler = adoptPtr(new SamplingTool(this));
         m_sampler->setup();
     }
 #endif
         m_sampler->setup();
     }
 #endif
index 9a4352e7a9d764c1c9aea9910d34729f97d6d8a8..7e34bba0362ba1bc877b7ac6ac9217267234c484 100644 (file)
 
 #include "ArgList.h"
 #include "JSCell.h"
 
 #include "ArgList.h"
 #include "JSCell.h"
+#include "JSFunction.h"
 #include "JSValue.h"
 #include "JSObject.h"
 #include "JSValue.h"
 #include "JSObject.h"
+#include "LLIntData.h"
 #include "Opcode.h"
 #include "RegisterFile.h"
 
 #include "Opcode.h"
 #include "RegisterFile.h"
 
@@ -42,9 +44,10 @@ namespace JSC {
 
     class CodeBlock;
     class EvalExecutable;
 
     class CodeBlock;
     class EvalExecutable;
+    class ExecutableBase;
     class FunctionExecutable;
     class FunctionExecutable;
-    class JSFunction;
     class JSGlobalObject;
     class JSGlobalObject;
+    class LLIntOffsetsExtractor;
     class ProgramExecutable;
     class Register;
     class ScopeChainNode;
     class ProgramExecutable;
     class Register;
     class ScopeChainNode;
@@ -62,36 +65,138 @@ namespace JSC {
         WillExecuteStatement
     };
 
         WillExecuteStatement
     };
 
+    enum StackFrameCodeType {
+        StackFrameGlobalCode,
+        StackFrameEvalCode,
+        StackFrameFunctionCode,
+        StackFrameNativeCode
+    };
+
+    struct StackFrame {
+        Strong<JSObject> callee;
+        StackFrameCodeType codeType;
+        Strong<ExecutableBase> executable;
+        int line;
+        UString sourceURL;
+        UString toString(CallFrame* callFrame) const
+        {
+            bool hasSourceURLInfo = !sourceURL.isNull() && !sourceURL.isEmpty();
+            bool hasLineInfo = line > -1;
+            String traceLine;
+            JSObject* stackFrameCallee = callee.get();
+
+            switch (codeType) {
+            case StackFrameEvalCode:
+                if (hasSourceURLInfo) {
+                    traceLine = hasLineInfo ? String::format("eval code@%s:%d", sourceURL.ascii().data(), line) 
+                                            : String::format("eval code@%s", sourceURL.ascii().data());
+                } else
+                    traceLine = String::format("eval code");
+                break;
+            case StackFrameNativeCode: {
+                if (callee) {
+                    UString functionName = getCalculatedDisplayName(callFrame, stackFrameCallee);
+                    traceLine = String::format("%s@[native code]", functionName.ascii().data());
+                } else
+                    traceLine = "[native code]";
+                break;
+            }
+            case StackFrameFunctionCode: {
+                UString functionName = getCalculatedDisplayName(callFrame, stackFrameCallee);
+                if (hasSourceURLInfo) {
+                    traceLine = hasLineInfo ? String::format("%s@%s:%d", functionName.ascii().data(), sourceURL.ascii().data(), line)
+                                            : String::format("%s@%s", functionName.ascii().data(), sourceURL.ascii().data());
+                } else
+                    traceLine = String::format("%s\n", functionName.ascii().data());
+                break;
+            }
+            case StackFrameGlobalCode:
+                if (hasSourceURLInfo) {
+                    traceLine = hasLineInfo ? String::format("global code@%s:%d", sourceURL.ascii().data(), line)
+                                            : String::format("global code@%s", sourceURL.ascii().data());
+                } else
+                    traceLine = String::format("global code");
+                    
+            }
+            return traceLine.impl();
+        }
+    };
+
+    class TopCallFrameSetter {
+    public:
+        TopCallFrameSetter(JSGlobalData& global, CallFrame* callFrame)
+            : globalData(global)
+            , oldCallFrame(global.topCallFrame) 
+        {
+            global.topCallFrame = callFrame;
+        }
+        
+        ~TopCallFrameSetter() 
+        {
+            globalData.topCallFrame = oldCallFrame;
+        }
+    private:
+        JSGlobalData& globalData;
+        CallFrame* oldCallFrame;
+    };
+    
+    class NativeCallFrameTracer {
+    public:
+        ALWAYS_INLINE NativeCallFrameTracer(JSGlobalData* global, CallFrame* callFrame)
+        {
+            ASSERT(global);
+            ASSERT(callFrame);
+            global->topCallFrame = callFrame;
+        }
+    };
+
     // 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 = 93, MaxSmallThreadReentryDepth = 32 };
+    enum { MaxLargeThreadReentryDepth = 64, MaxSmallThreadReentryDepth = 16 };
 
     class Interpreter {
         WTF_MAKE_FAST_ALLOCATED;
 
     class Interpreter {
         WTF_MAKE_FAST_ALLOCATED;
-        friend class JIT;
         friend class CachedCall;
         friend class CachedCall;
+        friend class LLIntOffsetsExtractor;
+        friend class JIT;
     public:
     public:
-        Interpreter(JSGlobalData&);
+        Interpreter();
+        ~Interpreter();
+        
+        void initialize(LLInt::Data*, bool canUseJIT);
 
         RegisterFile& registerFile() { return m_registerFile; }
         
         Opcode getOpcode(OpcodeID id)
         {
 
         RegisterFile& registerFile() { return m_registerFile; }
         
         Opcode getOpcode(OpcodeID id)
         {
-            #if ENABLE(COMPUTED_GOTO_INTERPRETER)
-                return m_opcodeTable[id];
-            #else
-                return id;
-            #endif
+            ASSERT(m_initialized);
+#if ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER) || ENABLE(LLINT)
+            return m_opcodeTable[id];
+#else
+            return id;
+#endif
         }
 
         OpcodeID getOpcodeID(Opcode opcode)
         {
         }
 
         OpcodeID getOpcodeID(Opcode opcode)
         {
-            #if ENABLE(COMPUTED_GOTO_INTERPRETER)
-                ASSERT(isOpcode(opcode));
-                return m_opcodeIDTable.get(opcode);
-            #else
-                return opcode;
-            #endif
+            ASSERT(m_initialized);
+#if ENABLE(LLINT)
+            ASSERT(isOpcode(opcode));
+            return m_opcodeIDTable.get(opcode);
+#elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
+            ASSERT(isOpcode(opcode));
+            if (!m_classicEnabled)
+                return static_cast<OpcodeID>(bitwise_cast<uintptr_t>(opcode));
+
+            return m_opcodeIDTable.get(opcode);
+#else
+            return opcode;
+#endif
+        }
+        
+        bool classicEnabled()
+        {
+            return m_classicEnabled;
         }
 
         bool isOpcode(Opcode);
         }
 
         bool isOpcode(Opcode);
@@ -99,19 +204,22 @@ namespace JSC {
         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(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 execute(EvalExecutable*, CallFrame*, JSValue thisValue, ScopeChainNode*);
+        JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, ScopeChainNode*, int globalRegisterOffset);
 
 
-        JSValue retrieveArguments(CallFrame*, JSFunction*) const;
-        JSValue retrieveCaller(CallFrame*, JSFunction*) const;
-        void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const;
+        JSValue retrieveArgumentsFromVMCode(CallFrame*, JSFunction*) const;
+        JSValue retrieveCallerFromVMCode(CallFrame*, JSFunction*) const;
+        JS_EXPORT_PRIVATE 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 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);
         NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset);
         NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
         NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset);
         NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
+        static const UString getTraceLine(CallFrame*, StackFrameCodeType, const UString&, int);
+        JS_EXPORT_PRIVATE static void getStackTrace(JSGlobalData*, Vector<StackFrame>& results);
+        static void addStackTraceIfNecessary(CallFrame*, JSObject* error);
 
         void dumpSampleData(ExecState* exec);
         void startSampling();
 
         void dumpSampleData(ExecState* exec);
         void startSampling();
@@ -119,32 +227,31 @@ namespace JSC {
     private:
         enum ExecutionFlag { Normal, InitializeAndReturn };
 
     private:
         enum ExecutionFlag { Normal, InitializeAndReturn };
 
-        CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argCount, ScopeChainNode*);
+        CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argumentCountIncludingThis, ScopeChainNode*);
         void endRepeatCall(CallFrameClosure&);
         JSValue execute(CallFrameClosure&);
 
         void endRepeatCall(CallFrameClosure&);
         JSValue execute(CallFrameClosure&);
 
-        JSValue execute(EvalExecutable*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*);
-
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
         NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE bool resolveGlobalDynamic(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC);
         NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE bool resolveGlobalDynamic(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC);
         NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue);
+        NEVER_INLINE bool resolveThisAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue);
         NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC);
 
         void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const Identifier& propertyName, const PropertySlot&);
         void uncacheGetByID(CodeBlock*, Instruction* vPC);
         void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const PutPropertySlot&);
         void uncachePutByID(CodeBlock*, Instruction* vPC);        
         NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC);
 
         void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const Identifier& propertyName, const PropertySlot&);
         void uncacheGetByID(CodeBlock*, Instruction* vPC);
         void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const PutPropertySlot&);
         void uncachePutByID(CodeBlock*, Instruction* vPC);        
-#endif // ENABLE(INTERPRETER)
+#endif // ENABLE(CLASSIC_INTERPRETER)
 
         NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValue, unsigned& bytecodeOffset, CodeBlock*&);
 
         static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc);
 
 
         NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValue, unsigned& bytecodeOffset, CodeBlock*&);
 
         static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc);
 
-        static CallFrame* findFunctionCallFrame(CallFrame*, JSFunction*);
+        static CallFrame* findFunctionCallFrameFromVMCode(CallFrame*, JSFunction*);
 
         JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*);
 
 
         JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*);
 
@@ -161,12 +268,34 @@ namespace JSC {
 
         RegisterFile m_registerFile;
         
 
         RegisterFile m_registerFile;
         
-#if ENABLE(COMPUTED_GOTO_INTERPRETER)
+#if ENABLE(LLINT)
+        Opcode* m_opcodeTable; // Maps OpcodeID => Opcode for compiling
+        HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
+#elif ENABLE(COMPUTED_GOTO_CLASSIC_INTERPRETER)
         Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
         HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
 #endif
         Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
         HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
 #endif
+
+#if !ASSERT_DISABLED
+        bool m_initialized;
+#endif
+        bool m_classicEnabled;
     };
     };
-    
+
+    // This value must not be an object that would require this conversion (WebCore's global object).
+    inline bool isValidThisObject(JSValue thisValue, ExecState* exec)
+    {
+        return !thisValue.isObject() || thisValue.toThisObject(exec) == thisValue;
+    }
+
+    inline JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, ScopeChainNode* scopeChain)
+    {
+        return execute(eval, callFrame, thisValue, scopeChain, m_registerFile.size() + 1 + RegisterFile::CallFrameHeaderSize);
+    }
+
+    JSValue eval(CallFrame*);
+    CallFrame* loadVarargs(CallFrame*, RegisterFile*, JSValue thisValue, JSValue arguments, int firstFreeRegister);
+
 } // namespace JSC
 
 #endif // Interpreter_h
 } // namespace JSC
 
 #endif // Interpreter_h
index fb02c12089b21ad3dcc1a4e99d862865b74d5123..a4a76b865569fa1dbfbfa9b64fc66066ad35ea5a 100644 (file)
@@ -42,6 +42,7 @@ namespace JSC {
     class JSPropertyNameIterator;
     class ScopeChainNode;
 
     class JSPropertyNameIterator;
     class ScopeChainNode;
 
+    struct InlineCallFrame;
     struct Instruction;
 
     typedef ExecState CallFrame;
     struct Instruction;
 
     typedef ExecState CallFrame;
@@ -60,6 +61,7 @@ namespace JSC {
         Register& operator=(CodeBlock*);
         Register& operator=(ScopeChainNode*);
         Register& operator=(Instruction*);
         Register& operator=(CodeBlock*);
         Register& operator=(ScopeChainNode*);
         Register& operator=(Instruction*);
+        Register& operator=(InlineCallFrame*);
 
         int32_t i() const;
         JSActivation* activation() const;
 
         int32_t i() const;
         JSActivation* activation() const;
@@ -69,6 +71,14 @@ namespace JSC {
         JSPropertyNameIterator* propertyNameIterator() const;
         ScopeChainNode* scopeChain() const;
         Instruction* vPC() const;
         JSPropertyNameIterator* propertyNameIterator() const;
         ScopeChainNode* scopeChain() const;
         Instruction* vPC() const;
+        InlineCallFrame* asInlineCallFrame() const;
+        int32_t unboxedInt32() const;
+        bool unboxedBoolean() const;
+        JSCell* unboxedCell() const;
+        int32_t payload() const;
+        int32_t tag() const;
+        int32_t& payload();
+        int32_t& tag();
 
         static Register withInt(int32_t i)
         {
 
         static Register withInt(int32_t i)
         {
@@ -76,7 +86,7 @@ namespace JSC {
             return r;
         }
 
             return r;
         }
 
-        static inline Register withCallee(JSObject* callee);
+        static Register withCallee(JSObject* callee);
 
     private:
         union {
 
     private:
         union {
@@ -84,6 +94,8 @@ namespace JSC {
             CallFrame* callFrame;
             CodeBlock* codeBlock;
             Instruction* vPC;
             CallFrame* callFrame;
             CodeBlock* codeBlock;
             Instruction* vPC;
+            InlineCallFrame* inlineCallFrame;
+            EncodedValueDescriptor encodedValue;
         } u;
     };
 
         } u;
     };
 
@@ -96,17 +108,11 @@ namespace JSC {
 
     ALWAYS_INLINE Register::Register(const JSValue& v)
     {
 
     ALWAYS_INLINE Register::Register(const JSValue& v)
     {
-#if ENABLE(JSC_ZOMBIES)
-        ASSERT(!v.isZombie());
-#endif
         u.value = JSValue::encode(v);
     }
 
     ALWAYS_INLINE Register& Register::operator=(const JSValue& v)
     {
         u.value = JSValue::encode(v);
     }
 
     ALWAYS_INLINE Register& Register::operator=(const JSValue& v)
     {
-#if ENABLE(JSC_ZOMBIES)
-        ASSERT(!v.isZombie());
-#endif
         u.value = JSValue::encode(v);
         return *this;
     }
         u.value = JSValue::encode(v);
         return *this;
     }
@@ -141,6 +147,12 @@ namespace JSC {
         return *this;
     }
 
         return *this;
     }
 
+    ALWAYS_INLINE Register& Register::operator=(InlineCallFrame* inlineCallFrame)
+    {
+        u.inlineCallFrame = inlineCallFrame;
+        return *this;
+    }
+
     ALWAYS_INLINE int32_t Register::i() const
     {
         return jsValue().asInt32();
     ALWAYS_INLINE int32_t Register::i() const
     {
         return jsValue().asInt32();
@@ -161,6 +173,50 @@ namespace JSC {
         return u.vPC;
     }
 
         return u.vPC;
     }
 
+    ALWAYS_INLINE InlineCallFrame* Register::asInlineCallFrame() const
+    {
+        return u.inlineCallFrame;
+    }
+        
+    ALWAYS_INLINE int32_t Register::unboxedInt32() const
+    {
+        return payload();
+    }
+
+    ALWAYS_INLINE bool Register::unboxedBoolean() const
+    {
+        return !!payload();
+    }
+
+    ALWAYS_INLINE JSCell* Register::unboxedCell() const
+    {
+#if USE(JSVALUE64)
+        return u.encodedValue.ptr;
+#else
+        return bitwise_cast<JSCell*>(payload());
+#endif
+    }
+
+    ALWAYS_INLINE int32_t Register::payload() const
+    {
+        return u.encodedValue.asBits.payload;
+    }
+
+    ALWAYS_INLINE int32_t Register::tag() const
+    {
+        return u.encodedValue.asBits.tag;
+    }
+
+    ALWAYS_INLINE int32_t& Register::payload()
+    {
+        return u.encodedValue.asBits.payload;
+    }
+
+    ALWAYS_INLINE int32_t& Register::tag()
+    {
+        return u.encodedValue.asBits.tag;
+    }
+
 } // namespace JSC
 
 namespace WTF {
 } // namespace JSC
 
 namespace WTF {
index e3b34bb08a40c5b0692c3e23a6b7be0aff0c7f11..b72352781a1bb66a642eb595d1df422a388d5106 100644 (file)
@@ -31,8 +31,6 @@
 
 #include "ConservativeRoots.h"
 #include "Interpreter.h"
 
 #include "ConservativeRoots.h"
 #include "Interpreter.h"
-#include "JSGlobalData.h"
-#include "JSGlobalObject.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -52,32 +50,40 @@ RegisterFile::~RegisterFile()
     m_reservation.deallocate();
 }
 
     m_reservation.deallocate();
 }
 
-void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
+bool RegisterFile::growSlowCase(Register* newEnd)
 {
 {
-    for (Register* it = start(); it != end(); ++it) {
-        JSValue v = it->jsValue();
-        if (!v.isCell())
-            continue;
-        conservativeRoots.add(v.asCell());
+    if (newEnd <= m_commitEnd) {
+        m_end = newEnd;
+        return true;
     }
     }
+
+    long delta = roundUpAllocationSize(reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_commitEnd), commitSize);
+    if (reinterpret_cast<char*>(m_commitEnd) + delta > static_cast<char*>(m_reservation.base()) + m_reservation.size())
+        return false;
+
+    m_reservation.commit(m_commitEnd, delta);
+    addToCommittedByteCount(delta);
+    m_commitEnd = reinterpret_cast_ptr<Register*>(reinterpret_cast<char*>(m_commitEnd) + delta);
+    m_end = newEnd;
+    return true;
 }
 
 }
 
-void RegisterFile::releaseExcessCapacity()
+void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
 {
 {
-    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_maxUsed = m_start;
+    conservativeRoots.add(begin(), end());
 }
 
 }
 
-void RegisterFile::setGlobalObject(JSGlobalObject* globalObject)
+void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots, DFGCodeBlocks& dfgCodeBlocks)
 {
 {
-    m_globalObject.set(globalObject->globalData(), globalObject, &m_globalObjectOwner, this);
+    conservativeRoots.add(begin(), end(), dfgCodeBlocks);
 }
 
 }
 
-JSGlobalObject* RegisterFile::globalObject()
+void RegisterFile::releaseExcessCapacity()
 {
 {
-    return m_globalObject.get();
+    ptrdiff_t delta = reinterpret_cast<uintptr_t>(m_commitEnd) - reinterpret_cast<uintptr_t>(m_reservation.base());
+    m_reservation.decommit(m_reservation.base(), delta);
+    addToCommittedByteCount(-delta);
+    m_commitEnd = static_cast<Register*>(m_reservation.base());
 }
 
 void RegisterFile::initializeThreading()
 }
 
 void RegisterFile::initializeThreading()
index f59c13a1b5327e7e4cf25f79c9c8b1cc1f6fed69..21ad7fbaea596fd6e81d5e13a6ad3b0209773e07 100644 (file)
 #ifndef RegisterFile_h
 #define RegisterFile_h
 
 #ifndef RegisterFile_h
 #define RegisterFile_h
 
-#include "Heap.h"
 #include "ExecutableAllocator.h"
 #include "Register.h"
 #include "ExecutableAllocator.h"
 #include "Register.h"
-#include "Weak.h"
-#include <stdio.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/PageReservation.h>
 #include <wtf/VMTags.h>
 
 namespace JSC {
 
 #include <wtf/Noncopyable.h>
 #include <wtf/PageReservation.h>
 #include <wtf/VMTags.h>
 
 namespace JSC {
 
-/*
-    A register file is a stack of register frames. We represent a register
-    frame by its offset from "base", the logical first entry in the register
-    file. The bottom-most register frame's offset from base is 0.
-
-    In a program where function "a" calls function "b" (global code -> a -> b),
-    the register file might look like this:
-
-    |       global frame     |        call frame      |        call frame      |     spare capacity     |
-    -----------------------------------------------------------------------------------------------------
-    |  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 | 11 | 12 | 13 | 14 |    |    |    |    |    | <-- index in buffer
-    -----------------------------------------------------------------------------------------------------
-    | -3 | -2 | -1 |  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 | 11 |    |    |    |    |    | <-- index relative to base
-    -----------------------------------------------------------------------------------------------------
-    |    <-globals | temps-> |  <-vars | temps->      |                 <-vars |
-       ^              ^                   ^                                       ^
-       |              |                   |                                       |
-     buffer    base (frame 0)          frame 1                                 frame 2
-
-    Since all variables, including globals, are accessed by negative offsets
-    from their register frame pointers, to keep old global offsets correct, new
-    globals must appear at the beginning of the register file, shifting base
-    to the right.
-
-    If we added one global variable to the register file depicted above, it
-    would look like this:
-
-    |         global frame        |<                                                                    >
-    ------------------------------->                                                                    <
-    |  0 |  1 |  2 |  3 |  4 |  5 |<                             >snip<                                 > <-- index in buffer
-    ------------------------------->                                                                    <
-    | -4 | -3 | -2 | -1 |  0 |  1 |<                                                                    > <-- index relative to base
-    ------------------------------->                                                                    <
-    |         <-globals | temps-> |
-       ^                   ^
-       |                   |
-     buffer         base (frame 0)
-
-    As you can see, global offsets relative to base have stayed constant,
-    but base itself has moved. To keep up with possible changes to base,
-    clients keep an indirect pointer, so their calculations update
-    automatically when base changes.
-
-    For client simplicity, the RegisterFile measures size and capacity from
-    "base", not "buffer".
-*/
-
-    class JSGlobalObject;
+    class ConservativeRoots;
+    class DFGCodeBlocks;
+    class LLIntOffsetsExtractor;
 
     class RegisterFile {
         WTF_MAKE_NONCOPYABLE(RegisterFile);
 
     class RegisterFile {
         WTF_MAKE_NONCOPYABLE(RegisterFile);
@@ -103,34 +55,23 @@ namespace JSC {
             CodeBlock = -1,
         };
 
             CodeBlock = -1,
         };
 
-        enum { ProgramCodeThisRegister = -CallFrameHeaderSize - 1 };
-
         static const size_t defaultCapacity = 512 * 1024;
         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;
 
         static const size_t commitSize = 16 * 1024;
         // Allow 8k of excess registers before we start trying to reap the registerfile
         static const ptrdiff_t maxExcessCapacity = 8 * 1024;
 
-        RegisterFile(JSGlobalData&, size_t capacity = defaultCapacity, size_t maxGlobals = defaultMaxGlobals);
+        RegisterFile(size_t capacity = defaultCapacity);
         ~RegisterFile();
         
         void gatherConservativeRoots(ConservativeRoots&);
         ~RegisterFile();
         
         void gatherConservativeRoots(ConservativeRoots&);
+        void gatherConservativeRoots(ConservativeRoots&, DFGCodeBlocks&);
 
 
-        Register* start() const { return m_start; }
+        Register* begin() const { return static_cast<Register*>(m_reservation.base()); }
         Register* end() const { return m_end; }
         Register* end() const { return m_end; }
-        size_t size() const { return m_end - m_start; }
+        size_t size() const { return end() - begin(); }
 
 
-        void setGlobalObject(JSGlobalObject*);
-        JSGlobalObject* globalObject();
-
-        bool grow(Register* newEnd);
-        void shrink(Register* newEnd);
-        
-        void setNumGlobals(size_t numGlobals) { m_numGlobals = numGlobals; }
-        int numGlobals() const { return m_numGlobals; }
-        size_t maxGlobals() const { return m_maxGlobals; }
-
-        Register* lastGlobal() const { return m_start - m_numGlobals; }
+        bool grow(Register*);
+        void shrink(Register*);
         
         static size_t committedByteCount();
         static void initializeThreading();
         
         static size_t committedByteCount();
         static void initializeThreading();
@@ -141,47 +82,24 @@ namespace JSC {
         }
 
     private:
         }
 
     private:
+        friend class LLIntOffsetsExtractor;
+        
+        bool growSlowCase(Register*);
         void releaseExcessCapacity();
         void addToCommittedByteCount(long);
         void releaseExcessCapacity();
         void addToCommittedByteCount(long);
-        size_t m_numGlobals;
-        const size_t m_maxGlobals;
-        Register* m_start;
         Register* m_end;
         Register* m_end;
-        Register* m_max;
-        Register* m_maxUsed;
         Register* m_commitEnd;
         PageReservation m_reservation;
         Register* m_commitEnd;
         PageReservation m_reservation;
-
-        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;
     };
 
     };
 
-    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_globalObject(globalData, 0, &m_globalObjectOwner, this)
+    inline RegisterFile::RegisterFile(size_t capacity)
+        : m_end(0)
     {
     {
-        ASSERT(maxGlobals && isPageAligned(maxGlobals));
         ASSERT(capacity && isPageAligned(capacity));
         ASSERT(capacity && isPageAligned(capacity));
-        size_t bufferLength = (capacity + maxGlobals) * sizeof(Register);
-        m_reservation = PageReservation::reserve(roundUpAllocationSize(bufferLength, commitSize), OSAllocator::JSVMStackPages);
-        void* base = m_reservation.base();
-        size_t committedSize = roundUpAllocationSize(maxGlobals * sizeof(Register), commitSize);
-        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_reservation = PageReservation::reserve(roundUpAllocationSize(capacity * sizeof(Register), commitSize), OSAllocator::JSVMStackPages);
+        m_end = static_cast<Register*>(m_reservation.base());
+        m_commitEnd = static_cast<Register*>(m_reservation.base());
     }
 
     inline void RegisterFile::shrink(Register* newEnd)
     }
 
     inline void RegisterFile::shrink(Register* newEnd)
@@ -189,30 +107,15 @@ namespace JSC {
         if (newEnd >= m_end)
             return;
         m_end = newEnd;
         if (newEnd >= m_end)
             return;
         m_end = newEnd;
-        if (m_end == m_start && (m_maxUsed - m_start) > maxExcessCapacity)
+        if (m_end == m_reservation.base() && (m_commitEnd - begin()) >= maxExcessCapacity)
             releaseExcessCapacity();
     }
 
     inline bool RegisterFile::grow(Register* newEnd)
     {
             releaseExcessCapacity();
     }
 
     inline bool RegisterFile::grow(Register* newEnd)
     {
-        if (newEnd < m_end)
+        if (newEnd <= m_end)
             return true;
             return true;
-
-        if (newEnd > m_max)
-            return false;
-
-        if (newEnd > m_commitEnd) {
-            size_t size = roundUpAllocationSize(reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_commitEnd), commitSize);
-            m_reservation.commit(m_commitEnd, size);
-            addToCommittedByteCount(static_cast<long>(size));
-            m_commitEnd = reinterpret_cast_ptr<Register*>(reinterpret_cast<char*>(m_commitEnd) + size);
-        }
-
-        if (newEnd > m_maxUsed)
-            m_maxUsed = newEnd;
-
-        m_end = newEnd;
-        return true;
+        return growSlowCase(newEnd);
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
diff --git a/javascriptcoregtk.pc.in b/javascriptcoregtk.pc.in
new file mode 100644 (file)
index 0000000..ca7c8e3
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: JavaScriptCoreGTK+
+Description: GTK+ version of the JavaScriptCore engine
+Version: @VERSION@
+Requires: glib-2.0
+Libs: -L${libdir} -ljavascriptcoregtk-@WEBKITGTK_API_VERSION@
+Cflags: -I${includedir}/webkitgtk-@WEBKITGTK_API_VERSION@
diff --git a/jit/CompactJITCodeMap.h b/jit/CompactJITCodeMap.h
new file mode 100644 (file)
index 0000000..5b92a89
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * 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 CompactJITCodeMap_h
+#define CompactJITCodeMap_h
+
+#include <wtf/Assertions.h>
+#include <wtf/FastAllocBase.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/UnusedParam.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+// Gives you a compressed map between between bytecode indices and machine code
+// entry points. The compression simply tries to use either 1, 2, or 4 bytes for
+// any given offset. The largest offset that can be stored is 2^30.
+
+// Example use:
+//
+// CompactJITCodeMap::Encoder encoder(map);
+// encoder.append(a, b);
+// encoder.append(c, d); // preconditions: c >= a, d >= b
+// OwnPtr<CompactJITCodeMap> map = encoder.finish();
+//
+// At some later time:
+//
+// Vector<BytecodeAndMachineOffset> decoded;
+// map->decode(decoded);
+
+struct BytecodeAndMachineOffset {
+    BytecodeAndMachineOffset() { }
+    
+    BytecodeAndMachineOffset(unsigned bytecodeIndex, unsigned machineCodeOffset)
+        : m_bytecodeIndex(bytecodeIndex)
+        , m_machineCodeOffset(machineCodeOffset)
+    {
+    }
+    
+    unsigned m_bytecodeIndex;
+    unsigned m_machineCodeOffset;
+    
+    static inline unsigned getBytecodeIndex(BytecodeAndMachineOffset* mapping)
+    {
+        return mapping->m_bytecodeIndex;
+    }
+    
+    static inline unsigned getMachineCodeOffset(BytecodeAndMachineOffset* mapping)
+    {
+        return mapping->m_machineCodeOffset;
+    }
+};
+
+class CompactJITCodeMap {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ~CompactJITCodeMap()
+    {
+        if (m_buffer)
+            fastFree(m_buffer);
+    }
+    
+    unsigned numberOfEntries() const
+    {
+        return m_numberOfEntries;
+    }
+    
+    void decode(Vector<BytecodeAndMachineOffset>& result) const;
+    
+private:
+    CompactJITCodeMap(uint8_t* buffer, unsigned size, unsigned numberOfEntries)
+        : m_buffer(buffer)
+#if !ASSERT_DISABLED
+        , m_size(size)
+#endif
+        , m_numberOfEntries(numberOfEntries)
+    {
+        UNUSED_PARAM(size);
+    }
+    
+    uint8_t at(unsigned index) const
+    {
+        ASSERT(index < m_size);
+        return m_buffer[index];
+    }
+    
+    unsigned decodeNumber(unsigned& index) const
+    {
+        uint8_t headValue = at(index++);
+        if (!(headValue & 128))
+            return headValue;
+        if (!(headValue & 64))
+            return (static_cast<unsigned>(headValue & ~128) << 8) | at(index++);
+        unsigned second = at(index++);
+        unsigned third  = at(index++);
+        unsigned fourth = at(index++);
+        return (static_cast<unsigned>(headValue & ~(128 + 64)) << 24) | (second << 16) | (third << 8) | fourth;
+    }
+    
+    uint8_t* m_buffer;
+#if !ASSERT_DISABLED
+    unsigned m_size;
+#endif
+    unsigned m_numberOfEntries;
+    
+public:
+    class Encoder {
+        WTF_MAKE_NONCOPYABLE(Encoder);
+    public:
+        Encoder();
+        ~Encoder();
+        
+        void ensureCapacityFor(unsigned numberOfEntriesToAdd);
+        void append(unsigned bytecodeIndex, unsigned machineCodeOffset);
+        PassOwnPtr<CompactJITCodeMap> finish();
+        
+    private:
+        void appendByte(uint8_t value);
+        void encodeNumber(uint32_t value);
+    
+        uint8_t* m_buffer;
+        unsigned m_size;
+        unsigned m_capacity;
+        unsigned m_numberOfEntries;
+        
+        unsigned m_previousBytecodeIndex;
+        unsigned m_previousMachineCodeOffset;
+    };
+    
+    class Decoder {
+        WTF_MAKE_NONCOPYABLE(Decoder);
+    public:
+        Decoder(const CompactJITCodeMap*);
+        
+        unsigned numberOfEntriesRemaining() const;
+        void read(unsigned& bytecodeIndex, unsigned& machineCodeOffset);
+        
+    private:
+        const CompactJITCodeMap* m_jitCodeMap;
+        unsigned m_previousBytecodeIndex;
+        unsigned m_previousMachineCodeOffset;
+        unsigned m_numberOfEntriesRemaining;
+        unsigned m_bufferIndex;
+    };
+
+private:
+    friend class Encoder;
+    friend class Decoder;
+};
+
+inline void CompactJITCodeMap::decode(Vector<BytecodeAndMachineOffset>& result) const
+{
+    Decoder decoder(this);
+    result.resize(decoder.numberOfEntriesRemaining());
+    for (unsigned i = 0; i < result.size(); ++i)
+        decoder.read(result[i].m_bytecodeIndex, result[i].m_machineCodeOffset);
+    
+    ASSERT(!decoder.numberOfEntriesRemaining());
+}
+
+inline CompactJITCodeMap::Encoder::Encoder()
+    : m_buffer(0)
+    , m_size(0)
+    , m_capacity(0)
+    , m_numberOfEntries(0)
+    , m_previousBytecodeIndex(0)
+    , m_previousMachineCodeOffset(0)
+{
+}
+
+inline CompactJITCodeMap::Encoder::~Encoder()
+{
+    if (m_buffer)
+        fastFree(m_buffer);
+}
+        
+inline void CompactJITCodeMap::Encoder::append(unsigned bytecodeIndex, unsigned machineCodeOffset)
+{
+    ASSERT(bytecodeIndex >= m_previousBytecodeIndex);
+    ASSERT(machineCodeOffset >= m_previousMachineCodeOffset);
+    ensureCapacityFor(1);
+    encodeNumber(bytecodeIndex - m_previousBytecodeIndex);
+    encodeNumber(machineCodeOffset - m_previousMachineCodeOffset);
+    m_previousBytecodeIndex = bytecodeIndex;
+    m_previousMachineCodeOffset = machineCodeOffset;
+    m_numberOfEntries++;
+}
+
+inline PassOwnPtr<CompactJITCodeMap> CompactJITCodeMap::Encoder::finish()
+{
+    m_capacity = m_size;
+    m_buffer = static_cast<uint8_t*>(fastRealloc(m_buffer, m_capacity));
+    OwnPtr<CompactJITCodeMap> result = adoptPtr(new CompactJITCodeMap(m_buffer, m_size, m_numberOfEntries));
+    m_buffer = 0;
+    m_size = 0;
+    m_capacity = 0;
+    m_numberOfEntries = 0;
+    m_previousBytecodeIndex = 0;
+    m_previousMachineCodeOffset = 0;
+    return result.release();
+}
+        
+inline void CompactJITCodeMap::Encoder::appendByte(uint8_t value)
+{
+    ASSERT(m_size + 1 <= m_capacity);
+    m_buffer[m_size++] = value;
+}
+    
+inline void CompactJITCodeMap::Encoder::encodeNumber(uint32_t value)
+{
+    ASSERT(m_size + 4 <= m_capacity);
+    ASSERT(value < (1 << 30));
+    if (value <= 127) {
+        uint8_t headValue = static_cast<uint8_t>(value);
+        ASSERT(!(headValue & 128));
+        appendByte(headValue);
+    } else if (value <= 16383) {
+        uint8_t headValue = static_cast<uint8_t>(value >> 8);
+        ASSERT(!(headValue & 128));
+        ASSERT(!(headValue & 64));
+        appendByte(headValue | 128);
+        appendByte(static_cast<uint8_t>(value));
+    } else {
+        uint8_t headValue = static_cast<uint8_t>(value >> 24);
+        ASSERT(!(headValue & 128));
+        ASSERT(!(headValue & 64));
+        appendByte(headValue | 128 | 64);
+        appendByte(static_cast<uint8_t>(value >> 16));
+        appendByte(static_cast<uint8_t>(value >> 8));
+        appendByte(static_cast<uint8_t>(value));
+    }
+}
+
+inline void CompactJITCodeMap::Encoder::ensureCapacityFor(unsigned numberOfEntriesToAdd)
+{
+    unsigned capacityNeeded = m_size + numberOfEntriesToAdd * 2 * 4;
+    if (capacityNeeded > m_capacity) {
+        m_capacity = capacityNeeded * 2;
+        m_buffer = static_cast<uint8_t*>(fastRealloc(m_buffer, m_capacity));
+    }
+}
+
+inline CompactJITCodeMap::Decoder::Decoder(const CompactJITCodeMap* jitCodeMap)
+    : m_jitCodeMap(jitCodeMap)
+    , m_previousBytecodeIndex(0)
+    , m_previousMachineCodeOffset(0)
+    , m_numberOfEntriesRemaining(jitCodeMap->m_numberOfEntries)
+    , m_bufferIndex(0)
+{
+}
+
+inline unsigned CompactJITCodeMap::Decoder::numberOfEntriesRemaining() const
+{
+    ASSERT(m_numberOfEntriesRemaining || m_bufferIndex == m_jitCodeMap->m_size);
+    return m_numberOfEntriesRemaining;
+}
+
+inline void CompactJITCodeMap::Decoder::read(unsigned& bytecodeIndex, unsigned& machineCodeOffset)
+{
+    ASSERT(numberOfEntriesRemaining());
+    
+    m_previousBytecodeIndex += m_jitCodeMap->decodeNumber(m_bufferIndex);
+    m_previousMachineCodeOffset += m_jitCodeMap->decodeNumber(m_bufferIndex);
+    bytecodeIndex = m_previousBytecodeIndex;
+    machineCodeOffset = m_previousMachineCodeOffset;
+    m_numberOfEntriesRemaining--;
+}
+
+} // namespace JSC
+
+#endif // CompactJITCodeMap_h
index 35531d92ed08db71ee0bb6ff0cb005b4bbd089bf..79399196e438c49f387b6eedf7aa4f8688aea8da 100644 (file)
 
 #include "ExecutableAllocator.h"
 
 
 #include "ExecutableAllocator.h"
 
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
+#include "CodeProfiling.h"
+#include <wtf/HashSet.h>
+#include <wtf/MetaAllocator.h>
+#include <wtf/PageReservation.h>
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+#include <wtf/PassOwnPtr.h>
+#endif
+#include <wtf/ThreadingPrimitives.h>
+#include <wtf/VMTags.h>
+#endif
+
+// Uncomment to create an artificial executable memory usage limit. This limit
+// is imperfect and is primarily useful for testing the VM's ability to handle
+// out-of-executable-memory situations.
+// #define EXECUTABLE_MEMORY_LIMIT 1000000
+
 #if ENABLE(ASSEMBLER)
 
 #if ENABLE(ASSEMBLER)
 
-namespace JSC {
+using namespace WTF;
 
 
-size_t ExecutableAllocator::pageSize = 0;
+namespace JSC {
 
 #if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
 
 
 #if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
 
-void ExecutableAllocator::intializePageSize()
+class DemandExecutableAllocator : public MetaAllocator {
+public:
+    DemandExecutableAllocator()
+        : MetaAllocator(32) // round up all allocations to 32 bytes
+    {
+        MutexLocker lock(allocatorsMutex());
+        allocators().add(this);
+        // Don't preallocate any memory here.
+    }
+    
+    virtual ~DemandExecutableAllocator()
+    {
+        {
+            MutexLocker lock(allocatorsMutex());
+            allocators().remove(this);
+        }
+        for (unsigned i = 0; i < reservations.size(); ++i)
+            reservations.at(i).deallocate();
+    }
+
+    static size_t bytesAllocatedByAllAllocators()
+    {
+        size_t total = 0;
+        MutexLocker lock(allocatorsMutex());
+        for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator)
+            total += (*allocator)->bytesAllocated();
+        return total;
+    }
+
+    static size_t bytesCommittedByAllocactors()
+    {
+        size_t total = 0;
+        MutexLocker lock(allocatorsMutex());
+        for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator)
+            total += (*allocator)->bytesCommitted();
+        return total;
+    }
+
+#if ENABLE(META_ALLOCATOR_PROFILE)
+    static void dumpProfileFromAllAllocators()
+    {
+        MutexLocker lock(allocatorsMutex());
+        for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator)
+            (*allocator)->dumpProfile();
+    }
+#endif
+
+protected:
+    virtual void* allocateNewSpace(size_t& numPages)
+    {
+        size_t newNumPages = (((numPages * pageSize() + JIT_ALLOCATOR_LARGE_ALLOC_SIZE - 1) / JIT_ALLOCATOR_LARGE_ALLOC_SIZE * JIT_ALLOCATOR_LARGE_ALLOC_SIZE) + pageSize() - 1) / pageSize();
+        
+        ASSERT(newNumPages >= numPages);
+        
+        numPages = newNumPages;
+        
+#ifdef EXECUTABLE_MEMORY_LIMIT
+        if (bytesAllocatedByAllAllocators() >= EXECUTABLE_MEMORY_LIMIT)
+            return 0;
+#endif
+        
+        PageReservation reservation = PageReservation::reserve(numPages * pageSize(), OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
+        if (!reservation)
+            CRASH();
+        
+        reservations.append(reservation);
+        
+        return reservation.base();
+    }
+    
+    virtual void notifyNeedPage(void* page)
+    {
+        OSAllocator::commit(page, pageSize(), EXECUTABLE_POOL_WRITABLE, true);
+    }
+    
+    virtual void notifyPageIsFree(void* page)
+    {
+        OSAllocator::decommit(page, pageSize());
+    }
+
+private:
+    Vector<PageReservation, 16> reservations;
+    static HashSet<DemandExecutableAllocator*>& allocators()
+    {
+        DEFINE_STATIC_LOCAL(HashSet<DemandExecutableAllocator*>, sAllocators, ());
+        return sAllocators;
+    }
+    static Mutex& allocatorsMutex()
+    {
+        DEFINE_STATIC_LOCAL(Mutex, mutex, ());
+        return mutex;
+    }
+};
+
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+void ExecutableAllocator::initializeAllocator()
 {
 {
-#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
 #else
-    ExecutableAllocator::pageSize = WTF::pageSize();
-#endif
+static DemandExecutableAllocator* gAllocator;
+
+namespace {
+static inline DemandExecutableAllocator* allocator()
+{
+    return gAllocator;
+}
 }
 
 }
 
-ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size)
+void ExecutableAllocator::initializeAllocator()
 {
 {
-    PageAllocation allocation = PageAllocation::allocate(size, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
-    if (!allocation)
-        CRASH();
-    return allocation;
+    ASSERT(!gAllocator);
+    gAllocator = new DemandExecutableAllocator();
+    CodeProfiling::notifyAllocator(gAllocator);
+}
+#endif
+
+ExecutableAllocator::ExecutableAllocator(JSGlobalData&)
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+    : m_allocator(adoptPtr(new  DemandExecutableAllocator()))
+#endif
+{
+    ASSERT(allocator());
 }
 
 }
 
-void ExecutablePool::systemRelease(ExecutablePool::Allocation& allocation)
+ExecutableAllocator::~ExecutableAllocator()
 {
 {
-    allocation.deallocate();
 }
 
 bool ExecutableAllocator::isValid() const
 {
     return true;
 }
 }
 
 bool ExecutableAllocator::isValid() const
 {
     return true;
 }
-    
+
 bool ExecutableAllocator::underMemoryPressure()
 {
 bool ExecutableAllocator::underMemoryPressure()
 {
+#ifdef EXECUTABLE_MEMORY_LIMIT
+    return DemandExecutableAllocator::bytesAllocatedByAllAllocators() > EXECUTABLE_MEMORY_LIMIT / 2;
+#else
     return false;
     return false;
+#endif
 }
 }
-    
+
+double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage)
+{
+    double result;
+#ifdef EXECUTABLE_MEMORY_LIMIT
+    size_t bytesAllocated = DemandExecutableAllocator::bytesAllocatedByAllAllocators() + addedMemoryUsage;
+    if (bytesAllocated >= EXECUTABLE_MEMORY_LIMIT)
+        bytesAllocated = EXECUTABLE_MEMORY_LIMIT;
+    result = static_cast<double>(EXECUTABLE_MEMORY_LIMIT) /
+        (EXECUTABLE_MEMORY_LIMIT - bytesAllocated);
+#else
+    UNUSED_PARAM(addedMemoryUsage);
+    result = 1.0;
+#endif
+    if (result < 1.0)
+        result = 1.0;
+    return result;
+
+}
+
+PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData&, size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort)
+{
+    RefPtr<ExecutableMemoryHandle> result = allocator()->allocate(sizeInBytes, ownerUID);
+    if (!result && effort == JITCompilationMustSucceed)
+        CRASH();
+    return result.release();
+}
+
 size_t ExecutableAllocator::committedByteCount()
 {
 size_t ExecutableAllocator::committedByteCount()
 {
-    return 0;
-} 
+    return DemandExecutableAllocator::bytesCommittedByAllocactors();
+}
 
 
+#if ENABLE(META_ALLOCATOR_PROFILE)
+void ExecutableAllocator::dumpProfile()
+{
+    DemandExecutableAllocator::dumpProfileFromAllAllocators();
+}
 #endif
 
 #endif
 
+#endif // ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
+
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
 
-#if OS(WINDOWS) || OS(SYMBIAN)
+#if OS(WINDOWS)
 #error "ASSEMBLER_WX_EXCLUSIVE not yet suported on this platform."
 #endif
 
 void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSetting setting)
 {
 #error "ASSEMBLER_WX_EXCLUSIVE not yet suported on this platform."
 #endif
 
 void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSetting setting)
 {
-    if (!pageSize)
-        intializePageSize();
+    size_t pageSize = WTF::pageSize();
 
     // Calculate the start of the page containing this region,
     // and account for this extra memory within size.
 
     // Calculate the start of the page containing this region,
     // and account for this extra memory within size.
@@ -106,23 +261,6 @@ void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSe
 
 #endif
 
 
 #endif
 
-#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 // HAVE(ASSEMBLER)
 }
 
 #endif // HAVE(ASSEMBLER)
index be315c70e8162cdac730e39fa9eddd9d5ef71b02..d179f2b4ace365edd05b3e9cfbe0020918f30119 100644 (file)
 
 #ifndef ExecutableAllocator_h
 #define ExecutableAllocator_h
 
 #ifndef ExecutableAllocator_h
 #define ExecutableAllocator_h
+#include "JITCompilationEffort.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/MetaAllocatorHandle.h>
 #include <wtf/PageAllocation.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/PageAllocation.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 
 #if OS(IOS)
 #include <libkern/OSCacheControl.h>
 
 #if OS(IOS)
 #include <libkern/OSCacheControl.h>
-#include <sys/mman.h>
 #endif
 
 #endif
 
-#if OS(SYMBIAN)
-#include <e32std.h>
+#if OS(IOS) || OS(QNX)
+#include <sys/mman.h>
 #endif
 
 #if CPU(MIPS) && OS(LINUX)
 #endif
 
 #if CPU(MIPS) && OS(LINUX)
 extern "C" __declspec(dllimport) void CacheRangeFlush(LPVOID pAddr, DWORD dwLength, DWORD dwFlags);
 #endif
 
 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)
+#define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (pageSize() * 4)
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
 #define PROTECTION_FLAGS_RW (PROT_READ | PROT_WRITE)
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
 #define PROTECTION_FLAGS_RW (PROT_READ | PROT_WRITE)
@@ -79,6 +73,9 @@ extern "C" __declspec(dllimport) void CacheRangeFlush(LPVOID pAddr, DWORD dwLeng
 
 namespace JSC {
 
 
 namespace JSC {
 
+class JSGlobalData;
+void releaseExecutableMemory(JSGlobalData&);
+
 inline size_t roundUpAllocationSize(size_t request, size_t granularity)
 {
     if ((std::numeric_limits<size_t>::max() - granularity) <= request)
 inline size_t roundUpAllocationSize(size_t request, size_t granularity)
 {
     if ((std::numeric_limits<size_t>::max() - granularity) <= request)
@@ -93,130 +90,38 @@ inline size_t roundUpAllocationSize(size_t request, size_t granularity)
 
 }
 
 
 }
 
-#if ENABLE(JIT) && ENABLE(ASSEMBLER)
-
 namespace JSC {
 
 namespace JSC {
 
-class JSGlobalData;
-void releaseExecutableMemory(JSGlobalData&);
+typedef WTF::MetaAllocatorHandle ExecutableMemoryHandle;
+
+#if ENABLE(ASSEMBLER)
 
 
-class ExecutablePool : public RefCounted<ExecutablePool> {
-public:
 #if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
 #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;
-    };
+class DemandExecutableAllocator;
 #endif
 #endif
-    typedef Vector<Allocation, 2> AllocationList;
-
-    static PassRefPtr<ExecutablePool> create(JSGlobalData& globalData, size_t n)
-    {
-        return adoptRef(new ExecutablePool(globalData, n));
-    }
-
-    void* alloc(JSGlobalData& globalData, size_t n)
-    {
-        ASSERT(m_freePtr <= m_end);
-
-        // Round 'n' up to a multiple of word size; if all allocations are of
-        // word sized quantities, then all subsequent allocations will be aligned.
-        n = roundUpAllocationSize(n, sizeof(void*));
-
-        if (static_cast<ptrdiff_t>(n) < (m_end - m_freePtr)) {
-            void* result = m_freePtr;
-            m_freePtr += n;
-            return result;
-        }
-
-        // Insufficient space to allocate in the existing pool
-        // so we need allocate into a new pool
-        return poolAllocate(globalData, n);
-    }
-    
-    void tryShrink(void* allocation, size_t oldSize, size_t newSize)
-    {
-        if (static_cast<char*>(allocation) + oldSize != m_freePtr)
-            return;
-        m_freePtr = static_cast<char*>(allocation) + roundUpAllocationSize(newSize, sizeof(void*));
-    }
-
-    ~ExecutablePool()
-    {
-        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; }
-
-private:
-    static Allocation systemAlloc(size_t n);
-    static void systemRelease(Allocation& alloc);
-
-    ExecutablePool(JSGlobalData&, size_t n);
-
-    void* poolAllocate(JSGlobalData&, size_t n);
-
-    char* m_freePtr;
-    char* m_end;
-    AllocationList m_pools;
-};
 
 class ExecutableAllocator {
     enum ProtectionSetting { Writable, Executable };
 
 public:
 
 class ExecutableAllocator {
     enum ProtectionSetting { Writable, Executable };
 
 public:
-    static size_t pageSize;
-    ExecutableAllocator(JSGlobalData& globalData)
-    {
-        if (!pageSize)
-            intializePageSize();
-        if (isValid())
-            m_smallAllocationPool = ExecutablePool::create(globalData, JIT_ALLOCATOR_LARGE_ALLOC_SIZE);
-#if !ENABLE(INTERPRETER)
-        else
-            CRASH();
-#endif
-    }
+    ExecutableAllocator(JSGlobalData&);
+    ~ExecutableAllocator();
+    
+    static void initializeAllocator();
 
     bool isValid() const;
 
     static bool underMemoryPressure();
 
     bool isValid() const;
 
     static bool underMemoryPressure();
+    
+    static double memoryPressureMultiplier(size_t addedMemoryUsage);
+    
+#if ENABLE(META_ALLOCATOR_PROFILE)
+    static void dumpProfile();
+#else
+    static void dumpProfile() { }
+#endif
 
 
-    PassRefPtr<ExecutablePool> poolForSize(JSGlobalData& globalData, size_t n)
-    {
-        // Try to fit in the existing small allocator
-        ASSERT(m_smallAllocationPool);
-        if (n < m_smallAllocationPool->available())
-            return m_smallAllocationPool;
-
-        // If the request is large, we just provide a unshared allocator
-        if (n > JIT_ALLOCATOR_LARGE_ALLOC_SIZE)
-            return ExecutablePool::create(globalData, n);
-
-        // Create a new allocator
-        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 ((pool->available() - n) > m_smallAllocationPool->available())
-            m_smallAllocationPool = pool;
-        return pool.release();
-    }
+    PassRefPtr<ExecutableMemoryHandle> allocate(JSGlobalData&, size_t sizeInBytes, void* ownerUID, JITCompilationEffort);
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
     static void makeWritable(void* start, size_t size)
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
     static void makeWritable(void* start, size_t size)
@@ -233,168 +138,33 @@ public:
     static void makeExecutable(void*, size_t) {}
 #endif
 
     static void makeExecutable(void*, size_t) {}
 #endif
 
-
-#if CPU(X86) || CPU(X86_64)
-    static void cacheFlush(void*, size_t)
-    {
-    }
-#elif CPU(MIPS)
-    static void cacheFlush(void* code, size_t size)
-    {
-#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));
-        //
-        // Modify "start" and "end" to avoid GCC 4.3.0-4.4.2 bug in
-        // mips_expand_synci_loop that may execute synci one more time.
-        // "start" points to the fisrt byte of the cache line.
-        // "end" points to the last byte of the line before the last cache line.
-        // Because size is always a multiple of 4, this is safe to set
-        // "end" to the last byte.
-        //
-        intptr_t start = reinterpret_cast<intptr_t>(code) & (-lineSize);
-        intptr_t end = ((reinterpret_cast<intptr_t>(code) + size - 1) & (-lineSize)) - 1;
-        __builtin___clear_cache(reinterpret_cast<char*>(start), reinterpret_cast<char*>(end));
-#else
-        intptr_t end = reinterpret_cast<intptr_t>(code) + size;
-        __builtin___clear_cache(reinterpret_cast<char*>(code), reinterpret_cast<char*>(end));
-#endif
-#else
-        _flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
-#endif
-    }
-#elif CPU(ARM_THUMB2) && OS(IOS)
-    static void cacheFlush(void* code, size_t size)
-    {
-        sys_cache_control(kCacheFunctionPrepareForExecution, code, size);
-    }
-#elif CPU(ARM_THUMB2) && OS(LINUX)
-    static void cacheFlush(void* code, size_t size)
-    {
-        asm volatile (
-            "push    {r7}\n"
-            "mov     r0, %0\n"
-            "mov     r1, %1\n"
-            "movw    r7, #0x2\n"
-            "movt    r7, #0xf\n"
-            "movs    r2, #0x0\n"
-            "svc     0x0\n"
-            "pop     {r7}\n"
-            :
-            : "r" (code), "r" (reinterpret_cast<char*>(code) + size)
-            : "r0", "r1", "r2");
-    }
-#elif OS(SYMBIAN)
-    static void cacheFlush(void* code, size_t size)
-    {
-        User::IMB_Range(code, static_cast<char*>(code) + size);
-    }
-#elif CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT)
-    static __asm void cacheFlush(void* code, size_t size);
-#elif CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(GCC)
-    static void cacheFlush(void* code, size_t size)
-    {
-        asm volatile (
-            "push    {r7}\n"
-            "mov     r0, %0\n"
-            "mov     r1, %1\n"
-            "mov     r7, #0xf0000\n"
-            "add     r7, r7, #0x2\n"
-            "mov     r2, #0x0\n"
-            "svc     0x0\n"
-            "pop     {r7}\n"
-            :
-            : "r" (code), "r" (reinterpret_cast<char*>(code) + size)
-            : "r0", "r1", "r2");
-    }
-#elif OS(WINCE)
-    static void cacheFlush(void* code, size_t size)
-    {
-        CacheRangeFlush(code, size, CACHE_SYNC_ALL);
-    }
-#elif PLATFORM(BREWMP)
-    static void cacheFlush(void* code, size_t size)
-    {
-        RefPtr<IMemCache1> memCache = createRefPtrInstance<IMemCache1>(AEECLSID_MemCache1);
-        IMemCache1_ClearCache(memCache.get(), reinterpret_cast<uint32>(code), size, MEMSPACE_CACHE_FLUSH, MEMSPACE_DATACACHE);
-        IMemCache1_ClearCache(memCache.get(), reinterpret_cast<uint32>(code), size, MEMSPACE_CACHE_INVALIDATE, MEMSPACE_INSTCACHE);
-    }
-#elif CPU(SH4) && OS(LINUX)
-    static void cacheFlush(void* code, size_t size)
-    {
-#ifdef CACHEFLUSH_D_L2
-        syscall(__NR_cacheflush, reinterpret_cast<unsigned>(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I | CACHEFLUSH_D_L2);
-#else
-        syscall(__NR_cacheflush, reinterpret_cast<unsigned>(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I);
-#endif
-    }
-#else
-    #error "The cacheFlush support is missing on this platform."
-#endif
     static size_t committedByteCount();
 
 private:
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
     static void reprotectRegion(void*, size_t, ProtectionSetting);
     static size_t committedByteCount();
 
 private:
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
     static void reprotectRegion(void*, size_t, ProtectionSetting);
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
+    // We create a MetaAllocator for each JS global object.
+    OwnPtr<DemandExecutableAllocator> m_allocator;
+    DemandExecutableAllocator* allocator() { return m_allocator.get(); }
+#endif
 #endif
 
 #endif
 
-    RefPtr<ExecutablePool> m_smallAllocationPool;
-    static void intializePageSize();
 };
 
 };
 
-inline ExecutablePool::ExecutablePool(JSGlobalData& globalData, size_t n)
-{
-    size_t allocSize = roundUpAllocationSize(n, JIT_ALLOCATOR_PAGE_SIZE);
-    Allocation mem = systemAlloc(allocSize);
-    if (!mem.base()) {
-        releaseExecutableMemory(globalData);
-        mem = systemAlloc(allocSize);
-    }
-    m_pools.append(mem);
-    m_freePtr = static_cast<char*>(mem.base());
-    if (!m_freePtr)
-        CRASH(); // Failed to allocate
-    m_end = m_freePtr + allocSize;
-}
-
-inline void* ExecutablePool::poolAllocate(JSGlobalData& globalData, size_t n)
-{
-    size_t allocSize = roundUpAllocationSize(n, JIT_ALLOCATOR_PAGE_SIZE);
-    
-    Allocation result = systemAlloc(allocSize);
-    if (!result.base()) {
-        releaseExecutableMemory(globalData);
-        result = systemAlloc(allocSize);
-        if (!result.base())
-            CRASH(); // Failed to allocate
-    }
-    
-    ASSERT(m_end >= m_freePtr);
-    if ((allocSize - n) > static_cast<size_t>(m_end - m_freePtr)) {
-        // Replace allocation pool
-        m_freePtr = static_cast<char*>(result.base()) + n;
-        m_end = static_cast<char*>(result.base()) + allocSize;
-    }
-
-    m_pools.append(result);
-    return result.base();
-}
-
-}
 
 #else
 
 
 #else
 
-namespace JSC {
 
 class ExecutableAllocator {
 public: 
     static size_t committedByteCount();
 };
 
 
 class ExecutableAllocator {
 public: 
     static size_t committedByteCount();
 };
 
-} // namespace JSC
 
 #endif // ENABLE(JIT) && ENABLE(ASSEMBLER)
 
 
 #endif // ENABLE(JIT) && ENABLE(ASSEMBLER)
 
+} // namespace JSC
+
 #endif // !defined(ExecutableAllocator)
 #endif // !defined(ExecutableAllocator)
index 792e931497faaf73e1cee7e3077beaece67bd853..65a3a7371c5d48a192d3a1c168088ba707dde739 100644 (file)
 
 #if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
 
 
 #if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
 
+#include "CodeProfiling.h"
 #include <errno.h>
 #include <errno.h>
-
-#include "TCSpinLock.h"
 #include <sys/mman.h>
 #include <unistd.h>
 #include <sys/mman.h>
 #include <unistd.h>
-#include <wtf/AVLTree.h>
+#include <wtf/MetaAllocator.h>
 #include <wtf/PageReservation.h>
 #include <wtf/VMTags.h>
 
 #include <wtf/PageReservation.h>
 #include <wtf/VMTags.h>
 
@@ -48,491 +47,145 @@ using namespace WTF;
 
 namespace JSC {
     
 
 namespace JSC {
     
-#define TwoPow(n) (1ull << n)
-
-class AllocationTableSizeClass {
-public:
-    AllocationTableSizeClass(size_t size, size_t blockSize, unsigned log2BlockSize)
-        : m_blockSize(blockSize)
-    {
-        ASSERT(blockSize == TwoPow(log2BlockSize));
-
-        // Calculate the number of blocks needed to hold size.
-        size_t blockMask = blockSize - 1;
-        m_blockCount = (size + blockMask) >> log2BlockSize;
-
-        // Align to the smallest power of two >= m_blockCount.
-        m_blockAlignment = 1;
-        while (m_blockAlignment < m_blockCount)
-            m_blockAlignment += m_blockAlignment;
-    }
-
-    size_t blockSize() const { return m_blockSize; }
-    size_t blockCount() const { return m_blockCount; }
-    size_t blockAlignment() const { return m_blockAlignment; }
-
-    size_t size()
-    {
-        return m_blockSize * m_blockCount;
-    }
-
-private:
-    size_t m_blockSize;
-    size_t m_blockCount;
-    size_t m_blockAlignment;
-};
-
-template<unsigned log2Entries>
-class AllocationTableLeaf {
-    typedef uint64_t BitField;
-
-public:
-    static const unsigned log2SubregionSize = 12; // 2^12 == pagesize
-    static const unsigned log2RegionSize = log2SubregionSize + log2Entries;
-
-    static const size_t subregionSize = TwoPow(log2SubregionSize);
-    static const size_t regionSize = TwoPow(log2RegionSize);
-    static const unsigned entries = TwoPow(log2Entries);
-    COMPILE_ASSERT(entries <= (sizeof(BitField) * 8), AllocationTableLeaf_entries_fit_in_BitField);
-
-    AllocationTableLeaf()
-        : m_allocated(0)
-    {
-    }
-
-    ~AllocationTableLeaf()
-    {
-        ASSERT(isEmpty());
-    }
-
-    size_t allocate(AllocationTableSizeClass& sizeClass)
-    {
-        ASSERT(sizeClass.blockSize() == subregionSize);
-        ASSERT(!isFull());
-
-        size_t alignment = sizeClass.blockAlignment();
-        size_t count = sizeClass.blockCount();
-        // Use this mask to check for spans of free blocks.
-        BitField mask = ((1ull << count) - 1) << (alignment - count);
-
-        // Step in units of alignment size.
-        for (unsigned i = 0; i < entries; i += alignment) {
-            if (!(m_allocated & mask)) {
-                m_allocated |= mask;
-                return (i + (alignment - count)) << log2SubregionSize;
-            }
-            mask <<= alignment;
-        }
-        return notFound;
-    }
-
-    void free(size_t location, AllocationTableSizeClass& sizeClass)
-    {
-        ASSERT(sizeClass.blockSize() == subregionSize);
-
-        size_t entry = location >> log2SubregionSize;
-        size_t count = sizeClass.blockCount();
-        BitField mask = ((1ull << count) - 1) << entry;
-
-        ASSERT((m_allocated & mask) == mask);
-        m_allocated &= ~mask;
-    }
-
-    bool isEmpty()
-    {
-        return !m_allocated;
-    }
-
-    bool isFull()
-    {
-        return !~m_allocated;
-    }
-
-    static size_t size()
-    {
-        return regionSize;
-    }
-
-    static AllocationTableSizeClass classForSize(size_t size)
-    {
-        return AllocationTableSizeClass(size, subregionSize, log2SubregionSize);
-    }
-
-#ifndef NDEBUG
-    void dump(size_t parentOffset = 0, unsigned indent = 0)
-    {
-        for (unsigned i = 0; i < indent; ++i)
-            fprintf(stderr, "    ");
-        fprintf(stderr, "%08x: [%016llx]\n", (int)parentOffset, m_allocated);
-    }
+#if CPU(ARM)
+static const size_t fixedPoolSize = 16 * 1024 * 1024;
+#elif CPU(X86_64)
+static const size_t fixedPoolSize = 1024 * 1024 * 1024;
+#else
+static const size_t fixedPoolSize = 32 * 1024 * 1024;
 #endif
 
 #endif
 
-private:
-    BitField m_allocated;
-};
-
-
-template<class NextLevel>
-class LazyAllocationTable {
+class FixedVMPoolExecutableAllocator : public MetaAllocator {
 public:
 public:
-    static const unsigned log2RegionSize = NextLevel::log2RegionSize;
-    static const unsigned entries = NextLevel::entries;
-
-    LazyAllocationTable()
-        : m_ptr(0)
-    {
-    }
-
-    ~LazyAllocationTable()
-    {
-        ASSERT(isEmpty());
-    }
-
-    size_t allocate(AllocationTableSizeClass& sizeClass)
-    {
-        if (!m_ptr)
-            m_ptr = new NextLevel();
-        return m_ptr->allocate(sizeClass);
-    }
-
-    void free(size_t location, AllocationTableSizeClass& sizeClass)
+    FixedVMPoolExecutableAllocator()
+        : MetaAllocator(32) // round up all allocations to 32 bytes
     {
     {
-        ASSERT(m_ptr);
-        m_ptr->free(location, sizeClass);
-        if (m_ptr->isEmpty()) {
-            delete m_ptr;
-            m_ptr = 0;
+        m_reservation = PageReservation::reserveWithGuardPages(fixedPoolSize, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
+#if !(ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
+        if (!m_reservation)
+            CRASH();
+#endif
+        if (m_reservation) {
+            ASSERT(m_reservation.size() == fixedPoolSize);
+            addFreshFreeSpace(m_reservation.base(), m_reservation.size());
         }
     }
         }
     }
-
-    bool isEmpty()
-    {
-        return !m_ptr;
-    }
-
-    bool isFull()
-    {
-        return m_ptr && m_ptr->isFull();
-    }
-
-    static size_t size()
+    
+protected:
+    virtual void* allocateNewSpace(size_t&)
     {
     {
-        return NextLevel::size();
+        // We're operating in a fixed pool, so new allocation is always prohibited.
+        return 0;
     }
     }
-
-#ifndef NDEBUG
-    void dump(size_t parentOffset = 0, unsigned indent = 0)
+    
+    virtual void notifyNeedPage(void* page)
     {
     {
-        ASSERT(m_ptr);
-        m_ptr->dump(parentOffset, indent);
-    }
+#if OS(DARWIN)
+        UNUSED_PARAM(page);
+#else
+        m_reservation.commit(page, pageSize());
 #endif
 #endif
-
-    static AllocationTableSizeClass classForSize(size_t size)
-    {
-        return NextLevel::classForSize(size);
     }
     }
-
-private:
-    NextLevel* m_ptr;
-};
-
-template<class NextLevel, unsigned log2Entries>
-class AllocationTableDirectory {
-    typedef uint64_t BitField;
-
-public:
-    static const unsigned log2SubregionSize = NextLevel::log2RegionSize;
-    static const unsigned log2RegionSize = log2SubregionSize + log2Entries;
-
-    static const size_t subregionSize = TwoPow(log2SubregionSize);
-    static const size_t regionSize = TwoPow(log2RegionSize);
-    static const unsigned entries = TwoPow(log2Entries);
-    COMPILE_ASSERT(entries <= (sizeof(BitField) * 8), AllocationTableDirectory_entries_fit_in_BitField);
-
-    AllocationTableDirectory()
-        : m_full(0)
-        , m_hasSuballocation(0)
-    {
-    }
-
-    ~AllocationTableDirectory()
-    {
-        ASSERT(isEmpty());
-    }
-
-    size_t allocate(AllocationTableSizeClass& sizeClass)
-    {
-        ASSERT(sizeClass.blockSize() <= subregionSize);
-        ASSERT(!isFull());
-
-        if (sizeClass.blockSize() < subregionSize) {
-            BitField bit = 1;
-            for (unsigned i = 0; i < entries; ++i, bit += bit) {
-                if (m_full & bit)
-                    continue;
-                size_t location = m_suballocations[i].allocate(sizeClass);
-                if (location != notFound) {
-                    // If this didn't already have a subregion, it does now!
-                    m_hasSuballocation |= bit;
-                    // Mirror the suballocation's full bit.
-                    if (m_suballocations[i].isFull())
-                        m_full |= bit;
-                    return (i * subregionSize) | location;
-                }
-            }
-            return notFound;
-        }
-
-        // A block is allocated if either it is fully allocated or contains suballocations.
-        BitField allocated = m_full | m_hasSuballocation;
-
-        size_t alignment = sizeClass.blockAlignment();
-        size_t count = sizeClass.blockCount();
-        // Use this mask to check for spans of free blocks.
-        BitField mask = ((1ull << count) - 1) << (alignment - count);
-
-        // Step in units of alignment size.
-        for (unsigned i = 0; i < entries; i += alignment) {
-            if (!(allocated & mask)) {
-                m_full |= mask;
-                return (i + (alignment - count)) << log2SubregionSize;
+    
+    virtual void notifyPageIsFree(void* page)
+    {
+#if OS(DARWIN)
+        for (;;) {
+            int result = madvise(page, pageSize(), MADV_FREE);
+            if (!result)
+                return;
+            ASSERT(result == -1);
+            if (errno != EAGAIN) {
+                ASSERT_NOT_REACHED(); // In debug mode, this should be a hard failure.
+                break; // In release mode, we should just ignore the error - not returning memory to the OS is better than crashing, especially since we _will_ be able to reuse the memory internally anyway.
             }
             }
-            mask <<= alignment;
-        }
-        return notFound;
-    }
-
-    void free(size_t location, AllocationTableSizeClass& sizeClass)
-    {
-        ASSERT(sizeClass.blockSize() <= subregionSize);
-
-        size_t entry = location >> log2SubregionSize;
-
-        if (sizeClass.blockSize() < subregionSize) {
-            BitField bit = 1ull << entry;
-            m_suballocations[entry].free(location & (subregionSize - 1), sizeClass);
-            // Check if the suballocation is now empty.
-            if (m_suballocations[entry].isEmpty())
-                m_hasSuballocation &= ~bit;
-            // No need to check, it clearly isn't full any more!
-            m_full &= ~bit;
-        } else {
-            size_t count = sizeClass.blockCount();
-            BitField mask = ((1ull << count) - 1) << entry;
-            ASSERT((m_full & mask) == mask);
-            ASSERT(!(m_hasSuballocation & mask));
-            m_full &= ~mask;
-        }
-    }
-
-    bool isEmpty()
-    {
-        return !(m_full | m_hasSuballocation);
-    }
-
-    bool isFull()
-    {   
-        return !~m_full;
-    }
-
-    static size_t size()
-    {
-        return regionSize;
-    }
-
-    static AllocationTableSizeClass classForSize(size_t size)
-    {
-        if (size < subregionSize) {
-            AllocationTableSizeClass sizeClass = NextLevel::classForSize(size);
-            if (sizeClass.size() < NextLevel::size())
-                return sizeClass;
-        }
-        return AllocationTableSizeClass(size, subregionSize, log2SubregionSize);
-    }
-
-#ifndef NDEBUG
-    void dump(size_t parentOffset = 0, unsigned indent = 0)
-    {
-        for (unsigned i = 0; i < indent; ++i)
-            fprintf(stderr, "    ");
-        fprintf(stderr, "%08x: [", (int)parentOffset);
-        for (unsigned i = 0; i < entries; ++i) {
-            BitField bit = 1ull << i;
-            char c = m_hasSuballocation & bit
-                ? (m_full & bit ? 'N' : 'n')
-                : (m_full & bit ? 'F' : '-');
-            fprintf(stderr, "%c", c);
-        }
-        fprintf(stderr, "]\n");
-
-        for (unsigned i = 0; i < entries; ++i) {
-            BitField bit = 1ull << i;
-            size_t offset = parentOffset | (subregionSize * i);
-            if (m_hasSuballocation & bit)
-                m_suballocations[i].dump(offset, indent + 1);
         }
         }
-    }
-#endif
-
-private:
-    NextLevel m_suballocations[entries];
-    // Subregions exist in one of four states:
-    // (1) empty (both bits clear)
-    // (2) fully allocated as a single allocation (m_full set)
-    // (3) partially allocated through suballocations (m_hasSuballocation set)
-    // (4) fully allocated through suballocations (both bits set)
-    BitField m_full;
-    BitField m_hasSuballocation;
-};
-
-
-typedef AllocationTableLeaf<6> PageTables256KB;
-typedef AllocationTableDirectory<PageTables256KB, 6> PageTables16MB;
-typedef AllocationTableDirectory<LazyAllocationTable<PageTables16MB>, 1> PageTables32MB;
-typedef AllocationTableDirectory<LazyAllocationTable<PageTables16MB>, 6> PageTables1GB;
-
-#if CPU(ARM)
-typedef PageTables16MB FixedVMPoolPageTables;
-#elif CPU(X86_64)
-typedef PageTables1GB FixedVMPoolPageTables;
 #else
 #else
-typedef PageTables32MB FixedVMPoolPageTables;
+        m_reservation.decommit(page, pageSize());
 #endif
 #endif
-
-
-class FixedVMPoolAllocator
-{
-public:
-    FixedVMPoolAllocator()
-    {
-        ASSERT(PageTables256KB::size() == 256 * 1024);
-        ASSERT(PageTables16MB::size() == 16 * 1024 * 1024);
-        ASSERT(PageTables32MB::size() == 32 * 1024 * 1024);
-        ASSERT(PageTables1GB::size() == 1024 * 1024 * 1024);
-
-        m_reservation = PageReservation::reserveWithGuardPages(FixedVMPoolPageTables::size(), OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
-#if !ENABLE(INTERPRETER)
-        if (!isValid())
-            CRASH();
-#endif
-    }
-    ExecutablePool::Allocation alloc(size_t requestedSize)
-    {
-        ASSERT(requestedSize);
-        AllocationTableSizeClass sizeClass = classForSize(requestedSize);
-        size_t size = sizeClass.size();
-        ASSERT(size);
-
-        if (size >= FixedVMPoolPageTables::size())
-            return ExecutablePool::Allocation(0, 0);
-        if (m_pages.isFull())
-            return ExecutablePool::Allocation(0, 0);
-
-        size_t offset = m_pages.allocate(sizeClass);
-        if (offset == notFound)
-            return ExecutablePool::Allocation(0, 0);
-
-        void* pointer = offsetToPointer(offset);
-        m_reservation.commit(pointer, size);
-        return ExecutablePool::Allocation(pointer, size);
-    }
-
-    void free(ExecutablePool::Allocation allocation)
-    {
-        void* pointer = allocation.base();
-        size_t size = allocation.size();
-        ASSERT(size);
-
-        m_reservation.decommit(pointer, size);
-
-        AllocationTableSizeClass sizeClass = classForSize(size);
-        ASSERT(sizeClass.size() == size);
-        m_pages.free(pointerToOffset(pointer), sizeClass);
-    }
-
-    size_t allocated()
-    {
-        return m_reservation.committed();
-    }
-
-    bool isValid() const
-    {
-        return !!m_reservation;
     }
 
 private:
     }
 
 private:
-    AllocationTableSizeClass classForSize(size_t size)
-    {
-        return FixedVMPoolPageTables::classForSize(size);
-    }
-
-    void* offsetToPointer(size_t offset)
-    {
-        return reinterpret_cast<void*>(reinterpret_cast<intptr_t>(m_reservation.base()) + offset);
-    }
-
-    size_t pointerToOffset(void* pointer)
-    {
-        return reinterpret_cast<intptr_t>(pointer) - reinterpret_cast<intptr_t>(m_reservation.base());
-    }
-
     PageReservation m_reservation;
     PageReservation m_reservation;
-    FixedVMPoolPageTables m_pages;
 };
 
 };
 
+static FixedVMPoolExecutableAllocator* allocator;
 
 
-static SpinLock spinlock = SPINLOCK_INITIALIZER;
-static FixedVMPoolAllocator* allocator = 0;
-
+void ExecutableAllocator::initializeAllocator()
+{
+    ASSERT(!allocator);
+    allocator = new FixedVMPoolExecutableAllocator();
+    CodeProfiling::notifyAllocator(allocator);
+}
 
 
-size_t ExecutableAllocator::committedByteCount()
+ExecutableAllocator::ExecutableAllocator(JSGlobalData&)
 {
 {
-    SpinLockHolder lockHolder(&spinlock);
-    return allocator ? allocator->allocated() : 0;
-}   
+    ASSERT(allocator);
+}
 
 
-void ExecutableAllocator::intializePageSize()
+ExecutableAllocator::~ExecutableAllocator()
 {
 {
-    ExecutableAllocator::pageSize = getpagesize();
 }
 
 bool ExecutableAllocator::isValid() const
 {
 }
 
 bool ExecutableAllocator::isValid() const
 {
-    SpinLockHolder lock_holder(&spinlock);
-    if (!allocator)
-        allocator = new FixedVMPoolAllocator();
-    return allocator->isValid();
+    return !!allocator->bytesReserved();
 }
 
 bool ExecutableAllocator::underMemoryPressure()
 {
 }
 
 bool ExecutableAllocator::underMemoryPressure()
 {
-    // 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));
+    MetaAllocator::Statistics statistics = allocator->currentStatistics();
+    return statistics.bytesAllocated > statistics.bytesReserved / 2;
 }
 
 }
 
-ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size)
+double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage)
 {
 {
-    SpinLockHolder lock_holder(&spinlock);
-    ASSERT(allocator);
-    return allocator->alloc(size);
+    MetaAllocator::Statistics statistics = allocator->currentStatistics();
+    ASSERT(statistics.bytesAllocated <= statistics.bytesReserved);
+    size_t bytesAllocated = statistics.bytesAllocated + addedMemoryUsage;
+    if (bytesAllocated >= statistics.bytesReserved)
+        bytesAllocated = statistics.bytesReserved;
+    double result = 1.0;
+    size_t divisor = statistics.bytesReserved - bytesAllocated;
+    if (divisor)
+        result = static_cast<double>(statistics.bytesReserved) / divisor;
+    if (result < 1.0)
+        result = 1.0;
+    return result;
 }
 
 }
 
-void ExecutablePool::systemRelease(ExecutablePool::Allocation& allocation) 
+PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData& globalData, size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort)
 {
 {
-    SpinLockHolder lock_holder(&spinlock);
-    ASSERT(allocator);
-    allocator->free(allocation);
+    RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes, ownerUID);
+    if (!result) {
+        if (effort == JITCompilationCanFail)
+            return result;
+        releaseExecutableMemory(globalData);
+        result = allocator->allocate(sizeInBytes, ownerUID);
+        if (!result)
+            CRASH();
+    }
+    return result.release();
 }
 
 }
 
+size_t ExecutableAllocator::committedByteCount()
+{
+    return allocator->bytesCommitted();
+}
+
+#if ENABLE(META_ALLOCATOR_PROFILE)
+void ExecutableAllocator::dumpProfile()
+{
+    allocator->dumpProfile();
+}
+#endif
+
 }
 
 
 }
 
 
-#endif // HAVE(ASSEMBLER)
+#endif // ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
 
 
-#if !ENABLE(JIT)
+#if !ENABLE(ASSEMBLER)
 // FIXME: Needed to satisfy JavaScriptCore.exp requirements when building only the interpreter.
 namespace JSC {
 size_t ExecutableAllocator::committedByteCount()
 // FIXME: Needed to satisfy JavaScriptCore.exp requirements when building only the interpreter.
 namespace JSC {
 size_t ExecutableAllocator::committedByteCount()
diff --git a/jit/HostCallReturnValue.cpp b/jit/HostCallReturnValue.cpp
new file mode 100644 (file)
index 0000000..9d449c3
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "HostCallReturnValue.h"
+
+#include "CallFrame.h"
+#include <wtf/InlineASM.h>
+#include "JSObject.h"
+#include "JSValueInlineMethods.h"
+#include "ScopeChain.h"
+
+namespace JSC {
+
+// Nothing to see here.
+
+} // namespace JSC
+
diff --git a/jit/HostCallReturnValue.h b/jit/HostCallReturnValue.h
new file mode 100644 (file)
index 0000000..12fe10b
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef HostCallReturnValue_h
+#define HostCallReturnValue_h
+
+#include "JSValue.h"
+#include "MacroAssemblerCodeRef.h"
+#include <wtf/Platform.h>
+
+// Unfortunately this only works on GCC-like compilers. And it's currently only used
+// by LLInt and DFG, which also are restricted to GCC-like compilers. We should
+// probably fix that at some point.
+#if COMPILER(GCC)
+
+#if CALLING_CONVENTION_IS_STDCALL
+#define HOST_CALL_RETURN_VALUE_OPTION CDECL
+#else
+#define HOST_CALL_RETURN_VALUE_OPTION
+#endif
+
+namespace JSC {
+
+extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue();
+
+// This is a public declaration only to convince CLANG not to elide it.
+extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState*);
+
+inline void initializeHostCallReturnValue()
+{
+    getHostCallReturnValueWithExecState(0);
+}
+
+}
+
+#else // COMPILER(GCC)
+
+namespace JSC {
+inline void initializeHostCallReturnValue() { }
+}
+
+#endif // COMPILER(GCC)
+
+#endif // HostCallReturnValue_h
+
index 26e1f630f924642e1677a694abc34e61b8822393..01b1260c991be4f544c3a5bbe37e482842792604 100644 (file)
@@ -35,7 +35,8 @@ JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse
 #endif
 
 #include "CodeBlock.h"
 #endif
 
 #include "CodeBlock.h"
-#include "CryptographicallyRandomNumber.h"
+#include <wtf/CryptographicallyRandomNumber.h>
+#include "DFGNode.h" // for DFG_SUCCESS_STATS
 #include "Interpreter.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
 #include "Interpreter.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
@@ -45,7 +46,6 @@ 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"
-#include "dfg/DFGNode.h" // for DFG_SUCCESS_STATS
 
 using namespace std;
 
 
 using namespace std;
 
@@ -73,14 +73,12 @@ JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock)
     : m_interpreter(globalData->interpreter)
     , m_globalData(globalData)
     , m_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_labels(codeBlock ? codeBlock->numberOfInstructions() : 0)
     , m_bytecodeOffset((unsigned)-1)
 #if USE(JSVALUE32_64)
     , m_jumpTargetIndex(0)
     , m_mappedBytecodeOffset((unsigned)-1)
     , m_bytecodeOffset((unsigned)-1)
 #if USE(JSVALUE32_64)
     , m_jumpTargetIndex(0)
     , m_mappedBytecodeOffset((unsigned)-1)
-    , m_mappedVirtualRegisterIndex((unsigned)-1)
+    , m_mappedVirtualRegisterIndex(RegisterFile::ReturnPC)
     , m_mappedTag((RegisterID)-1)
     , m_mappedPayload((RegisterID)-1)
 #else
     , m_mappedTag((RegisterID)-1)
     , m_mappedPayload((RegisterID)-1)
 #else
@@ -95,7 +93,33 @@ JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock)
 {
 }
 
 {
 }
 
-#if USE(JSVALUE32_64)
+#if ENABLE(DFG_JIT)
+void JIT::emitOptimizationCheck(OptimizationCheckKind kind)
+{
+    if (!shouldEmitProfiling())
+        return;
+    
+    Jump skipOptimize = branchAdd32(Signed, TrustedImm32(kind == LoopOptimizationCheck ? Options::executionCounterIncrementForLoop : Options::executionCounterIncrementForReturn), AbsoluteAddress(m_codeBlock->addressOfJITExecuteCounter()));
+    JITStubCall stubCall(this, kind == LoopOptimizationCheck ? cti_optimize_from_loop : cti_optimize_from_ret);
+    if (kind == LoopOptimizationCheck)
+        stubCall.addArgument(TrustedImm32(m_bytecodeOffset));
+    stubCall.call();
+    skipOptimize.link(this);
+}
+#endif
+
+#if CPU(X86)
+void JIT::emitTimeoutCheck()
+{
+    Jump skipTimeout = branchSub32(NonZero, TrustedImm32(1), AbsoluteAddress(&m_globalData->m_timeoutCount));
+    JITStubCall stubCall(this, cti_timeout_check);
+    stubCall.addArgument(regT1, regT0); // save last result registers.
+    stubCall.call(regT0);
+    store32(regT0, &m_globalData->m_timeoutCount);
+    stubCall.getArgument(0, regT1, regT0); // reload last result registers.
+    skipTimeout.link(this);
+}
+#elif USE(JSVALUE32_64)
 void JIT::emitTimeoutCheck()
 {
     Jump skipTimeout = branchSub32(NonZero, TrustedImm32(1), timeoutCheckRegister);
 void JIT::emitTimeoutCheck()
 {
     Jump skipTimeout = branchSub32(NonZero, TrustedImm32(1), timeoutCheckRegister);
@@ -175,7 +199,6 @@ void JIT::privateCompileMainPass()
     Instruction* instructionsBegin = m_codeBlock->instructions().begin();
     unsigned instructionCount = m_codeBlock->instructions().size();
 
     Instruction* instructionsBegin = m_codeBlock->instructions().begin();
     unsigned instructionCount = m_codeBlock->instructions().size();
 
-    m_propertyAccessInstructionIndex = 0;
     m_globalResolveInfoIndex = 0;
     m_callLinkInfoIndex = 0;
 
     m_globalResolveInfoIndex = 0;
     m_callLinkInfoIndex = 0;
 
@@ -195,25 +218,23 @@ void JIT::privateCompileMainPass()
 
         m_labels[m_bytecodeOffset] = label();
 
 
         m_labels[m_bytecodeOffset] = label();
 
+#if ENABLE(JIT_VERBOSE)
+        dataLog("Old JIT emitting code for bc#%u at offset 0x%lx.\n", m_bytecodeOffset, (long)debugOffset());
+#endif
+
         switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
         DEFINE_BINARY_OP(op_del_by_val)
         DEFINE_BINARY_OP(op_in)
         DEFINE_BINARY_OP(op_less)
         DEFINE_BINARY_OP(op_lesseq)
         switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
         DEFINE_BINARY_OP(op_del_by_val)
         DEFINE_BINARY_OP(op_in)
         DEFINE_BINARY_OP(op_less)
         DEFINE_BINARY_OP(op_lesseq)
-        DEFINE_UNARY_OP(op_is_boolean)
+        DEFINE_BINARY_OP(op_greater)
+        DEFINE_BINARY_OP(op_greatereq)
         DEFINE_UNARY_OP(op_is_function)
         DEFINE_UNARY_OP(op_is_function)
-        DEFINE_UNARY_OP(op_is_number)
         DEFINE_UNARY_OP(op_is_object)
         DEFINE_UNARY_OP(op_is_object)
-        DEFINE_UNARY_OP(op_is_string)
-        DEFINE_UNARY_OP(op_is_undefined)
-#if USE(JSVALUE64)
-        DEFINE_UNARY_OP(op_negate)
-#endif
         DEFINE_UNARY_OP(op_typeof)
 
         DEFINE_OP(op_add)
         DEFINE_OP(op_bitand)
         DEFINE_UNARY_OP(op_typeof)
 
         DEFINE_OP(op_add)
         DEFINE_OP(op_bitand)
-        DEFINE_OP(op_bitnot)
         DEFINE_OP(op_bitor)
         DEFINE_OP(op_bitxor)
         DEFINE_OP(op_call)
         DEFINE_OP(op_bitor)
         DEFINE_OP(op_bitxor)
         DEFINE_OP(op_call)
@@ -224,7 +245,6 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_get_callee)
         DEFINE_OP(op_create_this)
         DEFINE_OP(op_convert_this)
         DEFINE_OP(op_get_callee)
         DEFINE_OP(op_create_this)
         DEFINE_OP(op_convert_this)
-        DEFINE_OP(op_convert_this_strict)
         DEFINE_OP(op_init_lazy_reg)
         DEFINE_OP(op_create_arguments)
         DEFINE_OP(op_debug)
         DEFINE_OP(op_init_lazy_reg)
         DEFINE_OP(op_create_arguments)
         DEFINE_OP(op_debug)
@@ -245,22 +265,31 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_get_scoped_var)
         DEFINE_OP(op_check_has_instance)
         DEFINE_OP(op_instanceof)
         DEFINE_OP(op_get_scoped_var)
         DEFINE_OP(op_check_has_instance)
         DEFINE_OP(op_instanceof)
+        DEFINE_OP(op_is_undefined)
+        DEFINE_OP(op_is_boolean)
+        DEFINE_OP(op_is_number)
+        DEFINE_OP(op_is_string)
         DEFINE_OP(op_jeq_null)
         DEFINE_OP(op_jfalse)
         DEFINE_OP(op_jmp)
         DEFINE_OP(op_jmp_scopes)
         DEFINE_OP(op_jneq_null)
         DEFINE_OP(op_jneq_ptr)
         DEFINE_OP(op_jeq_null)
         DEFINE_OP(op_jfalse)
         DEFINE_OP(op_jmp)
         DEFINE_OP(op_jmp_scopes)
         DEFINE_OP(op_jneq_null)
         DEFINE_OP(op_jneq_ptr)
-        DEFINE_OP(op_jnless)
         DEFINE_OP(op_jless)
         DEFINE_OP(op_jlesseq)
         DEFINE_OP(op_jless)
         DEFINE_OP(op_jlesseq)
+        DEFINE_OP(op_jgreater)
+        DEFINE_OP(op_jgreatereq)
+        DEFINE_OP(op_jnless)
         DEFINE_OP(op_jnlesseq)
         DEFINE_OP(op_jnlesseq)
-        DEFINE_OP(op_jsr)
+        DEFINE_OP(op_jngreater)
+        DEFINE_OP(op_jngreatereq)
         DEFINE_OP(op_jtrue)
         DEFINE_OP(op_jtrue)
-        DEFINE_OP(op_load_varargs)
         DEFINE_OP(op_loop)
         DEFINE_OP(op_loop)
+        DEFINE_OP(op_loop_hint)
         DEFINE_OP(op_loop_if_less)
         DEFINE_OP(op_loop_if_lesseq)
         DEFINE_OP(op_loop_if_less)
         DEFINE_OP(op_loop_if_lesseq)
+        DEFINE_OP(op_loop_if_greater)
+        DEFINE_OP(op_loop_if_greatereq)
         DEFINE_OP(op_loop_if_true)
         DEFINE_OP(op_loop_if_false)
         DEFINE_OP(op_lshift)
         DEFINE_OP(op_loop_if_true)
         DEFINE_OP(op_loop_if_false)
         DEFINE_OP(op_lshift)
@@ -268,9 +297,7 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_mod)
         DEFINE_OP(op_mov)
         DEFINE_OP(op_mul)
         DEFINE_OP(op_mod)
         DEFINE_OP(op_mov)
         DEFINE_OP(op_mul)
-#if USE(JSVALUE32_64)
         DEFINE_OP(op_negate)
         DEFINE_OP(op_negate)
-#endif
         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)
@@ -291,13 +318,14 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_profile_will_call)
         DEFINE_OP(op_push_new_scope)
         DEFINE_OP(op_push_scope)
         DEFINE_OP(op_profile_will_call)
         DEFINE_OP(op_push_new_scope)
         DEFINE_OP(op_push_scope)
+        case op_put_by_id_transition_direct:
+        case op_put_by_id_transition_normal:
         DEFINE_OP(op_put_by_id)
         DEFINE_OP(op_put_by_index)
         DEFINE_OP(op_put_by_val)
         DEFINE_OP(op_put_by_id)
         DEFINE_OP(op_put_by_index)
         DEFINE_OP(op_put_by_val)
-        DEFINE_OP(op_put_getter)
+        DEFINE_OP(op_put_getter_setter)
         DEFINE_OP(op_put_global_var)
         DEFINE_OP(op_put_scoped_var)
         DEFINE_OP(op_put_global_var)
         DEFINE_OP(op_put_scoped_var)
-        DEFINE_OP(op_put_setter)
         DEFINE_OP(op_resolve)
         DEFINE_OP(op_resolve_base)
         DEFINE_OP(op_ensure_property_exists)
         DEFINE_OP(op_resolve)
         DEFINE_OP(op_resolve_base)
         DEFINE_OP(op_ensure_property_exists)
@@ -305,12 +333,12 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_resolve_global_dynamic)
         DEFINE_OP(op_resolve_skip)
         DEFINE_OP(op_resolve_with_base)
         DEFINE_OP(op_resolve_global_dynamic)
         DEFINE_OP(op_resolve_skip)
         DEFINE_OP(op_resolve_with_base)
+        DEFINE_OP(op_resolve_with_this)
         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_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_strcat)
         DEFINE_OP(op_stricteq)
         DEFINE_OP(op_sub)
         DEFINE_OP(op_strcat)
         DEFINE_OP(op_stricteq)
         DEFINE_OP(op_sub)
@@ -328,19 +356,13 @@ void JIT::privateCompileMainPass()
         case op_get_by_id_chain:
         case op_get_by_id_generic:
         case op_get_by_id_proto:
         case op_get_by_id_chain:
         case op_get_by_id_generic:
         case op_get_by_id_proto:
-        case op_get_by_id_proto_list:
         case op_get_by_id_self:
         case op_get_by_id_self:
-        case op_get_by_id_self_list:
         case op_get_by_id_getter_chain:
         case op_get_by_id_getter_proto:
         case op_get_by_id_getter_chain:
         case op_get_by_id_getter_proto:
-        case op_get_by_id_getter_proto_list:
         case op_get_by_id_getter_self:
         case op_get_by_id_getter_self:
-        case op_get_by_id_getter_self_list:
         case op_get_by_id_custom_chain:
         case op_get_by_id_custom_proto:
         case op_get_by_id_custom_chain:
         case op_get_by_id_custom_proto:
-        case op_get_by_id_custom_proto_list:
         case op_get_by_id_custom_self:
         case op_get_by_id_custom_self:
-        case op_get_by_id_custom_self_list:
         case op_get_string_length:
         case op_put_by_id_generic:
         case op_put_by_id_replace:
         case op_get_string_length:
         case op_put_by_id_generic:
         case op_put_by_id_replace:
@@ -349,8 +371,7 @@ void JIT::privateCompileMainPass()
         }
     }
 
         }
     }
 
-    ASSERT(m_propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
-    ASSERT(m_callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
+    ASSERT(m_callLinkInfoIndex == m_callStructureStubCompilationInfo.size());
 
 #ifndef NDEBUG
     // Reset this, in order to guard its use with ASSERTs.
 
 #ifndef NDEBUG
     // Reset this, in order to guard its use with ASSERTs.
@@ -358,7 +379,6 @@ void JIT::privateCompileMainPass()
 #endif
 }
 
 #endif
 }
 
-
 void JIT::privateCompileLinkPass()
 {
     unsigned jmpTableCount = m_jmpTable.size();
 void JIT::privateCompileLinkPass()
 {
     unsigned jmpTableCount = m_jmpTable.size();
@@ -374,6 +394,16 @@ void JIT::privateCompileSlowCases()
     m_propertyAccessInstructionIndex = 0;
     m_globalResolveInfoIndex = 0;
     m_callLinkInfoIndex = 0;
     m_propertyAccessInstructionIndex = 0;
     m_globalResolveInfoIndex = 0;
     m_callLinkInfoIndex = 0;
+    
+#if !ASSERT_DISABLED && ENABLE(VALUE_PROFILER)
+    // Use this to assert that slow-path code associates new profiling sites with existing
+    // ValueProfiles rather than creating new ones. This ensures that for a given instruction
+    // (say, get_by_id) we get combined statistics for both the fast-path executions of that
+    // instructions and the slow-path executions. Furthermore, if the slow-path code created
+    // new ValueProfiles then the ValueProfiles would no longer be sorted by bytecode offset,
+    // which would break the invariant necessary to use CodeBlock::valueProfileForBytecodeOffset().
+    unsigned numberOfValueProfiles = m_codeBlock->numberOfValueProfiles();
+#endif
 
     for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) {
 #if USE(JSVALUE64)
 
     for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) {
 #if USE(JSVALUE64)
@@ -385,11 +415,20 @@ void JIT::privateCompileSlowCases()
         unsigned firstTo = m_bytecodeOffset;
 #endif
         Instruction* currentInstruction = instructionsBegin + m_bytecodeOffset;
         unsigned firstTo = m_bytecodeOffset;
 #endif
         Instruction* currentInstruction = instructionsBegin + m_bytecodeOffset;
+        
+#if ENABLE(VALUE_PROFILER)
+        RareCaseProfile* rareCaseProfile = 0;
+        if (m_canBeOptimized)
+            rareCaseProfile = m_codeBlock->addRareCaseProfile(m_bytecodeOffset);
+#endif
+
+#if ENABLE(JIT_VERBOSE)
+        dataLog("Old JIT emitting slow code for bc#%u at offset 0x%lx.\n", m_bytecodeOffset, (long)debugOffset());
+#endif
 
         switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
         DEFINE_SLOWCASE_OP(op_add)
         DEFINE_SLOWCASE_OP(op_bitand)
 
         switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
         DEFINE_SLOWCASE_OP(op_add)
         DEFINE_SLOWCASE_OP(op_bitand)
-        DEFINE_SLOWCASE_OP(op_bitnot)
         DEFINE_SLOWCASE_OP(op_bitor)
         DEFINE_SLOWCASE_OP(op_bitxor)
         DEFINE_SLOWCASE_OP(op_call)
         DEFINE_SLOWCASE_OP(op_bitor)
         DEFINE_SLOWCASE_OP(op_bitxor)
         DEFINE_SLOWCASE_OP(op_call)
@@ -397,7 +436,7 @@ void JIT::privateCompileSlowCases()
         DEFINE_SLOWCASE_OP(op_call_varargs)
         DEFINE_SLOWCASE_OP(op_construct)
         DEFINE_SLOWCASE_OP(op_convert_this)
         DEFINE_SLOWCASE_OP(op_call_varargs)
         DEFINE_SLOWCASE_OP(op_construct)
         DEFINE_SLOWCASE_OP(op_convert_this)
-        DEFINE_SLOWCASE_OP(op_convert_this_strict)
+        DEFINE_SLOWCASE_OP(op_create_this)
         DEFINE_SLOWCASE_OP(op_div)
         DEFINE_SLOWCASE_OP(op_eq)
         DEFINE_SLOWCASE_OP(op_get_by_id)
         DEFINE_SLOWCASE_OP(op_div)
         DEFINE_SLOWCASE_OP(op_eq)
         DEFINE_SLOWCASE_OP(op_get_by_id)
@@ -408,30 +447,39 @@ void JIT::privateCompileSlowCases()
         DEFINE_SLOWCASE_OP(op_check_has_instance)
         DEFINE_SLOWCASE_OP(op_instanceof)
         DEFINE_SLOWCASE_OP(op_jfalse)
         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_jless)
         DEFINE_SLOWCASE_OP(op_jlesseq)
         DEFINE_SLOWCASE_OP(op_jless)
         DEFINE_SLOWCASE_OP(op_jlesseq)
+        DEFINE_SLOWCASE_OP(op_jgreater)
+        DEFINE_SLOWCASE_OP(op_jgreatereq)
+        DEFINE_SLOWCASE_OP(op_jnless)
         DEFINE_SLOWCASE_OP(op_jnlesseq)
         DEFINE_SLOWCASE_OP(op_jnlesseq)
+        DEFINE_SLOWCASE_OP(op_jngreater)
+        DEFINE_SLOWCASE_OP(op_jngreatereq)
         DEFINE_SLOWCASE_OP(op_jtrue)
         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_less)
         DEFINE_SLOWCASE_OP(op_loop_if_lesseq)
+        DEFINE_SLOWCASE_OP(op_loop_if_greater)
+        DEFINE_SLOWCASE_OP(op_loop_if_greatereq)
         DEFINE_SLOWCASE_OP(op_loop_if_true)
         DEFINE_SLOWCASE_OP(op_loop_if_false)
         DEFINE_SLOWCASE_OP(op_lshift)
         DEFINE_SLOWCASE_OP(op_method_check)
         DEFINE_SLOWCASE_OP(op_mod)
         DEFINE_SLOWCASE_OP(op_mul)
         DEFINE_SLOWCASE_OP(op_loop_if_true)
         DEFINE_SLOWCASE_OP(op_loop_if_false)
         DEFINE_SLOWCASE_OP(op_lshift)
         DEFINE_SLOWCASE_OP(op_method_check)
         DEFINE_SLOWCASE_OP(op_mod)
         DEFINE_SLOWCASE_OP(op_mul)
-#if USE(JSVALUE32_64)
         DEFINE_SLOWCASE_OP(op_negate)
         DEFINE_SLOWCASE_OP(op_negate)
-#endif
         DEFINE_SLOWCASE_OP(op_neq)
         DEFINE_SLOWCASE_OP(op_neq)
+        DEFINE_SLOWCASE_OP(op_new_array)
+        DEFINE_SLOWCASE_OP(op_new_object)
+        DEFINE_SLOWCASE_OP(op_new_func)
+        DEFINE_SLOWCASE_OP(op_new_func_exp)
         DEFINE_SLOWCASE_OP(op_not)
         DEFINE_SLOWCASE_OP(op_nstricteq)
         DEFINE_SLOWCASE_OP(op_post_dec)
         DEFINE_SLOWCASE_OP(op_post_inc)
         DEFINE_SLOWCASE_OP(op_pre_dec)
         DEFINE_SLOWCASE_OP(op_pre_inc)
         DEFINE_SLOWCASE_OP(op_not)
         DEFINE_SLOWCASE_OP(op_nstricteq)
         DEFINE_SLOWCASE_OP(op_post_dec)
         DEFINE_SLOWCASE_OP(op_post_inc)
         DEFINE_SLOWCASE_OP(op_pre_dec)
         DEFINE_SLOWCASE_OP(op_pre_inc)
+        case op_put_by_id_transition_direct:
+        case op_put_by_id_transition_normal:
         DEFINE_SLOWCASE_OP(op_put_by_id)
         DEFINE_SLOWCASE_OP(op_put_by_val)
         DEFINE_SLOWCASE_OP(op_resolve_global)
         DEFINE_SLOWCASE_OP(op_put_by_id)
         DEFINE_SLOWCASE_OP(op_put_by_val)
         DEFINE_SLOWCASE_OP(op_resolve_global)
@@ -448,14 +496,20 @@ void JIT::privateCompileSlowCases()
 
         ASSERT_WITH_MESSAGE(iter == m_slowCases.end() || firstTo != iter->to,"Not enough jumps linked in slow case codegen.");
         ASSERT_WITH_MESSAGE(firstTo == (iter - 1)->to, "Too many jumps linked in slow case codegen.");
 
         ASSERT_WITH_MESSAGE(iter == m_slowCases.end() || firstTo != iter->to,"Not enough jumps linked in slow case codegen.");
         ASSERT_WITH_MESSAGE(firstTo == (iter - 1)->to, "Too many jumps linked in slow case codegen.");
+        
+#if ENABLE(VALUE_PROFILER)
+        if (m_canBeOptimized)
+            add32(TrustedImm32(1), AbsoluteAddress(&rareCaseProfile->m_counter));
+#endif
 
         emitJumpSlowToHot(jump(), 0);
     }
 
 
         emitJumpSlowToHot(jump(), 0);
     }
 
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-    ASSERT(m_propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
+    ASSERT(m_propertyAccessInstructionIndex == m_propertyAccessCompilationInfo.size());
+    ASSERT(m_callLinkInfoIndex == m_callStructureStubCompilationInfo.size());
+#if ENABLE(VALUE_PROFILER)
+    ASSERT(numberOfValueProfiles == m_codeBlock->numberOfValueProfiles());
 #endif
 #endif
-    ASSERT(m_callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
 
 #ifndef NDEBUG
     // Reset this, in order to guard its use with ASSERTs.
 
 #ifndef NDEBUG
     // Reset this, in order to guard its use with ASSERTs.
@@ -463,15 +517,65 @@ void JIT::privateCompileSlowCases()
 #endif
 }
 
 #endif
 }
 
-JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
+ALWAYS_INLINE void PropertyStubCompilationInfo::copyToStubInfo(StructureStubInfo& info, LinkBuffer &linkBuffer)
+{
+    ASSERT(bytecodeIndex != std::numeric_limits<unsigned>::max());
+    info.bytecodeIndex = bytecodeIndex;
+    info.callReturnLocation = linkBuffer.locationOf(callReturnLocation);
+    info.hotPathBegin = linkBuffer.locationOf(hotPathBegin);
+
+    switch (m_type) {
+    case MethodCheck: {
+        CodeLocationDataLabelPtr structureToCompareLocation = linkBuffer.locationOf(methodCheckStructureToCompare);
+        info.patch.baseline.methodCheckProtoObj = MacroAssembler::differenceBetweenCodePtr(structureToCompareLocation, linkBuffer.locationOf(methodCheckProtoObj));
+        info.patch.baseline.methodCheckProtoStructureToCompare = MacroAssembler::differenceBetweenCodePtr(structureToCompareLocation, linkBuffer.locationOf(methodCheckProtoStructureToCompare));
+        info.patch.baseline.methodCheckPutFunction = MacroAssembler::differenceBetweenCodePtr(structureToCompareLocation, linkBuffer.locationOf(methodCheckPutFunction));
+        // No break - fall through to GetById.
+    }
+    case GetById: {
+        CodeLocationLabel hotPathBeginLocation = linkBuffer.locationOf(hotPathBegin);
+        info.patch.baseline.u.get.structureToCompare = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getStructureToCompare));
+        info.patch.baseline.u.get.structureCheck = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getStructureCheck));
+#if USE(JSVALUE64)
+        info.patch.baseline.u.get.displacementLabel = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getDisplacementLabel));
+#else
+        info.patch.baseline.u.get.displacementLabel1 = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getDisplacementLabel1));
+        info.patch.baseline.u.get.displacementLabel2 = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getDisplacementLabel2));
+#endif
+        info.patch.baseline.u.get.putResult = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getPutResult));
+        info.patch.baseline.u.get.coldPathBegin = MacroAssembler::differenceBetweenCodePtr(linkBuffer.locationOf(getColdPathBegin), linkBuffer.locationOf(callReturnLocation));
+        break;
+    }
+    case PutById:
+        CodeLocationLabel hotPathBeginLocation = linkBuffer.locationOf(hotPathBegin);
+        info.patch.baseline.u.put.structureToCompare = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(putStructureToCompare));
+#if USE(JSVALUE64)
+        info.patch.baseline.u.put.displacementLabel = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(putDisplacementLabel));
+#else
+        info.patch.baseline.u.put.displacementLabel1 = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(putDisplacementLabel1));
+        info.patch.baseline.u.put.displacementLabel2 = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(putDisplacementLabel2));
+#endif
+        break;
+    }
+}
+
+JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffort effort)
 {
 {
+#if ENABLE(JIT_VERBOSE_OSR)
+    printf("Compiling JIT code!\n");
+#endif
+    
+#if ENABLE(VALUE_PROFILER)
+    m_canBeOptimized = m_codeBlock->canCompileWithDFG();
+#endif
+
     // Just add a little bit of randomness to the codegen
     if (m_randomGenerator.getUint32() & 1)
         nop();
 
     // 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);
     preserveReturnAddressAfterCall(regT2);
     emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC);
+    emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
 
     Label beginLabel(this);
 
 
     Label beginLabel(this);
 
@@ -482,19 +586,43 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
 
     Jump registerFileCheck;
     if (m_codeBlock->codeType() == FunctionCode) {
 
     Jump registerFileCheck;
     if (m_codeBlock->codeType() == FunctionCode) {
-#if DFG_SUCCESS_STATS
+#if ENABLE(DFG_JIT)
+#if DFG_ENABLE(SUCCESS_STATS)
         static SamplingCounter counter("orignalJIT");
         emitCount(counter);
 #endif
         static SamplingCounter counter("orignalJIT");
         emitCount(counter);
 #endif
+#endif
 
 
-        // In the case of a fast linked call, we do not set this up in the caller.
-        emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
+#if ENABLE(VALUE_PROFILER)
+        ASSERT(m_bytecodeOffset == (unsigned)-1);
+        if (shouldEmitProfiling()) {
+            for (int argument = 0; argument < m_codeBlock->numParameters(); ++argument) {
+                // If this is a constructor, then we want to put in a dummy profiling site (to
+                // keep things consistent) but we don't actually want to record the dummy value.
+                if (m_codeBlock->m_isConstructor && !argument)
+                    continue;
+                int offset = CallFrame::argumentOffsetIncludingThis(argument) * static_cast<int>(sizeof(Register));
+#if USE(JSVALUE64)
+                loadPtr(Address(callFrameRegister, offset), regT0);
+#elif USE(JSVALUE32_64)
+                load32(Address(callFrameRegister, offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+                load32(Address(callFrameRegister, offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+#endif
+                emitValueProfilingSite(m_codeBlock->valueProfileForArgument(argument));
+            }
+        }
+#endif
 
 
-        addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, regT1);
+        addPtr(TrustedImm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, regT1);
         registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1);
     }
 
     Label functionBody = label();
         registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1);
     }
 
     Label functionBody = label();
+    
+#if ENABLE(VALUE_PROFILER)
+    if (m_canBeOptimized)
+        add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->m_executionEntryCount));
+#endif
 
     privateCompileMainPass();
     privateCompileLinkPass();
 
     privateCompileMainPass();
     privateCompileLinkPass();
@@ -513,17 +641,25 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
         arityCheck = label();
         preserveReturnAddressAfterCall(regT2);
         emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC);
         arityCheck = label();
         preserveReturnAddressAfterCall(regT2);
         emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC);
-        branch32(Equal, regT1, TrustedImm32(m_codeBlock->m_numParameters)).linkTo(beginLabel, this);
-        restoreArgumentReference();
+        emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
 
 
+        load32(payloadFor(RegisterFile::ArgumentCount), regT1);
+        branch32(AboveOrEqual, regT1, TrustedImm32(m_codeBlock->m_numParameters)).linkTo(beginLabel, this);
+
+        m_bytecodeOffset = 0;
         JITStubCall(this, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck).call(callFrameRegister);
         JITStubCall(this, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck).call(callFrameRegister);
+#if !ASSERT_DISABLED
+        m_bytecodeOffset = (unsigned)-1; // Reset this, in order to guard its use with ASSERTs.
+#endif
 
         jump(beginLabel);
     }
 
     ASSERT(m_jmpTable.isEmpty());
 
 
         jump(beginLabel);
     }
 
     ASSERT(m_jmpTable.isEmpty());
 
-    LinkBuffer patchBuffer(*m_globalData, this, m_globalData->executableAllocator);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock, effort);
+    if (patchBuffer.didFailToAllocate())
+        return JITCode();
 
     // Translate vPC offsets into addresses in JIT generated code, for switch tables.
     for (unsigned i = 0; i < m_switches.size(); ++i) {
 
     // Translate vPC offsets into addresses in JIT generated code, for switch tables.
     for (unsigned i = 0; i < m_switches.size(); ++i) {
@@ -569,74 +705,79 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
             m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(patchBuffer.returnAddressOffset(iter->from), iter->bytecodeOffset));
     }
 
             m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(patchBuffer.returnAddressOffset(iter->from), iter->bytecodeOffset));
     }
 
-    // Link absolute addresses for jsr
-    for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
-        patchBuffer.patch(iter->storeLocation, patchBuffer.locationOf(iter->target).executableAddress());
-
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-    for (unsigned i = 0; i < m_codeBlock->numberOfStructureStubInfos(); ++i) {
-        StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
-        info.callReturnLocation = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].callReturnLocation);
-        info.hotPathBegin = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].hotPathBegin);
-    }
-#endif
-#if ENABLE(JIT_OPTIMIZE_CALL)
+    m_codeBlock->setNumberOfStructureStubInfos(m_propertyAccessCompilationInfo.size());
+    for (unsigned i = 0; i < m_propertyAccessCompilationInfo.size(); ++i)
+        m_propertyAccessCompilationInfo[i].copyToStubInfo(m_codeBlock->structureStubInfo(i), patchBuffer);
+    m_codeBlock->setNumberOfCallLinkInfos(m_callStructureStubCompilationInfo.size());
     for (unsigned i = 0; i < m_codeBlock->numberOfCallLinkInfos(); ++i) {
         CallLinkInfo& info = m_codeBlock->callLinkInfo(i);
     for (unsigned i = 0; i < m_codeBlock->numberOfCallLinkInfos(); ++i) {
         CallLinkInfo& info = m_codeBlock->callLinkInfo(i);
-        info.isCall = m_callStructureStubCompilationInfo[i].isCall;
-        info.callReturnLocation = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].callReturnLocation);
+        info.callType = m_callStructureStubCompilationInfo[i].callType;
+        info.bytecodeIndex = m_callStructureStubCompilationInfo[i].bytecodeIndex;
+        info.callReturnLocation = CodeLocationLabel(patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].callReturnLocation));
         info.hotPathBegin = patchBuffer.locationOf(m_callStructureStubCompilationInfo[i].hotPathBegin);
         info.hotPathOther = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].hotPathOther);
     }
         info.hotPathBegin = patchBuffer.locationOf(m_callStructureStubCompilationInfo[i].hotPathBegin);
         info.hotPathOther = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].hotPathOther);
     }
-#endif
     unsigned methodCallCount = m_methodCallCompilationInfo.size();
     m_codeBlock->addMethodCallLinkInfos(methodCallCount);
     for (unsigned i = 0; i < methodCallCount; ++i) {
         MethodCallLinkInfo& info = m_codeBlock->methodCallLinkInfo(i);
     unsigned methodCallCount = m_methodCallCompilationInfo.size();
     m_codeBlock->addMethodCallLinkInfos(methodCallCount);
     for (unsigned i = 0; i < methodCallCount; ++i) {
         MethodCallLinkInfo& info = m_codeBlock->methodCallLinkInfo(i);
+        info.bytecodeIndex = m_methodCallCompilationInfo[i].bytecodeIndex;
         info.cachedStructure.setLocation(patchBuffer.locationOf(m_methodCallCompilationInfo[i].structureToCompare));
         info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
     }
 
         info.cachedStructure.setLocation(patchBuffer.locationOf(m_methodCallCompilationInfo[i].structureToCompare));
         info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
     }
 
+#if ENABLE(DFG_JIT) || ENABLE(LLINT)
+    if (canBeOptimized()
+#if ENABLE(LLINT)
+        || true
+#endif
+        ) {
+        CompactJITCodeMap::Encoder jitCodeMapEncoder;
+        for (unsigned bytecodeOffset = 0; bytecodeOffset < m_labels.size(); ++bytecodeOffset) {
+            if (m_labels[bytecodeOffset].isSet())
+                jitCodeMapEncoder.append(bytecodeOffset, patchBuffer.offsetOf(m_labels[bytecodeOffset]));
+        }
+        m_codeBlock->setJITCodeMap(jitCodeMapEncoder.finish());
+    }
+#endif
+
     if (m_codeBlock->codeType() == FunctionCode && functionEntryArityCheck)
         *functionEntryArityCheck = patchBuffer.locationOf(arityCheck);
     if (m_codeBlock->codeType() == FunctionCode && functionEntryArityCheck)
         *functionEntryArityCheck = patchBuffer.locationOf(arityCheck);
-
-    return patchBuffer.finalizeCode();
+    
+    CodeRef result = patchBuffer.finalizeCode();
+    
+    m_globalData->machineCodeBytesPerBytecodeWordForBaselineJIT.add(
+        static_cast<double>(result.size()) /
+        static_cast<double>(m_codeBlock->instructions().size()));
+    
+#if ENABLE(JIT_VERBOSE)
+    dataLog("JIT generated code for %p at [%p, %p).\n", m_codeBlock, result.executableMemory()->start(), result.executableMemory()->end());
+#endif
+    
+    return JITCode(result, JITCode::BaselineJIT);
 }
 
 }
 
-#if ENABLE(JIT_OPTIMIZE_CALL)
-
-void JIT::linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JIT::CodePtr code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData)
+void JIT::linkFor(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JIT::CodePtr code, CallLinkInfo* callLinkInfo, JSGlobalData* globalData, CodeSpecializationKind kind)
 {
     RepatchBuffer repatchBuffer(callerCodeBlock);
 
 {
     RepatchBuffer repatchBuffer(callerCodeBlock);
 
-    // 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);
-    }
+    ASSERT(!callLinkInfo->isLinked());
+    callLinkInfo->callee.set(*globalData, callLinkInfo->hotPathBegin, callerCodeBlock->ownerExecutable(), callee);
+    callLinkInfo->lastSeenCallee.set(*globalData, 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::linkConstruct(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JIT::CodePtr code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData)
-{
-    RepatchBuffer repatchBuffer(callerCodeBlock);
+    if (calleeCodeBlock)
+        calleeCodeBlock->linkIncomingCall(callLinkInfo);
 
 
-    // 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 slow patch so we do not continue to try to link.
+    if (kind == CodeForCall) {
+        repatchBuffer.relink(CodeLocationNearCall(callLinkInfo->callReturnLocation), globalData->jitStubs->ctiVirtualCall());
+        return;
     }
 
     }
 
-    // patch the call so we do not continue to try to link.
-    repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs->ctiVirtualConstruct());
+    ASSERT(kind == CodeForConstruct);
+    repatchBuffer.relink(CodeLocationNearCall(callLinkInfo->callReturnLocation), globalData->jitStubs->ctiVirtualConstruct());
 }
 }
-#endif // ENABLE(JIT_OPTIMIZE_CALL)
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index 6cc55fd7e5035838c1a2c1eae3b4678395d7da4b..af5076fb58d4c0683d38d264f729dab1f05d8c3d 100644 (file)
--- a/jit/JIT.h
+++ b/jit/JIT.h
 
 #if ENABLE(JIT)
 
 
 #if ENABLE(JIT)
 
+// Verbose logging of code generation
+#define ENABLE_JIT_VERBOSE 0
+// Verbose logging for OSR-related code.
+#define ENABLE_JIT_VERBOSE_OSR 0
+
 // We've run into some problems where changing the size of the class JIT leads to
 // performance fluctuations.  Try forcing alignment in an attempt to stabalize this.
 #if COMPILER(GCC)
 // We've run into some problems where changing the size of the class JIT leads to
 // performance fluctuations.  Try forcing alignment in an attempt to stabalize this.
 #if COMPILER(GCC)
 #define JIT_CLASS_ALIGNMENT
 #endif
 
 #define JIT_CLASS_ALIGNMENT
 #endif
 
-#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"
 #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 "CompactJITCodeMap.h"
 #include "Interpreter.h"
 #include "JSInterfaceJIT.h"
 #include "Opcode.h"
 #include "Interpreter.h"
 #include "JSInterfaceJIT.h"
 #include "Opcode.h"
@@ -49,6 +54,7 @@
 namespace JSC {
 
     class CodeBlock;
 namespace JSC {
 
     class CodeBlock;
+    class FunctionExecutable;
     class JIT;
     class JSPropertyNameIterator;
     class Interpreter;
     class JIT;
     class JSPropertyNameIterator;
     class Interpreter;
@@ -140,24 +146,126 @@ namespace JSC {
         }
     };
 
         }
     };
 
+    enum PropertyStubGetById_T { PropertyStubGetById };
+    enum PropertyStubPutById_T { PropertyStubPutById };
+
     struct PropertyStubCompilationInfo {
     struct PropertyStubCompilationInfo {
+        enum Type { GetById, PutById, MethodCheck } m_type;
+    
+        unsigned bytecodeIndex;
         MacroAssembler::Call callReturnLocation;
         MacroAssembler::Label hotPathBegin;
         MacroAssembler::Call callReturnLocation;
         MacroAssembler::Label hotPathBegin;
+        MacroAssembler::DataLabelPtr getStructureToCompare;
+        MacroAssembler::PatchableJump getStructureCheck;
+#if USE(JSVALUE64)
+        MacroAssembler::DataLabelCompact getDisplacementLabel;
+#else
+        MacroAssembler::DataLabelCompact getDisplacementLabel1;
+        MacroAssembler::DataLabelCompact getDisplacementLabel2;
+#endif
+        MacroAssembler::Label getPutResult;
+        MacroAssembler::Label getColdPathBegin;
+        MacroAssembler::DataLabelPtr putStructureToCompare;
+#if USE(JSVALUE64)
+        MacroAssembler::DataLabel32 putDisplacementLabel;
+#else
+        MacroAssembler::DataLabel32 putDisplacementLabel1;
+        MacroAssembler::DataLabel32 putDisplacementLabel2;
+#endif
+        MacroAssembler::DataLabelPtr methodCheckStructureToCompare;
+        MacroAssembler::DataLabelPtr methodCheckProtoObj;
+        MacroAssembler::DataLabelPtr methodCheckProtoStructureToCompare;
+        MacroAssembler::DataLabelPtr methodCheckPutFunction;
+
+#if !ASSERT_DISABLED
+        PropertyStubCompilationInfo()
+            : bytecodeIndex(std::numeric_limits<unsigned>::max())
+        {
+        }
+#endif
+
+
+        PropertyStubCompilationInfo(PropertyStubGetById_T, unsigned bytecodeIndex, MacroAssembler::Label hotPathBegin,
+#if USE(JSVALUE64)
+            MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::PatchableJump structureCheck, MacroAssembler::DataLabelCompact displacementLabel, MacroAssembler::Label putResult)
+#else
+            MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::PatchableJump structureCheck, MacroAssembler::DataLabelCompact displacementLabel1, MacroAssembler::DataLabelCompact displacementLabel2, MacroAssembler::Label putResult)
+#endif
+            : m_type(GetById)
+            , bytecodeIndex(bytecodeIndex)
+            , hotPathBegin(hotPathBegin)
+            , getStructureToCompare(structureToCompare)
+            , getStructureCheck(structureCheck)
+#if USE(JSVALUE64)
+            , getDisplacementLabel(displacementLabel)
+#else
+            , getDisplacementLabel1(displacementLabel1)
+            , getDisplacementLabel2(displacementLabel2)
+#endif
+            , getPutResult(putResult)
+        {
+        }
+
+        PropertyStubCompilationInfo(PropertyStubPutById_T, unsigned bytecodeIndex, MacroAssembler::Label hotPathBegin,
+#if USE(JSVALUE64)
+            MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::DataLabel32 displacementLabel)
+#else
+            MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::DataLabel32 displacementLabel1, MacroAssembler::DataLabel32 displacementLabel2)
+#endif
+            : m_type(PutById)
+            , bytecodeIndex(bytecodeIndex)
+            , hotPathBegin(hotPathBegin)
+            , putStructureToCompare(structureToCompare)
+#if USE(JSVALUE64)
+            , putDisplacementLabel(displacementLabel)
+#else
+            , putDisplacementLabel1(displacementLabel1)
+            , putDisplacementLabel2(displacementLabel2)
+#endif
+        {
+        }
+
+        void slowCaseInfo(PropertyStubGetById_T, MacroAssembler::Label coldPathBegin, MacroAssembler::Call call)
+        {
+            ASSERT(m_type == GetById || m_type == MethodCheck);
+            callReturnLocation = call;
+            getColdPathBegin = coldPathBegin;
+        }
+
+        void slowCaseInfo(PropertyStubPutById_T, MacroAssembler::Call call)
+        {
+            ASSERT(m_type == PutById);
+            callReturnLocation = call;
+        }
+
+        void addMethodCheckInfo(MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::DataLabelPtr protoObj, MacroAssembler::DataLabelPtr protoStructureToCompare, MacroAssembler::DataLabelPtr putFunction)
+        {
+            m_type = MethodCheck;
+            methodCheckStructureToCompare = structureToCompare;
+            methodCheckProtoObj = protoObj;
+            methodCheckProtoStructureToCompare = protoStructureToCompare;
+            methodCheckPutFunction = putFunction;
+        }
+
+        void copyToStubInfo(StructureStubInfo& info, LinkBuffer &patchBuffer);
     };
 
     struct StructureStubCompilationInfo {
         MacroAssembler::DataLabelPtr hotPathBegin;
         MacroAssembler::Call hotPathOther;
         MacroAssembler::Call callReturnLocation;
     };
 
     struct StructureStubCompilationInfo {
         MacroAssembler::DataLabelPtr hotPathBegin;
         MacroAssembler::Call hotPathOther;
         MacroAssembler::Call callReturnLocation;
-        bool isCall;
+        CallLinkInfo::CallType callType;
+        unsigned bytecodeIndex;
     };
 
     struct MethodCallCompilationInfo {
     };
 
     struct MethodCallCompilationInfo {
-        MethodCallCompilationInfo(unsigned propertyAccessIndex)
-            : propertyAccessIndex(propertyAccessIndex)
+        MethodCallCompilationInfo(unsigned bytecodeIndex, unsigned propertyAccessIndex)
+            : bytecodeIndex(bytecodeIndex)
+            , propertyAccessIndex(propertyAccessIndex)
         {
         }
 
         {
         }
 
+        unsigned bytecodeIndex;
         MacroAssembler::DataLabelPtr structureToCompare;
         unsigned propertyAccessIndex;
     };
         MacroAssembler::DataLabelPtr structureToCompare;
         unsigned propertyAccessIndex;
     };
@@ -169,6 +277,7 @@ namespace JSC {
 
     class JIT : private JSInterfaceJIT {
         friend class JITStubCall;
 
     class JIT : private JSInterfaceJIT {
         friend class JITStubCall;
+        friend struct PropertyStubCompilationInfo;
 
         using MacroAssembler::Jump;
         using MacroAssembler::JumpList;
 
         using MacroAssembler::Jump;
         using MacroAssembler::JumpList;
@@ -181,64 +290,77 @@ namespace JSC {
         static const int patchPutByIdDefaultOffset = 256;
 
     public:
         static const int patchPutByIdDefaultOffset = 256;
 
     public:
-        static JITCode compile(JSGlobalData* globalData, CodeBlock* codeBlock, CodePtr* functionEntryArityCheck = 0)
+        static JITCode compile(JSGlobalData* globalData, CodeBlock* codeBlock, JITCompilationEffort effort, CodePtr* functionEntryArityCheck = 0)
         {
         {
-            return JIT(globalData, codeBlock).privateCompile(functionEntryArityCheck);
+            return JIT(globalData, codeBlock).privateCompile(functionEntryArityCheck, effort);
         }
 
         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)
         {
             JIT jit(globalData, codeBlock);
         }
 
         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)
         {
             JIT jit(globalData, codeBlock);
+            jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
             jit.privateCompileGetByIdProto(stubInfo, structure, prototypeStructure, ident, slot, cachedOffset, returnAddress, callFrame);
         }
 
         static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
         {
             JIT jit(globalData, codeBlock);
             jit.privateCompileGetByIdProto(stubInfo, structure, prototypeStructure, ident, slot, cachedOffset, returnAddress, callFrame);
         }
 
         static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
         {
             JIT jit(globalData, codeBlock);
+            jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
             jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, ident, slot, cachedOffset);
         }
         static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
         {
             JIT jit(globalData, codeBlock);
             jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, ident, slot, cachedOffset);
         }
         static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
         {
             JIT jit(globalData, codeBlock);
+            jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
             jit.privateCompileGetByIdProtoList(stubInfo, prototypeStructureList, currentIndex, structure, prototypeStructure, ident, slot, cachedOffset, callFrame);
         }
         static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
         {
             JIT jit(globalData, codeBlock);
             jit.privateCompileGetByIdProtoList(stubInfo, prototypeStructureList, currentIndex, structure, prototypeStructure, ident, slot, cachedOffset, callFrame);
         }
         static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
         {
             JIT jit(globalData, codeBlock);
+            jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
             jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, ident, slot, cachedOffset, callFrame);
         }
 
         static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress)
         {
             JIT jit(globalData, codeBlock);
             jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, ident, slot, cachedOffset, callFrame);
         }
 
         static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress)
         {
             JIT jit(globalData, codeBlock);
+            jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
             jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, ident, slot, cachedOffset, returnAddress, callFrame);
         }
         
         static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
         {
             JIT jit(globalData, codeBlock);
             jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, ident, slot, cachedOffset, returnAddress, callFrame);
         }
         
         static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
         {
             JIT jit(globalData, codeBlock);
+            jit.m_bytecodeOffset = stubInfo->bytecodeIndex;
             jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress, direct);
         }
 
             jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress, direct);
         }
 
-        static void compileCTIMachineTrampolines(JSGlobalData* globalData, RefPtr<ExecutablePool>* executablePool, TrampolineStructure *trampolines)
+        static PassRefPtr<ExecutableMemoryHandle> compileCTIMachineTrampolines(JSGlobalData* globalData, TrampolineStructure *trampolines)
         {
             if (!globalData->canUseJIT())
         {
             if (!globalData->canUseJIT())
-                return;
+                return 0;
             JIT jit(globalData, 0);
             JIT jit(globalData, 0);
-            jit.privateCompileCTIMachineTrampolines(executablePool, globalData, trampolines);
+            return jit.privateCompileCTIMachineTrampolines(globalData, trampolines);
         }
 
         }
 
-        static CodePtr compileCTINativeCall(JSGlobalData* globalData, PassRefPtr<ExecutablePool> executablePool, NativeFunction func)
+        static CodeRef compileCTINativeCall(JSGlobalData* globalData, NativeFunction func)
         {
         {
-            if (!globalData->canUseJIT())
-                return CodePtr();
+            if (!globalData->canUseJIT()) {
+#if ENABLE(LLINT)
+                return CodeRef::createLLIntCodeRef(llint_native_call_trampoline);
+#else
+                return CodeRef();
+#endif
+            }
             JIT jit(globalData, 0);
             JIT jit(globalData, 0);
-            return jit.privateCompileCTINativeCall(executablePool, globalData, func);
+            return jit.privateCompileCTINativeCall(globalData, func);
         }
 
         }
 
+        static void resetPatchGetById(RepatchBuffer&, StructureStubInfo*);
+        static void resetPatchPutById(RepatchBuffer&, StructureStubInfo*);
         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(JSGlobalData&, CodeBlock* codeblock, MethodCallLinkInfo&, JSObjectWithGlobalObject*, Structure*, JSObject*, ReturnAddressPtr);
+        static void patchMethodCallProto(JSGlobalData&, CodeBlock* codeblock, MethodCallLinkInfo&, StructureStubInfo&, JSObject*, Structure*, JSObject*, ReturnAddressPtr);
 
         static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress)
         {
 
         static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress)
         {
@@ -246,27 +368,15 @@ namespace JSC {
             return jit.privateCompilePatchGetArrayLength(returnAddress);
         }
 
             return jit.privateCompilePatchGetArrayLength(returnAddress);
         }
 
-        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*);
+        static void linkFor(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, CodePtr, CallLinkInfo*, JSGlobalData*, CodeSpecializationKind);
 
     private:
 
     private:
-        struct JSRInfo {
-            DataLabelPtr storeLocation;
-            Label target;
-
-            JSRInfo(DataLabelPtr storeLocation, Label targetLocation)
-                : storeLocation(storeLocation)
-                , target(targetLocation)
-            {
-            }
-        };
-
         JIT(JSGlobalData*, CodeBlock* = 0);
 
         void privateCompileMainPass();
         void privateCompileLinkPass();
         void privateCompileSlowCases();
         JIT(JSGlobalData*, CodeBlock* = 0);
 
         void privateCompileMainPass();
         void privateCompileLinkPass();
         void privateCompileSlowCases();
-        JITCode privateCompile(CodePtr* functionEntryArityCheck);
+        JITCode privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffort);
         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);
@@ -274,155 +384,102 @@ namespace JSC {
         void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
         void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress, bool direct);
 
         void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
         void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress, bool direct);
 
-        void privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* data, TrampolineStructure *trampolines);
+        PassRefPtr<ExecutableMemoryHandle> privateCompileCTIMachineTrampolines(JSGlobalData*, TrampolineStructure*);
         Label privateCompileCTINativeCall(JSGlobalData*, bool isConstruct = false);
         Label privateCompileCTINativeCall(JSGlobalData*, bool isConstruct = false);
-        CodePtr privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executablePool, JSGlobalData* data, NativeFunction func);
+        CodeRef privateCompileCTINativeCall(JSGlobalData*, NativeFunction);
         void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress);
 
         void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress);
 
+        static bool isDirectPutById(StructureStubInfo*);
+
         void addSlowCase(Jump);
         void addSlowCase(JumpList);
         void addSlowCase(Jump);
         void addSlowCase(JumpList);
+        void addSlowCase();
         void addJump(Jump, int);
         void emitJumpSlowToHot(Jump, int);
 
         void addJump(Jump, int);
         void emitJumpSlowToHot(Jump, int);
 
-        void compileOpCall(OpcodeID, Instruction* instruction, unsigned callLinkInfoIndex);
-        void compileOpCallVarargs(Instruction* instruction);
-        void compileOpCallInitializeCallFrame();
-        void compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID);
-        void compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter);
+        void compileOpCall(OpcodeID, Instruction*, unsigned callLinkInfoIndex);
+        void compileOpCallSlowCase(OpcodeID, Instruction*, Vector<SlowCaseEntry>::iterator&, unsigned callLinkInfoIndex);
+        void compileLoadVarargs(Instruction*);
+        void compileCallEval();
+        void compileCallEvalSlowCase(Vector<SlowCaseEntry>::iterator&);
 
         enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
         void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type);
         bool isOperandConstantImmediateDouble(unsigned src);
         
 
         enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
         void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type);
         bool isOperandConstantImmediateDouble(unsigned src);
         
-        void emitLoadDouble(unsigned index, FPRegisterID value);
-        void emitLoadInt32ToDouble(unsigned index, FPRegisterID value);
+        void emitLoadDouble(int index, FPRegisterID value);
+        void emitLoadInt32ToDouble(int index, FPRegisterID value);
+        Jump emitJumpIfNotObject(RegisterID structureReg);
+        Jump emitJumpIfNotType(RegisterID baseReg, RegisterID scratchReg, JSType);
 
         void testPrototype(JSValue, JumpList& failureCases);
 
 
         void testPrototype(JSValue, JumpList& failureCases);
 
+        enum WriteBarrierMode { UnconditionalWriteBarrier, ShouldFilterImmediates };
+        // value register in write barrier is used before any scratch registers
+        // so may safely be the same as either of the scratch registers.
+        void emitWriteBarrier(RegisterID owner, RegisterID valueTag, RegisterID scratch, RegisterID scratch2, WriteBarrierMode, WriteBarrierUseKind);
+        void emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode, WriteBarrierUseKind);
+
+        template<typename ClassType, bool destructor, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr);
+        void emitAllocateBasicStorage(size_t, RegisterID result, RegisterID storagePtr);
+        template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr);
+        void emitAllocateJSFunction(FunctionExecutable*, RegisterID scopeChain, RegisterID result, RegisterID storagePtr);
+        void emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr);
+        
+#if ENABLE(VALUE_PROFILER)
+        // This assumes that the value to profile is in regT0 and that regT3 is available for
+        // scratch.
+        void emitValueProfilingSite(ValueProfile*);
+        void emitValueProfilingSite(unsigned bytecodeOffset);
+        void emitValueProfilingSite();
+#else
+        void emitValueProfilingSite(unsigned) { }
+        void emitValueProfilingSite() { }
+#endif
+
 #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);
 
-        void emitLoadTag(unsigned index, RegisterID tag);
-        void emitLoadPayload(unsigned index, RegisterID payload);
+        void emitLoadTag(int index, RegisterID tag);
+        void emitLoadPayload(int index, RegisterID payload);
 
         void emitLoad(const JSValue& v, RegisterID tag, RegisterID payload);
 
         void emitLoad(const JSValue& v, RegisterID tag, RegisterID payload);
-        void emitLoad(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
-        void emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1, unsigned index2, RegisterID tag2, RegisterID payload2);
-
-        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, TrustedImm32 payload, bool indexIsInt32 = false);
-        void emitStoreCell(unsigned index, RegisterID payload, bool indexIsCell = false);
-        void emitStoreBool(unsigned index, RegisterID payload, bool indexIsBool = false);
-        void emitStoreDouble(unsigned index, FPRegisterID value);
+        void emitLoad(int index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
+        void emitLoad2(int index1, RegisterID tag1, RegisterID payload1, int index2, RegisterID tag2, RegisterID payload2);
+
+        void emitStore(int index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
+        void emitStore(int index, const JSValue constant, RegisterID base = callFrameRegister);
+        void emitStoreInt32(int index, RegisterID payload, bool indexIsInt32 = false);
+        void emitStoreInt32(int index, TrustedImm32 payload, bool indexIsInt32 = false);
+        void emitStoreAndMapInt32(int index, RegisterID tag, RegisterID payload, bool indexIsInt32, size_t opcodeLength);
+        void emitStoreCell(int index, RegisterID payload, bool indexIsCell = false);
+        void emitStoreBool(int index, RegisterID payload, bool indexIsBool = false);
+        void emitStoreDouble(int index, FPRegisterID value);
 
         bool isLabeled(unsigned bytecodeOffset);
 
         bool isLabeled(unsigned bytecodeOffset);
-        void map(unsigned bytecodeOffset, unsigned virtualRegisterIndex, RegisterID tag, RegisterID payload);
+        void map(unsigned bytecodeOffset, int virtualRegisterIndex, RegisterID tag, RegisterID payload);
         void unmap(RegisterID);
         void unmap();
         void unmap(RegisterID);
         void unmap();
-        bool isMapped(unsigned virtualRegisterIndex);
-        bool getMappedPayload(unsigned virtualRegisterIndex, RegisterID& payload);
-        bool getMappedTag(unsigned virtualRegisterIndex, RegisterID& tag);
+        bool isMapped(int virtualRegisterIndex);
+        bool getMappedPayload(int virtualRegisterIndex, RegisterID& payload);
+        bool getMappedTag(int virtualRegisterIndex, RegisterID& tag);
 
 
-        void emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex);
-        void emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex, RegisterID tag);
-        void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, unsigned virtualRegisterIndex);
+        void emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex);
+        void emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex, RegisterID tag);
 
 
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
         void compileGetByIdHotPath();
         void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
         void compileGetByIdHotPath();
         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(RegisterID base, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
         void compileGetDirectOffset(JSObject* base, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
         void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, 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);
+        void compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, size_t cachedOffset);
 
         // Arithmetic opcode helpers
         void emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType);
         void emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType);
         void emitBinaryDoubleOp(OpcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true);
 
 
         // Arithmetic opcode helpers
         void emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType);
         void emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType);
         void emitBinaryDoubleOp(OpcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true);
 
-#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 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 patchOffsetGetByIdPropertyMapOffset1 = 19;
-        static const int patchOffsetGetByIdPropertyMapOffset2 = 22;
-        static const int patchOffsetGetByIdPutResult = 22;
-#if ENABLE(OPCODE_SAMPLING)
-        static const int patchOffsetGetByIdSlowCaseCall = 37;
-#else
-        static const int patchOffsetGetByIdSlowCaseCall = 27;
-#endif
-        static const int patchOffsetOpCallCompareToJump = 6;
-
-        static const int patchOffsetMethodCheckProtoObj = 11;
-        static const int patchOffsetMethodCheckProtoStruct = 18;
-        static const int patchOffsetMethodCheckPutFunction = 29;
-#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 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 patchOffsetGetByIdPropertyMapOffset1 = 20;
-        static const int patchOffsetGetByIdPropertyMapOffset2 = 28;
-        static const int patchOffsetGetByIdPutResult = 36;
-#if ENABLE(OPCODE_SAMPLING)
-        #error "OPCODE_SAMPLING is not yet supported"
-#else
-        static const int patchOffsetGetByIdSlowCaseCall = 32;
-#endif
-        static const int patchOffsetOpCallCompareToJump = 12;
-
-        static const int patchOffsetMethodCheckProtoObj = 12;
-        static const int patchOffsetMethodCheckProtoStruct = 20;
-        static const int patchOffsetMethodCheckPutFunction = 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 = 4;
-        // sequenceGetByIdSlowCase
-        static const int sequenceGetByIdSlowCaseInstructionSpace = 56;
-        static const int sequenceGetByIdSlowCaseConstantSpace = 2;
-        // sequencePutById
-        static const int sequencePutByIdInstructionSpace = 36;
-        static const int sequencePutByIdConstantSpace = 4;
-#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 patchOffsetPutByIdPropertyMapOffset1 = 36;
-        static const int patchOffsetPutByIdPropertyMapOffset2 = 48;
-        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
-        static const int patchOffsetGetByIdStructure = 10;
-        static const int patchOffsetGetByIdBranchToSlowCase = 26;
-        static const int patchOffsetGetByIdPropertyMapOffset1 = 28;
-        static const int patchOffsetGetByIdPropertyMapOffset2 = 30;
-        static const int patchOffsetGetByIdPutResult = 32;
-#if ENABLE(OPCODE_SAMPLING)
-        #error "OPCODE_SAMPLING is not yet supported"
-#else
-        static const int patchOffsetGetByIdSlowCaseCall = 30;
-#endif
-        static const int patchOffsetOpCallCompareToJump = 16;
-
-        static const int patchOffsetMethodCheckProtoObj = 24;
-        static const int patchOffsetMethodCheckProtoStruct = 34;
-        static const int patchOffsetMethodCheckPutFunction = 58;
-
+#if CPU(ARM_TRADITIONAL)
         // sequenceOpCall
         static const int sequenceOpCallInstructionSpace = 12;
         static const int sequenceOpCallConstantSpace = 2;
         // sequenceOpCall
         static const int sequenceOpCallInstructionSpace = 12;
         static const int sequenceOpCallConstantSpace = 2;
@@ -433,59 +490,12 @@ 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 sequenceGetByIdSlowCaseConstantSpace = 2;
+        static const int sequenceGetByIdSlowCaseInstructionSpace = 64;
+        static const int sequenceGetByIdSlowCaseConstantSpace = 4;
         // 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)
 #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;
         // sequenceOpCall
         static const int sequenceOpCallInstructionSpace = 12;
         static const int sequenceOpCallConstantSpace = 2;
@@ -496,36 +506,21 @@ namespace JSC {
         static const int sequenceGetByIdHotPathInstructionSpace = 36;
         static const int sequenceGetByIdHotPathConstantSpace = 5;
         // sequenceGetByIdSlowCase
         static const int sequenceGetByIdHotPathInstructionSpace = 36;
         static const int sequenceGetByIdHotPathConstantSpace = 5;
         // sequenceGetByIdSlowCase
-        static const int sequenceGetByIdSlowCaseInstructionSpace = 26;
-        static const int sequenceGetByIdSlowCaseConstantSpace = 2;
+        static const int sequenceGetByIdSlowCaseInstructionSpace = 38;
+        static const int sequenceGetByIdSlowCaseConstantSpace = 4;
         // sequencePutById
         static const int sequencePutByIdInstructionSpace = 36;
         static const int sequencePutByIdConstantSpace = 5;
         // 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 // USE(JSVALUE32_64)
         void emitGetVirtualRegister(int src, RegisterID dst);
         void emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2);
         void emitPutVirtualRegister(unsigned dst, RegisterID from = regT0);
 #endif
 
 #else // USE(JSVALUE32_64)
         void emitGetVirtualRegister(int src, RegisterID dst);
         void emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2);
         void emitPutVirtualRegister(unsigned dst, RegisterID from = regT0);
+        void emitStoreCell(unsigned dst, RegisterID payload, bool /* only used in JSValue32_64 */ = false)
+        {
+            emitPutVirtualRegister(dst, payload);
+        }
 
         int32_t getConstantOperandImmediateInt(unsigned src);
 
 
         int32_t getConstantOperandImmediateInt(unsigned src);
 
@@ -537,175 +532,27 @@ 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(JSVALUE32_64)
-        JIT::Jump emitJumpIfImmediateNumber(RegisterID reg)
-        {
-            return emitJumpIfImmediateInteger(reg);
-        }
-        
-        JIT::Jump emitJumpIfNotImmediateNumber(RegisterID reg)
-        {
-            return emitJumpIfNotImmediateInteger(reg);
-        }
-#endif
-        JIT::Jump emitJumpIfImmediateInteger(RegisterID);
-        JIT::Jump emitJumpIfNotImmediateInteger(RegisterID);
-        JIT::Jump emitJumpIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
+        Jump emitJumpIfImmediateInteger(RegisterID);
+        Jump emitJumpIfNotImmediateInteger(RegisterID);
+        Jump emitJumpIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
         void emitJumpSlowCaseIfNotImmediateInteger(RegisterID);
         void emitJumpSlowCaseIfNotImmediateNumber(RegisterID);
         void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
 
         void emitJumpSlowCaseIfNotImmediateInteger(RegisterID);
         void emitJumpSlowCaseIfNotImmediateNumber(RegisterID);
         void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
 
-#if USE(JSVALUE32_64)
-        void emitFastArithDeTagImmediate(RegisterID);
-        Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID);
-#endif
         void emitFastArithReTagImmediate(RegisterID src, RegisterID dest);
         void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
 
         void emitTagAsBoolImmediate(RegisterID reg);
         void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
         void emitFastArithReTagImmediate(RegisterID src, RegisterID dest);
         void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
 
         void emitTagAsBoolImmediate(RegisterID reg);
         void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
-#if USE(JSVALUE64)
         void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase);
         void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase);
-#else
-        void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes);
-#endif
 
 
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-        void compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned propertyAccessInstructionIndex);
+        void compileGetByIdHotPath(int baseVReg, Identifier*);
         void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
         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(RegisterID base, RegisterID result, size_t cachedOffset);
         void compileGetDirectOffset(JSObject* base, RegisterID result, size_t cachedOffset);
         void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch);
         void compileGetDirectOffset(JSObject* base, RegisterID result, size_t cachedOffset);
         void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch);
-        void compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset);
-
-#if CPU(X86_64)
-        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
-        static const int patchOffsetPutByIdStructure = 10;
-        static const int 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 patchOffsetGetByIdPropertyMapOffset = 28;
-        static const int patchOffsetGetByIdPutResult = 28;
-#if ENABLE(OPCODE_SAMPLING)
-        static const int patchOffsetGetByIdSlowCaseCall = 64;
-#else
-        static const int patchOffsetGetByIdSlowCaseCall = 41;
-#endif
-        static const int patchOffsetOpCallCompareToJump = 9;
-
-        static const int patchOffsetMethodCheckProtoObj = 20;
-        static const int patchOffsetMethodCheckProtoStruct = 30;
-        static const int patchOffsetMethodCheckPutFunction = 50;
-#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 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 patchOffsetGetByIdPropertyMapOffset = 22;
-        static const int patchOffsetGetByIdPutResult = 22;
-#if ENABLE(OPCODE_SAMPLING)
-        static const int patchOffsetGetByIdSlowCaseCall = 33;
-#else
-        static const int patchOffsetGetByIdSlowCaseCall = 23;
-#endif
-        static const int patchOffsetOpCallCompareToJump = 6;
-
-        static const int patchOffsetMethodCheckProtoObj = 11;
-        static const int patchOffsetMethodCheckProtoStruct = 18;
-        static const int patchOffsetMethodCheckPutFunction = 29;
-#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 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 patchOffsetGetByIdPropertyMapOffset = 46;
-        static const int patchOffsetGetByIdPutResult = 50;
-#if ENABLE(OPCODE_SAMPLING)
-        static const int patchOffsetGetByIdSlowCaseCall = 0; // FIMXE
-#else
-        static const int patchOffsetGetByIdSlowCaseCall = 28;
-#endif
-        static const int patchOffsetOpCallCompareToJump = 16;
-
-        static const int patchOffsetMethodCheckProtoObj = 24;
-        static const int patchOffsetMethodCheckProtoStruct = 34;
-        static const int patchOffsetMethodCheckPutFunction = 58;
-#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 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 patchOffsetGetByIdPropertyMapOffset = 20;
-        static const int patchOffsetGetByIdPutResult = 28;
-#if ENABLE(OPCODE_SAMPLING)
-        #error "OPCODE_SAMPLING is not yet supported"
-#else
-        static const int patchOffsetGetByIdSlowCaseCall = 28;
-#endif
-        static const int patchOffsetOpCallCompareToJump = 12;
+        void compilePutDirectOffset(RegisterID base, RegisterID value, size_t cachedOffset);
 
 
-        static const int patchOffsetMethodCheckProtoObj = 12;
-        static const int patchOffsetMethodCheckProtoStruct = 20;
-        static const int patchOffsetMethodCheckPutFunction = 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 = 28;
-        static const int sequenceGetByIdHotPathConstantSpace = 3;
-        // sequenceGetByIdSlowCase
-        static const int sequenceGetByIdSlowCaseInstructionSpace = 32;
-        static const int sequenceGetByIdSlowCaseConstantSpace = 2;
-        // sequencePutById
-        static const int sequencePutByIdInstructionSpace = 28;
-        static const int sequencePutByIdConstantSpace = 3;
-#elif CPU(MIPS)
-#if WTF_MIPS_ISA(1)
-        static const int patchOffsetPutByIdStructure = 16;
-        static const int patchOffsetPutByIdPropertyMapOffset = 68;
-        static const int patchOffsetGetByIdStructure = 16;
-        static const int patchOffsetGetByIdBranchToSlowCase = 48;
-        static const int patchOffsetGetByIdPropertyMapOffset = 68;
-        static const int patchOffsetGetByIdPutResult = 88;
-#if ENABLE(OPCODE_SAMPLING)
-        #error "OPCODE_SAMPLING is not yet supported"
-#else
-        static const int patchOffsetGetByIdSlowCaseCall = 40;
-#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 patchOffsetPutByIdPropertyMapOffset = 60;
-        static const int patchOffsetGetByIdStructure = 12;
-        static const int patchOffsetGetByIdBranchToSlowCase = 44;
-        static const int patchOffsetGetByIdPropertyMapOffset = 60;
-        static const int patchOffsetGetByIdPutResult = 76;
-#if ENABLE(OPCODE_SAMPLING)
-        #error "OPCODE_SAMPLING is not yet supported"
-#else
-        static const int patchOffsetGetByIdSlowCaseCall = 40;
-#endif
-        static const int patchOffsetOpCallCompareToJump = 32;
-        static const int patchOffsetMethodCheckProtoObj = 32;
-        static const int patchOffsetMethodCheckProtoStruct = 52;
-        static const int patchOffsetMethodCheckPutFunction = 84;
-#endif
-#endif
 #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)
@@ -717,14 +564,16 @@ namespace JSC {
         void endUninterruptedSequence(int, int, int);
 
 #else
         void endUninterruptedSequence(int, int, int);
 
 #else
-#define BEGIN_UNINTERRUPTED_SEQUENCE(name)  do { beginUninterruptedSequence(); } while (false)
-#define END_UNINTERRUPTED_SEQUENCE(name)  do { endUninterruptedSequence(); } while (false)
-#define END_UNINTERRUPTED_SEQUENCE_FOR_PUT(name, dst) do { endUninterruptedSequence(); } while (false)
+#define BEGIN_UNINTERRUPTED_SEQUENCE(name)
+#define END_UNINTERRUPTED_SEQUENCE(name)
+#define END_UNINTERRUPTED_SEQUENCE_FOR_PUT(name, dst)
 #endif
 
 #endif
 
+        void emit_compareAndJump(OpcodeID, unsigned op1, unsigned op2, unsigned target, RelationalCondition);
+        void emit_compareAndJumpSlow(unsigned op1, unsigned op2, unsigned target, DoubleCondition, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION), bool invert, Vector<SlowCaseEntry>::iterator&);
+
         void emit_op_add(Instruction*);
         void emit_op_bitand(Instruction*);
         void emit_op_add(Instruction*);
         void emit_op_bitand(Instruction*);
-        void emit_op_bitnot(Instruction*);
         void emit_op_bitor(Instruction*);
         void emit_op_bitxor(Instruction*);
         void emit_op_call(Instruction*);
         void emit_op_bitor(Instruction*);
         void emit_op_bitxor(Instruction*);
         void emit_op_call(Instruction*);
@@ -736,7 +585,6 @@ namespace JSC {
         void emit_op_get_callee(Instruction*);
         void emit_op_create_this(Instruction*);
         void emit_op_convert_this(Instruction*);
         void emit_op_get_callee(Instruction*);
         void emit_op_create_this(Instruction*);
         void emit_op_convert_this(Instruction*);
-        void emit_op_convert_this_strict(Instruction*);
         void emit_op_create_arguments(Instruction*);
         void emit_op_debug(Instruction*);
         void emit_op_del_by_id(Instruction*);
         void emit_op_create_arguments(Instruction*);
         void emit_op_debug(Instruction*);
         void emit_op_del_by_id(Instruction*);
@@ -756,22 +604,31 @@ namespace JSC {
         void emit_op_init_lazy_reg(Instruction*);
         void emit_op_check_has_instance(Instruction*);
         void emit_op_instanceof(Instruction*);
         void emit_op_init_lazy_reg(Instruction*);
         void emit_op_check_has_instance(Instruction*);
         void emit_op_instanceof(Instruction*);
+        void emit_op_is_undefined(Instruction*);
+        void emit_op_is_boolean(Instruction*);
+        void emit_op_is_number(Instruction*);
+        void emit_op_is_string(Instruction*);
         void emit_op_jeq_null(Instruction*);
         void emit_op_jfalse(Instruction*);
         void emit_op_jmp(Instruction*);
         void emit_op_jmp_scopes(Instruction*);
         void emit_op_jneq_null(Instruction*);
         void emit_op_jneq_ptr(Instruction*);
         void emit_op_jeq_null(Instruction*);
         void emit_op_jfalse(Instruction*);
         void emit_op_jmp(Instruction*);
         void emit_op_jmp_scopes(Instruction*);
         void emit_op_jneq_null(Instruction*);
         void emit_op_jneq_ptr(Instruction*);
-        void emit_op_jnless(Instruction*);
         void emit_op_jless(Instruction*);
         void emit_op_jless(Instruction*);
-        void emit_op_jlesseq(Instruction*, bool invert = false);
+        void emit_op_jlesseq(Instruction*);
+        void emit_op_jgreater(Instruction*);
+        void emit_op_jgreatereq(Instruction*);
+        void emit_op_jnless(Instruction*);
         void emit_op_jnlesseq(Instruction*);
         void emit_op_jnlesseq(Instruction*);
-        void emit_op_jsr(Instruction*);
+        void emit_op_jngreater(Instruction*);
+        void emit_op_jngreatereq(Instruction*);
         void emit_op_jtrue(Instruction*);
         void emit_op_jtrue(Instruction*);
-        void emit_op_load_varargs(Instruction*);
         void emit_op_loop(Instruction*);
         void emit_op_loop(Instruction*);
+        void emit_op_loop_hint(Instruction*);
         void emit_op_loop_if_less(Instruction*);
         void emit_op_loop_if_lesseq(Instruction*);
         void emit_op_loop_if_less(Instruction*);
         void emit_op_loop_if_lesseq(Instruction*);
+        void emit_op_loop_if_greater(Instruction*);
+        void emit_op_loop_if_greatereq(Instruction*);
         void emit_op_loop_if_true(Instruction*);
         void emit_op_loop_if_false(Instruction*);
         void emit_op_lshift(Instruction*);
         void emit_op_loop_if_true(Instruction*);
         void emit_op_loop_if_false(Instruction*);
         void emit_op_lshift(Instruction*);
@@ -804,10 +661,9 @@ namespace JSC {
         void emit_op_put_by_id(Instruction*);
         void emit_op_put_by_index(Instruction*);
         void emit_op_put_by_val(Instruction*);
         void emit_op_put_by_id(Instruction*);
         void emit_op_put_by_index(Instruction*);
         void emit_op_put_by_val(Instruction*);
-        void emit_op_put_getter(Instruction*);
+        void emit_op_put_getter_setter(Instruction*);
         void emit_op_put_global_var(Instruction*);
         void emit_op_put_scoped_var(Instruction*);
         void emit_op_put_global_var(Instruction*);
         void emit_op_put_scoped_var(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(Instruction*);
         void emit_op_resolve_base(Instruction*);
         void emit_op_ensure_property_exists(Instruction*);
@@ -815,10 +671,10 @@ namespace JSC {
         void emit_op_resolve_global_dynamic(Instruction*);
         void emit_op_resolve_skip(Instruction*);
         void emit_op_resolve_with_base(Instruction*);
         void emit_op_resolve_global_dynamic(Instruction*);
         void emit_op_resolve_skip(Instruction*);
         void emit_op_resolve_with_base(Instruction*);
+        void emit_op_resolve_with_this(Instruction*);
         void emit_op_ret(Instruction*);
         void emit_op_ret_object_or_this(Instruction*);
         void emit_op_rshift(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_stricteq(Instruction*);
         void emit_op_sub(Instruction*);
         void emit_op_strcat(Instruction*);
         void emit_op_stricteq(Instruction*);
         void emit_op_sub(Instruction*);
@@ -833,13 +689,9 @@ namespace JSC {
         void emit_op_to_primitive(Instruction*);
         void emit_op_unexpected_load(Instruction*);
         void emit_op_urshift(Instruction*);
         void emit_op_to_primitive(Instruction*);
         void emit_op_unexpected_load(Instruction*);
         void emit_op_urshift(Instruction*);
-#if ENABLE(JIT_USE_SOFT_MODULO)
-        void softModulo();
-#endif
 
         void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_bitand(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
         void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_bitand(Instruction*, Vector<SlowCaseEntry>::iterator&);
-        void emitSlow_op_bitnot(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_bitor(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_bitxor(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_call(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_bitor(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_bitxor(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_call(Instruction*, Vector<SlowCaseEntry>::iterator&);
@@ -847,7 +699,7 @@ namespace JSC {
         void emitSlow_op_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_convert_this(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_construct(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_create_this(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&);
@@ -858,14 +710,19 @@ namespace JSC {
         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_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_jless(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jless(Instruction*, Vector<SlowCaseEntry>::iterator&);
-        void emitSlow_op_jlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&, bool invert = false);
+        void emitSlow_op_jlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_jgreater(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_jgreatereq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_jngreater(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_jngreatereq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jtrue(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_less(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_lesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_loop_if_greater(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_loop_if_greatereq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_true(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_false(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_lshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_true(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_false(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_lshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
@@ -874,6 +731,7 @@ namespace JSC {
         void emitSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_negate(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_neq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_negate(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_neq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_new_object(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_not(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_nstricteq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_post_dec(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_not(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_nstricteq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_post_dec(Instruction*, Vector<SlowCaseEntry>::iterator&);
@@ -890,7 +748,9 @@ namespace JSC {
         void emitSlow_op_to_jsnumber(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_jsnumber(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
-
+        void emitSlow_op_new_func(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_new_func_exp(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_new_array(Instruction*, Vector<SlowCaseEntry>::iterator&);
         
         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);
@@ -922,12 +782,18 @@ namespace JSC {
             iter->from.link(this);
             ++iter;
         }
             iter->from.link(this);
             ++iter;
         }
-        void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, int vReg);
+        void linkDummySlowCase(Vector<SlowCaseEntry>::iterator& iter)
+        {
+            ASSERT(!iter->from.isSet());
+            ++iter;
+        }
+        void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, int virtualRegisterIndex);
 
         Jump checkStructure(RegisterID reg, Structure* structure);
 
         void restoreArgumentReference();
         void restoreArgumentReferenceForTrampoline();
 
         Jump checkStructure(RegisterID reg, Structure* structure);
 
         void restoreArgumentReference();
         void restoreArgumentReferenceForTrampoline();
+        void updateTopCallFrame();
 
         Call emitNakedCall(CodePtr function = CodePtr());
 
 
         Call emitNakedCall(CodePtr function = CodePtr());
 
@@ -938,6 +804,13 @@ namespace JSC {
         // Loads the character value of a single character string into dst.
         void emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures);
         
         // Loads the character value of a single character string into dst.
         void emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures);
         
+        enum OptimizationCheckKind { LoopOptimizationCheck, RetOptimizationCheck };
+#if ENABLE(DFG_JIT)
+        void emitOptimizationCheck(OptimizationCheckKind);
+#else
+        void emitOptimizationCheck(OptimizationCheckKind) { }
+#endif
+        
         void emitTimeoutCheck();
 #ifndef NDEBUG
         void printBytecodeOperandTypes(unsigned src1, unsigned src2);
         void emitTimeoutCheck();
 #ifndef NDEBUG
         void printBytecodeOperandTypes(unsigned src1, unsigned src2);
@@ -949,7 +822,7 @@ namespace JSC {
 #endif
 
 #if ENABLE(SAMPLING_COUNTERS)
 #endif
 
 #if ENABLE(SAMPLING_COUNTERS)
-        void emitCount(AbstractSamplingCounter&, uint32_t = 1);
+        void emitCount(AbstractSamplingCounter&, int32_t = 1);
 #endif
 
 #if ENABLE(OPCODE_SAMPLING)
 #endif
 
 #if ENABLE(OPCODE_SAMPLING)
@@ -962,6 +835,16 @@ namespace JSC {
         void sampleCodeBlock(CodeBlock*) {}
 #endif
 
         void sampleCodeBlock(CodeBlock*) {}
 #endif
 
+#if ENABLE(DFG_JIT)
+        bool canBeOptimized() { return m_canBeOptimized; }
+        bool shouldEmitProfiling() { return m_canBeOptimized; }
+#else
+        bool canBeOptimized() { return false; }
+        // Enables use of value profiler with tiered compilation turned off,
+        // in which case all code gets profiled.
+        bool shouldEmitProfiling() { return true; }
+#endif
+
         Interpreter* m_interpreter;
         JSGlobalData* m_globalData;
         CodeBlock* m_codeBlock;
         Interpreter* m_interpreter;
         JSGlobalData* m_globalData;
         CodeBlock* m_codeBlock;
@@ -974,7 +857,6 @@ namespace JSC {
         Vector<JumpTable> m_jmpTable;
 
         unsigned m_bytecodeOffset;
         Vector<JumpTable> m_jmpTable;
 
         unsigned m_bytecodeOffset;
-        Vector<JSRInfo> m_jsrSites;
         Vector<SlowCaseEntry> m_slowCases;
         Vector<SwitchRecord> m_switches;
 
         Vector<SlowCaseEntry> m_slowCases;
         Vector<SwitchRecord> m_switches;
 
@@ -985,7 +867,7 @@ namespace JSC {
 #if USE(JSVALUE32_64)
         unsigned m_jumpTargetIndex;
         unsigned m_mappedBytecodeOffset;
 #if USE(JSVALUE32_64)
         unsigned m_jumpTargetIndex;
         unsigned m_mappedBytecodeOffset;
-        unsigned m_mappedVirtualRegisterIndex;
+        int m_mappedVirtualRegisterIndex;
         RegisterID m_mappedTag;
         RegisterID m_mappedPayload;
 #else
         RegisterID m_mappedTag;
         RegisterID m_mappedPayload;
 #else
@@ -1000,7 +882,11 @@ namespace JSC {
 #endif
 #endif
         WeakRandom m_randomGenerator;
 #endif
 #endif
         WeakRandom m_randomGenerator;
-        static CodePtr stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool);
+        static CodeRef stringGetByValStubGenerator(JSGlobalData*);
+
+#if ENABLE(VALUE_PROFILER)
+        bool m_canBeOptimized;
+#endif
     } JIT_CLASS_ALIGNMENT;
 
     inline void JIT::emit_op_loop(Instruction* currentInstruction)
     } JIT_CLASS_ALIGNMENT;
 
     inline void JIT::emit_op_loop(Instruction* currentInstruction)
@@ -1009,6 +895,11 @@ namespace JSC {
         emit_op_jmp(currentInstruction);
     }
 
         emit_op_jmp(currentInstruction);
     }
 
+    inline void JIT::emit_op_loop_hint(Instruction*)
+    {
+        emitOptimizationCheck(LoopOptimizationCheck);
+    }
+
     inline void JIT::emit_op_loop_if_true(Instruction* currentInstruction)
     {
         emitTimeoutCheck();
     inline void JIT::emit_op_loop_if_true(Instruction* currentInstruction)
     {
         emitTimeoutCheck();
@@ -1042,6 +933,39 @@ namespace JSC {
         emitSlow_op_jless(currentInstruction, iter);
     }
 
         emitSlow_op_jless(currentInstruction, iter);
     }
 
+    inline void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
+    {
+        emitTimeoutCheck();
+        emit_op_jlesseq(currentInstruction);
+    }
+
+    inline void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+    {
+        emitSlow_op_jlesseq(currentInstruction, iter);
+    }
+
+    inline void JIT::emit_op_loop_if_greater(Instruction* currentInstruction)
+    {
+        emitTimeoutCheck();
+        emit_op_jgreater(currentInstruction);
+    }
+
+    inline void JIT::emitSlow_op_loop_if_greater(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+    {
+        emitSlow_op_jgreater(currentInstruction, iter);
+    }
+
+    inline void JIT::emit_op_loop_if_greatereq(Instruction* currentInstruction)
+    {
+        emitTimeoutCheck();
+        emit_op_jgreatereq(currentInstruction);
+    }
+
+    inline void JIT::emitSlow_op_loop_if_greatereq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+    {
+        emitSlow_op_jgreatereq(currentInstruction, iter);
+    }
+
 } // namespace JSC
 
 #endif // ENABLE(JIT)
 } // namespace JSC
 
 #endif // ENABLE(JIT)
index c2a84c5a4a634e36b6b469da5088e01c6866cc9d..a9390e35f2449d5028c33311689386baf3511ae6 100644 (file)
@@ -26,7 +26,6 @@
 #include "config.h"
 
 #if ENABLE(JIT)
 #include "config.h"
 
 #if ENABLE(JIT)
-#if USE(JSVALUE64)
 #include "JIT.h"
 
 #include "CodeBlock.h"
 #include "JIT.h"
 
 #include "CodeBlock.h"
@@ -47,6 +46,188 @@ using namespace std;
 
 namespace JSC {
 
 
 namespace JSC {
 
+void JIT::emit_op_jless(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJump(op_jless, op1, op2, target, LessThan);
+}
+
+void JIT::emit_op_jlesseq(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJump(op_jlesseq, op1, op2, target, LessThanOrEqual);
+}
+
+void JIT::emit_op_jgreater(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJump(op_jgreater, op1, op2, target, GreaterThan);
+}
+
+void JIT::emit_op_jgreatereq(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJump(op_jgreatereq, op1, op2, target, GreaterThanOrEqual);
+}
+
+void JIT::emit_op_jnless(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJump(op_jnless, op1, op2, target, GreaterThanOrEqual);
+}
+
+void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJump(op_jnlesseq, op1, op2, target, GreaterThan);
+}
+
+void JIT::emit_op_jngreater(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJump(op_jngreater, op1, op2, target, LessThanOrEqual);
+}
+
+void JIT::emit_op_jngreatereq(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJump(op_jngreatereq, op1, op2, target, LessThan);
+}
+
+void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJumpSlow(op1, op2, target, DoubleLessThan, cti_op_jless, false, iter);
+}
+
+void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJumpSlow(op1, op2, target, DoubleLessThanOrEqual, cti_op_jlesseq, false, iter);
+}
+
+void JIT::emitSlow_op_jgreater(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJumpSlow(op1, op2, target, DoubleGreaterThan, cti_op_jgreater, false, iter);
+}
+
+void JIT::emitSlow_op_jgreatereq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJumpSlow(op1, op2, target, DoubleGreaterThanOrEqual, cti_op_jgreatereq, false, iter);
+}
+
+void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJumpSlow(op1, op2, target, DoubleGreaterThanOrEqualOrUnordered, cti_op_jless, true, iter);
+}
+
+void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJumpSlow(op1, op2, target, DoubleGreaterThanOrUnordered, cti_op_jlesseq, true, iter);
+}
+
+void JIT::emitSlow_op_jngreater(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJumpSlow(op1, op2, target, DoubleLessThanOrEqualOrUnordered, cti_op_jgreater, true, iter);
+}
+
+void JIT::emitSlow_op_jngreatereq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    emit_compareAndJumpSlow(op1, op2, target, DoubleLessThanOrUnordered, cti_op_jgreatereq, true, iter);
+}
+
+#if USE(JSVALUE64)
+
+void JIT::emit_op_negate(Instruction* currentInstruction)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned src = currentInstruction[2].u.operand;
+
+    emitGetVirtualRegister(src, regT0);
+
+    Jump srcNotInt = emitJumpIfNotImmediateInteger(regT0);
+    addSlowCase(branchTest32(Zero, regT0, TrustedImm32(0x7fffffff)));
+    neg32(regT0);
+    emitFastArithReTagImmediate(regT0, regT0);
+
+    Jump end = jump();
+
+    srcNotInt.link(this);
+    emitJumpSlowCaseIfNotImmediateNumber(regT0);
+
+    move(TrustedImmPtr(reinterpret_cast<void*>(0x8000000000000000ull)), regT1);
+    xorPtr(regT1, regT0);
+
+    end.link(this);
+    emitPutVirtualRegister(dst);
+}
+
+void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+
+    linkSlowCase(iter); // 0x7fffffff check
+    linkSlowCase(iter); // double check
+
+    JITStubCall stubCall(this, cti_op_negate);
+    stubCall.addArgument(regT1, regT0);
+    stubCall.call(dst);
+}
+
 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;
@@ -242,318 +423,8 @@ void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEn
     stubCall.call(dst);
 }
 
     stubCall.call(dst);
 }
 
-void JIT::emit_op_jnless(Instruction* currentInstruction)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
-    // We generate inline code for the following cases in the fast path:
-    // - int immediate to constant int immediate
-    // - constant int immediate to int immediate
-    // - int immediate to int immediate
-
-    if (isOperandConstantImmediateChar(op1)) {
-        emitGetVirtualRegister(op2, regT0);
-        addSlowCase(emitJumpIfNotJSCell(regT0));
-        JumpList failures;
-        emitLoadCharacterString(regT0, regT0, failures);
-        addSlowCase(failures);
-        addJump(branch32(LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
-        return;
-    }
-    if (isOperandConstantImmediateChar(op2)) {
-        emitGetVirtualRegister(op1, regT0);
-        addSlowCase(emitJumpIfNotJSCell(regT0));
-        JumpList failures;
-        emitLoadCharacterString(regT0, regT0, failures);
-        addSlowCase(failures);
-        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
-        return;
-    }
-    if (isOperandConstantImmediateInt(op2)) {
-        emitGetVirtualRegister(op1, regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        int32_t op2imm = getConstantOperandImmediateInt(op2);
-        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target);
-    } else if (isOperandConstantImmediateInt(op1)) {
-        emitGetVirtualRegister(op2, regT1);
-        emitJumpSlowCaseIfNotImmediateInteger(regT1);
-        int32_t op1imm = getConstantOperandImmediateInt(op1);
-        addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target);
-    } else {
-        emitGetVirtualRegisters(op1, regT0, op2, regT1);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT1);
-
-        addJump(branch32(GreaterThanOrEqual, regT0, regT1), target);
-    }
-}
-
-void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
-    // We generate inline code for the following cases in the slow path:
-    // - floating-point number to constant int immediate
-    // - constant int immediate to floating-point number
-    // - floating-point number to floating-point number.
-    if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_jless);
-        stubCall.addArgument(op1, regT0);
-        stubCall.addArgument(op2, regT1);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
-        return;
-    }
-
-    if (isOperandConstantImmediateInt(op2)) {
-        linkSlowCase(iter);
-
-        if (supportsFloatingPoint()) {
-            Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
-            addPtr(tagTypeNumberRegister, regT0);
-            movePtrToDouble(regT0, fpRegT0);
-
-            int32_t op2imm = getConstantOperand(op2).asInt32();;
-
-            move(Imm32(op2imm), regT1);
-            convertInt32ToDouble(regT1, fpRegT1);
-
-            emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
-
-            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
-
-            fail1.link(this);
-        }
-
-        JITStubCall stubCall(this, cti_op_jless);
-        stubCall.addArgument(regT0);
-        stubCall.addArgument(op2, regT2);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
-
-    } else if (isOperandConstantImmediateInt(op1)) {
-        linkSlowCase(iter);
-
-        if (supportsFloatingPoint()) {
-            Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
-            addPtr(tagTypeNumberRegister, regT1);
-            movePtrToDouble(regT1, fpRegT1);
-
-            int32_t op1imm = getConstantOperand(op1).asInt32();;
-
-            move(Imm32(op1imm), regT0);
-            convertInt32ToDouble(regT0, fpRegT0);
-
-            emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
-
-            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
-
-            fail1.link(this);
-        }
-
-        JITStubCall stubCall(this, cti_op_jless);
-        stubCall.addArgument(op1, regT2);
-        stubCall.addArgument(regT1);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
-
-    } else {
-        linkSlowCase(iter);
-
-        if (supportsFloatingPoint()) {
-            Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
-            Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
-            Jump fail3 = emitJumpIfImmediateInteger(regT1);
-            addPtr(tagTypeNumberRegister, regT0);
-            addPtr(tagTypeNumberRegister, regT1);
-            movePtrToDouble(regT0, fpRegT0);
-            movePtrToDouble(regT1, fpRegT1);
-
-            emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
-
-            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
-
-            fail1.link(this);
-            fail2.link(this);
-            fail3.link(this);
-        }
-
-        linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_jless);
-        stubCall.addArgument(regT0);
-        stubCall.addArgument(regT1);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
-    }
-}
-
-void JIT::emit_op_jless(Instruction* currentInstruction)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
-    // We generate inline code for the following cases in the fast path:
-    // - int immediate to constant int immediate
-    // - constant int immediate to int immediate
-    // - int immediate to int immediate
-
-    if (isOperandConstantImmediateChar(op1)) {
-        emitGetVirtualRegister(op2, regT0);
-        addSlowCase(emitJumpIfNotJSCell(regT0));
-        JumpList failures;
-        emitLoadCharacterString(regT0, regT0, failures);
-        addSlowCase(failures);
-        addJump(branch32(GreaterThan, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
-        return;
-    }
-    if (isOperandConstantImmediateChar(op2)) {
-        emitGetVirtualRegister(op1, regT0);
-        addSlowCase(emitJumpIfNotJSCell(regT0));
-        JumpList failures;
-        emitLoadCharacterString(regT0, regT0, failures);
-        addSlowCase(failures);
-        addJump(branch32(LessThan, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
-        return;
-    }
-    if (isOperandConstantImmediateInt(op2)) {
-        emitGetVirtualRegister(op1, regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        int32_t op2imm = getConstantOperandImmediateInt(op2);
-        addJump(branch32(LessThan, regT0, Imm32(op2imm)), target);
-    } else if (isOperandConstantImmediateInt(op1)) {
-        emitGetVirtualRegister(op2, regT1);
-        emitJumpSlowCaseIfNotImmediateInteger(regT1);
-        int32_t op1imm = getConstantOperandImmediateInt(op1);
-        addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target);
-    } else {
-        emitGetVirtualRegisters(op1, regT0, op2, regT1);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT1);
-
-        addJump(branch32(LessThan, regT0, regT1), target);
-    }
-}
-
-void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
-    // We generate inline code for the following cases in the slow path:
-    // - floating-point number to constant int immediate
-    // - constant int immediate to floating-point number
-    // - floating-point number to floating-point number.
-    if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_jless);
-        stubCall.addArgument(op1, regT0);
-        stubCall.addArgument(op2, regT1);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
-        return;
-    }
-
-    if (isOperandConstantImmediateInt(op2)) {
-        linkSlowCase(iter);
-
-        if (supportsFloatingPoint()) {
-            Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
-            addPtr(tagTypeNumberRegister, regT0);
-            movePtrToDouble(regT0, fpRegT0);
-
-            int32_t op2imm = getConstantOperand(op2).asInt32();
-
-            move(Imm32(op2imm), regT1);
-            convertInt32ToDouble(regT1, fpRegT1);
-
-            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
-
-            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
-
-            fail1.link(this);
-        }
-
-        JITStubCall stubCall(this, cti_op_jless);
-        stubCall.addArgument(regT0);
-        stubCall.addArgument(op2, regT2);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
-
-    } else if (isOperandConstantImmediateInt(op1)) {
-        linkSlowCase(iter);
-
-        if (supportsFloatingPoint()) {
-            Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
-            addPtr(tagTypeNumberRegister, regT1);
-            movePtrToDouble(regT1, fpRegT1);
-
-            int32_t op1imm = getConstantOperand(op1).asInt32();
-
-            move(Imm32(op1imm), regT0);
-            convertInt32ToDouble(regT0, fpRegT0);
-
-            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
-
-            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
-
-            fail1.link(this);
-        }
-
-        JITStubCall stubCall(this, cti_op_jless);
-        stubCall.addArgument(op1, regT2);
-        stubCall.addArgument(regT1);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
-
-    } else {
-        linkSlowCase(iter);
-
-        if (supportsFloatingPoint()) {
-            Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
-            Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
-            Jump fail3 = emitJumpIfImmediateInteger(regT1);
-            addPtr(tagTypeNumberRegister, regT0);
-            addPtr(tagTypeNumberRegister, regT1);
-            movePtrToDouble(regT0, fpRegT0);
-            movePtrToDouble(regT1, fpRegT1);
-
-            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
-
-            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
-
-            fail1.link(this);
-            fail2.link(this);
-            fail3.link(this);
-        }
-
-        linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_jless);
-        stubCall.addArgument(regT0);
-        stubCall.addArgument(regT1);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
-    }
-}
-
-void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
+void JIT::emit_compareAndJump(OpcodeID, unsigned op1, unsigned op2, unsigned target, RelationalCondition condition)
 {
 {
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
     // We generate inline code for the following cases in the fast path:
     // - int immediate to constant int immediate
     // - constant int immediate to int immediate
     // We generate inline code for the following cases in the fast path:
     // - int immediate to constant int immediate
     // - constant int immediate to int immediate
@@ -565,7 +436,7 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
-        addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
+        addJump(branch32(commute(condition), regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
         return;
     }
     if (isOperandConstantImmediateChar(op2)) {
         return;
     }
     if (isOperandConstantImmediateChar(op2)) {
@@ -574,45 +445,48 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
-        addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
+        addJump(branch32(condition, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
         return;
     }
     if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         int32_t op2imm = getConstantOperandImmediateInt(op2);
         return;
     }
     if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         int32_t op2imm = getConstantOperandImmediateInt(op2);
-        addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(op2imm)), target);
+        addJump(branch32(condition, regT0, Imm32(op2imm)), target);
     } else if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
         int32_t op1imm = getConstantOperandImmediateInt(op1);
     } else if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
         int32_t op1imm = getConstantOperandImmediateInt(op1);
-        addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT1, Imm32(op1imm)), target);
+        addJump(branch32(commute(condition), regT1, Imm32(op1imm)), target);
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
 
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
 
-        addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, regT1), target);
+        addJump(branch32(condition, regT0, regT1), target);
     }
 }
 
     }
 }
 
-void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool invert)
+void JIT::emit_compareAndJumpSlow(unsigned op1, unsigned op2, unsigned target, DoubleCondition condition, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION), bool invert, Vector<SlowCaseEntry>::iterator& iter)
 {
 {
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
+    COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jlesseq), OPCODE_LENGTH_op_jlesseq_equals_op_jless);
+    COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jnless), OPCODE_LENGTH_op_jnless_equals_op_jless);
+    COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jnlesseq), OPCODE_LENGTH_op_jnlesseq_equals_op_jless);
+    COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jgreater), OPCODE_LENGTH_op_jgreater_equals_op_jless);
+    COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jgreatereq), OPCODE_LENGTH_op_jgreatereq_equals_op_jless);
+    COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jngreater), OPCODE_LENGTH_op_jngreater_equals_op_jless);
+    COMPILE_ASSERT(OPCODE_LENGTH(op_jless) == OPCODE_LENGTH(op_jngreatereq), OPCODE_LENGTH_op_jngreatereq_equals_op_jless);
+    
     // We generate inline code for the following cases in the slow path:
     // - floating-point number to constant int immediate
     // - constant int immediate to floating-point number
     // - floating-point number to floating-point number.
     // We generate inline code for the following cases in the slow path:
     // - floating-point number to constant int immediate
     // - constant int immediate to floating-point number
     // - floating-point number to floating-point number.
-
     if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
         linkSlowCase(iter);
         linkSlowCase(iter);
         linkSlowCase(iter);
         linkSlowCase(iter);
     if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
         linkSlowCase(iter);
         linkSlowCase(iter);
         linkSlowCase(iter);
         linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_jlesseq);
+        JITStubCall stubCall(this, stub);
         stubCall.addArgument(op1, regT0);
         stubCall.addArgument(op2, regT1);
         stubCall.call();
         stubCall.addArgument(op1, regT0);
         stubCall.addArgument(op2, regT1);
         stubCall.call();
@@ -628,19 +502,19 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
             addPtr(tagTypeNumberRegister, regT0);
             movePtrToDouble(regT0, fpRegT0);
 
             addPtr(tagTypeNumberRegister, regT0);
             movePtrToDouble(regT0, fpRegT0);
 
-            int32_t op2imm = getConstantOperand(op2).asInt32();;
+            int32_t op2imm = getConstantOperand(op2).asInt32();
 
             move(Imm32(op2imm), regT1);
             convertInt32ToDouble(regT1, fpRegT1);
 
 
             move(Imm32(op2imm), regT1);
             convertInt32ToDouble(regT1, fpRegT1);
 
-            emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target);
+            emitJumpSlowToHot(branchDouble(condition, fpRegT0, fpRegT1), target);
 
 
-            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
+            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jless));
 
             fail1.link(this);
         }
 
 
             fail1.link(this);
         }
 
-        JITStubCall stubCall(this, cti_op_jlesseq);
+        JITStubCall stubCall(this, stub);
         stubCall.addArgument(regT0);
         stubCall.addArgument(op2, regT2);
         stubCall.call();
         stubCall.addArgument(regT0);
         stubCall.addArgument(op2, regT2);
         stubCall.call();
@@ -654,24 +528,23 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
             addPtr(tagTypeNumberRegister, regT1);
             movePtrToDouble(regT1, fpRegT1);
 
             addPtr(tagTypeNumberRegister, regT1);
             movePtrToDouble(regT1, fpRegT1);
 
-            int32_t op1imm = getConstantOperand(op1).asInt32();;
+            int32_t op1imm = getConstantOperand(op1).asInt32();
 
             move(Imm32(op1imm), regT0);
             convertInt32ToDouble(regT0, fpRegT0);
 
 
             move(Imm32(op1imm), regT0);
             convertInt32ToDouble(regT0, fpRegT0);
 
-            emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target);
+            emitJumpSlowToHot(branchDouble(condition, fpRegT0, fpRegT1), target);
 
 
-            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
+            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jless));
 
             fail1.link(this);
         }
 
 
             fail1.link(this);
         }
 
-        JITStubCall stubCall(this, cti_op_jlesseq);
+        JITStubCall stubCall(this, stub);
         stubCall.addArgument(op1, regT2);
         stubCall.addArgument(regT1);
         stubCall.call();
         emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
         stubCall.addArgument(op1, regT2);
         stubCall.addArgument(regT1);
         stubCall.call();
         emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
-
     } else {
         linkSlowCase(iter);
 
     } else {
         linkSlowCase(iter);
 
@@ -684,9 +557,9 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
             movePtrToDouble(regT0, fpRegT0);
             movePtrToDouble(regT1, fpRegT1);
 
             movePtrToDouble(regT0, fpRegT0);
             movePtrToDouble(regT1, fpRegT1);
 
-            emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target);
+            emitJumpSlowToHot(branchDouble(condition, fpRegT0, fpRegT1), target);
 
 
-            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
+            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jless));
 
             fail1.link(this);
             fail2.link(this);
 
             fail1.link(this);
             fail2.link(this);
@@ -694,7 +567,7 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
         }
 
         linkSlowCase(iter);
         }
 
         linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_jlesseq);
+        JITStubCall stubCall(this, stub);
         stubCall.addArgument(regT0);
         stubCall.addArgument(regT1);
         stubCall.call();
         stubCall.addArgument(regT0);
         stubCall.addArgument(regT1);
         stubCall.call();
@@ -702,16 +575,6 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
     }
 }
 
     }
 }
 
-void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
-{
-    emit_op_jlesseq(currentInstruction, true);
-}
-
-void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    emitSlow_op_jlesseq(currentInstruction, iter, true);
-}
-
 void JIT::emit_op_bitand(Instruction* currentInstruction)
 {
     unsigned result = currentInstruction[1].u.operand;
 void JIT::emit_op_bitand(Instruction* currentInstruction)
 {
     unsigned result = currentInstruction[1].u.operand;
@@ -800,7 +663,7 @@ void JIT::emit_op_post_dec(Instruction* currentInstruction)
     emitGetVirtualRegister(srcDst, regT0);
     move(regT0, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
     emitGetVirtualRegister(srcDst, regT0);
     move(regT0, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
-    addSlowCase(branchSub32(Zero, TrustedImm32(1), regT1));
+    addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT1));
     emitFastArithIntToImmNoCheck(regT1, regT1);
     emitPutVirtualRegister(srcDst, regT1);
     emitPutVirtualRegister(result);
     emitFastArithIntToImmNoCheck(regT1, regT1);
     emitPutVirtualRegister(srcDst, regT1);
     emitPutVirtualRegister(result);
@@ -849,7 +712,7 @@ void JIT::emit_op_pre_dec(Instruction* currentInstruction)
 
     emitGetVirtualRegister(srcDst, regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
 
     emitGetVirtualRegister(srcDst, regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
-    addSlowCase(branchSub32(Zero, TrustedImm32(1), regT0));
+    addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0));
     emitFastArithIntToImmNoCheck(regT0, regT0);
     emitPutVirtualRegister(srcDst);
 }
     emitFastArithIntToImmNoCheck(regT0, regT0);
     emitPutVirtualRegister(srcDst);
 }
@@ -869,7 +732,7 @@ void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEn
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
-#if CPU(X86) || CPU(X86_64) || CPU(MIPS)
+#if CPU(X86) || CPU(X86_64)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
@@ -877,20 +740,25 @@ 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);
     // Make sure registers are correct for x86 IDIV instructions.
     ASSERT(regT0 == X86Registers::eax);
     ASSERT(regT1 == X86Registers::edx);
     ASSERT(regT2 == X86Registers::ecx);
-#endif
 
 
-    emitGetVirtualRegisters(op1, regT0, op2, regT2);
-    emitJumpSlowCaseIfNotImmediateInteger(regT0);
+    emitGetVirtualRegisters(op1, regT3, op2, regT2);
+    emitJumpSlowCaseIfNotImmediateInteger(regT3);
     emitJumpSlowCaseIfNotImmediateInteger(regT2);
 
     emitJumpSlowCaseIfNotImmediateInteger(regT2);
 
-    addSlowCase(branchPtr(Equal, regT2, TrustedImmPtr(JSValue::encode(jsNumber(0)))));
+    move(regT3, regT0);
+    addSlowCase(branchTest32(Zero, regT2));
+    Jump denominatorNotNeg1 = branch32(NotEqual, regT2, TrustedImm32(-1));
+    addSlowCase(branch32(Equal, regT0, TrustedImm32(-2147483647-1)));
+    denominatorNotNeg1.link(this);
     m_assembler.cdq();
     m_assembler.idivl_r(regT2);
     m_assembler.cdq();
     m_assembler.idivl_r(regT2);
+    Jump numeratorPositive = branch32(GreaterThanOrEqual, regT3, TrustedImm32(0));
+    addSlowCase(branchTest32(Zero, regT1));
+    numeratorPositive.link(this);
     emitFastArithReTagImmediate(regT1, regT0);
     emitPutVirtualRegister(result);
 }
     emitFastArithReTagImmediate(regT1, regT0);
     emitPutVirtualRegister(result);
 }
@@ -899,16 +767,18 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>
 {
     unsigned result = currentInstruction[1].u.operand;
 
 {
     unsigned result = currentInstruction[1].u.operand;
 
+    linkSlowCase(iter);
+    linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_mod);
     linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_mod);
-    stubCall.addArgument(regT0);
+    stubCall.addArgument(regT3);
     stubCall.addArgument(regT2);
     stubCall.call(result);
 }
 
     stubCall.addArgument(regT2);
     stubCall.call(result);
 }
 
-#else // CPU(X86) || CPU(X86_64) || CPU(MIPS)
+#else // CPU(X86) || CPU(X86_64)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
@@ -924,20 +794,7 @@ 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_USE_SOFT_MODULO)
-    unsigned result = currentInstruction[1].u.operand;
-    unsigned op1 = currentInstruction[2].u.operand;
-    unsigned op2 = currentInstruction[3].u.operand;
-    linkSlowCase(iter);
-    linkSlowCase(iter);
-    linkSlowCase(iter);
-    JITStubCall stubCall(this, cti_op_mod);
-    stubCall.addArgument(op1, regT2);
-    stubCall.addArgument(op2, regT2);
-    stubCall.call(result);
-#else
     ASSERT_NOT_REACHED();
     ASSERT_NOT_REACHED();
-#endif
 }
 
 #endif // CPU(X86) || CPU(X86_64)
 }
 
 #endif // CPU(X86) || CPU(X86_64)
@@ -951,14 +808,43 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsign
     emitGetVirtualRegisters(op1, regT0, op2, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT1);
     emitGetVirtualRegisters(op1, regT0, op2, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT1);
+#if ENABLE(VALUE_PROFILER)
+    RareCaseProfile* profile = m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
+#endif
     if (opcodeID == op_add)
         addSlowCase(branchAdd32(Overflow, regT1, regT0));
     else if (opcodeID == op_sub)
         addSlowCase(branchSub32(Overflow, regT1, regT0));
     else {
         ASSERT(opcodeID == op_mul);
     if (opcodeID == op_add)
         addSlowCase(branchAdd32(Overflow, regT1, regT0));
     else if (opcodeID == op_sub)
         addSlowCase(branchSub32(Overflow, regT1, regT0));
     else {
         ASSERT(opcodeID == op_mul);
+#if ENABLE(VALUE_PROFILER)
+        if (m_canBeOptimized) {
+            // We want to be able to measure if this is taking the slow case just
+            // because of negative zero. If this produces positive zero, then we
+            // don't want the slow case to be taken because that will throw off
+            // speculative compilation.
+            move(regT0, regT2);
+            addSlowCase(branchMul32(Overflow, regT1, regT2));
+            JumpList done;
+            done.append(branchTest32(NonZero, regT2));
+            Jump negativeZero = branch32(LessThan, regT0, TrustedImm32(0));
+            done.append(branch32(GreaterThanOrEqual, regT1, TrustedImm32(0)));
+            negativeZero.link(this);
+            // We only get here if we have a genuine negative zero. Record this,
+            // so that the speculative JIT knows that we failed speculation
+            // because of a negative zero.
+            add32(TrustedImm32(1), AbsoluteAddress(&profile->m_counter));
+            addSlowCase(jump());
+            done.link(this);
+            move(regT2, regT0);
+        } else {
+            addSlowCase(branchMul32(Overflow, regT1, regT0));
+            addSlowCase(branchTest32(Zero, regT0));
+        }
+#else
         addSlowCase(branchMul32(Overflow, regT1, regT0));
         addSlowCase(branchTest32(Zero, regT0));
         addSlowCase(branchMul32(Overflow, regT1, regT0));
         addSlowCase(branchTest32(Zero, regT0));
+#endif
     }
     emitFastArithIntToImmNoCheck(regT0, regT0);
 }
     }
     emitFastArithIntToImmNoCheck(regT0, regT0);
 }
@@ -1060,6 +946,7 @@ void JIT::emit_op_add(Instruction* currentInstruction)
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
+        addSlowCase();
         JITStubCall stubCall(this, cti_op_add);
         stubCall.addArgument(op1, regT2);
         stubCall.addArgument(op2, regT2);
         JITStubCall stubCall(this, cti_op_add);
         stubCall.addArgument(op1, regT2);
         stubCall.addArgument(op2, regT2);
@@ -1070,13 +957,13 @@ void JIT::emit_op_add(Instruction* currentInstruction)
     if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
     if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1)), regT0));
-        emitFastArithIntToImmNoCheck(regT0, regT0);
+        addSlowCase(branchAdd32(Overflow, regT0, Imm32(getConstantOperandImmediateInt(op1)), regT1));
+        emitFastArithIntToImmNoCheck(regT1, regT0);
     } else if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
     } else if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2)), regT0));
-        emitFastArithIntToImmNoCheck(regT0, regT0);
+        addSlowCase(branchAdd32(Overflow, regT0, Imm32(getConstantOperandImmediateInt(op2)), regT1));
+        emitFastArithIntToImmNoCheck(regT1, regT0);
     } else
         compileBinaryArithOp(op_add, result, op1, op2, types);
 
     } else
         compileBinaryArithOp(op_add, result, op1, op2, types);
 
@@ -1090,8 +977,10 @@ void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
-    if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
+    if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
+        linkDummySlowCase(iter);
         return;
         return;
+    }
 
     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1);
     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2);
 
     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1);
     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2);
@@ -1108,15 +997,23 @@ void JIT::emit_op_mul(Instruction* currentInstruction)
     // 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)) {
     // 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)) {
+#if ENABLE(VALUE_PROFILER)
+        // Add a special fast case profile because the DFG JIT will expect one.
+        m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
+#endif
         emitGetVirtualRegister(op2, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         emitGetVirtualRegister(op2, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
-        emitFastArithReTagImmediate(regT0, regT0);
+        addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT1));
+        emitFastArithReTagImmediate(regT1, regT0);
     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
     } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
+#if ENABLE(VALUE_PROFILER)
+        // Add a special fast case profile because the DFG JIT will expect one.
+        m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
+#endif
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
-        emitFastArithReTagImmediate(regT0, regT0);
+        addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT1));
+        emitFastArithReTagImmediate(regT1, regT0);
     } else
         compileBinaryArithOp(op_mul, result, op1, op2, types);
 
     } else
         compileBinaryArithOp(op_mul, result, op1, op2, types);
 
@@ -1180,10 +1077,37 @@ void JIT::emit_op_div(Instruction* currentInstruction)
         skipDoubleLoad.link(this);
     }
     divDouble(fpRegT1, fpRegT0);
         skipDoubleLoad.link(this);
     }
     divDouble(fpRegT1, fpRegT0);
-
+    
+#if ENABLE(VALUE_PROFILER)
+    // Is the result actually an integer? The DFG JIT would really like to know. If it's
+    // not an integer, we increment a count. If this together with the slow case counter
+    // are below threshold then the DFG JIT will compile this division with a specualtion
+    // that the remainder is zero.
+    
+    // As well, there are cases where a double result here would cause an important field
+    // in the heap to sometimes have doubles in it, resulting in double predictions getting
+    // propagated to a use site where it might cause damage (such as the index to an array
+    // access). So if we are DFG compiling anything in the program, we want this code to
+    // ensure that it produces integers whenever possible.
+    
+    // FIXME: This will fail to convert to integer if the result is zero. We should
+    // distinguish between positive zero and negative zero here.
+    
+    JumpList notInteger;
+    branchConvertDoubleToInt32(fpRegT0, regT0, notInteger, fpRegT1);
+    // If we've got an integer, we might as well make that the result of the division.
+    emitFastArithReTagImmediate(regT0, regT0);
+    Jump isInteger = jump();
+    notInteger.link(this);
+    add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter));
+    moveDoubleToPtr(fpRegT0, regT0);
+    subPtr(tagTypeNumberRegister, regT0);
+    isInteger.link(this);
+#else
     // Double result.
     moveDoubleToPtr(fpRegT0, regT0);
     subPtr(tagTypeNumberRegister, regT0);
     // Double result.
     moveDoubleToPtr(fpRegT0, regT0);
     subPtr(tagTypeNumberRegister, regT0);
+#endif
 
     emitPutVirtualRegister(dst, regT0);
 }
 
     emitPutVirtualRegister(dst, regT0);
 }
@@ -1238,7 +1162,8 @@ void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>
 
 /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
 
 
 /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
 
+#endif // USE(JSVALUE64)
+
 } // namespace JSC
 
 } // namespace JSC
 
-#endif // USE(JSVALUE64)
 #endif // ENABLE(JIT)
 #endif // ENABLE(JIT)
index 67946548dc14309a3fb6ab884d571edd0bc76985..62a359eebf94dfa784490b5ff1ba1ddd770f3653 100644 (file)
@@ -84,12 +84,8 @@ void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEnt
     stubCall.call(dst);
 }
 
     stubCall.call(dst);
 }
 
-void JIT::emit_op_jnless(Instruction* currentInstruction)
+void JIT::emit_compareAndJump(OpcodeID opcode, unsigned op1, unsigned op2, unsigned target, RelationalCondition condition)
 {
 {
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
     JumpList notInt32Op1;
     JumpList notInt32Op2;
 
     JumpList notInt32Op1;
     JumpList notInt32Op2;
 
@@ -100,7 +96,7 @@ void JIT::emit_op_jnless(Instruction* currentInstruction)
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
-        addJump(branch32(LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
+        addJump(branch32(commute(condition), regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
         return;
     }
     if (isOperandConstantImmediateChar(op2)) {
         return;
     }
     if (isOperandConstantImmediateChar(op2)) {
@@ -109,198 +105,22 @@ void JIT::emit_op_jnless(Instruction* currentInstruction)
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
-        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
-        return;
-    }
-    if (isOperandConstantImmediateInt(op1)) {
-        // Int32 less.
-        emitLoad(op2, regT3, regT2);
-        notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
-        addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
-    } else if (isOperandConstantImmediateInt(op2)) {
-        emitLoad(op1, regT1, regT0);
-        notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
-    } else {
-        emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-        notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-        notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
-        addJump(branch32(GreaterThanOrEqual, regT0, regT2), target);
-    }
-
-    if (!supportsFloatingPoint()) {
-        addSlowCase(notInt32Op1);
-        addSlowCase(notInt32Op2);
-        return;
-    }
-    Jump end = jump();
-
-    // Double less.
-    emitBinaryDoubleOp(op_jnless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
-    end.link(this);
-}
-
-void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
-    if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-    } else {
-        if (!supportsFloatingPoint()) {
-            if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
-                linkSlowCase(iter); // int32 check
-            linkSlowCase(iter); // int32 check
-        } else {
-            if (!isOperandConstantImmediateInt(op1)) {
-                linkSlowCase(iter); // double check
-                linkSlowCase(iter); // int32 check
-            }
-            if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
-                linkSlowCase(iter); // double check
-        }
-    }
-
-    JITStubCall stubCall(this, cti_op_jless);
-    stubCall.addArgument(op1);
-    stubCall.addArgument(op2);
-    stubCall.call();
-    emitJumpSlowToHot(branchTest32(Zero, regT0), target);
-}
-
-void JIT::emit_op_jless(Instruction* currentInstruction)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
-    JumpList notInt32Op1;
-    JumpList notInt32Op2;
-
-    // Character less.
-    if (isOperandConstantImmediateChar(op1)) {
-        emitLoad(op2, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
-        JumpList failures;
-        emitLoadCharacterString(regT0, regT0, failures);
-        addSlowCase(failures);
-        addJump(branch32(GreaterThan, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
-        return;
-    }
-    if (isOperandConstantImmediateChar(op2)) {
-        emitLoad(op1, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
-        JumpList failures;
-        emitLoadCharacterString(regT0, regT0, failures);
-        addSlowCase(failures);
-        addJump(branch32(LessThan, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
+        addJump(branch32(condition, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
         return;
     } 
     if (isOperandConstantImmediateInt(op1)) {
         emitLoad(op2, regT3, regT2);
         notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
         return;
     } 
     if (isOperandConstantImmediateInt(op1)) {
         emitLoad(op2, regT3, regT2);
         notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
-        addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
-    } else if (isOperandConstantImmediateInt(op2)) {
-        emitLoad(op1, regT1, regT0);
-        notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-        addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
-    } else {
-        emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-        notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-        notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
-        addJump(branch32(LessThan, regT0, regT2), target);
-    }
-
-    if (!supportsFloatingPoint()) {
-        addSlowCase(notInt32Op1);
-        addSlowCase(notInt32Op2);
-        return;
-    }
-    Jump end = jump();
-
-    // Double less.
-    emitBinaryDoubleOp(op_jless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
-    end.link(this);
-}
-
-void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-    
-    if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-    } else {
-        if (!supportsFloatingPoint()) {
-            if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
-                linkSlowCase(iter); // int32 check
-            linkSlowCase(iter); // int32 check
-        } else {
-            if (!isOperandConstantImmediateInt(op1)) {
-                linkSlowCase(iter); // double check
-                linkSlowCase(iter); // int32 check
-            }
-            if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
-                linkSlowCase(iter); // double check
-        }
-    }
-    JITStubCall stubCall(this, cti_op_jless);
-    stubCall.addArgument(op1);
-    stubCall.addArgument(op2);
-    stubCall.call();
-    emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
-}
-
-void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
-    JumpList notInt32Op1;
-    JumpList notInt32Op2;
-
-    // Character less.
-    if (isOperandConstantImmediateChar(op1)) {
-        emitLoad(op2, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
-        JumpList failures;
-        emitLoadCharacterString(regT0, regT0, failures);
-        addSlowCase(failures);
-        addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
-        return;
-    }
-    if (isOperandConstantImmediateChar(op2)) {
-        emitLoad(op1, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
-        JumpList failures;
-        emitLoadCharacterString(regT0, regT0, failures);
-        addSlowCase(failures);
-        addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
-        return;
-    }
-    if (isOperandConstantImmediateInt(op1)) {
-        emitLoad(op2, regT3, regT2);
-        notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
-        addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
+        addJump(branch32(commute(condition), regT2, Imm32(getConstantOperand(op1).asInt32())), target);
     } else if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
         notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     } else if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
         notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-        addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
+        addJump(branch32(condition, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
     } else {
         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
         notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     } else {
         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
         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(condition, regT0, regT2), target);
     }
 
     if (!supportsFloatingPoint()) {
     }
 
     if (!supportsFloatingPoint()) {
@@ -311,16 +131,12 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
     Jump end = jump();
 
     // Double less.
     Jump end = jump();
 
     // Double less.
-    emitBinaryDoubleOp(invert ? op_jnlesseq : op_jlesseq, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
+    emitBinaryDoubleOp(opcode, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
     end.link(this);
 }
 
     end.link(this);
 }
 
-void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool invert)
+void JIT::emit_compareAndJumpSlow(unsigned op1, unsigned op2, unsigned target, DoubleCondition, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION), bool invert, Vector<SlowCaseEntry>::iterator& iter)
 {
 {
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
     if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
         linkSlowCase(iter);
         linkSlowCase(iter);
     if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
         linkSlowCase(iter);
         linkSlowCase(iter);
@@ -340,24 +156,13 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
                 linkSlowCase(iter); // double check
         }
     }
                 linkSlowCase(iter); // double check
         }
     }
-
-    JITStubCall stubCall(this, cti_op_jlesseq);
+    JITStubCall stubCall(this, stub);
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
     stubCall.call();
     emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
 }
 
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
     stubCall.call();
     emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
 }
 
-void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
-{
-    emit_op_jlesseq(currentInstruction, true);
-}
-
-void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    emitSlow_op_jlesseq(currentInstruction, iter, true);
-}
-
 // LeftShift (<<)
 
 void JIT::emit_op_lshift(Instruction* currentInstruction)
 // LeftShift (<<)
 
 void JIT::emit_op_lshift(Instruction* currentInstruction)
@@ -370,7 +175,7 @@ void JIT::emit_op_lshift(Instruction* currentInstruction)
         emitLoad(op1, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
         emitLoad(op1, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
-        emitStoreInt32(dst, regT0, dst == op1);
+        emitStoreAndMapInt32(dst, regT1, regT0, dst == op1, OPCODE_LENGTH(op_lshift));
         return;
     }
 
         return;
     }
 
@@ -379,7 +184,7 @@ void JIT::emit_op_lshift(Instruction* currentInstruction)
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     lshift32(regT2, regT0);
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     lshift32(regT2, regT0);
-    emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
+    emitStoreAndMapInt32(dst, regT1, regT0, dst == op1 || dst == op2, OPCODE_LENGTH(op_lshift));
 }
 
 void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -411,32 +216,27 @@ void JIT::emitRightShift(Instruction* currentInstruction, bool isUnsigned)
     if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-        int shift = getConstantOperand(op2).asInt32();
+        int shift = getConstantOperand(op2).asInt32() & 0x1f;
+        if (shift) {
+            if (isUnsigned)
+                urshift32(Imm32(shift), regT0);
+            else
+                rshift32(Imm32(shift), regT0);
+        } else if (isUnsigned) // signed right shift by zero is simply toInt conversion
+            addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
+        emitStoreAndMapInt32(dst, regT1, regT0, dst == op1, OPCODE_LENGTH(op_rshift));
+    } else {
+        emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+        if (!isOperandConstantImmediateInt(op1))
+            addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
         if (isUnsigned) {
         if (isUnsigned) {
-            if (shift)
-                urshift32(Imm32(shift & 0x1f), regT0);
-            // unsigned shift < 0 or shift = k*2^32 may result in (essentially)
-            // 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, TrustedImm32(0)));
-        } else if (shift) { // signed right shift by zero is simply toInt conversion
-            rshift32(Imm32(shift & 0x1f), regT0);
-        }
-        emitStoreInt32(dst, regT0, dst == op1);
-        return;
+            urshift32(regT2, regT0);
+            addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
+        } else
+            rshift32(regT2, regT0);
+        emitStoreAndMapInt32(dst, regT1, regT0, dst == op1, OPCODE_LENGTH(op_rshift));
     }
     }
-
-    emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    if (!isOperandConstantImmediateInt(op1))
-        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
-    if (isUnsigned) {
-        urshift32(regT2, regT0);
-        addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
-    } else
-        rshift32(regT2, regT0);
-    emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
 }
 
 void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool isUnsigned)
 }
 
 void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool isUnsigned)
@@ -445,7 +245,7 @@ void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCas
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
     if (isOperandConstantImmediateInt(op2)) {
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
     if (isOperandConstantImmediateInt(op2)) {
-        int shift = getConstantOperand(op2).asInt32();
+        int shift = getConstantOperand(op2).asInt32() & 0x1f;
         // op1 = regT1:regT0
         linkSlowCase(iter); // int32 check
         if (supportsFloatingPointTruncate()) {
         // op1 = regT1:regT0
         linkSlowCase(iter); // int32 check
         if (supportsFloatingPointTruncate()) {
@@ -453,18 +253,19 @@ void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCas
             failures.append(branch32(AboveOrEqual, regT1, TrustedImm32(JSValue::LowestTag)));
             emitLoadDouble(op1, fpRegT0);
             failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
             failures.append(branch32(AboveOrEqual, regT1, TrustedImm32(JSValue::LowestTag)));
             emitLoadDouble(op1, fpRegT0);
             failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
-            if (isUnsigned) {
-                if (shift)
-                    urshift32(Imm32(shift & 0x1f), regT0);
-                if (shift < 0 || !(shift & 31))
-                    failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
-            } else if (shift)
-                rshift32(Imm32(shift & 0x1f), regT0);
+            if (shift) {
+                if (isUnsigned)
+                    urshift32(Imm32(shift), regT0);
+                else
+                    rshift32(Imm32(shift), regT0);
+            } else if (isUnsigned) // signed right shift by zero is simply toInt conversion
+                failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
+            move(TrustedImm32(JSValue::Int32Tag), regT1);
             emitStoreInt32(dst, regT0, false);
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
             failures.link(this);
         }
             emitStoreInt32(dst, regT0, false);
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
             failures.link(this);
         }
-        if (isUnsigned && (shift < 0 || !(shift & 31)))
+        if (isUnsigned && !shift)
             linkSlowCase(iter); // failed to box in hot path
     } else {
         // op1 = regT1:regT0
             linkSlowCase(iter); // failed to box in hot path
     } else {
         // op1 = regT1:regT0
@@ -472,19 +273,20 @@ 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, TrustedImm32(JSValue::LowestTag)); // op1 is not a double
+                JumpList failures;
+                failures.append(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); // op1 is not a double
                 emitLoadDouble(op1, fpRegT0);
                 emitLoadDouble(op1, fpRegT0);
-                Jump notInt = branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)); // op2 is not an int
-                Jump cantTruncate = branchTruncateDoubleToInt32(fpRegT0, regT0);
-                if (isUnsigned)
+                failures.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); // op2 is not an int
+                failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
+                if (isUnsigned) {
                     urshift32(regT2, regT0);
                     urshift32(regT2, regT0);
-                else
+                    failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
+                } else
                     rshift32(regT2, regT0);
                     rshift32(regT2, regT0);
+                move(TrustedImm32(JSValue::Int32Tag), regT1);
                 emitStoreInt32(dst, regT0, false);
                 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
                 emitStoreInt32(dst, regT0, false);
                 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
-                notDouble.link(this);
-                notInt.link(this);
-                cantTruncate.link(this);
+                failures.link(this);
             }
         }
 
             }
         }
 
@@ -537,7 +339,7 @@ void JIT::emit_op_bitand(Instruction* currentInstruction)
         emitLoad(op, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         and32(Imm32(constant), regT0);
         emitLoad(op, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         and32(Imm32(constant), regT0);
-        emitStoreInt32(dst, regT0, (op == dst));
+        emitStoreAndMapInt32(dst, regT1, regT0, dst == op, OPCODE_LENGTH(op_bitand));
         return;
     }
 
         return;
     }
 
@@ -545,7 +347,7 @@ void JIT::emit_op_bitand(Instruction* currentInstruction)
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     and32(regT2, regT0);
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     and32(regT2, regT0);
-    emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
+    emitStoreAndMapInt32(dst, regT1, regT0, (op1 == dst || op2 == dst), OPCODE_LENGTH(op_bitand));
 }
 
 void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_bitand(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -578,7 +380,7 @@ void JIT::emit_op_bitor(Instruction* currentInstruction)
         emitLoad(op, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         or32(Imm32(constant), regT0);
         emitLoad(op, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         or32(Imm32(constant), regT0);
-        emitStoreInt32(dst, regT0, (op == dst));
+        emitStoreAndMapInt32(dst, regT1, regT0, op == dst, OPCODE_LENGTH(op_bitor));
         return;
     }
 
         return;
     }
 
@@ -586,7 +388,7 @@ void JIT::emit_op_bitor(Instruction* currentInstruction)
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     or32(regT2, regT0);
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     or32(regT2, regT0);
-    emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
+    emitStoreAndMapInt32(dst, regT1, regT0, (op1 == dst || op2 == dst), OPCODE_LENGTH(op_bitor));
 }
 
 void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -619,7 +421,7 @@ void JIT::emit_op_bitxor(Instruction* currentInstruction)
         emitLoad(op, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         xor32(Imm32(constant), regT0);
         emitLoad(op, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         xor32(Imm32(constant), regT0);
-        emitStoreInt32(dst, regT0, (op == dst));
+        emitStoreAndMapInt32(dst, regT1, regT0, op == dst, OPCODE_LENGTH(op_bitxor));
         return;
     }
 
         return;
     }
 
@@ -627,7 +429,7 @@ void JIT::emit_op_bitxor(Instruction* currentInstruction)
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     xor32(regT2, regT0);
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     xor32(regT2, regT0);
-    emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
+    emitStoreAndMapInt32(dst, regT1, regT0, (op1 == dst || op2 == dst), OPCODE_LENGTH(op_bitxor));
 }
 
 void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -646,31 +448,6 @@ void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEnt
     stubCall.call(dst);
 }
 
     stubCall.call(dst);
 }
 
-// BitNot (~)
-
-void JIT::emit_op_bitnot(Instruction* currentInstruction)
-{
-    unsigned dst = currentInstruction[1].u.operand;
-    unsigned src = currentInstruction[2].u.operand;
-
-    emitLoad(src, regT1, regT0);
-    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-
-    not32(regT0);
-    emitStoreInt32(dst, regT0, (dst == src));
-}
-
-void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned dst = currentInstruction[1].u.operand;
-
-    linkSlowCase(iter); // int32 check
-
-    JITStubCall stubCall(this, cti_op_bitnot);
-    stubCall.addArgument(regT1, regT0);
-    stubCall.call(dst);
-}
-
 // PostInc (i++)
 
 void JIT::emit_op_post_inc(Instruction* currentInstruction)
 // PostInc (i++)
 
 void JIT::emit_op_post_inc(Instruction* currentInstruction)
@@ -684,10 +461,11 @@ void JIT::emit_op_post_inc(Instruction* currentInstruction)
     if (dst == srcDst) // x = x++ is a noop for ints.
         return;
 
     if (dst == srcDst) // x = x++ is a noop for ints.
         return;
 
-    emitStoreInt32(dst, regT0);
+    move(regT0, regT2);
+    addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT2));
+    emitStoreInt32(srcDst, regT2, true);
 
 
-    addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0));
-    emitStoreInt32(srcDst, regT0, true);
+    emitStoreAndMapInt32(dst, regT1, regT0, false, OPCODE_LENGTH(op_post_inc));
 }
 
 void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -701,7 +479,7 @@ void JIT::emitSlow_op_post_inc(Instruction* currentInstruction, Vector<SlowCaseE
 
     JITStubCall stubCall(this, cti_op_post_inc);
     stubCall.addArgument(srcDst);
 
     JITStubCall stubCall(this, cti_op_post_inc);
     stubCall.addArgument(srcDst);
-    stubCall.addArgument(Imm32(srcDst));
+    stubCall.addArgument(TrustedImm32(srcDst));
     stubCall.call(dst);
 }
 
     stubCall.call(dst);
 }
 
@@ -718,10 +496,11 @@ void JIT::emit_op_post_dec(Instruction* currentInstruction)
     if (dst == srcDst) // x = x-- is a noop for ints.
         return;
 
     if (dst == srcDst) // x = x-- is a noop for ints.
         return;
 
-    emitStoreInt32(dst, regT0);
+    move(regT0, regT2);
+    addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT2));
+    emitStoreInt32(srcDst, regT2, true);
 
 
-    addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0));
-    emitStoreInt32(srcDst, regT0, true);
+    emitStoreAndMapInt32(dst, regT1, regT0, false, OPCODE_LENGTH(op_post_dec));
 }
 
 void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -749,7 +528,7 @@ void JIT::emit_op_pre_inc(Instruction* currentInstruction)
 
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0));
 
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0));
-    emitStoreInt32(srcDst, regT0, true);
+    emitStoreAndMapInt32(srcDst, regT1, regT0, true, OPCODE_LENGTH(op_pre_inc));
 }
 
 void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_pre_inc(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -774,7 +553,7 @@ void JIT::emit_op_pre_dec(Instruction* currentInstruction)
 
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0));
 
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0));
-    emitStoreInt32(srcDst, regT0, true);
+    emitStoreAndMapInt32(srcDst, regT1, regT0, true, OPCODE_LENGTH(op_pre_dec));
 }
 
 void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -799,6 +578,7 @@ void JIT::emit_op_add(Instruction* currentInstruction)
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
+        addSlowCase();
         JITStubCall stubCall(this, cti_op_add);
         stubCall.addArgument(op1);
         stubCall.addArgument(op2);
         JITStubCall stubCall(this, cti_op_add);
         stubCall.addArgument(op1);
         stubCall.addArgument(op2);
@@ -839,9 +619,9 @@ void JIT::emit_op_add(Instruction* currentInstruction)
 void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType)
 {
     // Int32 case.
 void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType)
 {
     // Int32 case.
-    emitLoad(op, regT1, regT0);
+    emitLoad(op, regT1, regT2);
     Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
     Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
-    addSlowCase(branchAdd32(Overflow, Imm32(constant), regT0));
+    addSlowCase(branchAdd32(Overflow, regT2, Imm32(constant), regT0));
     emitStoreInt32(dst, regT0, (op == dst));
 
     // Double case.
     emitStoreInt32(dst, regT0, (op == dst));
 
     // Double case.
@@ -870,8 +650,10 @@ void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
-    if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
+    if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
+        linkDummySlowCase(iter);
         return;
         return;
+    }
 
     unsigned op;
     int32_t constant;
 
     unsigned op;
     int32_t constant;
@@ -950,8 +732,13 @@ void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultT
     // Int32 case.
     emitLoad(op, regT1, regT0);
     Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
     // Int32 case.
     emitLoad(op, regT1, regT0);
     Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
-    addSlowCase(branchSub32(Overflow, Imm32(constant), regT0));
-    emitStoreInt32(dst, regT0, (op == dst));
+#if ENABLE(JIT_CONSTANT_BLINDING)
+    addSlowCase(branchSub32(Overflow, regT0, Imm32(constant), regT2, regT3));
+#else
+    addSlowCase(branchSub32(Overflow, regT0, Imm32(constant), regT2));
+#endif
+    
+    emitStoreInt32(dst, regT2, (op == dst));
 
     // Double case.
     if (!supportsFloatingPoint()) {
 
     // Double case.
     if (!supportsFloatingPoint()) {
@@ -1054,15 +841,39 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi
                 subDouble(fpRegT0, fpRegT1);
                 emitStoreDouble(dst, fpRegT1);
                 break;
                 subDouble(fpRegT0, fpRegT1);
                 emitStoreDouble(dst, fpRegT1);
                 break;
-            case op_div:
+            case op_div: {
                 emitLoadDouble(op1, fpRegT1);
                 divDouble(fpRegT0, fpRegT1);
                 emitLoadDouble(op1, fpRegT1);
                 divDouble(fpRegT0, fpRegT1);
+
+#if ENABLE(VALUE_PROFILER)
+                // Is the result actually an integer? The DFG JIT would really like to know. If it's
+                // not an integer, we increment a count. If this together with the slow case counter
+                // are below threshold then the DFG JIT will compile this division with a specualtion
+                // that the remainder is zero.
+                
+                // As well, there are cases where a double result here would cause an important field
+                // in the heap to sometimes have doubles in it, resulting in double predictions getting
+                // propagated to a use site where it might cause damage (such as the index to an array
+                // access). So if we are DFG compiling anything in the program, we want this code to
+                // ensure that it produces integers whenever possible.
+                
+                // FIXME: This will fail to convert to integer if the result is zero. We should
+                // distinguish between positive zero and negative zero here.
+                
+                JumpList notInteger;
+                branchConvertDoubleToInt32(fpRegT1, regT2, notInteger, fpRegT0);
+                // If we've got an integer, we might as well make that the result of the division.
+                emitStoreInt32(dst, regT2);
+                Jump isInteger = jump();
+                notInteger.link(this);
+                add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter));
                 emitStoreDouble(dst, fpRegT1);
                 emitStoreDouble(dst, fpRegT1);
+                isInteger.link(this);
+#else
+                emitStoreDouble(dst, fpRegT1);
+#endif
                 break;
                 break;
-            case op_jnless:
-                emitLoadDouble(op1, fpRegT2);
-                addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst);
-                break;
+            }
             case op_jless:
                 emitLoadDouble(op1, fpRegT2);
                 addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst);
             case op_jless:
                 emitLoadDouble(op1, fpRegT2);
                 addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst);
@@ -1071,10 +882,30 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi
                 emitLoadDouble(op1, fpRegT2);
                 addJump(branchDouble(DoubleLessThanOrEqual, fpRegT2, fpRegT0), dst);
                 break;
                 emitLoadDouble(op1, fpRegT2);
                 addJump(branchDouble(DoubleLessThanOrEqual, fpRegT2, fpRegT0), dst);
                 break;
+            case op_jgreater:
+                emitLoadDouble(op1, fpRegT2);
+                addJump(branchDouble(DoubleGreaterThan, fpRegT2, fpRegT0), dst);
+                break;
+            case op_jgreatereq:
+                emitLoadDouble(op1, fpRegT2);
+                addJump(branchDouble(DoubleGreaterThanOrEqual, fpRegT2, fpRegT0), dst);
+                break;
+            case op_jnless:
+                emitLoadDouble(op1, fpRegT2);
+                addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst);
+                break;
             case op_jnlesseq:
                 emitLoadDouble(op1, fpRegT2);
                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst);
                 break;
             case op_jnlesseq:
                 emitLoadDouble(op1, fpRegT2);
                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst);
                 break;
+            case op_jngreater:
+                emitLoadDouble(op1, fpRegT2);
+                addJump(branchDouble(DoubleGreaterThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst);
+                break;
+            case op_jngreatereq:
+                emitLoadDouble(op1, fpRegT2);
+                addJump(branchDouble(DoubleGreaterThanOrUnordered, fpRegT0, fpRegT2), dst);
+                break;
             default:
                 ASSERT_NOT_REACHED();
         }
             default:
                 ASSERT_NOT_REACHED();
         }
@@ -1115,26 +946,69 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi
                 subDouble(fpRegT2, fpRegT0);
                 emitStoreDouble(dst, fpRegT0);
                 break;
                 subDouble(fpRegT2, fpRegT0);
                 emitStoreDouble(dst, fpRegT0);
                 break;
-            case op_div:
+            case op_div: {
                 emitLoadDouble(op2, fpRegT2);
                 divDouble(fpRegT2, fpRegT0);
                 emitLoadDouble(op2, fpRegT2);
                 divDouble(fpRegT2, fpRegT0);
+#if ENABLE(VALUE_PROFILER)
+                // Is the result actually an integer? The DFG JIT would really like to know. If it's
+                // not an integer, we increment a count. If this together with the slow case counter
+                // are below threshold then the DFG JIT will compile this division with a specualtion
+                // that the remainder is zero.
+                
+                // As well, there are cases where a double result here would cause an important field
+                // in the heap to sometimes have doubles in it, resulting in double predictions getting
+                // propagated to a use site where it might cause damage (such as the index to an array
+                // access). So if we are DFG compiling anything in the program, we want this code to
+                // ensure that it produces integers whenever possible.
+                
+                // FIXME: This will fail to convert to integer if the result is zero. We should
+                // distinguish between positive zero and negative zero here.
+                
+                JumpList notInteger;
+                branchConvertDoubleToInt32(fpRegT0, regT2, notInteger, fpRegT1);
+                // If we've got an integer, we might as well make that the result of the division.
+                emitStoreInt32(dst, regT2);
+                Jump isInteger = jump();
+                notInteger.link(this);
+                add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter));
                 emitStoreDouble(dst, fpRegT0);
                 emitStoreDouble(dst, fpRegT0);
+                isInteger.link(this);
+#else
+                emitStoreDouble(dst, fpRegT0);
+#endif
                 break;
                 break;
-            case op_jnless:
-                emitLoadDouble(op2, fpRegT1);
-                addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst);
-                break;
+            }
             case op_jless:
                 emitLoadDouble(op2, fpRegT1);
                 addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst);
                 break;
             case op_jless:
                 emitLoadDouble(op2, fpRegT1);
                 addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst);
                 break;
+            case op_jlesseq:
+                emitLoadDouble(op2, fpRegT1);
+                addJump(branchDouble(DoubleLessThanOrEqual, fpRegT0, fpRegT1), dst);
+                break;
+            case op_jgreater:
+                emitLoadDouble(op2, fpRegT1);
+                addJump(branchDouble(DoubleGreaterThan, fpRegT0, fpRegT1), dst);
+                break;
+            case op_jgreatereq:
+                emitLoadDouble(op2, fpRegT1);
+                addJump(branchDouble(DoubleGreaterThanOrEqual, fpRegT0, fpRegT1), dst);
+                break;
+            case op_jnless:
+                emitLoadDouble(op2, fpRegT1);
+                addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst);
+                break;
             case op_jnlesseq:
                 emitLoadDouble(op2, fpRegT1);
                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst);
                 break;
             case op_jnlesseq:
                 emitLoadDouble(op2, fpRegT1);
                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst);
                 break;
-            case op_jlesseq:
+            case op_jngreater:
                 emitLoadDouble(op2, fpRegT1);
                 emitLoadDouble(op2, fpRegT1);
-                addJump(branchDouble(DoubleLessThanOrEqual, fpRegT0, fpRegT1), dst);
+                addJump(branchDouble(DoubleGreaterThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst);
+                break;
+            case op_jngreatereq:
+                emitLoadDouble(op2, fpRegT1);
+                addJump(branchDouble(DoubleGreaterThanOrUnordered, fpRegT1, fpRegT0), dst);
                 break;
             default:
                 ASSERT_NOT_REACHED();
                 break;
             default:
                 ASSERT_NOT_REACHED();
@@ -1153,6 +1027,10 @@ void JIT::emit_op_mul(Instruction* currentInstruction)
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
+#if ENABLE(VALUE_PROFILER)
+    m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
+#endif
+
     JumpList notInt32Op1;
     JumpList notInt32Op2;
 
     JumpList notInt32Op1;
     JumpList notInt32Op2;
 
@@ -1194,6 +1072,12 @@ void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>
     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul));
 
     negZero.link(this);
     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul));
 
     negZero.link(this);
+#if ENABLE(VALUE_PROFILER)
+    // We only get here if we have a genuine negative zero. Record this,
+    // so that the speculative JIT knows that we failed speculation
+    // because of a negative zero.
+    add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter));
+#endif
     overflow.link(this);
 
     if (!supportsFloatingPoint()) {
     overflow.link(this);
 
     if (!supportsFloatingPoint()) {
@@ -1227,6 +1111,10 @@ void JIT::emit_op_div(Instruction* currentInstruction)
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
     unsigned op2 = currentInstruction[3].u.operand;
     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
 
+#if ENABLE(VALUE_PROFILER)
+    m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);
+#endif
+
     if (!supportsFloatingPoint()) {
         addSlowCase(jump());
         return;
     if (!supportsFloatingPoint()) {
         addSlowCase(jump());
         return;
@@ -1246,7 +1134,32 @@ void JIT::emit_op_div(Instruction* currentInstruction)
     convertInt32ToDouble(regT0, fpRegT0);
     convertInt32ToDouble(regT2, fpRegT1);
     divDouble(fpRegT1, fpRegT0);
     convertInt32ToDouble(regT0, fpRegT0);
     convertInt32ToDouble(regT2, fpRegT1);
     divDouble(fpRegT1, fpRegT0);
+#if ENABLE(VALUE_PROFILER)
+    // Is the result actually an integer? The DFG JIT would really like to know. If it's
+    // not an integer, we increment a count. If this together with the slow case counter
+    // are below threshold then the DFG JIT will compile this division with a specualtion
+    // that the remainder is zero.
+    
+    // As well, there are cases where a double result here would cause an important field
+    // in the heap to sometimes have doubles in it, resulting in double predictions getting
+    // propagated to a use site where it might cause damage (such as the index to an array
+    // access). So if we are DFG compiling anything in the program, we want this code to
+    // ensure that it produces integers whenever possible.
+    
+    // FIXME: This will fail to convert to integer if the result is zero. We should
+    // distinguish between positive zero and negative zero here.
+    
+    JumpList notInteger;
+    branchConvertDoubleToInt32(fpRegT0, regT2, notInteger, fpRegT1);
+    // If we've got an integer, we might as well make that the result of the division.
+    emitStoreInt32(dst, regT2);
+    end.append(jump());
+    notInteger.link(this);
+    add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter));
+    emitStoreDouble(dst, fpRegT0);
+#else
     emitStoreDouble(dst, fpRegT0);
     emitStoreDouble(dst, fpRegT0);
+#endif
     end.append(jump());
 
     // Double divide.
     end.append(jump());
 
     // Double divide.
@@ -1283,8 +1196,6 @@ void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
-#if CPU(X86) || CPU(X86_64) || CPU(MIPS)
-
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
     unsigned dst = currentInstruction[1].u.operand;
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
     unsigned dst = currentInstruction[1].u.operand;
@@ -1297,85 +1208,22 @@ void JIT::emit_op_mod(Instruction* currentInstruction)
     ASSERT(regT1 == X86Registers::edx);
     ASSERT(regT2 == X86Registers::ecx);
     ASSERT(regT3 == X86Registers::ebx);
     ASSERT(regT1 == X86Registers::edx);
     ASSERT(regT2 == X86Registers::ecx);
     ASSERT(regT3 == X86Registers::ebx);
-#endif
-
-    if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
-        emitLoad(op1, regT1, regT0);
-        move(Imm32(getConstantOperand(op2).asInt32()), regT2);
-        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-        if (getConstantOperand(op2).asInt32() == -1)
-            addSlowCase(branch32(Equal, regT0, TrustedImm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
-    } else {
-        emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-        addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
 
 
-        addSlowCase(branch32(Equal, regT0, TrustedImm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
-        addSlowCase(branch32(Equal, regT2, TrustedImm32(0))); // divide by 0
-    }
+    emitLoad2(op1, regT0, regT3, op2, regT1, regT2);
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT0, TrustedImm32(JSValue::Int32Tag)));
 
 
-    move(regT0, regT3); // Save dividend payload, in case of 0.
-#if CPU(X86) || CPU(X86_64)
+    move(regT3, regT0);
+    addSlowCase(branchTest32(Zero, regT2));
+    Jump denominatorNotNeg1 = branch32(NotEqual, regT2, TrustedImm32(-1));
+    addSlowCase(branch32(Equal, regT0, TrustedImm32(-2147483647-1)));
+    denominatorNotNeg1.link(this);
     m_assembler.cdq();
     m_assembler.idivl_r(regT2);
     m_assembler.cdq();
     m_assembler.idivl_r(regT2);
-#elif CPU(MIPS)
-    m_assembler.div(regT0, regT2);
-    m_assembler.mfhi(regT1);
-#endif
-
-    // If the remainder is zero and the dividend is negative, the result is -0.
-    Jump storeResult1 = branchTest32(NonZero, 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 numeratorPositive = branch32(GreaterThanOrEqual, regT3, TrustedImm32(0));
+    addSlowCase(branchTest32(Zero, regT1));
+    numeratorPositive.link(this);
     emitStoreInt32(dst, regT1, (op1 == dst || op2 == dst));
     emitStoreInt32(dst, regT1, (op1 == dst || op2 == dst));
-    end.link(this);
-}
-
-void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned dst = currentInstruction[1].u.operand;
-    unsigned op1 = currentInstruction[2].u.operand;
-    unsigned op2 = currentInstruction[3].u.operand;
-
-    if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
-        linkSlowCase(iter); // int32 check
-        if (getConstantOperand(op2).asInt32() == -1)
-            linkSlowCase(iter); // 0x80000000 check
-    } else {
-        linkSlowCase(iter); // int32 check
-        linkSlowCase(iter); // int32 check
-        linkSlowCase(iter); // 0 check
-        linkSlowCase(iter); // 0x80000000 check
-    }
-
-    JITStubCall stubCall(this, cti_op_mod);
-    stubCall.addArgument(op1);
-    stubCall.addArgument(op2);
-    stubCall.call(dst);
-}
-
-#else // CPU(X86) || CPU(X86_64) || CPU(MIPS)
-
-void JIT::emit_op_mod(Instruction* currentInstruction)
-{
-    unsigned dst = currentInstruction[1].u.operand;
-    unsigned op1 = currentInstruction[2].u.operand;
-    unsigned op2 = currentInstruction[3].u.operand;
-
-#if ENABLE(JIT_USE_SOFT_MODULO)
-    emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
-
-    addSlowCase(branch32(Equal, regT2, TrustedImm32(0)));
-
-    emitNakedCall(m_globalData->jitStubs->ctiSoftModulo());
-
-    emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
 #else
     JITStubCall stubCall(this, cti_op_mod);
     stubCall.addArgument(op1);
 #else
     JITStubCall stubCall(this, cti_op_mod);
     stubCall.addArgument(op1);
@@ -1386,15 +1234,15 @@ 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)
 {
-    UNUSED_PARAM(currentInstruction);
-    UNUSED_PARAM(iter);
-#if ENABLE(JIT_USE_SOFT_MODULO)
+#if CPU(X86) || CPU(X86_64)
     unsigned result = currentInstruction[1].u.operand;
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
     linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
     unsigned result = currentInstruction[1].u.operand;
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
     linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
+    linkSlowCase(iter);
+    linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_mod);
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
     JITStubCall stubCall(this, cti_op_mod);
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
@@ -1402,12 +1250,12 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>
 #else
     UNUSED_PARAM(currentInstruction);
     UNUSED_PARAM(iter);
 #else
     UNUSED_PARAM(currentInstruction);
     UNUSED_PARAM(iter);
-    ASSERT_NOT_REACHED();
+    // We would have really useful assertions here if it wasn't for the compiler's
+    // insistence on attribute noreturn.
+    // ASSERT_NOT_REACHED();
 #endif
 }
 
 #endif
 }
 
-#endif // CPU(X86) || CPU(X86_64)
-
 /* ------------------------------ END: OP_MOD ------------------------------ */
 
 } // namespace JSC
 /* ------------------------------ END: OP_MOD ------------------------------ */
 
 } // namespace JSC
index d0c266836ea7a2fed215880a440f1dc5d3d6a2ef..7664eb7463c64dd866183d8689cb4b86f57e8d35 100644 (file)
@@ -29,6 +29,7 @@
 #if USE(JSVALUE64)
 #include "JIT.h"
 
 #if USE(JSVALUE64)
 #include "JIT.h"
 
+#include "Arguments.h"
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
@@ -46,219 +47,168 @@ using namespace std;
 
 namespace JSC {
 
 
 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;
 void JIT::emit_op_call_put_result(Instruction* instruction)
 {
     int dst = instruction[1].u.operand;
+    emitValueProfilingSite();
     emitPutVirtualRegister(dst);
     emitPutVirtualRegister(dst);
+    if (canBeOptimized())
+        killLastResultRegister(); // Make lastResultRegister tracking simpler in the DFG.
 }
 
 }
 
-void JIT::compileOpCallVarargs(Instruction* instruction)
+void JIT::compileLoadVarargs(Instruction* instruction)
 {
 {
-    int callee = instruction[1].u.operand;
-    int argCountRegister = instruction[2].u.operand;
-    int registerOffset = instruction[3].u.operand;
-
-    emitGetVirtualRegister(argCountRegister, regT1);
-    emitFastArithImmToInt(regT1);
-    emitGetVirtualRegister(callee, regT0);
-    addPtr(Imm32(registerOffset), regT1, regT2);
-
-    // Check for JSFunctions.
-    emitJumpSlowCaseIfNotJSCell(regT0);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr)));
-
-    // Speculatively roll the callframe, assuming argCount will match the arity.
-    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);
-    storePtr(callFrameRegister, regT3);
-    addPtr(regT2, callFrameRegister);
-    emitNakedCall(m_globalData->jitStubs->ctiVirtualCall());
+    int thisValue = instruction[2].u.operand;
+    int arguments = instruction[3].u.operand;
+    int firstFreeRegister = instruction[4].u.operand;
 
 
-    sampleCodeBlock(m_codeBlock);
-}
+    killLastResultRegister();
 
 
-void JIT::compileOpCallVarargsSlowCase(Instruction*, Vector<SlowCaseEntry>::iterator& iter)
-{
-    linkSlowCase(iter);
-    linkSlowCase(iter);
+    JumpList slowCase;
+    JumpList end;
+    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) {
+        emitGetVirtualRegister(arguments, regT0);
+        slowCase.append(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue()))));
 
 
-    JITStubCall stubCall(this, cti_op_call_NotJSFunction);
-    stubCall.addArgument(regT0);
-    stubCall.addArgument(regT2);
-    stubCall.addArgument(regT1);
-    stubCall.call();
-    
-    sampleCodeBlock(m_codeBlock);
-}
-    
-#if !ENABLE(JIT_OPTIMIZE_CALL)
+        emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+        slowCase.append(branch32(Above, regT0, TrustedImm32(Arguments::MaxArguments + 1)));
+        // regT0: argumentCountIncludingThis
 
 
-/* ------------------------------ BEGIN: !ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
+        move(regT0, regT1);
+        add32(TrustedImm32(firstFreeRegister + RegisterFile::CallFrameHeaderSize), regT1);
+        lshift32(TrustedImm32(3), regT1);
+        addPtr(callFrameRegister, regT1);
+        // regT1: newCallFrame
 
 
-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;
+        slowCase.append(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1));
 
 
-    // Handle eval
-    Jump wasEval;
-    if (opcodeID == op_call_eval) {
-        JITStubCall stubCall(this, cti_op_call_eval);
-        stubCall.addArgument(callee, regT0);
-        stubCall.addArgument(JIT::Imm32(registerOffset));
-        stubCall.addArgument(JIT::Imm32(argCount));
-        stubCall.call();
-        wasEval = branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue())));
-    }
+        // Initialize ArgumentCount.
+        store32(regT0, Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
 
 
-    emitGetVirtualRegister(callee, regT0);
+        // Initialize 'this'.
+        emitGetVirtualRegister(thisValue, regT2);
+        storePtr(regT2, Address(regT1, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))));
 
 
-    // Check for JSFunctions.
-    emitJumpSlowCaseIfNotJSCell(regT0);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr)));
+        // Copy arguments.
+        neg32(regT0);
+        signExtend32ToPtr(regT0, regT0);
+        end.append(branchAddPtr(Zero, TrustedImm32(1), regT0));
+        // regT0: -argumentCount
 
 
-    // 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);
+        Label copyLoop = label();
+        loadPtr(BaseIndex(callFrameRegister, regT0, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT2);
+        storePtr(regT2, BaseIndex(regT1, regT0, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))));
+        branchAddPtr(NonZero, TrustedImm32(1), regT0).linkTo(copyLoop, this);
 
 
-    emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstruct() : m_globalData->jitStubs->ctiVirtualCall());
+        end.append(jump());
+    }
 
 
-    if (opcodeID == op_call_eval)
-        wasEval.link(this);
+    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())
+        slowCase.link(this);
 
 
-    sampleCodeBlock(m_codeBlock);
+    JITStubCall stubCall(this, cti_op_load_varargs);
+    stubCall.addArgument(thisValue, regT0);
+    stubCall.addArgument(arguments, regT0);
+    stubCall.addArgument(Imm32(firstFreeRegister));
+    stubCall.call(regT1);
+
+    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())
+        end.link(this);
 }
 
 }
 
-void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned, OpcodeID opcodeID)
+void JIT::compileCallEval()
 {
 {
-    int argCount = instruction[2].u.operand;
-    int registerOffset = instruction[3].u.operand;
-
-    linkSlowCase(iter);
-    linkSlowCase(iter);
-
-    JITStubCall stubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction);
-    stubCall.addArgument(regT0);
-    stubCall.addArgument(JIT::Imm32(registerOffset));
-    stubCall.addArgument(JIT::Imm32(argCount));
+    JITStubCall stubCall(this, cti_op_call_eval); // Initializes ScopeChain; ReturnPC; CodeBlock.
     stubCall.call();
     stubCall.call();
+    addSlowCase(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(JSValue()))));
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
 
     sampleCodeBlock(m_codeBlock);
 }
 
 
     sampleCodeBlock(m_codeBlock);
 }
 
-#else // !ENABLE(JIT_OPTIMIZE_CALL)
+void JIT::compileCallEvalSlowCase(Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCase(iter);
+
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
+    emitNakedCall(m_globalData->jitStubs->ctiVirtualCall());
 
 
-/* ------------------------------ BEGIN: ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
+    sampleCodeBlock(m_codeBlock);
+}
 
 void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
 {
     int callee = instruction[1].u.operand;
 
 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;
 
 
-    // Handle eval
-    Jump wasEval;
+    /* Caller always:
+        - Updates callFrameRegister to callee callFrame.
+        - Initializes ArgumentCount; CallerFrame; Callee.
+
+       For a JS call:
+        - Caller initializes ScopeChain.
+        - Callee initializes ReturnPC; CodeBlock.
+        - Callee restores callFrameRegister before return.
+
+       For a non-JS call:
+        - Caller initializes ScopeChain; ReturnPC; CodeBlock.
+        - Caller restores callFrameRegister after return.
+    */
+
+    if (opcodeID == op_call_varargs)
+        compileLoadVarargs(instruction);
+    else {
+        int argCount = instruction[2].u.operand;
+        int registerOffset = instruction[3].u.operand;
+
+        addPtr(TrustedImm32(registerOffset * sizeof(Register)), callFrameRegister, regT1);
+        store32(TrustedImm32(argCount), Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+    } // regT1 holds newCallFrame with ArgumentCount initialized.
+    
+    store32(TrustedImm32(instruction - m_codeBlock->instructions().begin()), Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+    emitGetVirtualRegister(callee, regT0); // regT0 holds callee.
+
+    storePtr(callFrameRegister, Address(regT1, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register))));
+    storePtr(regT0, Address(regT1, RegisterFile::Callee * static_cast<int>(sizeof(Register))));
+    move(regT1, callFrameRegister);
+
     if (opcodeID == op_call_eval) {
     if (opcodeID == op_call_eval) {
-        JITStubCall stubCall(this, cti_op_call_eval);
-        stubCall.addArgument(callee, regT0);
-        stubCall.addArgument(JIT::Imm32(registerOffset));
-        stubCall.addArgument(JIT::Imm32(argCount));
-        stubCall.call();
-        wasEval = branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue())));
+        compileCallEval();
+        return;
     }
 
     }
 
-    // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee.
-    // This deliberately leaves the callee in ecx, used when setting up the stack frame below
-    emitGetVirtualRegister(callee, regT0);
     DataLabelPtr addressOfLinkedFunctionCheck;
     DataLabelPtr addressOfLinkedFunctionCheck;
-
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
-
-    Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(JSValue::encode(JSValue())));
-
+    Jump slowCase = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(JSValue::encode(JSValue())));
     END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
     END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
+    addSlowCase(slowCase);
 
 
-    addSlowCase(jumpToSlow);
-    ASSERT_JIT_OFFSET(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow), patchOffsetOpCallCompareToJump);
+    ASSERT(m_callStructureStubCompilationInfo.size() == callLinkInfoIndex);
+    m_callStructureStubCompilationInfo.append(StructureStubCompilationInfo());
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
-    m_callStructureStubCompilationInfo[callLinkInfoIndex].isCall = opcodeID != op_construct;
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].callType = CallLinkInfo::callTypeFor(opcodeID);
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].bytecodeIndex = m_bytecodeOffset;
 
 
-    // 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)), regT1); // newScopeChain
-    
-    store32(TrustedImm32(Int32Tag), intTagFor(registerOffset + RegisterFile::ArgumentCount));
-    store32(Imm32(argCount), intPayloadFor(registerOffset + RegisterFile::ArgumentCount));
-    storePtr(callFrameRegister, Address(callFrameRegister, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register))));
-    storePtr(regT0, Address(callFrameRegister, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register))));
-    storePtr(regT1, Address(callFrameRegister, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register))));
-    addPtr(Imm32(registerOffset * sizeof(Register)), callFrameRegister);
-
-    // Call to the callee
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
+    emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
-    
-    if (opcodeID == op_call_eval)
-        wasEval.link(this);
 
     sampleCodeBlock(m_codeBlock);
 }
 
 
     sampleCodeBlock(m_codeBlock);
 }
 
-void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID)
+void JIT::compileOpCallSlowCase(OpcodeID opcodeID, Instruction*, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex)
 {
 {
-    int argCount = instruction[2].u.operand;
-    int registerOffset = instruction[3].u.operand;
+    if (opcodeID == op_call_eval) {
+        compileCallEvalSlowCase(iter);
+        return;
+    }
 
     linkSlowCase(iter);
 
     linkSlowCase(iter);
-
-    // Fast check for JS function.
-    Jump callLinkFailNotObject = emitJumpIfNotJSCell(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);
-
+    
     m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstructLink() : m_globalData->jitStubs->ctiVirtualCallLink());
 
     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(regT0);
-    stubCall.addArgument(JIT::Imm32(registerOffset));
-    stubCall.addArgument(JIT::Imm32(argCount));
-    stubCall.call();
-
     sampleCodeBlock(m_codeBlock);
 }
 
     sampleCodeBlock(m_codeBlock);
 }
 
-/* ------------------------------ END: !ENABLE / ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
-
-#endif // !ENABLE(JIT_OPTIMIZE_CALL)
-
 } // namespace JSC
 
 #endif // USE(JSVALUE64)
 } // namespace JSC
 
 #endif // USE(JSVALUE64)
index 0019d984e38499fc347db53d99304ae737b75335..81266052bbe7acad06eb0ccc2f937164bdfce2c2 100644 (file)
@@ -29,6 +29,7 @@
 #if USE(JSVALUE32_64)
 #include "JIT.h"
 
 #if USE(JSVALUE32_64)
 #include "JIT.h"
 
+#include "Arguments.h"
 #include "CodeBlock.h"
 #include "Interpreter.h"
 #include "JITInlineMethods.h"
 #include "CodeBlock.h"
 #include "Interpreter.h"
 #include "JITInlineMethods.h"
@@ -46,66 +47,17 @@ using namespace std;
 
 namespace JSC {
 
 
 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;
 void JIT::emit_op_call_put_result(Instruction* instruction)
 {
     int dst = instruction[1].u.operand;
+    emitValueProfilingSite();
     emitStore(dst, regT1, regT0);
 }
 
     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)
 {
 void JIT::emit_op_ret(Instruction* currentInstruction)
 {
+    emitOptimizationCheck(RetOptimizationCheck);
+    
     unsigned dst = currentInstruction[1].u.operand;
 
     emitLoad(dst, regT1, regT0);
     unsigned dst = currentInstruction[1].u.operand;
 
     emitLoad(dst, regT1, regT0);
@@ -118,13 +70,15 @@ void JIT::emit_op_ret(Instruction* currentInstruction)
 
 void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
 {
+    emitOptimizationCheck(RetOptimizationCheck);
+    
     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);
     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));
+    Jump notObject = emitJumpIfNotObject(regT2);
 
     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
 
     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
@@ -145,22 +99,22 @@ void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
 
 void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 
 void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call);
+    compileOpCallSlowCase(op_call, currentInstruction, iter, m_callLinkInfoIndex++);
 }
 
 void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 }
 
 void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call_eval);
+    compileOpCallSlowCase(op_call_eval, currentInstruction, iter, m_callLinkInfoIndex);
 }
 }
-
 void JIT::emitSlow_op_call_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 void JIT::emitSlow_op_call_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-    compileOpCallVarargsSlowCase(currentInstruction, iter);
+    compileOpCallSlowCase(op_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
 }
 
 void JIT::emitSlow_op_construct(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 }
 
 void JIT::emitSlow_op_construct(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_construct);
+    compileOpCallSlowCase(op_construct, currentInstruction, iter, m_callLinkInfoIndex++);
 }
 
 void JIT::emit_op_call(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_call(Instruction* currentInstruction)
@@ -170,12 +124,12 @@ void JIT::emit_op_call(Instruction* currentInstruction)
 
 void JIT::emit_op_call_eval(Instruction* currentInstruction)
 {
 
 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_call_varargs(Instruction* currentInstruction)
 {
 }
 
 void JIT::emit_op_call_varargs(Instruction* currentInstruction)
 {
-    compileOpCallVarargs(currentInstruction);
+    compileOpCall(op_call_varargs, currentInstruction, m_callLinkInfoIndex++);
 }
 
 void JIT::emit_op_construct(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_construct(Instruction* currentInstruction)
@@ -183,166 +137,163 @@ void JIT::emit_op_construct(Instruction* currentInstruction)
     compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++);
 }
 
     compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++);
 }
 
-#if !ENABLE(JIT_OPTIMIZE_CALL)
-
-/* ------------------------------ BEGIN: !ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
-
-void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
+void JIT::compileLoadVarargs(Instruction* instruction)
 {
 {
-    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));
+    int thisValue = instruction[2].u.operand;
+    int arguments = instruction[3].u.operand;
+    int firstFreeRegister = instruction[4].u.operand;
+
+    JumpList slowCase;
+    JumpList end;
+    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) {
+        emitLoadTag(arguments, regT1);
+        slowCase.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag)));
+
+        load32(payloadFor(RegisterFile::ArgumentCount), regT2);
+        slowCase.append(branch32(Above, regT2, TrustedImm32(Arguments::MaxArguments + 1)));
+        // regT2: argumentCountIncludingThis
+
+        move(regT2, regT3);
+        add32(TrustedImm32(firstFreeRegister + RegisterFile::CallFrameHeaderSize), regT3);
+        lshift32(TrustedImm32(3), regT3);
+        addPtr(callFrameRegister, regT3);
+        // regT3: newCallFrame
+
+        slowCase.append(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT3));
+
+        // Initialize ArgumentCount.
+        store32(regT2, payloadFor(RegisterFile::ArgumentCount, regT3));
+
+        // Initialize 'this'.
+        emitLoad(thisValue, regT1, regT0);
+        store32(regT0, Address(regT3, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + (CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))));
+        store32(regT1, Address(regT3, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + (CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))));
+
+        // Copy arguments.
+        neg32(regT2);
+        end.append(branchAdd32(Zero, TrustedImm32(1), regT2));
+        // regT2: -argumentCount;
+
+        Label copyLoop = label();
+        load32(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))), regT0);
+        load32(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))), regT1);
+        store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))));
+        store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) +(CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register)))));
+        branchAdd32(NonZero, TrustedImm32(1), regT2).linkTo(copyLoop, this);
+
+        end.append(jump());
     }
 
     }
 
-    emitLoad(callee, regT1, regT0);
-
-    emitJumpSlowCaseIfNotJSCell(callee, regT1);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr)));
+    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())
+        slowCase.link(this);
 
 
-    // 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);
+    JITStubCall stubCall(this, cti_op_load_varargs);
+    stubCall.addArgument(thisValue);
+    stubCall.addArgument(arguments);
+    stubCall.addArgument(Imm32(firstFreeRegister));
+    stubCall.call(regT3);
 
 
-    emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstruct() : m_globalData->jitStubs->ctiVirtualCall());
+    if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())
+        end.link(this);
+}
 
 
-    if (opcodeID == op_call_eval)
-        wasEval.link(this);
+void JIT::compileCallEval()
+{
+    JITStubCall stubCall(this, cti_op_call_eval); // Initializes ScopeChain; ReturnPC; CodeBlock.
+    stubCall.call();
+    addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
 
     sampleCodeBlock(m_codeBlock);
 }
 
 
     sampleCodeBlock(m_codeBlock);
 }
 
-void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned, OpcodeID opcodeID)
+void JIT::compileCallEvalSlowCase(Vector<SlowCaseEntry>::iterator& iter)
 {
 {
-    int callee = instruction[1].u.operand;
-    int argCount = instruction[2].u.operand;
-    int registerOffset = instruction[3].u.operand;
-
-    linkSlowCaseIfNotJSCell(iter, callee);
     linkSlowCase(iter);
 
     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();
+    emitLoad(RegisterFile::Callee, regT1, regT0);
+    emitNakedCall(m_globalData->jitStubs->ctiVirtualCall());
 
     sampleCodeBlock(m_codeBlock);
 }
 
 
     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;
 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));
-    }
+    /* Caller always:
+        - Updates callFrameRegister to callee callFrame.
+        - Initializes ArgumentCount; CallerFrame; Callee.
 
 
-    emitLoad(callee, regT1, regT0);
-
-    DataLabelPtr addressOfLinkedFunctionCheck;
+       For a JS call:
+        - Caller initializes ScopeChain.
+        - Callee initializes ReturnPC; CodeBlock.
+        - Callee restores callFrameRegister before return.
 
 
-    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
+       For a non-JS call:
+        - Caller initializes ScopeChain; ReturnPC; CodeBlock.
+        - Caller restores callFrameRegister after return.
+    */
+    
+    if (opcodeID == op_call_varargs)
+        compileLoadVarargs(instruction);
+    else {
+        int argCount = instruction[2].u.operand;
+        int registerOffset = instruction[3].u.operand;
 
 
-    Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(0));
+        addPtr(TrustedImm32(registerOffset * sizeof(Register)), callFrameRegister, regT3);
 
 
-    END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
+        store32(TrustedImm32(argCount), payloadFor(RegisterFile::ArgumentCount, regT3));
+    } // regT3 holds newCallFrame with ArgumentCount initialized.
+    
+    storePtr(TrustedImmPtr(instruction), tagFor(RegisterFile::ArgumentCount, callFrameRegister));
+    emitLoad(callee, regT1, regT0); // regT1, regT0 holds callee.
 
 
-    addSlowCase(jumpToSlow);
-    ASSERT_JIT_OFFSET(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow), patchOffsetOpCallCompareToJump);
-    m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
-    m_callStructureStubCompilationInfo[callLinkInfoIndex].isCall = opcodeID != op_construct;
+    storePtr(callFrameRegister, Address(regT3, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register))));
+    emitStore(RegisterFile::Callee, regT1, regT0, regT3);
+    move(regT3, callFrameRegister);
 
 
-    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+    if (opcodeID == op_call_eval) {
+        compileCallEval();
+        return;
+    }
 
 
-    // The following is the fast case, only used whan a callee can be linked.
+    DataLabelPtr addressOfLinkedFunctionCheck;
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
+    Jump slowCase = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(0));
+    END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
 
 
-    // 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);
+    addSlowCase(slowCase);
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
 
 
-    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);
+    ASSERT(m_callStructureStubCompilationInfo.size() == callLinkInfoIndex);
+    m_callStructureStubCompilationInfo.append(StructureStubCompilationInfo());
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].callType = CallLinkInfo::callTypeFor(opcodeID);
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].bytecodeIndex = m_bytecodeOffset;
 
 
-    // Call to the callee
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
-    
-    if (opcodeID == op_call_eval)
-        wasEval.link(this);
 
     sampleCodeBlock(m_codeBlock);
 }
 
 
     sampleCodeBlock(m_codeBlock);
 }
 
-void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID)
+void JIT::compileOpCallSlowCase(OpcodeID opcodeID, Instruction*, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex)
 {
 {
-    int callee = instruction[1].u.operand;
-    int argCount = instruction[2].u.operand;
-    int registerOffset = instruction[3].u.operand;
+    if (opcodeID == op_call_eval) {
+        compileCallEvalSlowCase(iter);
+        return;
+    }
 
     linkSlowCase(iter);
     linkSlowCase(iter);
 
     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());
 
     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);
 }
 
     sampleCodeBlock(m_codeBlock);
 }
 
-/* ------------------------------ END: !ENABLE / ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
-
-#endif // !ENABLE(JIT_OPTIMIZE_CALL)
-
 } // namespace JSC
 
 #endif // USE(JSVALUE32_64)
 } // namespace JSC
 
 #endif // USE(JSVALUE32_64)
index 082d2a73756a4bf4245dd2420c0e32b8a4f1496a..3ae5ff234e9adef6be3bfc3f85d486a4d0b0d688 100644 (file)
 #define JITCode_h
 
 #if ENABLE(JIT)
 #define JITCode_h
 
 #if ENABLE(JIT)
-
 #include "CallFrame.h"
 #include "JSValue.h"
 #include "MacroAssemblerCodeRef.h"
 #include "Profiler.h"
 #include "CallFrame.h"
 #include "JSValue.h"
 #include "MacroAssemblerCodeRef.h"
 #include "Profiler.h"
+#endif
 
 namespace JSC {
 
 
 namespace JSC {
 
+#if ENABLE(JIT)
     class JSGlobalData;
     class RegisterFile;
     class JSGlobalData;
     class RegisterFile;
-
+#endif
+    
     class JITCode {
     class JITCode {
+#if ENABLE(JIT)
         typedef MacroAssemblerCodeRef CodeRef;
         typedef MacroAssemblerCodePtr CodePtr;
         typedef MacroAssemblerCodeRef CodeRef;
         typedef MacroAssemblerCodePtr CodePtr;
+#else
+        JITCode() { }
+#endif
     public:
     public:
+        enum JITType { None, HostCallThunk, InterpreterThunk, BaselineJIT, DFGJIT };
+        
+        static JITType bottomTierJIT()
+        {
+            return BaselineJIT;
+        }
+        
+        static JITType topTierJIT()
+        {
+            return DFGJIT;
+        }
+        
+        static JITType nextTierJIT(JITType jitType)
+        {
+            ASSERT_UNUSED(jitType, jitType == BaselineJIT || jitType == DFGJIT);
+            return DFGJIT;
+        }
+        
+        static bool isOptimizingJIT(JITType jitType)
+        {
+            return jitType == DFGJIT;
+        }
+        
+        static bool isBaselineCode(JITType jitType)
+        {
+            return jitType == InterpreterThunk || jitType == BaselineJIT;
+        }
+        
+#if ENABLE(JIT)
         JITCode()
         JITCode()
+            : m_jitType(None)
         {
         }
 
         {
         }
 
-        JITCode(const CodeRef ref)
+        JITCode(const CodeRef ref, JITType jitType)
             : m_ref(ref)
             : m_ref(ref)
+            , m_jitType(jitType)
         {
         {
+            ASSERT(jitType != None);
         }
         }
-
+        
         bool operator !() const
         {
         bool operator !() const
         {
-            return !m_ref.m_code.executableAddress();
+            return !m_ref;
         }
 
         CodePtr addressForCall()
         {
         }
 
         CodePtr addressForCall()
         {
-            return m_ref.m_code;
+            return m_ref.code();
+        }
+
+        void* executableAddressAtOffset(size_t offset) const
+        {
+            ASSERT(offset < size());
+            return reinterpret_cast<char*>(m_ref.code().executableAddress()) + offset;
+        }
+        
+        void* dataAddressAtOffset(size_t offset) const
+        {
+            ASSERT(offset < size());
+            return reinterpret_cast<char*>(m_ref.code().dataLocation()) + offset;
         }
 
         // This function returns the offset in bytes of 'pointerIntoCode' into
         }
 
         // This function returns the offset in bytes of 'pointerIntoCode' into
@@ -66,7 +116,7 @@ namespace JSC {
         // block of code.  It is ASSERTed that no codeblock >4gb in size.
         unsigned offsetOf(void* pointerIntoCode)
         {
         // block of code.  It is ASSERTed that no codeblock >4gb in size.
         unsigned offsetOf(void* pointerIntoCode)
         {
-            intptr_t result = reinterpret_cast<intptr_t>(pointerIntoCode) - reinterpret_cast<intptr_t>(m_ref.m_code.executableAddress());
+            intptr_t result = reinterpret_cast<intptr_t>(pointerIntoCode) - reinterpret_cast<intptr_t>(m_ref.code().executableAddress());
             ASSERT(static_cast<intptr_t>(static_cast<unsigned>(result)) == result);
             return static_cast<unsigned>(result);
         }
             ASSERT(static_cast<intptr_t>(static_cast<unsigned>(result)) == result);
             return static_cast<unsigned>(result);
         }
@@ -74,50 +124,56 @@ namespace JSC {
         // Execute the code!
         inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData)
         {
         // Execute the code!
         inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData)
         {
-            JSValue result = JSValue::decode(ctiTrampoline(m_ref.m_code.executableAddress(), registerFile, callFrame, 0, Profiler::enabledProfilerReference(), globalData));
+            JSValue result = JSValue::decode(ctiTrampoline(m_ref.code().executableAddress(), registerFile, callFrame, 0, Profiler::enabledProfilerReference(), globalData));
             return globalData->exception ? jsNull() : result;
         }
 
             return globalData->exception ? jsNull() : result;
         }
 
-        void* start()
+        void* start() const
         {
         {
-            return m_ref.m_code.dataLocation();
+            return m_ref.code().dataLocation();
         }
 
         }
 
-        size_t size()
+        size_t size() const
         {
         {
-            ASSERT(m_ref.m_code.executableAddress());
-            return m_ref.m_size;
+            ASSERT(m_ref.code().executableAddress());
+            return m_ref.size();
         }
 
         }
 
-        ExecutablePool* getExecutablePool()
+        ExecutableMemoryHandle* getExecutableMemory()
         {
         {
-            return m_ref.m_executablePool.get();
+            return m_ref.executableMemory();
+        }
+        
+        JITType jitType()
+        {
+            return m_jitType;
         }
 
         // Host functions are a bit special; they have a m_code pointer but they
         // do not individully ref the executable pool containing the trampoline.
         }
 
         // Host functions are a bit special; they have a m_code pointer but they
         // do not individully ref the executable pool containing the trampoline.
-        static JITCode HostFunction(CodePtr code)
+        static JITCode HostFunction(CodeRef code)
         {
         {
-            return JITCode(code.dataLocation(), 0, 0);
+            return JITCode(code, HostCallThunk);
         }
 
         void clear()
         {
             m_ref.~CodeRef();
         }
 
         void clear()
         {
             m_ref.~CodeRef();
-            new (&m_ref) CodeRef();
+            new (NotNull, &m_ref) CodeRef();
         }
 
     private:
         }
 
     private:
-        JITCode(void* code, PassRefPtr<ExecutablePool> executablePool, size_t size)
-            : m_ref(code, executablePool, size)
+        JITCode(PassRefPtr<ExecutableMemoryHandle> executableMemory, JITType jitType)
+            : m_ref(executableMemory)
+            , m_jitType(jitType)
         {
         }
 
         CodeRef m_ref;
         {
         }
 
         CodeRef m_ref;
+        JITType m_jitType;
+#endif // ENABLE(JIT)
     };
 
 };
 
 #endif
     };
 
 };
 
 #endif
-
-#endif
diff --git a/jit/JITCompilationEffort.h b/jit/JITCompilationEffort.h
new file mode 100644 (file)
index 0000000..5eb6801
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef JITCompilationEffort_h
+#define JITCompilationEffort_h
+
+namespace JSC {
+
+enum JITCompilationEffort {
+    JITCompilationCanFail,
+    JITCompilationMustSucceed
+};
+
+} // namespace JSC
+
+#endif // JITCompilationEffort_h
+
diff --git a/jit/JITDriver.h b/jit/JITDriver.h
new file mode 100644 (file)
index 0000000..66cf519
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef JITDriver_h
+#define JITDriver_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#include "BytecodeGenerator.h"
+#include "DFGDriver.h"
+#include "JIT.h"
+#include "LLIntEntrypoints.h"
+
+namespace JSC {
+
+template<typename CodeBlockType>
+inline bool jitCompileIfAppropriate(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType, JITCompilationEffort effort)
+{
+    if (jitType == codeBlock->getJITType())
+        return true;
+    
+    if (!globalData.canUseJIT())
+        return true;
+    
+    codeBlock->unlinkIncomingCalls();
+    
+    JITCode oldJITCode = jitCode;
+    
+    bool dfgCompiled = false;
+    if (jitType == JITCode::DFGJIT)
+        dfgCompiled = DFG::tryCompile(globalData, codeBlock.get(), jitCode);
+    if (dfgCompiled) {
+        if (codeBlock->alternative())
+            codeBlock->alternative()->unlinkIncomingCalls();
+    } else {
+        if (codeBlock->alternative()) {
+            codeBlock = static_pointer_cast<CodeBlockType>(codeBlock->releaseAlternative());
+            jitCode = oldJITCode;
+            return false;
+        }
+        jitCode = JIT::compile(&globalData, codeBlock.get(), effort);
+        if (!jitCode) {
+            jitCode = oldJITCode;
+            return false;
+        }
+    }
+    codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr());
+    
+    return true;
+}
+
+inline bool jitCompileFunctionIfAppropriate(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, JITCompilationEffort effort)
+{
+    if (jitType == codeBlock->getJITType())
+        return true;
+    
+    if (!globalData.canUseJIT())
+        return true;
+    
+    codeBlock->unlinkIncomingCalls();
+    
+    JITCode oldJITCode = jitCode;
+    MacroAssemblerCodePtr oldJITCodeWithArityCheck = jitCodeWithArityCheck;
+    
+    bool dfgCompiled = false;
+    if (jitType == JITCode::DFGJIT)
+        dfgCompiled = DFG::tryCompileFunction(globalData, codeBlock.get(), jitCode, jitCodeWithArityCheck);
+    if (dfgCompiled) {
+        if (codeBlock->alternative())
+            codeBlock->alternative()->unlinkIncomingCalls();
+    } else {
+        if (codeBlock->alternative()) {
+            codeBlock = static_pointer_cast<FunctionCodeBlock>(codeBlock->releaseAlternative());
+            symbolTable = codeBlock->sharedSymbolTable();
+            jitCode = oldJITCode;
+            jitCodeWithArityCheck = oldJITCodeWithArityCheck;
+            return false;
+        }
+        jitCode = JIT::compile(&globalData, codeBlock.get(), effort, &jitCodeWithArityCheck);
+        if (!jitCode) {
+            jitCode = oldJITCode;
+            jitCodeWithArityCheck = oldJITCodeWithArityCheck;
+            return false;
+        }
+    }
+    codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
+    
+    return true;
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // JITDriver_h
+
diff --git a/jit/JITExceptions.cpp b/jit/JITExceptions.cpp
new file mode 100644 (file)
index 0000000..2955fac
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "JITExceptions.h"
+
+#include "CallFrame.h"
+#include "CodeBlock.h"
+#include "Interpreter.h"
+#include "JSGlobalData.h"
+#include "JSValue.h"
+
+#if ENABLE(JIT)
+
+namespace JSC {
+
+ExceptionHandler genericThrow(JSGlobalData* globalData, ExecState* callFrame, JSValue exceptionValue, unsigned vPCIndex)
+{
+    ASSERT(exceptionValue);
+
+    globalData->exception = JSValue();
+    HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex); // This may update callFrame & exceptionValue!
+    globalData->exception = exceptionValue;
+
+    void* catchRoutine;
+    Instruction* catchPCForInterpreter = 0;
+    if (handler) {
+        catchRoutine = handler->nativeCode.executableAddress();
+        catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target];
+    } else
+        catchRoutine = FunctionPtr(ctiOpThrowNotCaught).value();
+    
+    globalData->callFrameForThrow = callFrame;
+    globalData->targetMachinePCForThrow = catchRoutine;
+    globalData->targetInterpreterPCForThrow = catchPCForInterpreter;
+    
+    ASSERT(catchRoutine);
+    ExceptionHandler exceptionHandler = { catchRoutine, callFrame };
+    return exceptionHandler;
+}
+
+ExceptionHandler jitThrow(JSGlobalData* globalData, ExecState* callFrame, JSValue exceptionValue, ReturnAddressPtr faultLocation)
+{
+    return genericThrow(globalData, callFrame, exceptionValue, callFrame->codeBlock()->bytecodeOffset(callFrame, faultLocation));
+}
+
+}
+
+#endif
diff --git a/jit/JITExceptions.h b/jit/JITExceptions.h
new file mode 100644 (file)
index 0000000..59ded18
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef JITExceptions_h
+#define JITExceptions_h
+
+#include "JSValue.h"
+#include "MacroAssemblerCodeRef.h"
+
+#if ENABLE(ASSEMBLER)
+
+namespace JSC {
+
+class ExecState;
+class JSGlobalData;
+
+// This header gives other parts of the system access to the JIT's prototocol
+// for the throwing and handling exceptions.
+
+struct ExceptionHandler {
+    void* catchRoutine;
+    ExecState* callFrame;
+};
+
+ExceptionHandler genericThrow(JSGlobalData*, ExecState*, JSValue exceptionValue, unsigned vPCIndex);
+
+ExceptionHandler jitThrow(JSGlobalData*, ExecState*, JSValue exceptionValue, ReturnAddressPtr faultLocation);
+
+} // namespace JSC
+
+#endif
+
+#endif // JITExceptions_h
+
index 693ae98fdfda3bce0af0a1e8c90a2d03423ab786..cd33821f292eeb832123e39c7b9174263def9c7e 100644 (file)
@@ -84,12 +84,21 @@ ALWAYS_INLINE void JIT::emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHea
 
 ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures)
 {
 
 ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures)
 {
-    failures.append(branchPtr(NotEqual, Address(src), TrustedImmPtr(m_globalData->jsStringVPtr)));
-    failures.append(branchTest32(NonZero, Address(src, OBJECT_OFFSETOF(JSString, m_fiberCount))));
+    failures.append(branchPtr(NotEqual, Address(src, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
     failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), TrustedImm32(1)));
     loadPtr(MacroAssembler::Address(src, ThunkHelpers::jsStringValueOffset()), dst);
     failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), TrustedImm32(1)));
     loadPtr(MacroAssembler::Address(src, ThunkHelpers::jsStringValueOffset()), dst);
+    failures.append(branchTest32(Zero, dst));
+    loadPtr(MacroAssembler::Address(dst, ThunkHelpers::stringImplFlagsOffset()), regT1);
     loadPtr(MacroAssembler::Address(dst, ThunkHelpers::stringImplDataOffset()), dst);
     loadPtr(MacroAssembler::Address(dst, ThunkHelpers::stringImplDataOffset()), dst);
+
+    JumpList is16Bit;
+    JumpList cont8Bit;
+    is16Bit.append(branchTest32(Zero, regT1, TrustedImm32(ThunkHelpers::stringImpl8BitFlag())));
+    load8(MacroAssembler::Address(dst, 0), dst);
+    cont8Bit.append(jump());
+    is16Bit.link(this);
     load16(MacroAssembler::Address(dst, 0), dst);
     load16(MacroAssembler::Address(dst, 0), dst);
+    cont8Bit.link(this);
 }
 
 ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from)
 }
 
 ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from)
@@ -123,7 +132,6 @@ ALWAYS_INLINE bool JIT::atJumpTarget()
 
 ALWAYS_INLINE void JIT::beginUninterruptedSequence(int insnSpace, int constSpace)
 {
 
 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
@@ -173,7 +181,6 @@ ALWAYS_INLINE void JIT::endUninterruptedSequence(int insnSpace, int constSpace,
     ASSERT(differenceBetween(m_uninterruptedInstructionSequenceBegin, label()) <= insnSpace);
     ASSERT(sizeOfConstantPool() - m_uninterruptedConstantSequenceBegin <= constSpace);
 #endif
     ASSERT(differenceBetween(m_uninterruptedInstructionSequenceBegin, label()) <= insnSpace);
     ASSERT(sizeOfConstantPool() - m_uninterruptedConstantSequenceBegin <= constSpace);
 #endif
-    JSInterfaceJIT::endUninterruptedSequence();
 }
 
 #endif
 }
 
 #endif
@@ -253,6 +260,19 @@ ALWAYS_INLINE void JIT::restoreArgumentReference()
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
 }
 
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
 }
 
+ALWAYS_INLINE void JIT::updateTopCallFrame()
+{
+    ASSERT(static_cast<int>(m_bytecodeOffset) >= 0);
+    if (m_bytecodeOffset) {
+#if USE(JSVALUE32_64)
+        storePtr(TrustedImmPtr(m_codeBlock->instructions().begin() + m_bytecodeOffset + 1), intTagFor(RegisterFile::ArgumentCount));
+#else
+        store32(TrustedImm32(m_bytecodeOffset + 1), intTagFor(RegisterFile::ArgumentCount));
+#endif
+    }
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
+}
+
 ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
 {
 #if CPU(X86)
 ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
 {
 #if CPU(X86)
@@ -294,6 +314,14 @@ ALWAYS_INLINE void JIT::addSlowCase(JumpList jumpList)
         m_slowCases.append(SlowCaseEntry(jumpVector[i], m_bytecodeOffset));
 }
 
         m_slowCases.append(SlowCaseEntry(jumpVector[i], m_bytecodeOffset));
 }
 
+ALWAYS_INLINE void JIT::addSlowCase()
+{
+    ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
+    
+    Jump emptyJump; // Doing it this way to make Windows happy.
+    m_slowCases.append(SlowCaseEntry(emptyJump, m_bytecodeOffset));
+}
+
 ALWAYS_INLINE void JIT::addJump(Jump jump, int relativeOffset)
 {
     ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
 ALWAYS_INLINE void JIT::addJump(Jump jump, int relativeOffset)
 {
     ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
@@ -308,6 +336,17 @@ ALWAYS_INLINE void JIT::emitJumpSlowToHot(Jump jump, int relativeOffset)
     jump.linkTo(m_labels[m_bytecodeOffset + relativeOffset], this);
 }
 
     jump.linkTo(m_labels[m_bytecodeOffset + relativeOffset], this);
 }
 
+ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotObject(RegisterID structureReg)
+{
+    return branch8(Below, Address(structureReg, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType));
+}
+
+ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotType(RegisterID baseReg, RegisterID scratchReg, JSType type)
+{
+    loadPtr(Address(baseReg, JSCell::structureOffset()), scratchReg);
+    return branch8(NotEqual, Address(scratchReg, Structure::typeInfoTypeOffset()), TrustedImm32(type));
+}
+
 #if ENABLE(SAMPLING_FLAGS)
 ALWAYS_INLINE void JIT::setSamplingFlag(int32_t flag)
 {
 #if ENABLE(SAMPLING_FLAGS)
 ALWAYS_INLINE void JIT::setSamplingFlag(int32_t flag)
 {
@@ -325,17 +364,9 @@ ALWAYS_INLINE void JIT::clearSamplingFlag(int32_t flag)
 #endif
 
 #if ENABLE(SAMPLING_COUNTERS)
 #endif
 
 #if ENABLE(SAMPLING_COUNTERS)
-ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t count)
-{
-#if CPU(X86_64) // Or any other 64-bit plattform.
-    addPtr(TrustedImm32(count), AbsoluteAddress(counter.addressOfCounter()));
-#elif CPU(X86) // Or any other little-endian 32-bit plattform.
-    intptr_t hiWord = reinterpret_cast<intptr_t>(counter.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
+ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, int32_t count)
+{
+    add64(TrustedImm32(count), AbsoluteAddress(counter.addressOfCounter()));
 }
 #endif
 
 }
 #endif
 
@@ -374,9 +405,185 @@ ALWAYS_INLINE bool JIT::isOperandConstantImmediateChar(unsigned src)
     return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isString() && asString(getConstantOperand(src).asCell())->length() == 1;
 }
 
     return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isString() && asString(getConstantOperand(src).asCell())->length() == 1;
 }
 
+template <typename ClassType, bool destructor, typename StructureType> inline void JIT::emitAllocateBasicJSObject(StructureType structure, RegisterID result, RegisterID storagePtr)
+{
+    MarkedAllocator* allocator = 0;
+    if (destructor)
+        allocator = &m_globalData->heap.allocatorForObjectWithDestructor(sizeof(ClassType));
+    else
+        allocator = &m_globalData->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType));
+    loadPtr(&allocator->m_freeList.head, result);
+    addSlowCase(branchTestPtr(Zero, result));
+
+    // remove the object from the free list
+    loadPtr(Address(result), storagePtr);
+    storePtr(storagePtr, &allocator->m_freeList.head);
+
+    // initialize the object's structure
+    storePtr(structure, Address(result, JSCell::structureOffset()));
+
+    // initialize the object's classInfo pointer
+    storePtr(TrustedImmPtr(&ClassType::s_info), Address(result, JSCell::classInfoOffset()));
+
+    // initialize the inheritor ID
+    storePtr(TrustedImmPtr(0), Address(result, JSObject::offsetOfInheritorID()));
+
+    // initialize the object's property storage pointer
+    addPtr(TrustedImm32(sizeof(JSObject)), result, storagePtr);
+    storePtr(storagePtr, Address(result, ClassType::offsetOfPropertyStorage()));
+}
+
+template <typename T> inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch)
+{
+    emitAllocateBasicJSObject<JSFinalObject, false, T>(structure, result, scratch);
+}
+
+inline void JIT::emitAllocateJSFunction(FunctionExecutable* executable, RegisterID scopeChain, RegisterID result, RegisterID storagePtr)
+{
+    emitAllocateBasicJSObject<JSFunction, true>(TrustedImmPtr(m_codeBlock->globalObject()->namedFunctionStructure()), result, storagePtr);
+
+    // store the function's scope chain
+    storePtr(scopeChain, Address(result, JSFunction::offsetOfScopeChain()));
+
+    // store the function's executable member
+    storePtr(TrustedImmPtr(executable), Address(result, JSFunction::offsetOfExecutable()));
+
+    // store the function's name
+    ASSERT(executable->nameValue());
+    int functionNameOffset = sizeof(JSValue) * m_codeBlock->globalObject()->functionNameOffset();
+    storePtr(TrustedImmPtr(executable->nameValue()), Address(regT1, functionNameOffset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+#if USE(JSVALUE32_64)
+    store32(TrustedImm32(JSValue::CellTag), Address(regT1, functionNameOffset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+#endif
+}
+
+inline void JIT::emitAllocateBasicStorage(size_t size, RegisterID result, RegisterID storagePtr)
+{
+    CopiedAllocator* allocator = &m_globalData->heap.storageAllocator();
+
+    // FIXME: We need to check for wrap-around.
+    // Check to make sure that the allocation will fit in the current block.
+    loadPtr(&allocator->m_currentOffset, result);
+    addPtr(TrustedImm32(size), result);
+    loadPtr(&allocator->m_currentBlock, storagePtr);
+    addPtr(TrustedImm32(HeapBlock::s_blockSize), storagePtr);
+    addSlowCase(branchPtr(AboveOrEqual, result, storagePtr));
+
+    // Load the original offset.
+    loadPtr(&allocator->m_currentOffset, result);
+
+    // Bump the pointer forward.
+    move(result, storagePtr);
+    addPtr(TrustedImm32(size), storagePtr);
+    storePtr(storagePtr, &allocator->m_currentOffset);
+}
+
+inline void JIT::emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr)
+{
+    unsigned initialLength = std::max(length, 4U);
+    size_t initialStorage = JSArray::storageSize(initialLength);
+
+    // We allocate the backing store first to ensure that garbage collection 
+    // doesn't happen during JSArray initialization.
+    emitAllocateBasicStorage(initialStorage, storageResult, storagePtr);
+
+    // Allocate the cell for the array.
+    emitAllocateBasicJSObject<JSArray, false>(TrustedImmPtr(m_codeBlock->globalObject()->arrayStructure()), cellResult, storagePtr);
+
+    // Store all the necessary info in the ArrayStorage.
+    storePtr(storageResult, Address(storageResult, ArrayStorage::allocBaseOffset()));
+    store32(Imm32(length), Address(storageResult, ArrayStorage::lengthOffset()));
+    store32(Imm32(length), Address(storageResult, ArrayStorage::numValuesInVectorOffset()));
+
+    // Store the newly allocated ArrayStorage.
+    storePtr(storageResult, Address(cellResult, JSArray::storageOffset()));
+
+    // Store the vector length and index bias.
+    store32(Imm32(initialLength), Address(cellResult, JSArray::vectorLengthOffset()));
+    store32(TrustedImm32(0), Address(cellResult, JSArray::indexBiasOffset()));
+
+    // Initialize the sparse value map.
+    storePtr(TrustedImmPtr(0), Address(cellResult, JSArray::sparseValueMapOffset()));
+
+        // Store the values we have.
+    for (unsigned i = 0; i < length; i++) {
+#if USE(JSVALUE64)
+        loadPtr(Address(callFrameRegister, (valuesRegister + i) * sizeof(Register)), storagePtr);
+        storePtr(storagePtr, Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i));
+#else
+        load32(Address(callFrameRegister, (valuesRegister + i) * sizeof(Register)), storagePtr);
+        store32(storagePtr, Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i));
+        load32(Address(callFrameRegister, (valuesRegister + i) * sizeof(Register) + sizeof(uint32_t)), storagePtr);
+        store32(storagePtr, Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i + sizeof(uint32_t)));
+#endif
+    }
+
+    // Zero out the remaining slots.
+    for (unsigned i = length; i < initialLength; i++) {
+#if USE(JSVALUE64)
+        storePtr(TrustedImmPtr(0), Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i));
+#else
+        store32(TrustedImm32(static_cast<int>(JSValue::EmptyValueTag)), Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+        store32(TrustedImm32(0), Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+#endif
+    }
+}
+
+#if ENABLE(VALUE_PROFILER)
+inline void JIT::emitValueProfilingSite(ValueProfile* valueProfile)
+{
+    ASSERT(shouldEmitProfiling());
+    ASSERT(valueProfile);
+
+    const RegisterID value = regT0;
+#if USE(JSVALUE32_64)
+    const RegisterID valueTag = regT1;
+#endif
+    const RegisterID scratch = regT3;
+    
+    if (ValueProfile::numberOfBuckets == 1) {
+        // We're in a simple configuration: only one bucket, so we can just do a direct
+        // store.
+#if USE(JSVALUE64)
+        storePtr(value, valueProfile->m_buckets);
+#else
+        EncodedValueDescriptor* descriptor = bitwise_cast<EncodedValueDescriptor*>(valueProfile->m_buckets);
+        store32(value, &descriptor->asBits.payload);
+        store32(valueTag, &descriptor->asBits.tag);
+#endif
+        return;
+    }
+    
+    if (m_randomGenerator.getUint32() & 1)
+        add32(TrustedImm32(1), bucketCounterRegister);
+    else
+        add32(TrustedImm32(3), bucketCounterRegister);
+    and32(TrustedImm32(ValueProfile::bucketIndexMask), bucketCounterRegister);
+    move(TrustedImmPtr(valueProfile->m_buckets), scratch);
+#if USE(JSVALUE64)
+    storePtr(value, BaseIndex(scratch, bucketCounterRegister, TimesEight));
+#elif USE(JSVALUE32_64)
+    store32(value, BaseIndex(scratch, bucketCounterRegister, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+    store32(valueTag, BaseIndex(scratch, bucketCounterRegister, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+#endif
+}
+
+inline void JIT::emitValueProfilingSite(unsigned bytecodeOffset)
+{
+    if (!shouldEmitProfiling())
+        return;
+    emitValueProfilingSite(m_codeBlock->valueProfileForBytecodeOffset(bytecodeOffset));
+}
+
+inline void JIT::emitValueProfilingSite()
+{
+    emitValueProfilingSite(m_bytecodeOffset);
+}
+#endif
+
 #if USE(JSVALUE32_64)
 
 #if USE(JSVALUE32_64)
 
-inline void JIT::emitLoadTag(unsigned index, RegisterID tag)
+inline void JIT::emitLoadTag(int index, RegisterID tag)
 {
     RegisterID mappedTag;
     if (getMappedTag(index, mappedTag)) {
 {
     RegisterID mappedTag;
     if (getMappedTag(index, mappedTag)) {
@@ -395,7 +602,7 @@ inline void JIT::emitLoadTag(unsigned index, RegisterID tag)
     unmap(tag);
 }
 
     unmap(tag);
 }
 
-inline void JIT::emitLoadPayload(unsigned index, RegisterID payload)
+inline void JIT::emitLoadPayload(int index, RegisterID payload)
 {
     RegisterID mappedPayload;
     if (getMappedPayload(index, mappedPayload)) {
 {
     RegisterID mappedPayload;
     if (getMappedPayload(index, mappedPayload)) {
@@ -420,7 +627,7 @@ inline void JIT::emitLoad(const JSValue& v, RegisterID tag, RegisterID payload)
     move(Imm32(v.tag()), tag);
 }
 
     move(Imm32(v.tag()), tag);
 }
 
-inline void JIT::emitLoad(unsigned index, RegisterID tag, RegisterID payload, RegisterID base)
+inline void JIT::emitLoad(int index, RegisterID tag, RegisterID payload, RegisterID base)
 {
     ASSERT(tag != payload);
 
 {
     ASSERT(tag != payload);
 
@@ -441,7 +648,7 @@ inline void JIT::emitLoad(unsigned index, RegisterID tag, RegisterID payload, Re
     load32(tagFor(index, base), tag);
 }
 
     load32(tagFor(index, base), tag);
 }
 
-inline void JIT::emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1, unsigned index2, RegisterID tag2, RegisterID payload2)
+inline void JIT::emitLoad2(int index1, RegisterID tag1, RegisterID payload1, int index2, RegisterID tag2, RegisterID payload2)
 {
     if (isMapped(index1)) {
         emitLoad(index1, tag1, payload1);
 {
     if (isMapped(index1)) {
         emitLoad(index1, tag1, payload1);
@@ -452,7 +659,7 @@ inline void JIT::emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1
     emitLoad(index1, tag1, payload1);
 }
 
     emitLoad(index1, tag1, payload1);
 }
 
-inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
+inline void JIT::emitLoadDouble(int index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
         WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
         WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
@@ -461,7 +668,7 @@ inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
         loadDouble(addressFor(index), value);
 }
 
         loadDouble(addressFor(index), value);
 }
 
-inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
+inline void JIT::emitLoadInt32ToDouble(int index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
         WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
         WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
@@ -471,46 +678,52 @@ inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
         convertInt32ToDouble(payloadFor(index), value);
 }
 
         convertInt32ToDouble(payloadFor(index), value);
 }
 
-inline void JIT::emitStore(unsigned index, RegisterID tag, RegisterID payload, RegisterID base)
+inline void JIT::emitStore(int index, RegisterID tag, RegisterID payload, RegisterID base)
 {
     store32(payload, payloadFor(index, base));
     store32(tag, tagFor(index, base));
 }
 
 {
     store32(payload, payloadFor(index, base));
     store32(tag, tagFor(index, base));
 }
 
-inline void JIT::emitStoreInt32(unsigned index, RegisterID payload, bool indexIsInt32)
+inline void JIT::emitStoreInt32(int index, RegisterID payload, bool indexIsInt32)
 {
     store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsInt32)
         store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
 }
 
 {
     store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsInt32)
         store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
 }
 
-inline void JIT::emitStoreInt32(unsigned index, TrustedImm32 payload, bool indexIsInt32)
+inline void JIT::emitStoreAndMapInt32(int index, RegisterID tag, RegisterID payload, bool indexIsInt32, size_t opcodeLength)
+{
+    emitStoreInt32(index, payload, indexIsInt32);
+    map(m_bytecodeOffset + opcodeLength, index, tag, payload);
+}
+
+inline void JIT::emitStoreInt32(int index, TrustedImm32 payload, bool indexIsInt32)
 {
     store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsInt32)
         store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
 }
 
 {
     store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsInt32)
         store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
 }
 
-inline void JIT::emitStoreCell(unsigned index, RegisterID payload, bool indexIsCell)
+inline void JIT::emitStoreCell(int index, RegisterID payload, bool indexIsCell)
 {
     store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsCell)
         store32(TrustedImm32(JSValue::CellTag), tagFor(index, callFrameRegister));
 }
 
 {
     store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsCell)
         store32(TrustedImm32(JSValue::CellTag), tagFor(index, callFrameRegister));
 }
 
-inline void JIT::emitStoreBool(unsigned index, RegisterID payload, bool indexIsBool)
+inline void JIT::emitStoreBool(int index, RegisterID payload, bool indexIsBool)
 {
     store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsBool)
         store32(TrustedImm32(JSValue::BooleanTag), tagFor(index, callFrameRegister));
 }
 
 {
     store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsBool)
         store32(TrustedImm32(JSValue::BooleanTag), tagFor(index, callFrameRegister));
 }
 
-inline void JIT::emitStoreDouble(unsigned index, FPRegisterID value)
+inline void JIT::emitStoreDouble(int index, FPRegisterID value)
 {
     storeDouble(value, addressFor(index));
 }
 
 {
     storeDouble(value, addressFor(index));
 }
 
-inline void JIT::emitStore(unsigned index, const JSValue constant, RegisterID base)
+inline void JIT::emitStore(int index, const JSValue constant, RegisterID base)
 {
     store32(Imm32(constant.payload()), payloadFor(index, base));
     store32(Imm32(constant.tag()), tagFor(index, base));
 {
     store32(Imm32(constant.payload()), payloadFor(index, base));
     store32(Imm32(constant.tag()), tagFor(index, base));
@@ -533,7 +746,7 @@ inline bool JIT::isLabeled(unsigned bytecodeOffset)
     return false;
 }
 
     return false;
 }
 
-inline void JIT::map(unsigned bytecodeOffset, unsigned virtualRegisterIndex, RegisterID tag, RegisterID payload)
+inline void JIT::map(unsigned bytecodeOffset, int virtualRegisterIndex, RegisterID tag, RegisterID payload)
 {
     if (isLabeled(bytecodeOffset))
         return;
 {
     if (isLabeled(bytecodeOffset))
         return;
@@ -542,6 +755,9 @@ inline void JIT::map(unsigned bytecodeOffset, unsigned virtualRegisterIndex, Reg
     m_mappedVirtualRegisterIndex = virtualRegisterIndex;
     m_mappedTag = tag;
     m_mappedPayload = payload;
     m_mappedVirtualRegisterIndex = virtualRegisterIndex;
     m_mappedTag = tag;
     m_mappedPayload = payload;
+    
+    ASSERT(!canBeOptimized() || m_mappedPayload == regT0);
+    ASSERT(!canBeOptimized() || m_mappedTag == regT1);
 }
 
 inline void JIT::unmap(RegisterID registerID)
 }
 
 inline void JIT::unmap(RegisterID registerID)
@@ -555,12 +771,12 @@ inline void JIT::unmap(RegisterID registerID)
 inline void JIT::unmap()
 {
     m_mappedBytecodeOffset = (unsigned)-1;
 inline void JIT::unmap()
 {
     m_mappedBytecodeOffset = (unsigned)-1;
-    m_mappedVirtualRegisterIndex = (unsigned)-1;
+    m_mappedVirtualRegisterIndex = RegisterFile::ReturnPC;
     m_mappedTag = (RegisterID)-1;
     m_mappedPayload = (RegisterID)-1;
 }
 
     m_mappedTag = (RegisterID)-1;
     m_mappedPayload = (RegisterID)-1;
 }
 
-inline bool JIT::isMapped(unsigned virtualRegisterIndex)
+inline bool JIT::isMapped(int virtualRegisterIndex)
 {
     if (m_mappedBytecodeOffset != m_bytecodeOffset)
         return false;
 {
     if (m_mappedBytecodeOffset != m_bytecodeOffset)
         return false;
@@ -569,7 +785,7 @@ inline bool JIT::isMapped(unsigned virtualRegisterIndex)
     return true;
 }
 
     return true;
 }
 
-inline bool JIT::getMappedPayload(unsigned virtualRegisterIndex, RegisterID& payload)
+inline bool JIT::getMappedPayload(int virtualRegisterIndex, RegisterID& payload)
 {
     if (m_mappedBytecodeOffset != m_bytecodeOffset)
         return false;
 {
     if (m_mappedBytecodeOffset != m_bytecodeOffset)
         return false;
@@ -581,7 +797,7 @@ inline bool JIT::getMappedPayload(unsigned virtualRegisterIndex, RegisterID& pay
     return true;
 }
 
     return true;
 }
 
-inline bool JIT::getMappedTag(unsigned virtualRegisterIndex, RegisterID& tag)
+inline bool JIT::getMappedTag(int virtualRegisterIndex, RegisterID& tag)
 {
     if (m_mappedBytecodeOffset != m_bytecodeOffset)
         return false;
 {
     if (m_mappedBytecodeOffset != m_bytecodeOffset)
         return false;
@@ -593,7 +809,7 @@ inline bool JIT::getMappedTag(unsigned virtualRegisterIndex, RegisterID& tag)
     return true;
 }
 
     return true;
 }
 
-inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex)
+inline void JIT::emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex)
 {
     if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex)) {
         if (m_codeBlock->isConstantRegisterIndex(virtualRegisterIndex))
 {
     if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex)) {
         if (m_codeBlock->isConstantRegisterIndex(virtualRegisterIndex))
@@ -603,7 +819,7 @@ inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex)
     }
 }
 
     }
 }
 
-inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex, RegisterID tag)
+inline void JIT::emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex, RegisterID tag)
 {
     if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex)) {
         if (m_codeBlock->isConstantRegisterIndex(virtualRegisterIndex))
 {
     if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex)) {
         if (m_codeBlock->isConstantRegisterIndex(virtualRegisterIndex))
@@ -613,12 +829,6 @@ inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex, Regi
     }
 }
 
     }
 }
 
-inline void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, unsigned virtualRegisterIndex)
-{
-    if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex))
-        linkSlowCase(iter);
-}
-
 ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
 {
     return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32();
 ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
 {
     return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32();
@@ -656,7 +866,10 @@ ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst)
     // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
     if (m_codeBlock->isConstantRegisterIndex(src)) {
         JSValue value = m_codeBlock->getConstant(src);
     // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
     if (m_codeBlock->isConstantRegisterIndex(src)) {
         JSValue value = m_codeBlock->getConstant(src);
-        move(ImmPtr(JSValue::encode(value)), dst);
+        if (!value.isNumber())
+            move(TrustedImmPtr(JSValue::encode(value)), dst);
+        else
+            move(ImmPtr(JSValue::encode(value)), dst);
         killLastResultRegister();
         return;
     }
         killLastResultRegister();
         return;
     }
@@ -748,7 +961,7 @@ ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, int vReg)
 
 #if USE(JSVALUE64)
 
 
 #if USE(JSVALUE64)
 
-inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
+inline void JIT::emitLoadDouble(int index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
         WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
         WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
@@ -757,7 +970,7 @@ inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
         loadDouble(addressFor(index), value);
 }
 
         loadDouble(addressFor(index), value);
 }
 
-inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
+inline void JIT::emitLoadInt32ToDouble(int index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
         ASSERT(isOperandConstantImmediateInt(index));
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
         ASSERT(isOperandConstantImmediateInt(index));
index 4cdd35aa96f48ef84057ad301b7672438b53c9ff..d68f4109d6d172105a6ad4eea04296d2a684437b 100644 (file)
@@ -29,6 +29,8 @@
 #include "JIT.h"
 
 #include "Arguments.h"
 #include "JIT.h"
 
 #include "Arguments.h"
+#include "CopiedSpaceInlineMethods.h"
+#include "Heap.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
 #include "JSArray.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
 #include "JSArray.h"
@@ -41,15 +43,14 @@ namespace JSC {
 
 #if USE(JSVALUE64)
 
 
 #if USE(JSVALUE64)
 
-void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, TrampolineStructure *trampolines)
+PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGlobalData* globalData, TrampolineStructure *trampolines)
 {
 {
-#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);
     // (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), TrustedImmPtr(m_globalData->jsStringVPtr));
+    Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info));
 
     // 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);
@@ -60,117 +61,158 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     emitFastArithIntToImmNoCheck(regT0, regT0);
     
     ret();
     emitFastArithIntToImmNoCheck(regT0, regT0);
     
     ret();
-#endif
 
     // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
     COMPILE_ASSERT(sizeof(CodeType) == 4, CodeTypeEnumMustBe32Bit);
 
 
     // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
     COMPILE_ASSERT(sizeof(CodeType) == 4, CodeTypeEnumMustBe32Bit);
 
+    JumpList callSlowCase;
+    JumpList constructSlowCase;
+
     // VirtualCallLink Trampoline
     // VirtualCallLink Trampoline
-    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
-    JumpList callLinkFailures;
+    // regT0 holds callee; callFrame is moved and partially initialized.
     Label virtualCallLinkBegin = align();
     Label virtualCallLinkBegin = align();
-    compileOpCallInitializeCallFrame();
+    callSlowCase.append(emitJumpIfNotJSCell(regT0));
+    callSlowCase.append(emitJumpIfNotType(regT0, regT1, JSFunctionType));
+
+    // Finish canonical initialization before JS function call.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+    // Also initialize ReturnPC for use by lazy linking and exceptions.
     preserveReturnAddressAfterCall(regT3);
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     preserveReturnAddressAfterCall(regT3);
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+    
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
     restoreArgumentReference();
     Call callLazyLinkCall = call();
     restoreArgumentReference();
     Call callLazyLinkCall = call();
-    callLinkFailures.append(branchTestPtr(Zero, regT0));
     restoreReturnAddressBeforeReturn(regT3);
     restoreReturnAddressBeforeReturn(regT3);
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
     jump(regT0);
 
     // VirtualConstructLink Trampoline
     jump(regT0);
 
     // VirtualConstructLink Trampoline
-    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    // regT0 holds callee; callFrame is moved and partially initialized.
     Label virtualConstructLinkBegin = align();
     Label virtualConstructLinkBegin = align();
-    compileOpCallInitializeCallFrame();
+    constructSlowCase.append(emitJumpIfNotJSCell(regT0));
+    constructSlowCase.append(emitJumpIfNotType(regT0, regT1, JSFunctionType));
+
+    // Finish canonical initialization before JS function call.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+    // Also initialize ReturnPC for use by lazy linking and exeptions.
     preserveReturnAddressAfterCall(regT3);
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     preserveReturnAddressAfterCall(regT3);
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+    
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
     restoreArgumentReference();
     Call callLazyLinkConstruct = call();
     restoreArgumentReference();
     Call callLazyLinkConstruct = call();
-    callLinkFailures.append(branchTestPtr(Zero, regT0));
     restoreReturnAddressBeforeReturn(regT3);
     restoreReturnAddressBeforeReturn(regT3);
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
     jump(regT0);
 
     // VirtualCall Trampoline
     jump(regT0);
 
     // VirtualCall Trampoline
-    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    // regT0 holds callee; regT2 will hold the FunctionExecutable.
     Label virtualCallBegin = align();
     Label virtualCallBegin = align();
-    compileOpCallInitializeCallFrame();
+    callSlowCase.append(emitJumpIfNotJSCell(regT0));
+    callSlowCase.append(emitJumpIfNotType(regT0, regT1, JSFunctionType));
 
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    // Finish canonical initialization before JS function call.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
 
-    Jump hasCodeBlock3 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0));
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    Jump hasCodeBlock1 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0));
     preserveReturnAddressAfterCall(regT3);
     preserveReturnAddressAfterCall(regT3);
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
     restoreArgumentReference();
     Call callCompileCall = call();
     restoreArgumentReference();
     Call callCompileCall = 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);
-    hasCodeBlock3.link(this);
 
 
+    hasCodeBlock1.link(this);
     loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForCallWithArityCheck)), regT0);
     jump(regT0);
 
     // VirtualConstruct Trampoline
     loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForCallWithArityCheck)), regT0);
     jump(regT0);
 
     // VirtualConstruct Trampoline
-    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    // regT0 holds callee; regT2 will hold the FunctionExecutable.
     Label virtualConstructBegin = align();
     Label virtualConstructBegin = align();
-    compileOpCallInitializeCallFrame();
+    constructSlowCase.append(emitJumpIfNotJSCell(regT0));
+    constructSlowCase.append(emitJumpIfNotType(regT0, regT1, JSFunctionType));
 
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    // Finish canonical initialization before JS function call.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
 
-    Jump hasCodeBlock4 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0));
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    Jump hasCodeBlock2 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0));
     preserveReturnAddressAfterCall(regT3);
     preserveReturnAddressAfterCall(regT3);
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
     restoreArgumentReference();
     Call callCompileConstruct = call();
     restoreArgumentReference();
     Call callCompileConstruct = 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);
-    hasCodeBlock4.link(this);
 
 
+    hasCodeBlock2.link(this);
     loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForConstructWithArityCheck)), regT0);
     jump(regT0);
     loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForConstructWithArityCheck)), regT0);
     jump(regT0);
-    
-    // If the parser fails we want to be able to be able to keep going,
-    // So we handle this as a parse failure.
-    callLinkFailures.link(this);
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+
+    callSlowCase.link(this);
+    // Finish canonical initialization before JS function call.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2, regT2);
+    emitPutCellToCallFrameHeader(regT2, RegisterFile::ScopeChain);
+
+    // Also initialize ReturnPC and CodeBlock, like a JS function would.
+    preserveReturnAddressAfterCall(regT3);
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+    emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
+
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
+    restoreArgumentReference();
+    Call callCallNotJSFunction = call();
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
     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()));
+    restoreReturnAddressBeforeReturn(regT3);
+    ret();
+
+    constructSlowCase.link(this);
+    // Finish canonical initialization before JS function call.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2, regT2);
+    emitPutCellToCallFrameHeader(regT2, RegisterFile::ScopeChain);
+
+    // Also initialize ReturnPC and CodeBlock, like a JS function would.
+    preserveReturnAddressAfterCall(regT3);
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+    emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
+
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
+    restoreArgumentReference();
+    Call callConstructNotJSFunction = call();
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+    restoreReturnAddressBeforeReturn(regT3);
     ret();
 
     // NativeCall Trampoline
     Label nativeCallThunk = privateCompileCTINativeCall(globalData);    
     Label nativeConstructThunk = privateCompileCTINativeCall(globalData, true);    
 
     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);
     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.
 
     // 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);
+    LinkBuffer patchBuffer(*m_globalData, this, GLOBAL_THUNK_ID);
 
 
-#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));
     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));
     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));
     patchBuffer.link(callCompileCall, FunctionPtr(cti_op_call_jitCompile));
     patchBuffer.link(callCompileConstruct, FunctionPtr(cti_op_construct_jitCompile));
+    patchBuffer.link(callCallNotJSFunction, FunctionPtr(cti_op_call_NotJSFunction));
+    patchBuffer.link(callConstructNotJSFunction, FunctionPtr(cti_op_construct_NotJSConstruct));
 
     CodeRef finalCode = patchBuffer.finalizeCode();
 
     CodeRef finalCode = patchBuffer.finalizeCode();
-    *executablePool = finalCode.m_executablePool;
+    RefPtr<ExecutableMemoryHandle> executableMemory = finalCode.executableMemory();
 
     trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
     trampolines->ctiVirtualConstructLink = patchBuffer.trampolineAt(virtualConstructLinkBegin);
 
     trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
     trampolines->ctiVirtualConstructLink = patchBuffer.trampolineAt(virtualConstructLinkBegin);
@@ -178,9 +220,9 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     trampolines->ctiVirtualConstruct = patchBuffer.trampolineAt(virtualConstructBegin);
     trampolines->ctiNativeCall = patchBuffer.trampolineAt(nativeCallThunk);
     trampolines->ctiNativeConstruct = patchBuffer.trampolineAt(nativeConstructThunk);
     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);
     trampolines->ctiStringLengthTrampoline = patchBuffer.trampolineAt(stringLengthBegin);
-#endif
+    
+    return executableMemory.release();
 }
 
 JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isConstruct)
 }
 
 JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isConstruct)
@@ -190,6 +232,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
     Label nativeCallThunk = align();
     
     emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
     Label nativeCallThunk = align();
     
     emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
 
 #if CPU(X86_64)
     // Load caller frame's scope chain into this callframe so that whatever we call can
 
 #if CPU(X86_64)
     // Load caller frame's scope chain into this callframe so that whatever we call can
@@ -266,9 +309,8 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
 
     restoreReturnAddressBeforeReturn(regT3);
 
 
     restoreReturnAddressBeforeReturn(regT3);
 
-#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
-#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
 #else
 #else
+#error "JIT not supported on this platform."
     UNUSED_PARAM(executableOffsetToFunction);
     breakpoint();
 #endif
     UNUSED_PARAM(executableOffsetToFunction);
     breakpoint();
 #endif
@@ -290,6 +332,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
     storePtr(regT1, regT2);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
 
     storePtr(regT1, regT2);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
 
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
     // Set the return address.
     move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
     restoreReturnAddressBeforeReturn(regT1);
     // Set the return address.
     move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
     restoreReturnAddressBeforeReturn(regT1);
@@ -299,9 +342,9 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
     return nativeCallThunk;
 }
 
     return nativeCallThunk;
 }
 
-JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool>, JSGlobalData* globalData, NativeFunction)
+JIT::CodeRef JIT::privateCompileCTINativeCall(JSGlobalData* globalData, NativeFunction)
 {
 {
-    return globalData->jitStubs->ctiNativeCall();
+    return CodeRef::createSelfManagedCodeRef(globalData->jitStubs->ctiNativeCall());
 }
 
 void JIT::emit_op_mov(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_mov(Instruction* currentInstruction)
@@ -309,19 +352,29 @@ void JIT::emit_op_mov(Instruction* currentInstruction)
     int dst = currentInstruction[1].u.operand;
     int src = currentInstruction[2].u.operand;
 
     int dst = currentInstruction[1].u.operand;
     int src = currentInstruction[2].u.operand;
 
-    if (m_codeBlock->isConstantRegisterIndex(src)) {
-        storePtr(ImmPtr(JSValue::encode(getConstantOperand(src))), Address(callFrameRegister, dst * sizeof(Register)));
-        if (dst == m_lastResultBytecodeRegister)
-            killLastResultRegister();
-    } else if ((src == m_lastResultBytecodeRegister) || (dst == m_lastResultBytecodeRegister)) {
-        // If either the src or dst is the cached register go though
-        // get/put registers to make sure we track this correctly.
+    if (canBeOptimized()) {
+        // Use simpler approach, since the DFG thinks that the last result register
+        // is always set to the destination on every operation.
         emitGetVirtualRegister(src, regT0);
         emitPutVirtualRegister(dst);
     } else {
         emitGetVirtualRegister(src, regT0);
         emitPutVirtualRegister(dst);
     } else {
-        // Perform the copy via regT1; do not disturb any mapping in regT0.
-        loadPtr(Address(callFrameRegister, src * sizeof(Register)), regT1);
-        storePtr(regT1, Address(callFrameRegister, dst * sizeof(Register)));
+        if (m_codeBlock->isConstantRegisterIndex(src)) {
+            if (!getConstantOperand(src).isNumber())
+                storePtr(TrustedImmPtr(JSValue::encode(getConstantOperand(src))), Address(callFrameRegister, dst * sizeof(Register)));
+            else
+                storePtr(ImmPtr(JSValue::encode(getConstantOperand(src))), Address(callFrameRegister, dst * sizeof(Register)));
+            if (dst == m_lastResultBytecodeRegister)
+                killLastResultRegister();
+        } else if ((src == m_lastResultBytecodeRegister) || (dst == m_lastResultBytecodeRegister)) {
+            // If either the src or dst is the cached register go though
+            // get/put registers to make sure we track this correctly.
+            emitGetVirtualRegister(src, regT0);
+            emitPutVirtualRegister(dst);
+        } else {
+            // Perform the copy via regT1; do not disturb any mapping in regT0.
+            loadPtr(Address(callFrameRegister, src * sizeof(Register)), regT1);
+            storePtr(regT1, Address(callFrameRegister, dst * sizeof(Register)));
+        }
     }
 }
 
     }
 }
 
@@ -339,28 +392,16 @@ void JIT::emit_op_jmp(Instruction* currentInstruction)
     addJump(jump(), target);
 }
 
     addJump(jump(), target);
 }
 
-void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
+void JIT::emit_op_new_object(Instruction* currentInstruction)
 {
 {
-    emitTimeoutCheck();
-
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-    if (isOperandConstantImmediateInt(op2)) {
-        emitGetVirtualRegister(op1, regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        int32_t op2imm = getConstantOperandImmediateInt(op2);
-        addJump(branch32(LessThanOrEqual, regT0, Imm32(op2imm)), target);
-    } else {
-        emitGetVirtualRegisters(op1, regT0, op2, regT1);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT1);
-        addJump(branch32(LessThanOrEqual, regT0, regT1), target);
-    }
+    emitAllocateJSFinalObject(TrustedImmPtr(m_codeBlock->globalObject()->emptyObjectStructure()), regT0, regT1);
+    
+    emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
 }
 
-void JIT::emit_op_new_object(Instruction* currentInstruction)
+void JIT::emitSlow_op_new_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 {
+    linkSlowCase(iter);
     JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
 }
 
     JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
 }
 
@@ -397,7 +438,7 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction)
 
     // Check that prototype is an object
     loadPtr(Address(regT1, JSCell::structureOffset()), regT3);
 
     // Check that prototype is an object
     loadPtr(Address(regT1, JSCell::structureOffset()), regT3);
-    addSlowCase(branch8(NotEqual, Address(regT3, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)));
+    addSlowCase(emitJumpIfNotObject(regT3));
     
     // Fixme: this check is only needed because the JSC API allows HasInstance to be overridden; we should deprecate this.
     // Check that baseVal 'ImplementsDefaultHasInstance'.
     
     // Fixme: this check is only needed because the JSC API allows HasInstance to be overridden; we should deprecate this.
     // Check that baseVal 'ImplementsDefaultHasInstance'.
@@ -425,86 +466,87 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction)
     emitPutVirtualRegister(dst);
 }
 
     emitPutVirtualRegister(dst);
 }
 
-void JIT::emit_op_call(Instruction* currentInstruction)
+void JIT::emit_op_is_undefined(Instruction* currentInstruction)
 {
 {
-    compileOpCall(op_call, currentInstruction, m_callLinkInfoIndex++);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned value = currentInstruction[2].u.operand;
+    
+    emitGetVirtualRegister(value, regT0);
+    Jump isCell = emitJumpIfJSCell(regT0);
+
+    comparePtr(Equal, regT0, TrustedImm32(ValueUndefined), regT0);
+    Jump done = jump();
+    
+    isCell.link(this);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
+    test8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0);
+    
+    done.link(this);
+    emitTagAsBoolImmediate(regT0);
+    emitPutVirtualRegister(dst);
 }
 
 }
 
-void JIT::emit_op_call_eval(Instruction* currentInstruction)
+void JIT::emit_op_is_boolean(Instruction* currentInstruction)
 {
 {
-    compileOpCall(op_call_eval, currentInstruction, m_callLinkInfoIndex++);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned value = currentInstruction[2].u.operand;
+    
+    emitGetVirtualRegister(value, regT0);
+    xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), regT0);
+    testPtr(Zero, regT0, TrustedImm32(static_cast<int32_t>(~1)), regT0);
+    emitTagAsBoolImmediate(regT0);
+    emitPutVirtualRegister(dst);
 }
 
 }
 
-void JIT::emit_op_call_varargs(Instruction* currentInstruction)
+void JIT::emit_op_is_number(Instruction* currentInstruction)
 {
 {
-    compileOpCallVarargs(currentInstruction);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned value = currentInstruction[2].u.operand;
+    
+    emitGetVirtualRegister(value, regT0);
+    testPtr(NonZero, regT0, tagTypeNumberRegister, regT0);
+    emitTagAsBoolImmediate(regT0);
+    emitPutVirtualRegister(dst);
 }
 
 }
 
-void JIT::emit_op_construct(Instruction* currentInstruction)
+void JIT::emit_op_is_string(Instruction* currentInstruction)
 {
 {
-    compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned value = currentInstruction[2].u.operand;
+    
+    emitGetVirtualRegister(value, regT0);
+    Jump isNotCell = emitJumpIfNotJSCell(regT0);
+    
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
+    compare8(Equal, Address(regT1, Structure::typeInfoTypeOffset()), TrustedImm32(StringType), regT0);
+    emitTagAsBoolImmediate(regT0);
+    Jump done = jump();
+    
+    isNotCell.link(this);
+    move(TrustedImm32(ValueFalse), regT0);
+    
+    done.link(this);
+    emitPutVirtualRegister(dst);
 }
 
 }
 
-void JIT::emit_op_get_global_var(Instruction* currentInstruction)
+void JIT::emit_op_call(Instruction* currentInstruction)
 {
 {
-    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);
+    compileOpCall(op_call, currentInstruction, m_callLinkInfoIndex++);
 }
 
 }
 
-void JIT::emit_op_put_global_var(Instruction* currentInstruction)
+void JIT::emit_op_call_eval(Instruction* currentInstruction)
 {
 {
-    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)));
+    compileOpCall(op_call_eval, currentInstruction, m_callLinkInfoIndex);
 }
 
 }
 
-void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
+void JIT::emit_op_call_varargs(Instruction* currentInstruction)
 {
 {
-    int skip = currentInstruction[3].u.operand;
-
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0);
-    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
-    ASSERT(skip || !checkTopLevel);
-    if (checkTopLevel && skip--) {
-        Jump activationNotCreated;
-        if (checkTopLevel)
-            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
-        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
-        activationNotCreated.link(this);
-    }
-    while (skip--)
-        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
-
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT0);
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT0);
-    loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0);
-    emitPutVirtualRegister(currentInstruction[1].u.operand);
+    compileOpCall(op_call_varargs, currentInstruction, m_callLinkInfoIndex++);
 }
 
 }
 
-void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
+void JIT::emit_op_construct(Instruction* currentInstruction)
 {
 {
-    int skip = currentInstruction[2].u.operand;
-
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1);
-    emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);
-    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
-    ASSERT(skip || !checkTopLevel);
-    if (checkTopLevel && skip--) {
-        Jump activationNotCreated;
-        if (checkTopLevel)
-            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
-        loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1);
-        activationNotCreated.link(this);
-    }
-    while (skip--)
-        loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1);
-
-    loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1);
-    loadPtr(Address(regT1, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT1);
-    storePtr(regT0, Address(regT1, currentInstruction[1].u.operand * sizeof(Register)));
+    compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++);
 }
 
 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
@@ -534,6 +576,8 @@ void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction)
 
 void JIT::emit_op_ret(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_ret(Instruction* currentInstruction)
 {
+    emitOptimizationCheck(RetOptimizationCheck);
+    
     ASSERT(callFrameRegister != regT1);
     ASSERT(regT1 != returnValueRegister);
     ASSERT(returnValueRegister != callFrameRegister);
     ASSERT(callFrameRegister != regT1);
     ASSERT(regT1 != returnValueRegister);
     ASSERT(returnValueRegister != callFrameRegister);
@@ -554,6 +598,8 @@ void JIT::emit_op_ret(Instruction* currentInstruction)
 
 void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
 {
+    emitOptimizationCheck(RetOptimizationCheck);
+    
     ASSERT(callFrameRegister != regT1);
     ASSERT(regT1 != returnValueRegister);
     ASSERT(returnValueRegister != callFrameRegister);
     ASSERT(callFrameRegister != regT1);
     ASSERT(regT1 != returnValueRegister);
     ASSERT(returnValueRegister != callFrameRegister);
@@ -562,7 +608,7 @@ void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
     emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);
     Jump notJSCell = emitJumpIfNotJSCell(returnValueRegister);
     loadPtr(Address(returnValueRegister, JSCell::structureOffset()), regT2);
     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));
+    Jump notObject = emitJumpIfNotObject(regT2);
 
     // Grab the return address.
     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
 
     // Grab the return address.
     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
@@ -594,7 +640,7 @@ void JIT::emit_op_resolve(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
 {
     JITStubCall stubCall(this, cti_op_resolve);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
-    stubCall.call(currentInstruction[1].u.operand);
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_to_primitive(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_to_primitive(Instruction* currentInstruction)
@@ -605,7 +651,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), TrustedImmPtr(m_globalData->jsStringVPtr)));
+    addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
     isImm.link(this);
 
     if (dst != src)
     isImm.link(this);
 
     if (dst != src)
@@ -616,8 +662,8 @@ void JIT::emit_op_to_primitive(Instruction* currentInstruction)
 void JIT::emit_op_strcat(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_strcat);
 void JIT::emit_op_strcat(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_strcat);
-    stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
-    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -625,13 +671,13 @@ void JIT::emit_op_resolve_base(Instruction* currentInstruction)
 {
     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)));
 {
     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);
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_ensure_property_exists);
 }
 
 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(TrustedImm32(currentInstruction[1].u.operand));
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
@@ -640,8 +686,8 @@ void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_skip);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
 {
     JITStubCall stubCall(this, cti_op_resolve_skip);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
-    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
-    stubCall.call(currentInstruction[1].u.operand);
+    stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand));
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool)
 }
 
 void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool)
@@ -662,6 +708,7 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool)
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_propertyStorage)), regT0);
     load32(Address(regT2, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), regT1);
     loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0);
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_propertyStorage)), regT0);
     load32(Address(regT2, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), regT1);
     loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0);
+    emitValueProfilingSite();
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
@@ -675,9 +722,9 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<Slo
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_resolve_global);
     stubCall.addArgument(TrustedImmPtr(ident));
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_resolve_global);
     stubCall.addArgument(TrustedImmPtr(ident));
-    stubCall.addArgument(Imm32(currentIndex));
+    stubCall.addArgument(TrustedImm32(currentIndex));
     stubCall.addArgument(regT0);
     stubCall.addArgument(regT0);
-    stubCall.call(dst);
+    stubCall.callWithValueProfiling(dst);
 }
 
 void JIT::emit_op_not(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_not(Instruction* currentInstruction)
@@ -759,22 +806,6 @@ void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
     addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue(ptr)))), target);            
 }
 
     addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue(ptr)))), target);            
 }
 
-void JIT::emit_op_jsr(Instruction* currentInstruction)
-{
-    int retAddrDst = currentInstruction[1].u.operand;
-    int target = currentInstruction[2].u.operand;
-    DataLabelPtr storeLocation = storePtrWithPatch(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
-    addJump(jump(), target);
-    m_jsrSites.append(JSRInfo(storeLocation, label()));
-    killLastResultRegister();
-}
-
-void JIT::emit_op_sret(Instruction* currentInstruction)
-{
-    jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand));
-    killLastResultRegister();
-}
-
 void JIT::emit_op_eq(Instruction* currentInstruction)
 {
     emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
 void JIT::emit_op_eq(Instruction* currentInstruction)
 {
     emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
@@ -784,28 +815,20 @@ void JIT::emit_op_eq(Instruction* currentInstruction)
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
-void JIT::emit_op_bitnot(Instruction* currentInstruction)
-{
-    emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
-    emitJumpSlowCaseIfNotImmediateInteger(regT0);
-    not32(regT0);
-    emitFastArithIntToImmNoCheck(regT0, regT0);
-    emitPutVirtualRegister(currentInstruction[1].u.operand);
-}
-
 void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_with_base);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
 void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_with_base);
     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(TrustedImm32(currentInstruction[1].u.operand));
+    stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
 }
 
 }
 
-void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
+void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
 {
 {
-    JITStubCall stubCall(this, cti_op_new_func_exp);
-    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
-    stubCall.call(currentInstruction[1].u.operand);
+    JITStubCall stubCall(this, cti_op_resolve_with_this);
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
+    stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand));
+    stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
 }
 
 void JIT::emit_op_jtrue(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_jtrue(Instruction* currentInstruction)
@@ -878,7 +901,7 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction)
         isNotObject.append(emitJumpIfNotJSCell(regT0));
     if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) {
         loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
         isNotObject.append(emitJumpIfNotJSCell(regT0));
     if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) {
         loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
-        isNotObject.append(branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)));
+        isNotObject.append(emitJumpIfNotObject(regT2));
     }
 
     // We could inline the case where you have a valid cache, but
     }
 
     // We could inline the case where you have a valid cache, but
@@ -991,17 +1014,25 @@ void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqTy
     unsigned src2 = currentInstruction[3].u.operand;
 
     emitGetVirtualRegisters(src1, regT0, src2, regT1);
     unsigned src2 = currentInstruction[3].u.operand;
 
     emitGetVirtualRegisters(src1, regT0, src2, regT1);
-
-    // Jump to a slow case if either operand is a number, or if both are JSCell*s.
+    
+    // Jump slow if both are cells (to cover strings).
     move(regT0, regT2);
     orPtr(regT1, regT2);
     addSlowCase(emitJumpIfJSCell(regT2));
     move(regT0, regT2);
     orPtr(regT1, regT2);
     addSlowCase(emitJumpIfJSCell(regT2));
-    addSlowCase(emitJumpIfImmediateNumber(regT2));
+    
+    // Jump slow if either is a double. First test if it's an integer, which is fine, and then test
+    // if it's a double.
+    Jump leftOK = emitJumpIfImmediateInteger(regT0);
+    addSlowCase(emitJumpIfImmediateNumber(regT0));
+    leftOK.link(this);
+    Jump rightOK = emitJumpIfImmediateInteger(regT1);
+    addSlowCase(emitJumpIfImmediateNumber(regT1));
+    rightOK.link(this);
 
     if (type == OpStrictEq)
 
     if (type == OpStrictEq)
-        compare32(Equal, regT1, regT0, regT0);
+        comparePtr(Equal, regT1, regT0, regT0);
     else
     else
-        compare32(NotEqual, regT1, regT0, regT0);
+        comparePtr(NotEqual, regT1, regT0, regT0);
     emitTagAsBoolImmediate(regT0);
 
     emitPutVirtualRegister(dst);
     emitTagAsBoolImmediate(regT0);
 
     emitPutVirtualRegister(dst);
@@ -1054,7 +1085,7 @@ void JIT::emit_op_catch(Instruction* currentInstruction)
 void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_jmp_scopes);
 void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_jmp_scopes);
-    stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand));
     stubCall.call();
     addJump(jump(), currentInstruction[2].u.operand);
 }
     stubCall.call();
     addJump(jump(), currentInstruction[2].u.operand);
 }
@@ -1072,7 +1103,7 @@ void JIT::emit_op_switch_imm(Instruction* currentInstruction)
 
     JITStubCall stubCall(this, cti_op_switch_imm);
     stubCall.addArgument(scrutinee, regT2);
 
     JITStubCall stubCall(this, cti_op_switch_imm);
     stubCall.addArgument(scrutinee, regT2);
-    stubCall.addArgument(Imm32(tableIndex));
+    stubCall.addArgument(TrustedImm32(tableIndex));
     stubCall.call();
     jump(regT0);
 }
     stubCall.call();
     jump(regT0);
 }
@@ -1090,7 +1121,7 @@ void JIT::emit_op_switch_char(Instruction* currentInstruction)
 
     JITStubCall stubCall(this, cti_op_switch_char);
     stubCall.addArgument(scrutinee, regT2);
 
     JITStubCall stubCall(this, cti_op_switch_char);
     stubCall.addArgument(scrutinee, regT2);
-    stubCall.addArgument(Imm32(tableIndex));
+    stubCall.addArgument(TrustedImm32(tableIndex));
     stubCall.call();
     jump(regT0);
 }
     stubCall.call();
     jump(regT0);
 }
@@ -1107,7 +1138,7 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction)
 
     JITStubCall stubCall(this, cti_op_switch_string);
     stubCall.addArgument(scrutinee, regT2);
 
     JITStubCall stubCall(this, cti_op_switch_string);
     stubCall.addArgument(scrutinee, regT2);
-    stubCall.addArgument(Imm32(tableIndex));
+    stubCall.addArgument(TrustedImm32(tableIndex));
     stubCall.call();
     jump(regT0);
 }
     stubCall.call();
     jump(regT0);
 }
@@ -1115,7 +1146,10 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction)
 void JIT::emit_op_throw_reference_error(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_throw_reference_error);
 void JIT::emit_op_throw_reference_error(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_throw_reference_error);
-    stubCall.addArgument(ImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[1].u.operand))));
+    if (!m_codeBlock->getConstant(currentInstruction[1].u.operand).isNumber())
+        stubCall.addArgument(TrustedImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[1].u.operand))));
+    else
+        stubCall.addArgument(ImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[1].u.operand))));
     stubCall.call();
 }
 
     stubCall.call();
 }
 
@@ -1126,9 +1160,9 @@ void JIT::emit_op_debug(Instruction* currentInstruction)
     breakpoint();
 #else
     JITStubCall stubCall(this, cti_op_debug);
     breakpoint();
 #else
     JITStubCall stubCall(this, cti_op_debug);
-    stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
-    stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
-    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand));
     stubCall.call();
 #endif
 }
     stubCall.call();
 #endif
 }
@@ -1208,10 +1242,7 @@ void JIT::emit_op_create_arguments(Instruction* currentInstruction)
     unsigned dst = currentInstruction[1].u.operand;
 
     Jump argsCreated = branchTestPtr(NonZero, Address(callFrameRegister, sizeof(Register) * dst));
     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();
+    JITStubCall(this, cti_op_create_arguments).call();
     emitPutVirtualRegister(dst);
     emitPutVirtualRegister(unmodifiedArgumentsRegister(dst));
     argsCreated.link(this);
     emitPutVirtualRegister(dst);
     emitPutVirtualRegister(unmodifiedArgumentsRegister(dst));
     argsCreated.link(this);
@@ -1229,25 +1260,7 @@ 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, 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);
+    addSlowCase(branchPtr(Equal, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
 }
 
 void JIT::emit_op_get_callee(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_get_callee(Instruction* currentInstruction)
@@ -1259,6 +1272,31 @@ void JIT::emit_op_get_callee(Instruction* currentInstruction)
 
 void JIT::emit_op_create_this(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_create_this(Instruction* currentInstruction)
 {
+    emitGetVirtualRegister(currentInstruction[2].u.operand, regT2);
+    emitJumpSlowCaseIfNotJSCell(regT2, currentInstruction[2].u.operand);
+    loadPtr(Address(regT2, JSCell::structureOffset()), regT1);
+    addSlowCase(emitJumpIfNotObject(regT1));
+    
+    // now we know that the prototype is an object, but we don't know if it's got an
+    // inheritor ID
+    
+    loadPtr(Address(regT2, JSObject::offsetOfInheritorID()), regT2);
+    addSlowCase(branchTestPtr(Zero, regT2));
+    
+    // now regT2 contains the inheritorID, which is the structure that the newly
+    // allocated object will have.
+    
+    emitAllocateJSFinalObject(regT2, regT0, regT1);
+    
+    emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand); // not a cell
+    linkSlowCase(iter); // not an object
+    linkSlowCase(iter); // doesn't have an inheritor ID
+    linkSlowCase(iter); // allocation failed
     JITStubCall stubCall(this, cti_op_create_this);
     stubCall.addArgument(currentInstruction[2].u.operand, regT1);
     stubCall.call(currentInstruction[1].u.operand);
     JITStubCall stubCall(this, cti_op_create_this);
     stubCall.addArgument(currentInstruction[2].u.operand, regT1);
     stubCall.call(currentInstruction[1].u.operand);
@@ -1292,17 +1330,17 @@ void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
 
 void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 
 void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
+    void* globalThis = m_codeBlock->globalObject()->globalScopeChain()->globalThis.get();
+
     linkSlowCase(iter);
     linkSlowCase(iter);
-    linkSlowCase(iter);
-    JITStubCall stubCall(this, cti_op_convert_this);
-    stubCall.addArgument(regT0);
-    stubCall.call(currentInstruction[1].u.operand);
-}
+    Jump isNotUndefined = branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsUndefined())));
+    move(TrustedImmPtr(globalThis), regT0);
+    emitPutVirtualRegister(currentInstruction[1].u.operand, regT0);
+    emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_convert_this));
 
 
-void JIT::emitSlow_op_convert_this_strict(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
+    isNotUndefined.link(this);
     linkSlowCase(iter);
     linkSlowCase(iter);
-    JITStubCall stubCall(this, cti_op_convert_this_strict);
+    JITStubCall stubCall(this, cti_op_convert_this);
     stubCall.addArgument(regT0);
     stubCall.call(currentInstruction[1].u.operand);
 }
     stubCall.addArgument(regT0);
     stubCall.call(currentInstruction[1].u.operand);
 }
@@ -1316,46 +1354,6 @@ void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowC
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
-void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-    if (isOperandConstantImmediateInt(op2)) {
-        linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_loop_if_lesseq);
-        stubCall.addArgument(regT0);
-        stubCall.addArgument(currentInstruction[2].u.operand, regT2);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
-    } else {
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        JITStubCall stubCall(this, cti_op_loop_if_lesseq);
-        stubCall.addArgument(regT0);
-        stubCall.addArgument(regT1);
-        stubCall.call();
-        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
-    }
-}
-
-void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned base = currentInstruction[1].u.operand;
-    unsigned property = currentInstruction[2].u.operand;
-    unsigned value = currentInstruction[3].u.operand;
-
-    linkSlowCase(iter); // property int32 check
-    linkSlowCaseIfNotJSCell(iter, base); // base cell check
-    linkSlowCase(iter); // base not array check
-    linkSlowCase(iter); // in vector check
-
-    JITStubCall stubPutByValCall(this, cti_op_put_by_val);
-    stubPutByValCall.addArgument(regT0);
-    stubPutByValCall.addArgument(property, regT2);
-    stubPutByValCall.addArgument(value, regT2);
-    stubPutByValCall.call();
-}
-
 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);
@@ -1374,14 +1372,6 @@ void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEnt
     emitJumpSlowToHot(branchTest32(Zero, regT0), currentInstruction[2].u.operand); // inverted!
 }
 
     emitJumpSlowToHot(branchTest32(Zero, regT0), currentInstruction[2].u.operand); // inverted!
 }
 
-void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    linkSlowCase(iter);
-    JITStubCall stubCall(this, cti_op_bitnot);
-    stubCall.addArgument(regT0);
-    stubCall.call(currentInstruction[1].u.operand);
-}
-
 void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     linkSlowCase(iter);
 void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     linkSlowCase(iter);
@@ -1434,6 +1424,7 @@ void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry>
 
 void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 
 void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
+    linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_stricteq);
     linkSlowCase(iter);
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_stricteq);
@@ -1444,6 +1435,7 @@ void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseE
 
 void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 
 void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
+    linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_nstricteq);
     linkSlowCase(iter);
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_nstricteq);
@@ -1483,22 +1475,22 @@ void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCas
 
 void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 
 void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call);
+    compileOpCallSlowCase(op_call, currentInstruction, iter, m_callLinkInfoIndex++);
 }
 
 void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 }
 
 void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call_eval);
+    compileOpCallSlowCase(op_call_eval, currentInstruction, iter, m_callLinkInfoIndex);
 }
 }
-
 void JIT::emitSlow_op_call_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 void JIT::emitSlow_op_call_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-    compileOpCallVarargsSlowCase(currentInstruction, iter);
+    compileOpCallSlowCase(op_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
 }
 
 void JIT::emitSlow_op_construct(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 }
 
 void JIT::emitSlow_op_construct(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_construct);
+    compileOpCallSlowCase(op_construct, currentInstruction, iter, m_callLinkInfoIndex++);
 }
 
 void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -1548,23 +1540,10 @@ void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction)
     // regT1 now contains the integer index of the argument we want, including this
     emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT2);
     addSlowCase(branch32(AboveOrEqual, regT1, regT2));
     // 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);
+
+    neg32(regT1);
+    signExtend32ToPtr(regT1, regT1);
+    loadPtr(BaseIndex(callFrameRegister, regT1, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT0);
     emitPutVirtualRegister(dst, regT0);
 }
 
     emitPutVirtualRegister(dst, regT0);
 }
 
@@ -1579,10 +1558,7 @@ void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vecto
     
     linkSlowCase(iter);
     linkSlowCase(iter);
     
     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();
+    JITStubCall(this, cti_op_create_arguments).call();
     emitPutVirtualRegister(arguments);
     emitPutVirtualRegister(unmodifiedArgumentsRegister(arguments));
     
     emitPutVirtualRegister(arguments);
     emitPutVirtualRegister(unmodifiedArgumentsRegister(arguments));
     
@@ -1637,9 +1613,9 @@ void JIT::emitSlow_op_resolve_global_dynamic(Instruction* currentInstruction, Ve
     linkSlowCase(iter); // We managed to skip all the nodes in the scope chain, but the cache missed.
     JITStubCall stubCall(this, cti_op_resolve_global);
     stubCall.addArgument(TrustedImmPtr(ident));
     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(TrustedImmPtr(ident));
-    stubCall.addArgument(Imm32(currentIndex));
+    stubCall.addArgument(TrustedImm32(currentIndex));
     stubCall.addArgument(regT0);
     stubCall.addArgument(regT0);
-    stubCall.call(dst);
+    stubCall.callWithValueProfiling(dst);
 }
 
 void JIT::emit_op_new_regexp(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_new_regexp(Instruction* currentInstruction)
@@ -1649,107 +1625,110 @@ void JIT::emit_op_new_regexp(Instruction* currentInstruction)
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
-void JIT::emit_op_load_varargs(Instruction* currentInstruction)
+void JIT::emit_op_new_func(Instruction* currentInstruction)
 {
 {
-    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;
-    }
-
+    Jump lazyJump;
+    int dst = currentInstruction[1].u.operand;
+    if (currentInstruction[3].u.operand) {
 #if USE(JSVALUE32_64)
 #if USE(JSVALUE32_64)
-    addSlowCase(branch32(NotEqual, tagFor(argsOffset), TrustedImm32(JSValue::EmptyValueTag)));
+        lazyJump = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag));
 #else
 #else
-    addSlowCase(branchTestPtr(NonZero, addressFor(argsOffset)));
+        lazyJump = branchTestPtr(NonZero, addressFor(dst));
 #endif
 #endif
-    // 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
-    
-    // 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))));
+    FunctionExecutable* executable = m_codeBlock->functionDecl(currentInstruction[2].u.operand);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+    emitAllocateJSFunction(executable, regT2, regT0, regT1);
+
+    emitStoreCell(dst, regT0);
+
+    if (currentInstruction[3].u.operand) {
+#if USE(JSVALUE32_64)        
+        unmap();
+#else
+        killLastResultRegister();
 #endif
 #endif
-    branchSubPtr(NonZero, TrustedImm32(1), regT0).linkTo(loopStart, this);
-    endBranch.link(this);
+        lazyJump.link(this);
+    }
 }
 
 }
 
-void JIT::emitSlow_op_load_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+void JIT::emitSlow_op_new_func(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;
-    
-    linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
-    JITStubCall stubCall(this, cti_op_load_varargs);
-    stubCall.addArgument(Imm32(argsOffset));
-    stubCall.call();
-    
-    store32(TrustedImm32(Int32Tag), intTagFor(argCountDst));
-    store32(returnValueRegister, intPayloadFor(argCountDst));
+    JITStubCall stubCall(this, cti_op_new_func);
+    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
+    stubCall.call(currentInstruction[1].u.operand);
 }
 
 }
 
-void JIT::emit_op_new_func(Instruction* currentInstruction)
+void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
 {
 {
-    Jump lazyJump;
-    int dst = currentInstruction[1].u.operand;
-    if (currentInstruction[3].u.operand) {
-#if USE(JSVALUE32_64)
-        lazyJump = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag));
-#else
-        lazyJump = branchTestPtr(NonZero, addressFor(dst));
-#endif
+    FunctionExecutable* executable = m_codeBlock->functionExpr(currentInstruction[2].u.operand);
+
+    // We only inline the allocation of a anonymous function expressions
+    // If we want to be able to allocate a named function expression, we would
+    // need to be able to do inline allocation of a JSStaticScopeObject.
+    if (executable->name().isNull()) {
+        emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+        emitAllocateJSFunction(executable, regT2, regT0, regT1);
+        emitStoreCell(currentInstruction[1].u.operand, regT0);
+        return;
     }
     }
-    JITStubCall stubCall(this, cti_op_new_func);
-    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
+
+    JITStubCall stubCall(this, cti_op_new_func_exp);
+    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
+    stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emitSlow_op_new_func_exp(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    FunctionExecutable* executable = m_codeBlock->functionExpr(currentInstruction[2].u.operand);
+    if (!executable->name().isNull())
+        return;
+    linkSlowCase(iter);
+    JITStubCall stubCall(this, cti_op_new_func_exp);
+    stubCall.addArgument(TrustedImmPtr(executable));
     stubCall.call(currentInstruction[1].u.operand);
     stubCall.call(currentInstruction[1].u.operand);
-    if (currentInstruction[3].u.operand)
-        lazyJump.link(this);
 }
 
 void JIT::emit_op_new_array(Instruction* currentInstruction)
 {
 }
 
 void JIT::emit_op_new_array(Instruction* currentInstruction)
 {
+    int length = currentInstruction[3].u.operand;
+    if (CopiedSpace::isOversize(JSArray::storageSize(length))) {
+        JITStubCall stubCall(this, cti_op_new_array);
+        stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand));
+        stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand));
+        stubCall.call(currentInstruction[1].u.operand);
+        return;
+    }
+    int dst = currentInstruction[1].u.operand;
+    int values = currentInstruction[2].u.operand;
+
+    emitAllocateJSArray(values, length, regT0, regT1, regT2);
+    emitStoreCell(dst, regT0); 
+}
+
+void JIT::emitSlow_op_new_array(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    // If the allocation would be oversize, we will already make the proper stub call above in 
+    // emit_op_new_array.
+    int length = currentInstruction[3].u.operand;
+    if (CopiedSpace::isOversize(JSArray::storageSize(length)))
+        return;
+    linkSlowCase(iter); // Not enough space in CopiedSpace for storage.
+    linkSlowCase(iter); // Not enough space in MarkedSpace for cell.
+
     JITStubCall stubCall(this, cti_op_new_array);
     JITStubCall stubCall(this, cti_op_new_array);
-    stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
-    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand));
+    stubCall.addArgument(TrustedImm32(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.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.addArgument(TrustedImm32(currentInstruction[2].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
index 4f4c5c0b186f7149e96a9368034a7fcab7f29803..76e11e48cb25eaf1369dcf18c63190ba35a45b08 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, TrampolineStructure *trampolines)
+PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGlobalData* globalData, TrampolineStructure *trampolines)
 {
 {
-#if ENABLE(JIT_USE_SOFT_MODULO)
-    Label softModBegin = align();
-    softModulo();
-#endif
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
     // (1) This function provides fast property access for string length
     Label stringLengthBegin = align();
 
     // regT0 holds payload, regT1 holds tag
 
     Jump string_failureCases1 = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
     // (1) This function provides fast property access for string length
     Label stringLengthBegin = align();
 
     // regT0 holds payload, regT1 holds tag
 
     Jump string_failureCases1 = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
-    Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr));
+    Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info));
 
     // 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);
@@ -63,135 +58,167 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     move(TrustedImm32(JSValue::Int32Tag), regT1);
 
     ret();
     move(TrustedImm32(JSValue::Int32Tag), regT1);
 
     ret();
-#endif
     
     
-    JumpList callLinkFailures;
-    // (2) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
-#if ENABLE(JIT_OPTIMIZE_CALL)
+    JumpList callSlowCase;
+    JumpList constructSlowCase;
+
     // VirtualCallLink Trampoline
     // VirtualCallLink Trampoline
-    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    // regT1, regT0 holds callee; callFrame is moved and partially initialized.
     Label virtualCallLinkBegin = align();
     Label virtualCallLinkBegin = align();
-    compileOpCallInitializeCallFrame();
+    callSlowCase.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+    callSlowCase.append(emitJumpIfNotType(regT0, regT1, JSFunctionType));
+
+    // Finish canonical initialization before JS function call.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+    // Also initialize ReturnPC for use by lazy linking and exceptions.
     preserveReturnAddressAfterCall(regT3);
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     preserveReturnAddressAfterCall(regT3);
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+    
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
     restoreArgumentReference();
     Call callLazyLinkCall = call();
     restoreArgumentReference();
     Call callLazyLinkCall = call();
-    callLinkFailures.append(branchTestPtr(Zero, regT0));
     restoreReturnAddressBeforeReturn(regT3);
     restoreReturnAddressBeforeReturn(regT3);
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
     jump(regT0);
 
     // VirtualConstructLink Trampoline
     jump(regT0);
 
     // VirtualConstructLink Trampoline
-    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    // regT1, regT0 holds callee; callFrame is moved and partially initialized.
     Label virtualConstructLinkBegin = align();
     Label virtualConstructLinkBegin = align();
-    compileOpCallInitializeCallFrame();
+    constructSlowCase.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+    constructSlowCase.append(emitJumpIfNotType(regT0, regT1, JSFunctionType));
+
+    // Finish canonical initialization before JS function call.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+    // Also initialize ReturnPC for use by lazy linking and exeptions.
     preserveReturnAddressAfterCall(regT3);
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     preserveReturnAddressAfterCall(regT3);
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+    
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
     restoreArgumentReference();
     Call callLazyLinkConstruct = call();
     restoreReturnAddressBeforeReturn(regT3);
     restoreArgumentReference();
     Call callLazyLinkConstruct = call();
     restoreReturnAddressBeforeReturn(regT3);
-    callLinkFailures.append(branchTestPtr(Zero, regT0));
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
     jump(regT0);
 
     jump(regT0);
 
-#endif // ENABLE(JIT_OPTIMIZE_CALL)
-
     // VirtualCall Trampoline
     // VirtualCall Trampoline
-    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    // regT1, regT0 holds callee; regT2 will hold the FunctionExecutable.
     Label virtualCallBegin = align();
     Label virtualCallBegin = align();
-    compileOpCallInitializeCallFrame();
+    callSlowCase.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+    callSlowCase.append(emitJumpIfNotType(regT0, regT1, JSFunctionType));
 
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    // Finish canonical initialization before JS function call.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
 
-    Jump hasCodeBlock3 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0));
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    Jump hasCodeBlock1 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0));
     preserveReturnAddressAfterCall(regT3);
     preserveReturnAddressAfterCall(regT3);
+    
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
     restoreArgumentReference();
     Call callCompileCall = call();
     restoreArgumentReference();
     Call callCompileCall = 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);
-    hasCodeBlock3.link(this);
 
 
+    hasCodeBlock1.link(this);
     loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForCallWithArityCheck)), regT0);
     jump(regT0);
 
     // VirtualConstruct Trampoline
     loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForCallWithArityCheck)), regT0);
     jump(regT0);
 
     // VirtualConstruct Trampoline
-    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    // regT1, regT0 holds callee; regT2 will hold the FunctionExecutable.
     Label virtualConstructBegin = align();
     Label virtualConstructBegin = align();
-    compileOpCallInitializeCallFrame();
+    constructSlowCase.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+    constructSlowCase.append(emitJumpIfNotType(regT0, regT1, JSFunctionType));
 
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    // Finish canonical initialization before JS function call.
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
 
-    Jump hasCodeBlock4 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0));
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    Jump hasCodeBlock2 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0));
     preserveReturnAddressAfterCall(regT3);
     preserveReturnAddressAfterCall(regT3);
+    
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
     restoreArgumentReference();
     restoreArgumentReference();
-    Call callCompileCconstruct = call();
-    callLinkFailures.append(branchTestPtr(Zero, regT0));
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
+    Call callCompileConstruct = call();
     restoreReturnAddressBeforeReturn(regT3);
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
     restoreReturnAddressBeforeReturn(regT3);
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
-    hasCodeBlock4.link(this);
 
 
+    hasCodeBlock2.link(this);
     loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForConstructWithArityCheck)), regT0);
     jump(regT0);
     loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForConstructWithArityCheck)), regT0);
     jump(regT0);
-    
-    // If the parser fails we want to be able to be able to keep going,
-    // So we handle this as a parse failure.
-    callLinkFailures.link(this);
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+
+    callSlowCase.link(this);
+    // Finish canonical initialization before JS function call.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2, regT2);
+    emitPutCellToCallFrameHeader(regT2, RegisterFile::ScopeChain);
+
+    // Also initialize ReturnPC and CodeBlock, like a JS function would.
+    preserveReturnAddressAfterCall(regT3);
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+    emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
+
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
+    restoreArgumentReference();
+    Call callCallNotJSFunction = call();
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
     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()));
+    restoreReturnAddressBeforeReturn(regT3);
+    ret();
+
+    constructSlowCase.link(this);
+    // Finish canonical initialization before JS function call.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2, regT2);
+    emitPutCellToCallFrameHeader(regT2, RegisterFile::ScopeChain);
+
+    // Also initialize ReturnPC and CodeBlock, like a JS function would.
+    preserveReturnAddressAfterCall(regT3);
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+    emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
+
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
+    restoreArgumentReference();
+    Call callConstructNotJSFunction = call();
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+    restoreReturnAddressBeforeReturn(regT3);
     ret();
 
     // NativeCall Trampoline
     Label nativeCallThunk = privateCompileCTINativeCall(globalData);    
     Label nativeConstructThunk = privateCompileCTINativeCall(globalData, true);    
 
     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);
     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.
 
     // 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);
+    LinkBuffer patchBuffer(*m_globalData, this, GLOBAL_THUNK_ID);
 
 
-#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));
     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));
     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(callCompileCall, FunctionPtr(cti_op_call_jitCompile));
-    patchBuffer.link(callCompileCconstruct, FunctionPtr(cti_op_construct_jitCompile));
+    patchBuffer.link(callCompileConstruct, FunctionPtr(cti_op_construct_jitCompile));
+    patchBuffer.link(callCallNotJSFunction, FunctionPtr(cti_op_call_NotJSFunction));
+    patchBuffer.link(callConstructNotJSFunction, FunctionPtr(cti_op_construct_NotJSConstruct));
 
     CodeRef finalCode = patchBuffer.finalizeCode();
 
     CodeRef finalCode = patchBuffer.finalizeCode();
-    *executablePool = finalCode.m_executablePool;
+    RefPtr<ExecutableMemoryHandle> executableMemory = finalCode.executableMemory();
 
 
+    trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
+    trampolines->ctiVirtualConstructLink = patchBuffer.trampolineAt(virtualConstructLinkBegin);
     trampolines->ctiVirtualCall = patchBuffer.trampolineAt(virtualCallBegin);
     trampolines->ctiVirtualConstruct = patchBuffer.trampolineAt(virtualConstructBegin);
     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);
     trampolines->ctiNativeCall = patchBuffer.trampolineAt(nativeCallThunk);
     trampolines->ctiNativeConstruct = patchBuffer.trampolineAt(nativeConstructThunk);
-#endif
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
     trampolines->ctiStringLengthTrampoline = patchBuffer.trampolineAt(stringLengthBegin);
     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
+
+    return executableMemory.release();
 }
 
 JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isConstruct)
 }
 
 JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isConstruct)
@@ -201,6 +228,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
     Label nativeCallThunk = align();
 
     emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
     Label nativeCallThunk = align();
 
     emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
 
 #if CPU(X86)
     // Load caller frame's scope chain into this callframe so that whatever we call can
 
 #if CPU(X86)
     // Load caller frame's scope chain into this callframe so that whatever we call can
@@ -252,7 +280,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
     // get to its global data.
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
     // get to its global data.
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
-    emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
     preserveReturnAddressAfterCall(regT3); // Callee preserved
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
 
     preserveReturnAddressAfterCall(regT3); // Callee preserved
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
@@ -298,9 +326,8 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
 
     restoreReturnAddressBeforeReturn(regT3);
 
 
     restoreReturnAddressBeforeReturn(regT3);
 
-#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
-#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
 #else
 #else
+#error "JIT not supported on this platform."
     UNUSED_PARAM(executableOffsetToFunction);
     breakpoint();
 #endif // CPU(X86)
     UNUSED_PARAM(executableOffsetToFunction);
     breakpoint();
 #endif // CPU(X86)
@@ -320,7 +347,8 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
     move(TrustedImmPtr(&globalData->exceptionLocation), regT2);
     storePtr(regT1, regT2);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
     move(TrustedImmPtr(&globalData->exceptionLocation), regT2);
     storePtr(regT1, regT2);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
-
+    
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
     // Set the return address.
     move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
     restoreReturnAddressBeforeReturn(regT1);
     // Set the return address.
     move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
     restoreReturnAddressBeforeReturn(regT1);
@@ -330,12 +358,12 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
     return nativeCallThunk;
 }
 
     return nativeCallThunk;
 }
 
-JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executablePool, JSGlobalData* globalData, NativeFunction func)
+JIT::CodeRef JIT::privateCompileCTINativeCall(JSGlobalData* globalData, NativeFunction func)
 {
     Call nativeCall;
 {
     Call nativeCall;
-    Label nativeCallThunk = align();
 
     emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
 
     emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
 
 #if CPU(X86)
     // Load caller frame's scope chain into this callframe so that whatever we call can
 
 #if CPU(X86)
     // Load caller frame's scope chain into this callframe so that whatever we call can
@@ -420,7 +448,7 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa
     // get to its global data.
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
     // get to its global data.
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
-    emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
     preserveReturnAddressAfterCall(regT3); // Callee preserved
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
 
     preserveReturnAddressAfterCall(regT3); // Callee preserved
     emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
@@ -437,9 +465,8 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa
     nativeCall = call();
 
     restoreReturnAddressBeforeReturn(regT3);
     nativeCall = call();
 
     restoreReturnAddressBeforeReturn(regT3);
-#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
-#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
 #else
 #else
+#error "JIT not supported on this platform."
     breakpoint();
 #endif // CPU(X86)
 
     breakpoint();
 #endif // CPU(X86)
 
@@ -458,7 +485,8 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa
     move(TrustedImmPtr(&globalData->exceptionLocation), regT2);
     storePtr(regT1, regT2);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
     move(TrustedImmPtr(&globalData->exceptionLocation), regT2);
     storePtr(regT1, regT2);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
-
+    
+    storePtr(callFrameRegister, &m_globalData->topCallFrame);
     // Set the return address.
     move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
     restoreReturnAddressBeforeReturn(regT1);
     // Set the return address.
     move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
     restoreReturnAddressBeforeReturn(regT1);
@@ -466,12 +494,10 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa
     ret();
 
     // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
     ret();
 
     // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
-    LinkBuffer patchBuffer(*m_globalData, this, executablePool);
+    LinkBuffer patchBuffer(*m_globalData, this, GLOBAL_THUNK_ID);
 
     patchBuffer.link(nativeCall, FunctionPtr(func));
 
     patchBuffer.link(nativeCall, FunctionPtr(func));
-    patchBuffer.finalizeCode();
-
-    return patchBuffer.trampolineAt(nativeCallThunk);
+    return patchBuffer.finalizeCode();
 }
 
 void JIT::emit_op_mov(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_mov(Instruction* currentInstruction)
@@ -502,53 +528,16 @@ void JIT::emit_op_jmp(Instruction* currentInstruction)
     addJump(jump(), target);
 }
 
     addJump(jump(), target);
 }
 
-void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
-{
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
-    emitTimeoutCheck();
-
-    if (isOperandConstantImmediateInt(op1)) {
-        emitLoad(op2, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op1).asInt32())), target);
-        return;
-    }
-
-    if (isOperandConstantImmediateInt(op2)) {
-        emitLoad(op1, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-        addJump(branch32(LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
-        return;
-    }
-
-    emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
-    addJump(branch32(LessThanOrEqual, regT0, regT2), target);
-}
-
-void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+void JIT::emit_op_new_object(Instruction* currentInstruction)
 {
 {
-    unsigned op1 = currentInstruction[1].u.operand;
-    unsigned op2 = currentInstruction[2].u.operand;
-    unsigned target = currentInstruction[3].u.operand;
-
-    if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
-        linkSlowCase(iter); // int32 check
-    linkSlowCase(iter); // int32 check
-
-    JITStubCall stubCall(this, cti_op_loop_if_lesseq);
-    stubCall.addArgument(op1);
-    stubCall.addArgument(op2);
-    stubCall.call();
-    emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
+    emitAllocateJSFinalObject(TrustedImmPtr(m_codeBlock->globalObject()->emptyObjectStructure()), regT0, regT1);
+    
+    emitStoreCell(currentInstruction[1].u.operand, regT0);
 }
 
 }
 
-void JIT::emit_op_new_object(Instruction* currentInstruction)
+void JIT::emitSlow_op_new_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 {
+    linkSlowCase(iter);
     JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
 }
 
     JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
 }
 
@@ -585,7 +574,7 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction)
     
     // Check that prototype is an object
     loadPtr(Address(regT1, JSCell::structureOffset()), regT3);
     
     // Check that prototype is an object
     loadPtr(Address(regT1, JSCell::structureOffset()), regT3);
-    addSlowCase(branch8(NotEqual, Address(regT3, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)));
+    addSlowCase(emitJumpIfNotObject(regT3));
 
     // Fixme: this check is only needed because the JSC API allows HasInstance to be overridden; we should deprecate this.
     // Check that baseVal 'ImplementsDefaultHasInstance'.
 
     // Fixme: this check is only needed because the JSC API allows HasInstance to be overridden; we should deprecate this.
     // Check that baseVal 'ImplementsDefaultHasInstance'.
@@ -644,87 +633,63 @@ void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCas
     stubCall.call(dst);
 }
 
     stubCall.call(dst);
 }
 
-void JIT::emit_op_get_global_var(Instruction* currentInstruction)
+void JIT::emit_op_is_undefined(Instruction* currentInstruction)
 {
 {
-    int dst = currentInstruction[1].u.operand;
-    JSGlobalObject* globalObject = m_codeBlock->globalObject();
-    ASSERT(globalObject->isGlobalObject());
-    int index = currentInstruction[2].u.operand;
-
-    loadPtr(&globalObject->m_registers, regT2);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned value = currentInstruction[2].u.operand;
+    
+    emitLoad(value, regT1, regT0);
+    Jump isCell = branch32(Equal, regT1, TrustedImm32(JSValue::CellTag));
 
 
-    emitLoad(index, regT1, regT0, regT2);
-    emitStore(dst, regT1, regT0);
-    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_global_var), dst, regT1, regT0);
+    compare32(Equal, regT1, TrustedImm32(JSValue::UndefinedTag), regT0);
+    Jump done = jump();
+    
+    isCell.link(this);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
+    test8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0);
+    
+    done.link(this);
+    emitStoreBool(dst, regT0);
 }
 
 }
 
-void JIT::emit_op_put_global_var(Instruction* currentInstruction)
+void JIT::emit_op_is_boolean(Instruction* currentInstruction)
 {
 {
-    JSGlobalObject* globalObject = m_codeBlock->globalObject();
-    ASSERT(globalObject->isGlobalObject());
-    int index = currentInstruction[1].u.operand;
-    int value = currentInstruction[2].u.operand;
-
-    emitLoad(value, regT1, regT0);
-
-    loadPtr(&globalObject->m_registers, regT2);
-    emitStore(index, regT1, regT0, regT2);
-    map(m_bytecodeOffset + OPCODE_LENGTH(op_put_global_var), value, regT1, regT0);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned value = currentInstruction[2].u.operand;
+    
+    emitLoadTag(value, regT0);
+    compare32(Equal, regT0, TrustedImm32(JSValue::BooleanTag), regT0);
+    emitStoreBool(dst, regT0);
 }
 
 }
 
-void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
+void JIT::emit_op_is_number(Instruction* currentInstruction)
 {
 {
-    int dst = currentInstruction[1].u.operand;
-    int index = currentInstruction[2].u.operand;
-    int skip = currentInstruction[3].u.operand;
-
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
-    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
-    ASSERT(skip || !checkTopLevel);
-    if (checkTopLevel && skip--) {
-        Jump activationNotCreated;
-        if (checkTopLevel)
-            activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), TrustedImm32(JSValue::EmptyValueTag));
-        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
-        activationNotCreated.link(this);
-    }
-    while (skip--)
-        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
-
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2);
-
-    emitLoad(index, regT1, regT0, regT2);
-    emitStore(dst, regT1, regT0);
-    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_scoped_var), dst, regT1, regT0);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned value = currentInstruction[2].u.operand;
+    
+    emitLoadTag(value, regT0);
+    add32(TrustedImm32(1), regT0);
+    compare32(Below, regT0, TrustedImm32(JSValue::LowestTag + 1), regT0);
+    emitStoreBool(dst, regT0);
 }
 
 }
 
-void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
+void JIT::emit_op_is_string(Instruction* currentInstruction)
 {
 {
-    int index = currentInstruction[1].u.operand;
-    int skip = currentInstruction[2].u.operand;
-    int value = currentInstruction[3].u.operand;
-
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned value = currentInstruction[2].u.operand;
+    
     emitLoad(value, regT1, regT0);
     emitLoad(value, regT1, regT0);
-
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
-    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
-    ASSERT(skip || !checkTopLevel);
-    if (checkTopLevel && skip--) {
-        Jump activationNotCreated;
-        if (checkTopLevel)
-            activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), TrustedImm32(JSValue::EmptyValueTag));
-        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
-        activationNotCreated.link(this);
-    }
-    while (skip--)
-        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
-
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2);
-
-    emitStore(index, regT1, regT0, regT2);
-    map(m_bytecodeOffset + OPCODE_LENGTH(op_put_scoped_var), value, regT1, regT0);
+    Jump isNotCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
+    
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
+    compare8(Equal, Address(regT1, Structure::typeInfoTypeOffset()), TrustedImm32(StringType), regT0);
+    Jump done = jump();
+    
+    isNotCell.link(this);
+    move(TrustedImm32(0), regT0);
+    
+    done.link(this);
+    emitStoreBool(dst, regT0);
 }
 
 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
@@ -756,7 +721,7 @@ void JIT::emit_op_resolve(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
 {
     JITStubCall stubCall(this, cti_op_resolve);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
-    stubCall.call(currentInstruction[1].u.operand);
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_to_primitive(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_to_primitive(Instruction* currentInstruction)
@@ -767,7 +732,7 @@ void JIT::emit_op_to_primitive(Instruction* currentInstruction)
     emitLoad(src, regT1, regT0);
 
     Jump isImm = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
     emitLoad(src, regT1, regT0);
 
     Jump isImm = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
-    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
+    addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
     isImm.link(this);
 
     if (dst != src)
     isImm.link(this);
 
     if (dst != src)
@@ -789,8 +754,8 @@ void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowC
 void JIT::emit_op_strcat(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_strcat);
 void JIT::emit_op_strcat(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_strcat);
-    stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
-    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -798,13 +763,13 @@ void JIT::emit_op_resolve_base(Instruction* currentInstruction)
 {
     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)));
 {
     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);
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_ensure_property_exists);
 }
 
 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(TrustedImm32(currentInstruction[1].u.operand));
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
@@ -813,8 +778,8 @@ void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_skip);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
 {
     JITStubCall stubCall(this, cti_op_resolve_skip);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
-    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
-    stubCall.call(currentInstruction[1].u.operand);
+    stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand));
+    stubCall.callWithValueProfiling(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool dynamic)
 }
 
 void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool dynamic)
@@ -839,6 +804,7 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool dynamic)
     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
     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
+    emitValueProfilingSite();
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + (dynamic ? OPCODE_LENGTH(op_resolve_global_dynamic) : OPCODE_LENGTH(op_resolve_global)), dst, regT1, regT0);
 }
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + (dynamic ? OPCODE_LENGTH(op_resolve_global_dynamic) : OPCODE_LENGTH(op_resolve_global)), dst, regT1, regT0);
 }
@@ -853,8 +819,8 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<Slo
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_resolve_global);
     stubCall.addArgument(TrustedImmPtr(ident));
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_resolve_global);
     stubCall.addArgument(TrustedImmPtr(ident));
-    stubCall.addArgument(Imm32(currentIndex));
-    stubCall.call(dst);
+    stubCall.addArgument(TrustedImm32(currentIndex));
+    stubCall.callWithValueProfiling(dst);
 }
 
 void JIT::emit_op_not(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_not(Instruction* currentInstruction)
@@ -904,7 +870,7 @@ void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEnt
 
     if (supportsFloatingPoint()) {
         // regT1 contains the tag from the hot path.
 
     if (supportsFloatingPoint()) {
         // regT1 contains the tag from the hot path.
-        Jump notNumber = branch32(Above, regT1, Imm32(JSValue::LowestTag));
+        Jump notNumber = branch32(Above, regT1, TrustedImm32(JSValue::LowestTag));
 
         emitLoadDouble(cond, fpRegT0);
         emitJumpSlowToHot(branchDoubleZeroOrNaN(fpRegT0, fpRegT1), target);
 
         emitLoadDouble(cond, fpRegT0);
         emitJumpSlowToHot(branchDoubleZeroOrNaN(fpRegT0, fpRegT1), target);
@@ -940,7 +906,7 @@ void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntr
 
     if (supportsFloatingPoint()) {
         // regT1 contains the tag from the hot path.
 
     if (supportsFloatingPoint()) {
         // regT1 contains the tag from the hot path.
-        Jump notNumber = branch32(Above, regT1, Imm32(JSValue::LowestTag));
+        Jump notNumber = branch32(Above, regT1, TrustedImm32(JSValue::LowestTag));
 
         emitLoadDouble(cond, fpRegT0);
         emitJumpSlowToHot(branchDoubleNonZero(fpRegT0, fpRegT1), target);
 
         emitLoadDouble(cond, fpRegT0);
         emitJumpSlowToHot(branchDoubleNonZero(fpRegT0, fpRegT1), target);
@@ -1016,20 +982,6 @@ void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
     addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(ptr)), target);
 }
 
     addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(ptr)), target);
 }
 
-void JIT::emit_op_jsr(Instruction* currentInstruction)
-{
-    int retAddrDst = currentInstruction[1].u.operand;
-    int target = currentInstruction[2].u.operand;
-    DataLabelPtr storeLocation = storePtrWithPatch(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
-    addJump(jump(), target);
-    m_jsrSites.append(JSRInfo(storeLocation, label()));
-}
-
-void JIT::emit_op_sret(Instruction* currentInstruction)
-{
-    jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand));
-}
-
 void JIT::emit_op_eq(Instruction* currentInstruction)
 {
     unsigned dst = currentInstruction[1].u.operand;
 void JIT::emit_op_eq(Instruction* currentInstruction)
 {
     unsigned dst = currentInstruction[1].u.operand;
@@ -1058,8 +1010,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), TrustedImmPtr(m_globalData->jsStringVPtr)));
-    genericCase.append(branchPtr(NotEqual, Address(regT2), TrustedImmPtr(m_globalData->jsStringVPtr)));
+    genericCase.append(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
+    genericCase.append(branchPtr(NotEqual, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
 
     // String case.
     JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
 
     // String case.
     JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
@@ -1106,8 +1058,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), TrustedImmPtr(m_globalData->jsStringVPtr)));
-    genericCase.append(branchPtr(NotEqual, Address(regT2), TrustedImmPtr(m_globalData->jsStringVPtr)));
+    genericCase.append(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
+    genericCase.append(branchPtr(NotEqual, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
 
     // String case.
     JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
 
     // String case.
     JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
@@ -1135,20 +1087,24 @@ void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqTy
     unsigned src1 = currentInstruction[2].u.operand;
     unsigned src2 = currentInstruction[3].u.operand;
 
     unsigned src1 = currentInstruction[2].u.operand;
     unsigned src2 = currentInstruction[3].u.operand;
 
-    emitLoadTag(src1, regT0);
-    emitLoadTag(src2, regT1);
+    emitLoad2(src1, regT1, regT0, src2, regT3, regT2);
+
+    // Bail if the tags differ, or are double.
+    addSlowCase(branch32(NotEqual, regT1, regT3));
+    addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::LowestTag)));
 
 
-    // Jump to a slow case if either operand is double, or if both operands are
-    // cells and/or Int32s.
-    move(regT0, regT2);
-    and32(regT1, regT2);
-    addSlowCase(branch32(Below, regT2, TrustedImm32(JSValue::LowestTag)));
-    addSlowCase(branch32(AboveOrEqual, regT2, TrustedImm32(JSValue::CellTag)));
+    // Jump to a slow case if both are strings.
+    Jump notCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
+    Jump firstNotString = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info));
+    addSlowCase(branchPtr(Equal, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
+    notCell.link(this);
+    firstNotString.link(this);
 
 
+    // Simply compare the payloads.
     if (type == OpStrictEq)
     if (type == OpStrictEq)
-        compare32(Equal, regT0, regT1, regT0);
+        compare32(Equal, regT0, regT2, regT0);
     else
     else
-        compare32(NotEqual, regT0, regT1, regT0);
+        compare32(NotEqual, regT0, regT2, regT0);
 
     emitStoreBool(dst, regT0);
 }
 
     emitStoreBool(dst, regT0);
 }
@@ -1164,6 +1120,7 @@ void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseE
     unsigned src1 = currentInstruction[2].u.operand;
     unsigned src2 = currentInstruction[3].u.operand;
 
     unsigned src1 = currentInstruction[2].u.operand;
     unsigned src2 = currentInstruction[3].u.operand;
 
+    linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
 
     linkSlowCase(iter);
     linkSlowCase(iter);
 
@@ -1184,6 +1141,7 @@ void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCase
     unsigned src1 = currentInstruction[2].u.operand;
     unsigned src2 = currentInstruction[3].u.operand;
 
     unsigned src1 = currentInstruction[2].u.operand;
     unsigned src2 = currentInstruction[3].u.operand;
 
+    linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
 
     linkSlowCase(iter);
     linkSlowCase(iter);
 
@@ -1245,15 +1203,16 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_with_base);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
 {
     JITStubCall stubCall(this, cti_op_resolve_with_base);
     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(TrustedImm32(currentInstruction[1].u.operand));
+    stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
 }
 
 }
 
-void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
+void JIT::emit_op_resolve_with_this(Instruction* currentInstruction)
 {
 {
-    JITStubCall stubCall(this, cti_op_new_func_exp);
-    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
-    stubCall.call(currentInstruction[1].u.operand);
+    JITStubCall stubCall(this, cti_op_resolve_with_this);
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
+    stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand));
+    stubCall.callWithValueProfiling(currentInstruction[2].u.operand);
 }
 
 void JIT::emit_op_throw(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_throw(Instruction* currentInstruction)
@@ -1285,7 +1244,7 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction)
         isNotObject.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
     if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) {
         loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
         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)));
+        isNotObject.append(emitJumpIfNotObject(regT2));
     }
 
     // We could inline the case where you have a valid cache, but
     }
 
     // We could inline the case where you have a valid cache, but
@@ -1444,7 +1403,7 @@ void JIT::emit_op_catch(Instruction* currentInstruction)
 void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_jmp_scopes);
 void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_jmp_scopes);
-    stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[1].u.operand));
     stubCall.call();
     addJump(jump(), currentInstruction[2].u.operand);
 }
     stubCall.call();
     addJump(jump(), currentInstruction[2].u.operand);
 }
@@ -1462,7 +1421,7 @@ void JIT::emit_op_switch_imm(Instruction* currentInstruction)
 
     JITStubCall stubCall(this, cti_op_switch_imm);
     stubCall.addArgument(scrutinee);
 
     JITStubCall stubCall(this, cti_op_switch_imm);
     stubCall.addArgument(scrutinee);
-    stubCall.addArgument(Imm32(tableIndex));
+    stubCall.addArgument(TrustedImm32(tableIndex));
     stubCall.call();
     jump(regT0);
 }
     stubCall.call();
     jump(regT0);
 }
@@ -1480,7 +1439,7 @@ void JIT::emit_op_switch_char(Instruction* currentInstruction)
 
     JITStubCall stubCall(this, cti_op_switch_char);
     stubCall.addArgument(scrutinee);
 
     JITStubCall stubCall(this, cti_op_switch_char);
     stubCall.addArgument(scrutinee);
-    stubCall.addArgument(Imm32(tableIndex));
+    stubCall.addArgument(TrustedImm32(tableIndex));
     stubCall.call();
     jump(regT0);
 }
     stubCall.call();
     jump(regT0);
 }
@@ -1497,7 +1456,7 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction)
 
     JITStubCall stubCall(this, cti_op_switch_string);
     stubCall.addArgument(scrutinee);
 
     JITStubCall stubCall(this, cti_op_switch_string);
     stubCall.addArgument(scrutinee);
-    stubCall.addArgument(Imm32(tableIndex));
+    stubCall.addArgument(TrustedImm32(tableIndex));
     stubCall.call();
     jump(regT0);
 }
     stubCall.call();
     jump(regT0);
 }
@@ -1550,11 +1509,7 @@ void JIT::emit_op_create_arguments(Instruction* currentInstruction)
 
     Jump argsCreated = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag));
 
 
     Jump argsCreated = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag));
 
-    if (m_codeBlock->m_numParameters == 1)
-        JITStubCall(this, cti_op_create_arguments_no_params).call();
-    else
-        JITStubCall(this, cti_op_create_arguments).call();
-
+    JITStubCall(this, cti_op_create_arguments).call();
     emitStore(dst, regT1, regT0);
     emitStore(unmodifiedArgumentsRegister(dst), regT1, regT0);
 
     emitStore(dst, regT1, regT0);
     emitStore(unmodifiedArgumentsRegister(dst), regT1, regT0);
 
@@ -1577,6 +1532,31 @@ void JIT::emit_op_get_callee(Instruction* currentInstruction)
 
 void JIT::emit_op_create_this(Instruction* currentInstruction)
 {
 
 void JIT::emit_op_create_this(Instruction* currentInstruction)
 {
+    emitLoad(currentInstruction[2].u.operand, regT1, regT0);
+    emitJumpSlowCaseIfNotJSCell(currentInstruction[2].u.operand, regT1);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
+    addSlowCase(emitJumpIfNotObject(regT1));
+    
+    // now we know that the prototype is an object, but we don't know if it's got an
+    // inheritor ID
+    
+    loadPtr(Address(regT0, JSObject::offsetOfInheritorID()), regT2);
+    addSlowCase(branchTestPtr(Zero, regT2));
+    
+    // now regT2 contains the inheritorID, which is the structure that the newly
+    // allocated object will have.
+    
+    emitAllocateJSFinalObject(regT2, regT0, regT1);
+
+    emitStoreCell(currentInstruction[1].u.operand, regT0);
+}
+
+void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand); // not a cell
+    linkSlowCase(iter); // not an object
+    linkSlowCase(iter); // doesn't have an inheritor ID
+    linkSlowCase(iter); // allocation failed
     unsigned protoRegister = currentInstruction[2].u.operand;
     emitLoad(protoRegister, regT1, regT0);
     JITStubCall stubCall(this, cti_op_create_this);
     unsigned protoRegister = currentInstruction[2].u.operand;
     emitLoad(protoRegister, regT1, regT0);
     JITStubCall stubCall(this, cti_op_create_this);
@@ -1591,52 +1571,26 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction)
     emitLoad(thisRegister, regT1, regT0);
 
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
     emitLoad(thisRegister, regT1, regT0);
 
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
-
-    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
-    addSlowCase(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion)));
+    addSlowCase(branchPtr(Equal, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
 
     map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0);
 }
 
 
     map(m_bytecodeOffset + 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)
 {
+    void* globalThis = m_codeBlock->globalObject()->globalScopeChain()->globalThis.get();
     unsigned thisRegister = currentInstruction[1].u.operand;
 
     linkSlowCase(iter);
     unsigned thisRegister = currentInstruction[1].u.operand;
 
     linkSlowCase(iter);
-    linkSlowCase(iter);
+    Jump isNotUndefined = branch32(NotEqual, regT1, TrustedImm32(JSValue::UndefinedTag));
+    move(TrustedImmPtr(globalThis), regT0);
+    move(TrustedImm32(JSValue::CellTag), regT1);
+    emitStore(thisRegister, regT1, regT0);
+    emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_convert_this));
 
 
-    JITStubCall stubCall(this, cti_op_convert_this);
-    stubCall.addArgument(regT1, regT0);
-    stubCall.call(thisRegister);
-}
-
-void JIT::emitSlow_op_convert_this_strict(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned thisRegister = currentInstruction[1].u.operand;
-    
+    isNotUndefined.link(this);
     linkSlowCase(iter);
     linkSlowCase(iter);
-    
-    JITStubCall stubCall(this, cti_op_convert_this_strict);
+    JITStubCall stubCall(this, cti_op_convert_this);
     stubCall.addArgument(regT1, regT0);
     stubCall.call(thisRegister);
 }
     stubCall.addArgument(regT1, regT0);
     stubCall.call(thisRegister);
 }
@@ -1668,7 +1622,7 @@ 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)));
     int dst = currentInstruction[1].u.operand;
     int argumentsRegister = currentInstruction[2].u.operand;
     addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), TrustedImm32(JSValue::EmptyValueTag)));
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+    load32(payloadFor(RegisterFile::ArgumentCount), regT0);
     sub32(TrustedImm32(1), regT0);
     emitStoreInt32(dst, regT0);
 }
     sub32(TrustedImm32(1), regT0);
     emitStoreInt32(dst, regT0);
 }
@@ -1696,27 +1650,12 @@ void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction)
     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
     add32(TrustedImm32(1), regT2);
     // regT2 now contains the integer index of the argument we want, including this
     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);
+    load32(payloadFor(RegisterFile::ArgumentCount), regT3);
     addSlowCase(branch32(AboveOrEqual, regT2, 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);
+    neg32(regT2);
+    loadPtr(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT0);
+    loadPtr(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT1);
     emitStore(dst, regT1, regT0);
 }
 
     emitStore(dst, regT1, regT0);
 }
 
@@ -1731,11 +1670,7 @@ void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vecto
 
     linkSlowCase(iter);
     linkSlowCase(iter);
 
     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();
-    
+    JITStubCall(this, cti_op_create_arguments).call();
     emitStore(arguments, regT1, regT0);
     emitStore(unmodifiedArgumentsRegister(arguments), regT1, regT0);
     
     emitStore(arguments, regT1, regT0);
     emitStore(unmodifiedArgumentsRegister(arguments), regT1, regT0);
     
@@ -1746,96 +1681,6 @@ void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vecto
     stubCall.call(dst);
 }
 
     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)
 } // namespace JSC
 
 #endif // USE(JSVALUE32_64)
index ce3d3c1f385504a83359a1aeecee9f665a430256..8c7148c9def19fb56a32ed0ee61390483841e395 100644 (file)
@@ -50,24 +50,33 @@ using namespace std;
 namespace JSC {
 #if USE(JSVALUE64)
 
 namespace JSC {
 #if USE(JSVALUE64)
 
-JIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+JIT::CodeRef JIT::stringGetByValStubGenerator(JSGlobalData* globalData)
 {
     JSInterfaceJIT jit;
     JumpList failures;
 {
     JSInterfaceJIT jit;
     JumpList failures;
-    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.branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
 
     // 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);
 
     // 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);
-    
+    failures.append(jit.branchTest32(Zero, regT0));
+
     // Do an unsigned compare to simultaneously filter negative indices as well as indices that are too large
     failures.append(jit.branch32(AboveOrEqual, regT1, regT2));
     
     // Load the character
     // Do an unsigned compare to simultaneously filter negative indices as well as indices that are too large
     failures.append(jit.branch32(AboveOrEqual, regT1, regT2));
     
     // Load the character
+    JumpList is16Bit;
+    JumpList cont8Bit;
+    // Load the string flags
+    jit.loadPtr(Address(regT0, ThunkHelpers::stringImplFlagsOffset()), regT2);
+    jit.loadPtr(Address(regT0, ThunkHelpers::stringImplDataOffset()), regT0);
+    is16Bit.append(jit.branchTest32(Zero, regT2, TrustedImm32(ThunkHelpers::stringImpl8BitFlag())));
+    jit.load8(BaseIndex(regT0, regT1, TimesOne, 0), regT0);
+    cont8Bit.append(jit.jump());
+    is16Bit.link(&jit);
     jit.load16(BaseIndex(regT0, regT1, TimesTwo, 0), regT0);
     jit.load16(BaseIndex(regT0, regT1, TimesTwo, 0), regT0);
-    
+    cont8Bit.link(&jit);
+
     failures.append(jit.branch32(AboveOrEqual, regT0, TrustedImm32(0x100)));
     jit.move(TrustedImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1);
     jit.loadPtr(BaseIndex(regT1, regT0, ScalePtr, 0), regT0);
     failures.append(jit.branch32(AboveOrEqual, regT0, TrustedImm32(0x100)));
     jit.move(TrustedImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1);
     jit.loadPtr(BaseIndex(regT1, regT0, ScalePtr, 0), regT0);
@@ -77,8 +86,8 @@ JIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, Executab
     jit.move(TrustedImm32(0), regT0);
     jit.ret();
     
     jit.move(TrustedImm32(0), regT0);
     jit.ret();
     
-    LinkBuffer patchBuffer(*globalData, &jit, pool);
-    return patchBuffer.finalizeCode().m_code;
+    LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
+    return patchBuffer.finalizeCode();
 }
 
 void JIT::emit_op_get_by_val(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_get_by_val(Instruction* currentInstruction)
@@ -99,7 +108,7 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
     zeroExtend32ToPtr(regT1, regT1);
 
     emitJumpSlowCaseIfNotJSCell(regT0, base);
     zeroExtend32ToPtr(regT1, regT1);
 
     emitJumpSlowCaseIfNotJSCell(regT0, base);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
+    addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
 
     loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
     addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset())));
 
     loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
     addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset())));
@@ -107,6 +116,7 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
     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));
 
+    emitValueProfilingSite();
     emitPutVirtualRegister(dst);
 }
 
     emitPutVirtualRegister(dst);
 }
 
@@ -120,8 +130,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), TrustedImmPtr(m_globalData->jsStringVPtr));
-    emitNakedCall(m_globalData->getCTIStub(stringGetByValStubGenerator));
+    Jump notString = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info));
+    emitNakedCall(CodeLocationLabel(m_globalData->getCTIStub(stringGetByValStubGenerator).code()));
     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));
@@ -136,11 +146,13 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas
     stubCall.addArgument(base, regT2);
     stubCall.addArgument(property, regT2);
     stubCall.call(dst);
     stubCall.addArgument(base, regT2);
     stubCall.addArgument(property, regT2);
     stubCall.call(dst);
+
+    emitValueProfilingSite();
 }
 
 void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch)
 {
 }
 
 void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch)
 {
-    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), scratch);
+    loadPtr(Address(base, JSObject::offsetOfPropertyStorage()), scratch);
     loadPtr(BaseIndex(scratch, offset, ScalePtr, 0), result);
 }
 
     loadPtr(BaseIndex(scratch, offset, ScalePtr, 0), result);
 }
 
@@ -197,53 +209,65 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction)
     // See comment in op_get_by_val.
     zeroExtend32ToPtr(regT1, regT1);
     emitJumpSlowCaseIfNotJSCell(regT0, base);
     // See comment in op_get_by_val.
     zeroExtend32ToPtr(regT1, regT1);
     emitJumpSlowCaseIfNotJSCell(regT0, base);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
+    addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
     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);
     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);
-    emitGetVirtualRegister(value, regT0);
-    storePtr(regT0, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+    emitGetVirtualRegister(value, regT3);
+    storePtr(regT3, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
     Jump end = jump();
     
     empty.link(this);
     add32(TrustedImm32(1), Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
     branch32(Below, regT1, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length))).linkTo(storeResult, this);
 
     Jump end = jump();
     
     empty.link(this);
     add32(TrustedImm32(1), Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
     branch32(Below, regT1, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length))).linkTo(storeResult, this);
 
-    move(regT1, regT0);
-    add32(TrustedImm32(1), regT0);
-    store32(regT0, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length)));
+    add32(TrustedImm32(1), regT1);
+    store32(regT1, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length)));
+    sub32(TrustedImm32(1), regT1);
     jump().linkTo(storeResult, this);
 
     end.link(this);
     jump().linkTo(storeResult, this);
 
     end.link(this);
+
+    emitWriteBarrier(regT0, regT3, regT1, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess);
 }
 
 }
 
-void JIT::emit_op_put_by_index(Instruction* currentInstruction)
+void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
 {
-    JITStubCall stubCall(this, cti_op_put_by_index);
-    stubCall.addArgument(currentInstruction[1].u.operand, regT2);
-    stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand));
-    stubCall.addArgument(currentInstruction[3].u.operand, regT2);
-    stubCall.call();
+    unsigned base = currentInstruction[1].u.operand;
+    unsigned property = currentInstruction[2].u.operand;
+    unsigned value = currentInstruction[3].u.operand;
+
+    linkSlowCase(iter); // property int32 check
+    linkSlowCaseIfNotJSCell(iter, base); // base cell check
+    linkSlowCase(iter); // base not array check
+    linkSlowCase(iter); // in vector check
+
+    JITStubCall stubPutByValCall(this, cti_op_put_by_val);
+    stubPutByValCall.addArgument(regT0);
+    stubPutByValCall.addArgument(property, regT2);
+    stubPutByValCall.addArgument(value, regT2);
+    stubPutByValCall.call();
 }
 
 }
 
-void JIT::emit_op_put_getter(Instruction* currentInstruction)
+void JIT::emit_op_put_by_index(Instruction* currentInstruction)
 {
 {
-    JITStubCall stubCall(this, cti_op_put_getter);
+    JITStubCall stubCall(this, cti_op_put_by_index);
     stubCall.addArgument(currentInstruction[1].u.operand, regT2);
     stubCall.addArgument(currentInstruction[1].u.operand, regT2);
-    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(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();
 }
 
-void JIT::emit_op_put_setter(Instruction* currentInstruction)
+void JIT::emit_op_put_getter_setter(Instruction* currentInstruction)
 {
 {
-    JITStubCall stubCall(this, cti_op_put_setter);
+    JITStubCall stubCall(this, cti_op_put_getter_setter);
     stubCall.addArgument(currentInstruction[1].u.operand, regT2);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.addArgument(currentInstruction[3].u.operand, regT2);
     stubCall.addArgument(currentInstruction[1].u.operand, regT2);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.addArgument(currentInstruction[3].u.operand, regT2);
+    stubCall.addArgument(currentInstruction[4].u.operand, regT2);
     stubCall.call();
 }
 
     stubCall.call();
 }
 
@@ -255,67 +279,6 @@ void JIT::emit_op_del_by_id(Instruction* currentInstruction)
     stubCall.call(currentInstruction[1].u.operand);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
-
-#if !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-
-/* ------------------------------ BEGIN: !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
-
-// Treat these as nops - the call will be handed as a regular get_by_id/op_call pair.
-void JIT::emit_op_method_check(Instruction*) {}
-void JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&) { ASSERT_NOT_REACHED(); }
-#if ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
-#error "JIT_OPTIMIZE_METHOD_CALLS requires JIT_OPTIMIZE_PROPERTY_ACCESS"
-#endif
-
-void JIT::emit_op_get_by_id(Instruction* currentInstruction)
-{
-    unsigned resultVReg = currentInstruction[1].u.operand;
-    unsigned baseVReg = currentInstruction[2].u.operand;
-    Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
-
-    emitGetVirtualRegister(baseVReg, regT0);
-    JITStubCall stubCall(this, cti_op_get_by_id_generic);
-    stubCall.addArgument(regT0);
-    stubCall.addArgument(TrustedImmPtr(ident));
-    stubCall.call(resultVReg);
-
-    m_propertyAccessInstructionIndex++;
-}
-
-void JIT::emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&)
-{
-    ASSERT_NOT_REACHED();
-}
-
-void JIT::emit_op_put_by_id(Instruction* currentInstruction)
-{
-    unsigned baseVReg = currentInstruction[1].u.operand;
-    Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
-    unsigned valueVReg = currentInstruction[3].u.operand;
-    unsigned direct = currentInstruction[8].u.operand;
-
-    emitGetVirtualRegisters(baseVReg, regT0, valueVReg, regT1);
-
-    JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct_generic, cti_op_put_by_id_generic);
-    stubCall.addArgument(regT0);
-    stubCall.addArgument(TrustedImmPtr(ident));
-    stubCall.addArgument(regT1);
-    stubCall.call();
-
-    m_propertyAccessInstructionIndex++;
-}
-
-void JIT::emitSlow_op_put_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&)
-{
-    ASSERT_NOT_REACHED();
-}
-
-#else // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-
-/* ------------------------------ BEGIN: ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
-
-#if ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
-
 void JIT::emit_op_method_check(Instruction* currentInstruction)
 {
     // Assert that the following instruction is a get_by_id.
 void JIT::emit_op_method_check(Instruction* currentInstruction)
 {
     // Assert that the following instruction is a get_by_id.
@@ -329,7 +292,7 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     emitGetVirtualRegister(baseVReg, regT0);
 
     // Do the method check - check the object & its prototype's structure inline (this is the common case).
     emitGetVirtualRegister(baseVReg, regT0);
 
     // Do the method check - check the object & its prototype's structure inline (this is the common case).
-    m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_propertyAccessInstructionIndex));
+    m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_bytecodeOffset, m_propertyAccessCompilationInfo.size()));
     MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
 
     Jump notCell = emitJumpIfNotJSCell(regT0);
     MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
 
     Jump notCell = emitJumpIfNotJSCell(regT0);
@@ -347,10 +310,6 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
 
     Jump match = jump();
 
 
     Jump match = jump();
 
-    ASSERT_JIT_OFFSET_UNUSED(protoObj, differenceBetween(info.structureToCompare, protoObj), patchOffsetMethodCheckProtoObj);
-    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoStructureToCompare), patchOffsetMethodCheckProtoStruct);
-    ASSERT_JIT_OFFSET_UNUSED(putFunction, differenceBetween(info.structureToCompare, putFunction), patchOffsetMethodCheckPutFunction);
-
     // Link the failure cases here.
     notCell.link(this);
     structureCheck.link(this);
     // Link the failure cases here.
     notCell.link(this);
     structureCheck.link(this);
@@ -358,13 +317,16 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
 
     // Do a regular(ish) get_by_id (the slow case will be link to
     // cti_op_get_by_id_method_check instead of cti_op_get_by_id.
 
     // Do a regular(ish) get_by_id (the slow case will be link to
     // cti_op_get_by_id_method_check instead of cti_op_get_by_id.
-    compileGetByIdHotPath(resultVReg, baseVReg, ident, m_propertyAccessInstructionIndex++);
+    compileGetByIdHotPath(baseVReg, ident);
 
     match.link(this);
 
     match.link(this);
+    emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
     emitPutVirtualRegister(resultVReg);
 
     // We've already generated the following get_by_id, so make sure it's skipped over.
     m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
     emitPutVirtualRegister(resultVReg);
 
     // We've already generated the following get_by_id, so make sure it's skipped over.
     m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
+
+    m_propertyAccessCompilationInfo.last().addMethodCheckInfo(info.structureToCompare, protoObj, protoStructureToCompare, putFunction);
 }
 
 void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -375,19 +337,12 @@ void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowC
     Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
 
     compileGetByIdSlowCase(resultVReg, baseVReg, ident, iter, true);
     Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
 
     compileGetByIdSlowCase(resultVReg, baseVReg, ident, iter, true);
+    emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
 
     // We've already generated the following get_by_id, so make sure it's skipped over.
     m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
 }
 
 
     // We've already generated the following get_by_id, so make sure it's skipped over.
     m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
 }
 
-#else //!ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
-
-// Treat these as nops - the call will be handed as a regular get_by_id/op_call pair.
-void JIT::emit_op_method_check(Instruction*) {}
-void JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&) { ASSERT_NOT_REACHED(); }
-
-#endif
-
 void JIT::emit_op_get_by_id(Instruction* currentInstruction)
 {
     unsigned resultVReg = currentInstruction[1].u.operand;
 void JIT::emit_op_get_by_id(Instruction* currentInstruction)
 {
     unsigned resultVReg = currentInstruction[1].u.operand;
@@ -395,11 +350,12 @@ void JIT::emit_op_get_by_id(Instruction* currentInstruction)
     Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
 
     emitGetVirtualRegister(baseVReg, regT0);
     Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
 
     emitGetVirtualRegister(baseVReg, regT0);
-    compileGetByIdHotPath(resultVReg, baseVReg, ident, m_propertyAccessInstructionIndex++);
+    compileGetByIdHotPath(baseVReg, ident);
+    emitValueProfilingSite();
     emitPutVirtualRegister(resultVReg);
 }
 
     emitPutVirtualRegister(resultVReg);
 }
 
-void JIT::compileGetByIdHotPath(int, int baseVReg, Identifier*, unsigned propertyAccessInstructionIndex)
+void JIT::compileGetByIdHotPath(int baseVReg, Identifier*)
 {
     // As for put_by_id, get_by_id requires the offset of the Structure and the offset of the access to be patched.
     // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump
 {
     // As for put_by_id, get_by_id requires the offset of the Structure and the offset of the access to be patched.
     // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump
@@ -411,23 +367,19 @@ void JIT::compileGetByIdHotPath(int, int baseVReg, Identifier*, unsigned propert
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
 
     Label hotPathBegin(this);
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
 
     Label hotPathBegin(this);
-    m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
 
     DataLabelPtr structureToCompare;
 
     DataLabelPtr structureToCompare;
-    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+    PatchableJump structureCheck = patchableBranchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
     addSlowCase(structureCheck);
     addSlowCase(structureCheck);
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure);
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase)
 
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0);
+    loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT0);
     DataLabelCompact displacementLabel = loadPtrWithCompactAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0);
     DataLabelCompact displacementLabel = loadPtrWithCompactAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0);
-    ASSERT_JIT_OFFSET_UNUSED(displacementLabel, differenceBetween(hotPathBegin, displacementLabel), patchOffsetGetByIdPropertyMapOffset);
 
     Label putResult(this);
 
     END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
 
 
     Label putResult(this);
 
     END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
 
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, putResult), patchOffsetGetByIdPutResult);
+    m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo(PropertyStubGetById, m_bytecodeOffset, hotPathBegin, structureToCompare, structureCheck, displacementLabel, putResult));
 }
 
 void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -437,6 +389,7 @@ void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCase
     Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
 
     compileGetByIdSlowCase(resultVReg, baseVReg, ident, iter, false);
     Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
 
     compileGetByIdSlowCase(resultVReg, baseVReg, ident, iter, false);
+    emitValueProfilingSite();
 }
 
 void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck)
 }
 
 void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck)
@@ -452,9 +405,7 @@ void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident
 
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
 
 
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
 
-#ifndef NDEBUG
     Label coldPathBegin(this);
     Label coldPathBegin(this);
-#endif
     JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id);
     stubCall.addArgument(regT0);
     stubCall.addArgument(TrustedImmPtr(ident));
     JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id);
     stubCall.addArgument(regT0);
     stubCall.addArgument(TrustedImmPtr(ident));
@@ -462,11 +413,8 @@ void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident
 
     END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
 
 
     END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
 
-    ASSERT_JIT_OFFSET(differenceBetween(coldPathBegin, call), patchOffsetGetByIdSlowCaseCall);
-
     // Track the location of the call; this will be used to recover patch information.
     // Track the location of the call; this will be used to recover patch information.
-    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call;
-    m_propertyAccessInstructionIndex++;
+    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].slowCaseInfo(PropertyStubGetById, coldPathBegin, call);
 }
 
 void JIT::emit_op_put_by_id(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_put_by_id(Instruction* currentInstruction)
@@ -474,8 +422,6 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
     unsigned baseVReg = currentInstruction[1].u.operand;
     unsigned valueVReg = currentInstruction[3].u.operand;
 
     unsigned baseVReg = currentInstruction[1].u.operand;
     unsigned valueVReg = currentInstruction[3].u.operand;
 
-    unsigned propertyAccessInstructionIndex = m_propertyAccessInstructionIndex++;
-
     // In order to be able to patch both the Structure, and the object offset, we store one pointer,
     // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code
     // such that the Structure & offset are always at the same distance from this.
     // In order to be able to patch both the Structure, and the object offset, we store one pointer,
     // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code
     // such that the Structure & offset are always at the same distance from this.
@@ -488,19 +434,19 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
     BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById);
 
     Label hotPathBegin(this);
     BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById);
 
     Label hotPathBegin(this);
-    m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
 
     // 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, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
 
     // 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, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure);
 
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0);
-    DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchPutByIdDefaultOffset));
+    loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT2);
+    DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT2, patchPutByIdDefaultOffset));
 
     END_UNINTERRUPTED_SEQUENCE(sequencePutById);
 
 
     END_UNINTERRUPTED_SEQUENCE(sequencePutById);
 
-    ASSERT_JIT_OFFSET_UNUSED(displacementLabel, differenceBetween(hotPathBegin, displacementLabel), patchOffsetPutByIdPropertyMapOffset);
+    emitWriteBarrier(regT0, regT1, regT2, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess);
+
+    m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo(PropertyStubPutById, m_bytecodeOffset, hotPathBegin, structureToCompare, displacementLabel));
 }
 
 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)
@@ -509,8 +455,6 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase
     Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
     unsigned direct = currentInstruction[8].u.operand;
 
     Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
     unsigned direct = currentInstruction[8].u.operand;
 
-    unsigned propertyAccessInstructionIndex = m_propertyAccessInstructionIndex++;
-
     linkSlowCaseIfNotJSCell(iter, baseVReg);
     linkSlowCase(iter);
 
     linkSlowCaseIfNotJSCell(iter, baseVReg);
     linkSlowCase(iter);
 
@@ -521,37 +465,30 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase
     Call call = stubCall.call();
 
     // Track the location of the call; this will be used to recover patch information.
     Call call = stubCall.call();
 
     // Track the location of the call; this will be used to recover patch information.
-    m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
+    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].slowCaseInfo(PropertyStubPutById, call);
 }
 
 // Compile a store into an object's property storage.  May overwrite the
 // value in objectReg.
 }
 
 // Compile a store into an object's property storage.  May overwrite the
 // value in objectReg.
-void JIT::compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset)
+void JIT::compilePutDirectOffset(RegisterID base, RegisterID value, size_t cachedOffset)
 {
     int offset = cachedOffset * sizeof(JSValue);
 {
     int offset = cachedOffset * sizeof(JSValue);
-    if (structure->isUsingInlineStorage())
-        offset += JSObject::offsetOfInlineStorage();
-    else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
+    loadPtr(Address(base, JSObject::offsetOfPropertyStorage()), base);
     storePtr(value, Address(base, offset));
 }
 
 // Compile a load from an object's property storage.  May overwrite base.
     storePtr(value, Address(base, offset));
 }
 
 // Compile a load from an object's property storage.  May overwrite base.
-void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset)
+void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, size_t cachedOffset)
 {
     int offset = cachedOffset * sizeof(JSValue);
 {
     int offset = cachedOffset * sizeof(JSValue);
-    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);
-    }
+    loadPtr(Address(base, JSObject::offsetOfPropertyStorage()), result);
+    loadPtr(Address(result, offset), result);
 }
 
 void JIT::compileGetDirectOffset(JSObject* base, RegisterID result, size_t cachedOffset)
 {
 }
 
 void JIT::compileGetDirectOffset(JSObject* base, RegisterID result, size_t cachedOffset)
 {
-    loadPtr(static_cast<void*>(&base->m_propertyStorage[cachedOffset]), result);
+    loadPtr(base->addressOfPropertyStorage(), result);
+    loadPtr(Address(result, cachedOffset * sizeof(WriteBarrier<Unknown>)), 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)
@@ -560,16 +497,29 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
     // Check eax is an object of the right Structure.
     failureCases.append(emitJumpIfNotJSCell(regT0));
     failureCases.append(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(oldStructure)));
     // Check eax is an object of the right Structure.
     failureCases.append(emitJumpIfNotJSCell(regT0));
     failureCases.append(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(oldStructure)));
+    
     testPrototype(oldStructure->storedPrototype(), failureCases);
     testPrototype(oldStructure->storedPrototype(), failureCases);
+    
+    ASSERT(oldStructure->storedPrototype().isNull() || oldStructure->storedPrototype().asCell()->structure() == chain->head()->get());
 
     // ecx = baseObject->m_structure
     if (!direct) {
 
     // ecx = baseObject->m_structure
     if (!direct) {
-        for (WriteBarrier<Structure>* it = chain->head(); *it; ++it)
+        for (WriteBarrier<Structure>* it = chain->head(); *it; ++it) {
+            ASSERT((*it)->storedPrototype().isNull() || (*it)->storedPrototype().asCell()->structure() == it[1].get());
             testPrototype((*it)->storedPrototype(), failureCases);
             testPrototype((*it)->storedPrototype(), failureCases);
+        }
     }
 
     }
 
-    Call callTarget;
-
+    // If we succeed in all of our checks, and the code was optimizable, then make sure we
+    // decrement the rare case counter.
+#if ENABLE(VALUE_PROFILER)
+    if (m_codeBlock->canCompileWithDFG()) {
+        sub32(
+            TrustedImm32(1),
+            AbsoluteAddress(&m_codeBlock->rareCaseProfileForBytecodeOffset(stubInfo->bytecodeIndex)->m_counter));
+    }
+#endif
+    
     // emit a call only if storage realloc is needed
     bool willNeedStorageRealloc = oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
     if (willNeedStorageRealloc) {
     // emit a call only if storage realloc is needed
     bool willNeedStorageRealloc = oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
     if (willNeedStorageRealloc) {
@@ -582,17 +532,20 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
         stubCall.skipArgument(); // ident
         stubCall.skipArgument(); // value
         stubCall.addArgument(TrustedImm32(oldStructure->propertyStorageCapacity()));
         stubCall.skipArgument(); // ident
         stubCall.skipArgument(); // value
         stubCall.addArgument(TrustedImm32(oldStructure->propertyStorageCapacity()));
-        stubCall.addArgument(TrustedImm32(newStructure->propertyStorageCapacity()));
+        stubCall.addArgument(TrustedImmPtr(newStructure));
         stubCall.call(regT0);
         emitGetJITStubArg(2, regT1);
 
         restoreReturnAddressBeforeReturn(regT3);
     }
 
         stubCall.call(regT0);
         emitGetJITStubArg(2, regT1);
 
         restoreReturnAddressBeforeReturn(regT3);
     }
 
-    storePtrWithWriteBarrier(TrustedImmPtr(newStructure), regT0, Address(regT0, JSCell::structureOffset()));
+    // Planting the new structure triggers the write barrier so we need
+    // an unconditional barrier here.
+    emitWriteBarrier(regT0, regT1, regT2, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);
 
 
-    // write the value
-    compilePutDirectOffset(regT0, regT1, newStructure, cachedOffset);
+    ASSERT(newStructure->classInfo() == oldStructure->classInfo());
+    storePtr(TrustedImmPtr(newStructure), Address(regT0, JSCell::structureOffset()));
+    compilePutDirectOffset(regT0, regT1, cachedOffset);
 
     ret();
     
 
     ret();
     
@@ -601,7 +554,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
     restoreArgumentReferenceForTrampoline();
     Call failureCall = tailRecursiveCall();
 
     restoreArgumentReferenceForTrampoline();
     Call failureCall = tailRecursiveCall();
 
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
 
     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));
 
@@ -610,10 +563,9 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
         patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
     }
     
         patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
     }
     
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-    stubInfo->stubRoutine = entryLabel;
+    stubInfo->stubRoutine = patchBuffer.finalizeCode();
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relinkCallerToTrampoline(returnAddress, entryLabel);
+    repatchBuffer.relinkCallerToTrampoline(returnAddress, CodeLocationLabel(stubInfo->stubRoutine.code()));
 }
 
 void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
 }
 
 void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
@@ -627,8 +579,8 @@ void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, St
     int offset = sizeof(JSValue) * cachedOffset;
 
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     int offset = sizeof(JSValue) * cachedOffset;
 
     // 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.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset), offset);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.get.structureToCompare), structure);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel), 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)
@@ -642,8 +594,8 @@ void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo,
     int offset = sizeof(JSValue) * cachedOffset;
 
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     int offset = sizeof(JSValue) * cachedOffset;
 
     // 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);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.put.structureToCompare), structure);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(stubInfo->patch.baseline.u.put.displacementLabel), offset);
 }
 
 void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
 }
 
 void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
@@ -651,7 +603,7 @@ 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), TrustedImmPtr(m_globalData->jsArrayVPtr));
+    Jump failureCases1 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
 
     // Checks out okay! - get the length from the storage
     loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
 
     // Checks out okay! - get the length from the storage
     loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
@@ -661,24 +613,23 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
     emitFastArithIntToImmNoCheck(regT2, regT0);
     Jump success = jump();
 
     emitFastArithIntToImmNoCheck(regT2, regT0);
     Jump success = jump();
 
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
 
     // Use the patch information to link the failure cases back to the original slow case routine.
 
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
+    CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin);
     patchBuffer.link(failureCases1, slowCaseBegin);
     patchBuffer.link(failureCases2, slowCaseBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(failureCases1, slowCaseBegin);
     patchBuffer.link(failureCases2, slowCaseBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
     // Track the stub we have created so that it will be deleted later.
 
     // Track the stub we have created so that it will be deleted later.
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-    stubInfo->stubRoutine = entryLabel;
+    stubInfo->stubRoutine = patchBuffer.finalizeCode();
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code()));
 
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_array_fail));
 
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_array_fail));
@@ -719,15 +670,15 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
     } else
         compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
     } else
         compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
 
     // Use the patch information to link the failure cases back to the original slow case routine.
 
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
+    CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin);
     patchBuffer.link(failureCases1, slowCaseBegin);
     patchBuffer.link(failureCases2, slowCaseBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(failureCases1, slowCaseBegin);
     patchBuffer.link(failureCases2, slowCaseBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
     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) {
@@ -736,13 +687,12 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
         }
     }
     // Track the stub we have created so that it will be deleted later.
         }
     }
     // Track the stub we have created so that it will be deleted later.
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-    stubInfo->stubRoutine = entryLabel;
+    stubInfo->stubRoutine = patchBuffer.finalizeCode();
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code()));
 
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
 
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
@@ -752,9 +702,10 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
 {
     Jump failureCase = checkStructure(regT0, structure);
     bool needsStubLink = false;
 {
     Jump failureCase = checkStructure(regT0, structure);
     bool needsStubLink = false;
+    bool isDirect = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(regT0, regT1, structure, cachedOffset);
+        compileGetDirectOffset(regT0, 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);
@@ -768,11 +719,13 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
-    } else
-        compileGetDirectOffset(regT0, regT0, structure, cachedOffset);
+    } else {
+        isDirect = true;
+        compileGetDirectOffset(regT0, regT0, cachedOffset);
+    }
     Jump success = jump();
 
     Jump success = jump();
 
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
 
     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) {
@@ -782,23 +735,23 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
     }
 
     // Use the patch information to link the failure cases back to the original slow case routine.
     }
 
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine;
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(polymorphicStructures->list[currentIndex - 1].stubRoutine.code());
     if (!lastProtoBegin)
     if (!lastProtoBegin)
-        lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
+        lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin);
 
     patchBuffer.link(failureCase, lastProtoBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
 
     patchBuffer.link(failureCase, lastProtoBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
 
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+    MacroAssemblerCodeRef stubCode = patchBuffer.finalizeCode();
 
 
-    polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), entryLabel, structure);
+    polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, isDirect);
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubCode.code()));
 }
 
 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
 }
 
 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
@@ -816,6 +769,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
 
     // Checks out okay!
     bool needsStubLink = false;
 
     // Checks out okay!
     bool needsStubLink = false;
+    bool isDirect = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
         compileGetDirectOffset(protoObject, regT1, cachedOffset);
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
         compileGetDirectOffset(protoObject, regT1, cachedOffset);
@@ -832,12 +786,14 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
-    } else
+    } else {
+        isDirect = true;
         compileGetDirectOffset(protoObject, regT0, cachedOffset);
         compileGetDirectOffset(protoObject, regT0, cachedOffset);
+    }
 
     Jump success = jump();
 
 
     Jump success = jump();
 
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
 
     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) {
@@ -847,20 +803,20 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
     }
 
     // Use the patch information to link the failure cases back to the original slow case routine.
     }
 
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(prototypeStructures->list[currentIndex - 1].stubRoutine.code());
     patchBuffer.link(failureCases1, lastProtoBegin);
     patchBuffer.link(failureCases2, lastProtoBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(failureCases1, lastProtoBegin);
     patchBuffer.link(failureCases2, lastProtoBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
 
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-    prototypeStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), entryLabel, structure, prototypeStructure);
+    MacroAssemblerCodeRef stubCode = patchBuffer.finalizeCode();
+    prototypeStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, prototypeStructure, isDirect);
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubCode.code()));
 }
 
 void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
 }
 
 void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
@@ -883,6 +839,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     ASSERT(protoObject);
     
     bool needsStubLink = false;
     ASSERT(protoObject);
     
     bool needsStubLink = false;
+    bool isDirect = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
         compileGetDirectOffset(protoObject, regT1, cachedOffset);
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
         compileGetDirectOffset(protoObject, regT1, cachedOffset);
@@ -899,11 +856,13 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
-    } else
+    } else {
+        isDirect = true;
         compileGetDirectOffset(protoObject, regT0, cachedOffset);
         compileGetDirectOffset(protoObject, regT0, cachedOffset);
+    }
     Jump success = jump();
 
     Jump success = jump();
 
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
     
     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) {
@@ -913,22 +872,22 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     }
 
     // Use the patch information to link the failure cases back to the original slow case routine.
     }
 
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(prototypeStructures->list[currentIndex - 1].stubRoutine.code());
 
     patchBuffer.link(bucketsOfFail, lastProtoBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
 
     patchBuffer.link(bucketsOfFail, lastProtoBegin);
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
 
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+    CodeRef stubRoutine = patchBuffer.finalizeCode();
 
     // Track the stub we have created so that it will be deleted later.
 
     // Track the stub we have created so that it will be deleted later.
-    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, chain);
+    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect);
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
 }
 
 void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
 }
 
 void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
@@ -971,7 +930,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
         compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
 
         compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
 
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
 
     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) {
@@ -981,30 +940,175 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
     }
 
     // Use the patch information to link the failure cases back to the original slow case routine.
     }
 
     // Use the patch information to link the failure cases back to the original slow case routine.
-    patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall));
+    patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin));
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
 
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
     // Track the stub we have created so that it will be deleted later.
 
     // Track the stub we have created so that it will be deleted later.
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-    stubInfo->stubRoutine = entryLabel;
+    CodeRef stubRoutine = patchBuffer.finalizeCode();
+    stubInfo->stubRoutine = stubRoutine;
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
 
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
 }
 
 
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
 }
 
-/* ------------------------------ END: !ENABLE / ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
+void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
+{
+    int skip = currentInstruction[3].u.operand;
+
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0);
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
+        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
+        activationNotCreated.link(this);
+    }
+    while (skip--)
+        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
+
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT0);
+    loadPtr(Address(regT0, JSVariableObject::offsetOfRegisters()), regT0);
+    loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0);
+    emitValueProfilingSite();
+    emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
+{
+    int skip = currentInstruction[2].u.operand;
+
+    emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);
+
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1);
+    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);
 
 
-#endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+    emitWriteBarrier(regT1, regT0, regT2, regT3, ShouldFilterImmediates, WriteBarrierForVariableAccess);
+
+    loadPtr(Address(regT1, JSVariableObject::offsetOfRegisters()), regT1);
+    storePtr(regT0, Address(regT1, currentInstruction[1].u.operand * sizeof(Register)));
+}
+
+void JIT::emit_op_get_global_var(Instruction* currentInstruction)
+{
+    JSVariableObject* globalObject = m_codeBlock->globalObject();
+    loadPtr(&globalObject->m_registers, regT0);
+    loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0);
+    emitValueProfilingSite();
+    emitPutVirtualRegister(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_put_global_var(Instruction* currentInstruction)
+{
+    JSGlobalObject* globalObject = m_codeBlock->globalObject();
+
+    emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
+
+    move(TrustedImmPtr(globalObject), regT1);
+    loadPtr(Address(regT1, JSVariableObject::offsetOfRegisters()), regT1);
+    storePtr(regT0, Address(regT1, currentInstruction[1].u.operand * sizeof(Register)));
+    emitWriteBarrier(globalObject, regT0, regT2, ShouldFilterImmediates, WriteBarrierForVariableAccess);
+}
+
+void JIT::resetPatchGetById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo)
+{
+    repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_get_by_id);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.get.structureToCompare), reinterpret_cast<void*>(-1));
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel), 0);
+    repatchBuffer.relink(stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck), stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin));
+}
+
+void JIT::resetPatchPutById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo)
+{
+    if (isDirectPutById(stubInfo))
+        repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_put_by_id_direct);
+    else
+        repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_put_by_id);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.put.structureToCompare), reinterpret_cast<void*>(-1));
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.put.displacementLabel), 0);
+}
 
 #endif // USE(JSVALUE64)
 
 
 #endif // USE(JSVALUE64)
 
+void JIT::emitWriteBarrier(RegisterID owner, RegisterID value, RegisterID scratch, RegisterID scratch2, WriteBarrierMode mode, WriteBarrierUseKind useKind)
+{
+    UNUSED_PARAM(owner);
+    UNUSED_PARAM(scratch);
+    UNUSED_PARAM(scratch2);
+    UNUSED_PARAM(useKind);
+    UNUSED_PARAM(value);
+    UNUSED_PARAM(mode);
+    ASSERT(owner != scratch);
+    ASSERT(owner != scratch2);
+    
+#if ENABLE(WRITE_BARRIER_PROFILING)
+    emitCount(WriteBarrierCounters::jitCounterFor(useKind));
+#endif
+    
+#if ENABLE(GGC)
+    Jump filterCells;
+    if (mode == ShouldFilterImmediates)
+        filterCells = emitJumpIfNotJSCell(value);
+    move(owner, scratch);
+    andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch);
+    move(owner, scratch2);
+    // consume additional 8 bits as we're using an approximate filter
+    rshift32(TrustedImm32(MarkedBlock::atomShift + 8), scratch2);
+    andPtr(TrustedImm32(MarkedBlock::atomMask >> 8), scratch2);
+    Jump filter = branchTest8(Zero, BaseIndex(scratch, scratch2, TimesOne, MarkedBlock::offsetOfMarks()));
+    move(owner, scratch2);
+    rshift32(TrustedImm32(MarkedBlock::cardShift), scratch2);
+    andPtr(TrustedImm32(MarkedBlock::cardMask), scratch2);
+    store8(TrustedImm32(1), BaseIndex(scratch, scratch2, TimesOne, MarkedBlock::offsetOfCards()));
+    filter.link(this);
+    if (mode == ShouldFilterImmediates)
+        filterCells.link(this);
+#endif
+}
+
+void JIT::emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode mode, WriteBarrierUseKind useKind)
+{
+    UNUSED_PARAM(owner);
+    UNUSED_PARAM(scratch);
+    UNUSED_PARAM(useKind);
+    UNUSED_PARAM(value);
+    UNUSED_PARAM(mode);
+    
+#if ENABLE(WRITE_BARRIER_PROFILING)
+    emitCount(WriteBarrierCounters::jitCounterFor(useKind));
+#endif
+    
+#if ENABLE(GGC)
+    Jump filterCells;
+    if (mode == ShouldFilterImmediates)
+        filterCells = emitJumpIfNotJSCell(value);
+    uint8_t* cardAddress = Heap::addressOfCardFor(owner);
+    move(TrustedImmPtr(cardAddress), scratch);
+    store8(TrustedImm32(1), Address(scratch));
+    if (mode == ShouldFilterImmediates)
+        filterCells.link(this);
+#endif
+}
+
 void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
 {
     if (prototype.isNull())
 void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
 {
     if (prototype.isNull())
@@ -1015,19 +1119,43 @@ void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
     failureCases.append(branchPtr(NotEqual, Address(regT3, JSCell::structureOffset()), TrustedImmPtr(prototype.asCell()->structure())));
 }
 
     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)
+void JIT::patchMethodCallProto(JSGlobalData& globalData, CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, StructureStubInfo& stubInfo, JSObject* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress)
 {
     RepatchBuffer repatchBuffer(codeBlock);
     
 {
     RepatchBuffer repatchBuffer(codeBlock);
     
-    ASSERT(!methodCallLinkInfo.cachedStructure);
     CodeLocationDataLabelPtr structureLocation = methodCallLinkInfo.cachedStructure.location();
     methodCallLinkInfo.cachedStructure.set(globalData, structureLocation, codeBlock->ownerExecutable(), structure);
     
     Structure* prototypeStructure = proto->structure();
     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));
+    methodCallLinkInfo.cachedPrototypeStructure.set(globalData, structureLocation.dataLabelPtrAtOffset(stubInfo.patch.baseline.methodCheckProtoStructureToCompare), codeBlock->ownerExecutable(), prototypeStructure);
+    methodCallLinkInfo.cachedPrototype.set(globalData, structureLocation.dataLabelPtrAtOffset(stubInfo.patch.baseline.methodCheckProtoObj), codeBlock->ownerExecutable(), proto);
+    methodCallLinkInfo.cachedFunction.set(globalData, structureLocation.dataLabelPtrAtOffset(stubInfo.patch.baseline.methodCheckPutFunction), codeBlock->ownerExecutable(), callee);
+    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_method_check_update));
+}
+
+bool JIT::isDirectPutById(StructureStubInfo* stubInfo)
+{
+    switch (stubInfo->accessType) {
+    case access_put_by_id_transition_normal:
+        return false;
+    case access_put_by_id_transition_direct:
+        return true;
+    case access_put_by_id_replace:
+    case access_put_by_id_generic: {
+        void* oldCall = MacroAssembler::readCallTarget(stubInfo->callReturnLocation).executableAddress();
+        if (oldCall == bitwise_cast<void*>(cti_op_put_by_id_direct)
+            || oldCall == bitwise_cast<void*>(cti_op_put_by_id_direct_generic)
+            || oldCall == bitwise_cast<void*>(cti_op_put_by_id_direct_fail))
+            return true;
+        ASSERT(oldCall == bitwise_cast<void*>(cti_op_put_by_id)
+               || oldCall == bitwise_cast<void*>(cti_op_put_by_id_generic)
+               || oldCall == bitwise_cast<void*>(cti_op_put_by_id_fail));
+        return false;
+    }
+    default:
+        ASSERT_NOT_REACHED();
+        return false;
+    }
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 3b3050e0bdd75b9c6c342fc54e38c4c185602e9d..550ad0b2ef2a6d32193c24d4928c7c6d94e80db5 100644 (file)
@@ -57,34 +57,23 @@ void JIT::emit_op_put_by_index(Instruction* currentInstruction)
     
     JITStubCall stubCall(this, cti_op_put_by_index);
     stubCall.addArgument(base);
     
     JITStubCall stubCall(this, cti_op_put_by_index);
     stubCall.addArgument(base);
-    stubCall.addArgument(Imm32(property));
+    stubCall.addArgument(TrustedImm32(property));
     stubCall.addArgument(value);
     stubCall.call();
 }
 
     stubCall.addArgument(value);
     stubCall.call();
 }
 
-void JIT::emit_op_put_getter(Instruction* currentInstruction)
+void JIT::emit_op_put_getter_setter(Instruction* currentInstruction)
 {
     unsigned base = currentInstruction[1].u.operand;
     unsigned property = currentInstruction[2].u.operand;
 {
     unsigned base = currentInstruction[1].u.operand;
     unsigned property = currentInstruction[2].u.operand;
-    unsigned function = currentInstruction[3].u.operand;
+    unsigned getter = currentInstruction[3].u.operand;
+    unsigned setter = currentInstruction[4].u.operand;
     
     
-    JITStubCall stubCall(this, cti_op_put_getter);
+    JITStubCall stubCall(this, cti_op_put_getter_setter);
     stubCall.addArgument(base);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property)));
     stubCall.addArgument(base);
     stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property)));
-    stubCall.addArgument(function);
-    stubCall.call();
-}
-
-void JIT::emit_op_put_setter(Instruction* currentInstruction)
-{
-    unsigned base = currentInstruction[1].u.operand;
-    unsigned property = currentInstruction[2].u.operand;
-    unsigned function = currentInstruction[3].u.operand;
-    
-    JITStubCall stubCall(this, cti_op_put_setter);
-    stubCall.addArgument(base);
-    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property)));
-    stubCall.addArgument(function);
+    stubCall.addArgument(getter);
+    stubCall.addArgument(setter);
     stubCall.call();
 }
 
     stubCall.call();
 }
 
@@ -100,100 +89,6 @@ void JIT::emit_op_del_by_id(Instruction* currentInstruction)
     stubCall.call(dst);
 }
 
     stubCall.call(dst);
 }
 
-
-#if !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-
-/* ------------------------------ BEGIN: !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
-
-// Treat these as nops - the call will be handed as a regular get_by_id/op_call pair.
-void JIT::emit_op_method_check(Instruction*) {}
-void JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&) { ASSERT_NOT_REACHED(); }
-#if ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
-#error "JIT_OPTIMIZE_METHOD_CALLS requires JIT_OPTIMIZE_PROPERTY_ACCESS"
-#endif
-
-void JIT::emit_op_get_by_val(Instruction* currentInstruction)
-{
-    unsigned dst = currentInstruction[1].u.operand;
-    unsigned base = currentInstruction[2].u.operand;
-    unsigned property = currentInstruction[3].u.operand;
-    
-    JITStubCall stubCall(this, cti_op_get_by_val);
-    stubCall.addArgument(base);
-    stubCall.addArgument(property);
-    stubCall.call(dst);
-}
-
-void JIT::emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&)
-{
-    ASSERT_NOT_REACHED();
-}
-
-void JIT::emit_op_put_by_val(Instruction* currentInstruction)
-{
-    unsigned base = currentInstruction[1].u.operand;
-    unsigned property = currentInstruction[2].u.operand;
-    unsigned value = currentInstruction[3].u.operand;
-    
-    JITStubCall stubCall(this, cti_op_put_by_val);
-    stubCall.addArgument(base);
-    stubCall.addArgument(property);
-    stubCall.addArgument(value);
-    stubCall.call();
-}
-
-void JIT::emitSlow_op_put_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&)
-{
-    ASSERT_NOT_REACHED();
-}
-
-void JIT::emit_op_get_by_id(Instruction* currentInstruction)
-{
-    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);
-    
-    m_propertyAccessInstructionIndex++;
-}
-
-void JIT::emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&)
-{
-    m_propertyAccessInstructionIndex++;
-    ASSERT_NOT_REACHED();
-}
-
-void JIT::emit_op_put_by_id(Instruction* currentInstruction)
-{
-    int base = currentInstruction[1].u.operand;
-    int ident = currentInstruction[2].u.operand;
-    int value = currentInstruction[3].u.operand;
-    
-    JITStubCall stubCall(this, cti_op_put_by_id_generic);
-    stubCall.addArgument(base);
-    stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident))));
-    stubCall.addArgument(value);
-    stubCall.call();
-    
-    m_propertyAccessInstructionIndex++;
-}
-
-void JIT::emitSlow_op_put_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&)
-{
-    m_propertyAccessInstructionIndex++;
-    ASSERT_NOT_REACHED();
-}
-
-#else // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-
-/* ------------------------------ BEGIN: ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
-
-#if ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
-
 void JIT::emit_op_method_check(Instruction* currentInstruction)
 {
     // Assert that the following instruction is a get_by_id.
 void JIT::emit_op_method_check(Instruction* currentInstruction)
 {
     // Assert that the following instruction is a get_by_id.
@@ -202,7 +97,7 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     currentInstruction += OPCODE_LENGTH(op_method_check);
     
     // Do the method check - check the object & its prototype's structure inline (this is the common case).
     currentInstruction += OPCODE_LENGTH(op_method_check);
     
     // Do the method check - check the object & its prototype's structure inline (this is the common case).
-    m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_propertyAccessInstructionIndex));
+    m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_bytecodeOffset, m_propertyAccessCompilationInfo.size()));
     MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
     
     int dst = currentInstruction[1].u.operand;
     MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
     
     int dst = currentInstruction[1].u.operand;
@@ -225,10 +120,6 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     move(TrustedImm32(JSValue::CellTag), regT1);
     Jump match = jump();
     
     move(TrustedImm32(JSValue::CellTag), regT1);
     Jump match = jump();
     
-    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);
     protoStructureCheck.link(this);
     // Link the failure cases here.
     structureCheck.link(this);
     protoStructureCheck.link(this);
@@ -238,11 +129,14 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     compileGetByIdHotPath();
     
     match.link(this);
     compileGetByIdHotPath();
     
     match.link(this);
+    emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
     emitStore(dst, regT1, regT0);
     emitStore(dst, regT1, regT0);
-    map(m_bytecodeOffset + OPCODE_LENGTH(op_method_check), dst, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id), dst, regT1, regT0);
     
     // We've already generated the following get_by_id, so make sure it's skipped over.
     m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
     
     // We've already generated the following get_by_id, so make sure it's skipped over.
     m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
+
+    m_propertyAccessCompilationInfo.last().addMethodCheckInfo(info.structureToCompare, protoObj, protoStructureToCompare, putFunction);
 }
 
 void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -254,36 +148,39 @@ void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowC
     int ident = currentInstruction[3].u.operand;
     
     compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter, true);
     int ident = currentInstruction[3].u.operand;
     
     compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter, true);
+    emitValueProfilingSite(m_bytecodeOffset + OPCODE_LENGTH(op_method_check));
     
     // We've already generated the following get_by_id, so make sure it's skipped over.
     m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
 }
 
     
     // We've already generated the following get_by_id, so make sure it's skipped over.
     m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
 }
 
-#else //!ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
-
-// Treat these as nops - the call will be handed as a regular get_by_id/op_call pair.
-void JIT::emit_op_method_check(Instruction*) {}
-void JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&) { ASSERT_NOT_REACHED(); }
-
-#endif
-
-JIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+JIT::CodeRef JIT::stringGetByValStubGenerator(JSGlobalData* globalData)
 {
     JSInterfaceJIT jit;
     JumpList failures;
 {
     JSInterfaceJIT jit;
     JumpList failures;
-    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.branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
     
     // Load string length to regT1, and start the process of loading the data pointer into regT0
     jit.load32(Address(regT0, ThunkHelpers::jsStringLengthOffset()), regT1);
     jit.loadPtr(Address(regT0, ThunkHelpers::jsStringValueOffset()), regT0);
     
     // Load string length to regT1, and start the process of loading the data pointer into regT0
     jit.load32(Address(regT0, ThunkHelpers::jsStringLengthOffset()), regT1);
     jit.loadPtr(Address(regT0, ThunkHelpers::jsStringValueOffset()), regT0);
-    jit.loadPtr(Address(regT0, ThunkHelpers::stringImplDataOffset()), regT0);
+    failures.append(jit.branchTest32(Zero, regT0));
     
     // Do an unsigned compare to simultaneously filter negative indices as well as indices that are too large
     failures.append(jit.branch32(AboveOrEqual, regT2, regT1));
     
     // Load the character
     
     // Do an unsigned compare to simultaneously filter negative indices as well as indices that are too large
     failures.append(jit.branch32(AboveOrEqual, regT2, regT1));
     
     // Load the character
+    JumpList is16Bit;
+    JumpList cont8Bit;
+    // Load the string flags
+    jit.loadPtr(Address(regT0, ThunkHelpers::stringImplFlagsOffset()), regT1);
+    jit.loadPtr(Address(regT0, ThunkHelpers::stringImplDataOffset()), regT0);
+    is16Bit.append(jit.branchTest32(Zero, regT1, TrustedImm32(ThunkHelpers::stringImpl8BitFlag())));
+    jit.load8(BaseIndex(regT0, regT2, TimesOne, 0), regT0);
+    cont8Bit.append(jit.jump());
+    is16Bit.link(&jit);
     jit.load16(BaseIndex(regT0, regT2, TimesTwo, 0), regT0);
     jit.load16(BaseIndex(regT0, regT2, TimesTwo, 0), regT0);
+
+    cont8Bit.link(&jit);
     
     failures.append(jit.branch32(AboveOrEqual, regT0, TrustedImm32(0x100)));
     jit.move(TrustedImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1);
     
     failures.append(jit.branch32(AboveOrEqual, regT0, TrustedImm32(0x100)));
     jit.move(TrustedImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1);
@@ -295,8 +192,8 @@ JIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, Executab
     jit.move(TrustedImm32(0), regT0);
     jit.ret();
     
     jit.move(TrustedImm32(0), regT0);
     jit.ret();
     
-    LinkBuffer patchBuffer(*globalData, &jit, pool);
-    return patchBuffer.finalizeCode().m_code;
+    LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
+    return patchBuffer.finalizeCode();
 }
 
 void JIT::emit_op_get_by_val(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_get_by_val(Instruction* currentInstruction)
@@ -309,7 +206,7 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
     
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
+    addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
     
     loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
     addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
     
     loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
     addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
@@ -318,6 +215,7 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
     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)));
     
     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)));
     
+    emitValueProfilingSite();
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0);
 }
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0);
 }
@@ -333,8 +231,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), TrustedImmPtr(m_globalData->jsStringVPtr));
-    emitNakedCall(m_globalData->getCTIStub(stringGetByValStubGenerator));
+    Jump notString = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info));
+    emitNakedCall(m_globalData->getCTIStub(stringGetByValStubGenerator).code());
     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));
@@ -349,6 +247,8 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas
     stubCall.addArgument(base);
     stubCall.addArgument(property);
     stubCall.call(dst);
     stubCall.addArgument(base);
     stubCall.addArgument(property);
     stubCall.call(dst);
+
+    emitValueProfilingSite();
 }
 
 void JIT::emit_op_put_by_val(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_put_by_val(Instruction* currentInstruction)
@@ -361,9 +261,10 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction)
     
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     
     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
+    addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
     addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
     addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
-    
+
+    emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);
     loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
     
     Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
     loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
     
     Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
@@ -411,6 +312,7 @@ void JIT::emit_op_get_by_id(Instruction* currentInstruction)
     emitLoad(base, regT1, regT0);
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     compileGetByIdHotPath();
     emitLoad(base, regT1, regT0);
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     compileGetByIdHotPath();
+    emitValueProfilingSite();
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_id), dst, regT1, regT0);
 }
     emitStore(dst, regT1, regT0);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_id), dst, regT1, regT0);
 }
@@ -425,25 +327,20 @@ void JIT::compileGetByIdHotPath()
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
     
     Label hotPathBegin(this);
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
     
     Label hotPathBegin(this);
-    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
-    m_propertyAccessInstructionIndex++;
     
     DataLabelPtr structureToCompare;
     
     DataLabelPtr structureToCompare;
-    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+    PatchableJump structureCheck = patchableBranchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
     addSlowCase(structureCheck);
     addSlowCase(structureCheck);
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure);
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase);
     
     
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT2);
+    loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT2);
     DataLabelCompact displacementLabel1 = loadPtrWithCompactAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT0); // payload
     DataLabelCompact displacementLabel1 = loadPtrWithCompactAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT0); // payload
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel1), patchOffsetGetByIdPropertyMapOffset1);
     DataLabelCompact displacementLabel2 = loadPtrWithCompactAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT1); // tag
     DataLabelCompact displacementLabel2 = loadPtrWithCompactAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT1); // tag
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel2), patchOffsetGetByIdPropertyMapOffset2);
     
     Label putResult(this);
     
     Label putResult(this);
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, putResult), patchOffsetGetByIdPutResult);
     
     END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
     
     END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
+
+    m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo(PropertyStubGetById, m_bytecodeOffset, hotPathBegin, structureToCompare, structureCheck, displacementLabel1, displacementLabel2, putResult));
 }
 
 void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 }
 
 void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -453,6 +350,7 @@ void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCase
     int ident = currentInstruction[3].u.operand;
     
     compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter);
     int ident = currentInstruction[3].u.operand;
     
     compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter);
+    emitValueProfilingSite();
 }
 
 void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck)
 }
 
 void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck)
@@ -467,9 +365,7 @@ void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<Sl
     
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
     
     
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
     
-#ifndef NDEBUG
     Label coldPathBegin(this);
     Label coldPathBegin(this);
-#endif
     JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id);
     stubCall.addArgument(regT1, regT0);
     stubCall.addArgument(TrustedImmPtr(ident));
     JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id);
     stubCall.addArgument(regT1, regT0);
     stubCall.addArgument(TrustedImmPtr(ident));
@@ -477,11 +373,8 @@ void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<Sl
     
     END_UNINTERRUPTED_SEQUENCE_FOR_PUT(sequenceGetByIdSlowCase, dst);
     
     
     END_UNINTERRUPTED_SEQUENCE_FOR_PUT(sequenceGetByIdSlowCase, dst);
     
-    ASSERT_JIT_OFFSET(differenceBetween(coldPathBegin, call), patchOffsetGetByIdSlowCaseCall);
-    
     // Track the location of the call; this will be used to recover patch information.
     // Track the location of the call; this will be used to recover patch information.
-    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call;
-    m_propertyAccessInstructionIndex++;
+    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].slowCaseInfo(PropertyStubGetById, coldPathBegin, call);
 }
 
 void JIT::emit_op_put_by_id(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_put_by_id(Instruction* currentInstruction)
@@ -500,22 +393,20 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
     BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById);
     
     Label hotPathBegin(this);
     BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById);
     
     Label hotPathBegin(this);
-    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
-    m_propertyAccessInstructionIndex++;
     
     // 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, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
     
     // 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, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure);
     
     
-    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
+    loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT1);
+    DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT1, patchPutByIdDefaultOffset)); // payload
+    DataLabel32 displacementLabel2 = storePtrWithAddressOffsetPatch(regT3, Address(regT1, patchPutByIdDefaultOffset)); // tag
     
     END_UNINTERRUPTED_SEQUENCE(sequencePutById);
     
     END_UNINTERRUPTED_SEQUENCE(sequencePutById);
-    
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel1), patchOffsetPutByIdPropertyMapOffset1);
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel2), patchOffsetPutByIdPropertyMapOffset2);
+
+    emitWriteBarrier(regT0, regT2, regT1, regT2, ShouldFilterImmediates, WriteBarrierForPropertyAccess);
+
+    m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo(PropertyStubPutById, m_bytecodeOffset, hotPathBegin, structureToCompare, displacementLabel1, displacementLabel2));
 }
 
 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)
@@ -528,50 +419,42 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase
     linkSlowCase(iter);
     
     JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id);
     linkSlowCase(iter);
     
     JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id);
-    stubCall.addArgument(regT1, regT0);
+    stubCall.addArgument(base);
     stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident))));
     stubCall.addArgument(regT3, regT2); 
     Call call = stubCall.call();
     
     // Track the location of the call; this will be used to recover patch information.
     stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident))));
     stubCall.addArgument(regT3, regT2); 
     Call call = stubCall.call();
     
     // Track the location of the call; this will be used to recover patch information.
-    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call;
-    m_propertyAccessInstructionIndex++;
+    m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].slowCaseInfo(PropertyStubPutById, call);
 }
 
 // Compile a store into an object's property storage.  May overwrite base.
 }
 
 // Compile a store into an object's property storage.  May overwrite base.
-void JIT::compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, Structure* structure, size_t cachedOffset)
+void JIT::compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, size_t cachedOffset)
 {
     int offset = cachedOffset;
 {
     int offset = cachedOffset;
-    if (structure->isUsingInlineStorage())
-        offset += JSObject::offsetOfInlineStorage() /  sizeof(Register);
-    else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
+    loadPtr(Address(base, JSObject::offsetOfPropertyStorage()), base);
     emitStore(offset, valueTag, valuePayload, base);
 }
 
 // Compile a load from an object's property storage.  May overwrite base.
     emitStore(offset, valueTag, valuePayload, base);
 }
 
 // Compile a load from an object's property storage.  May overwrite base.
-void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset)
+void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
 {
     int offset = cachedOffset;
 {
     int offset = cachedOffset;
-    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);
-    }
+    RegisterID temp = resultPayload;
+    loadPtr(Address(base, JSObject::offsetOfPropertyStorage()), temp);
+    emitLoad(offset, resultTag, resultPayload, temp);
 }
 
 void JIT::compileGetDirectOffset(JSObject* base, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
 {
 }
 
 void JIT::compileGetDirectOffset(JSObject* base, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
 {
-    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);
+    loadPtr(base->addressOfPropertyStorage(), resultTag);
+    load32(Address(resultTag, cachedOffset * sizeof(WriteBarrier<Unknown>) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
+    load32(Address(resultTag, cachedOffset * sizeof(WriteBarrier<Unknown>) + 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)
 {
-    // The code below assumes that regT0 contains the basePayload and regT1 contains the baseTag.  Restore them from 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);
 #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);
@@ -593,6 +476,16 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
             testPrototype((*it)->storedPrototype(), failureCases);
     }
 
             testPrototype((*it)->storedPrototype(), failureCases);
     }
 
+    // If we succeed in all of our checks, and the code was optimizable, then make sure we
+    // decrement the rare case counter.
+#if ENABLE(VALUE_PROFILER)
+    if (m_codeBlock->canCompileWithDFG()) {
+        sub32(
+            TrustedImm32(1),
+            AbsoluteAddress(&m_codeBlock->rareCaseProfileForBytecodeOffset(stubInfo->bytecodeIndex)->m_counter));
+    }
+#endif
+    
     // Reallocate property storage if needed.
     Call callTarget;
     bool willNeedStorageRealloc = oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
     // Reallocate property storage if needed.
     Call callTarget;
     bool willNeedStorageRealloc = oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
@@ -606,9 +499,9 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
         stubCall.skipArgument(); // ident
         stubCall.skipArgument(); // value
         stubCall.addArgument(TrustedImm32(oldStructure->propertyStorageCapacity()));
         stubCall.skipArgument(); // ident
         stubCall.skipArgument(); // value
         stubCall.addArgument(TrustedImm32(oldStructure->propertyStorageCapacity()));
-        stubCall.addArgument(TrustedImm32(newStructure->propertyStorageCapacity()));
+        stubCall.addArgument(TrustedImmPtr(newStructure));
         stubCall.call(regT0);
         stubCall.call(regT0);
-        
+
         restoreReturnAddressBeforeReturn(regT3);
 
 #if CPU(MIPS) || CPU(SH4) || CPU(ARM)
         restoreReturnAddressBeforeReturn(regT3);
 
 #if CPU(MIPS) || CPU(SH4) || CPU(ARM)
@@ -622,8 +515,9 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
 #endif
     }
 
 #endif
     }
 
-    storePtrWithWriteBarrier(TrustedImmPtr(newStructure), regT0, Address(regT0, JSCell::structureOffset()));
-    
+    emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);
+
+    storePtr(TrustedImmPtr(newStructure), Address(regT0, JSCell::structureOffset()));
 #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);
 #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);
@@ -632,10 +526,8 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
     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
     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);
-
+    compilePutDirectOffset(regT0, regT2, regT3, cachedOffset);
+    
     ret();
     
     ASSERT(!failureCases.empty());
     ret();
     
     ASSERT(!failureCases.empty());
@@ -643,7 +535,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
     restoreArgumentReferenceForTrampoline();
     Call failureCall = tailRecursiveCall();
     
     restoreArgumentReferenceForTrampoline();
     Call failureCall = tailRecursiveCall();
     
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
     
     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));
     
@@ -652,10 +544,9 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
         patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
     }
     
         patchBuffer.link(m_calls[0].from, FunctionPtr(cti_op_put_by_id_transition_realloc));
     }
     
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-    stubInfo->stubRoutine = entryLabel;
+    stubInfo->stubRoutine = patchBuffer.finalizeCode();
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relinkCallerToTrampoline(returnAddress, entryLabel);
+    repatchBuffer.relinkCallerToTrampoline(returnAddress, CodeLocationLabel(stubInfo->stubRoutine.code()));
 }
 
 void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
 }
 
 void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
@@ -669,9 +560,9 @@ void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, St
     int offset = sizeof(JSValue) * cachedOffset;
 
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     int offset = sizeof(JSValue) * cachedOffset;
 
     // 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.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
-    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.get.structureToCompare), structure);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel2), 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)
@@ -685,9 +576,9 @@ void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo,
     int offset = sizeof(JSValue) * cachedOffset;
 
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     int offset = sizeof(JSValue) * cachedOffset;
 
     // 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 + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
-    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.put.structureToCompare), structure);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(stubInfo->patch.baseline.u.put.displacementLabel1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(stubInfo->patch.baseline.u.put.displacementLabel2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag
 }
 
 void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
 }
 
 void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
@@ -697,7 +588,7 @@ 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), TrustedImmPtr(m_globalData->jsArrayVPtr));
+    Jump failureCases1 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
     
     // Checks out okay! - get the length from the storage
     loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
     
     // Checks out okay! - get the length from the storage
     loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
@@ -708,24 +599,23 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
     move(TrustedImm32(JSValue::Int32Tag), regT1);
     Jump success = jump();
     
     move(TrustedImm32(JSValue::Int32Tag), regT1);
     Jump success = jump();
     
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
     
     // Use the patch information to link the failure cases back to the original slow case routine.
     
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
+    CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin);
     patchBuffer.link(failureCases1, slowCaseBegin);
     patchBuffer.link(failureCases2, slowCaseBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(failureCases1, slowCaseBegin);
     patchBuffer.link(failureCases2, slowCaseBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
     // Track the stub we have created so that it will be deleted later.
     
     // Track the stub we have created so that it will be deleted later.
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-    stubInfo->stubRoutine = entryLabel;
+    stubInfo->stubRoutine = patchBuffer.finalizeCode();
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code()));
     
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_array_fail));
     
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_array_fail));
@@ -768,15 +658,15 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
     
     Jump success = jump();
     
     
     Jump success = jump();
     
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
     
     // Use the patch information to link the failure cases back to the original slow case routine.
     
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
+    CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin);
     patchBuffer.link(failureCases1, slowCaseBegin);
     patchBuffer.link(failureCases2, slowCaseBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(failureCases1, slowCaseBegin);
     patchBuffer.link(failureCases2, slowCaseBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
     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) {
@@ -786,13 +676,12 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
     }
 
     // Track the stub we have created so that it will be deleted later.
     }
 
     // Track the stub we have created so that it will be deleted later.
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-    stubInfo->stubRoutine = entryLabel;
+    stubInfo->stubRoutine = patchBuffer.finalizeCode();
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code()));
     
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
     
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
@@ -804,9 +693,10 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
     // regT0 holds a JSCell*
     Jump failureCase = checkStructure(regT0, structure);
     bool needsStubLink = false;
     // regT0 holds a JSCell*
     Jump failureCase = checkStructure(regT0, structure);
     bool needsStubLink = false;
+    bool isDirect = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(regT0, regT2, regT1, structure, cachedOffset);
+        compileGetDirectOffset(regT0, 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);
@@ -820,12 +710,14 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
-    } else
-        compileGetDirectOffset(regT0, regT1, regT0, structure, cachedOffset);
+    } else {
+        isDirect = true;
+        compileGetDirectOffset(regT0, regT1, regT0, cachedOffset);
+    }
 
     Jump success = jump();
     
 
     Jump success = jump();
     
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
     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)
@@ -833,23 +725,23 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
         }
     }    
     // Use the patch information to link the failure cases back to the original slow case routine.
         }
     }    
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine;
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(polymorphicStructures->list[currentIndex - 1].stubRoutine.code());
     if (!lastProtoBegin)
     if (!lastProtoBegin)
-        lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
+        lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin);
     
     patchBuffer.link(failureCase, lastProtoBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     
     patchBuffer.link(failureCase, lastProtoBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
 
 
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+    CodeRef stubRoutine = patchBuffer.finalizeCode();
 
 
-    polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), entryLabel, structure);
+    polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
 }
 
 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
 }
 
 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
@@ -868,6 +760,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
     Jump failureCases2 = branchPtr(NotEqual, Address(regT3, JSCell::structureOffset()), TrustedImmPtr(prototypeStructure));
     
     bool needsStubLink = false;
     Jump failureCases2 = branchPtr(NotEqual, Address(regT3, JSCell::structureOffset()), TrustedImmPtr(prototypeStructure));
     
     bool needsStubLink = false;
+    bool isDirect = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
         compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
         compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
@@ -884,12 +777,14 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
-    } else
+    } else {
+        isDirect = true;
         compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
         compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+    }
     
     Jump success = jump();
     
     
     Jump success = jump();
     
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
     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)
@@ -897,21 +792,21 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
         }
     }
     // Use the patch information to link the failure cases back to the original slow case routine.
         }
     }
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(prototypeStructures->list[currentIndex - 1].stubRoutine.code());
     patchBuffer.link(failureCases1, lastProtoBegin);
     patchBuffer.link(failureCases2, lastProtoBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     patchBuffer.link(failureCases1, lastProtoBegin);
     patchBuffer.link(failureCases2, lastProtoBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
     
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+    CodeRef stubRoutine = patchBuffer.finalizeCode();
 
 
-    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, prototypeStructure);
+    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, prototypeStructure, isDirect);
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
 }
 
 void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
 }
 
 void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
@@ -935,6 +830,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     ASSERT(protoObject);
     
     bool needsStubLink = false;
     ASSERT(protoObject);
     
     bool needsStubLink = false;
+    bool isDirect = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
         compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
         compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
@@ -951,12 +847,14 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
-    } else
+    } else {
+        isDirect = true;
         compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
         compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+    }
 
     Jump success = jump();
     
 
     Jump success = jump();
     
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
     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)
@@ -964,22 +862,22 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
         }
     }
     // Use the patch information to link the failure cases back to the original slow case routine.
         }
     }
     // Use the patch information to link the failure cases back to the original slow case routine.
-    CodeLocationLabel lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
+    CodeLocationLabel lastProtoBegin = CodeLocationLabel(prototypeStructures->list[currentIndex - 1].stubRoutine.code());
     
     patchBuffer.link(bucketsOfFail, lastProtoBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     
     patchBuffer.link(bucketsOfFail, lastProtoBegin);
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
     
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+    CodeRef stubRoutine = patchBuffer.finalizeCode();
     
     // Track the stub we have created so that it will be deleted later.
     
     // Track the stub we have created so that it will be deleted later.
-    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, chain);
+    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect);
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
 }
 
 void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
 }
 
 void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
@@ -1023,7 +921,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
         compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     Jump success = jump();
     
         compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     Jump success = jump();
     
-    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock);
     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,33 +929,29 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
         }
     }
     // Use the patch information to link the failure cases back to the original slow case routine.
         }
     }
     // Use the patch information to link the failure cases back to the original slow case routine.
-    patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall));
+    patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin));
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     
     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
-    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
+    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult));
     
     // Track the stub we have created so that it will be deleted later.
     
     // Track the stub we have created so that it will be deleted later.
-    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-    stubInfo->stubRoutine = entryLabel;
+    CodeRef stubRoutine = patchBuffer.finalizeCode();
+    stubInfo->stubRoutine = stubRoutine;
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
-    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck);
     RepatchBuffer repatchBuffer(m_codeBlock);
     RepatchBuffer repatchBuffer(m_codeBlock);
-    repatchBuffer.relink(jumpLocation, entryLabel);
+    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
     
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
 }
 
     
     // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
 }
 
-/* ------------------------------ END: !ENABLE / ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) ------------------------------ */
-
-#endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-
 void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID offset)
 {
     ASSERT(sizeof(JSValue) == 8);
     
 void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID offset)
 {
     ASSERT(sizeof(JSValue) == 8);
     
-    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
+    loadPtr(Address(base, JSObject::offsetOfPropertyStorage()), 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);
 }
@@ -1108,6 +1002,113 @@ void JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowC
     stubCall.call(dst);
 }
 
     stubCall.call(dst);
 }
 
+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;
+
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), TrustedImm32(JSValue::EmptyValueTag));
+        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
+        activationNotCreated.link(this);
+    }
+    while (skip--)
+        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
+
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
+    loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2);
+
+    emitLoad(index, regT1, regT0, regT2);
+    emitValueProfilingSite();
+    emitStore(dst, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_scoped_var), dst, regT1, regT0);
+}
+
+void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
+{
+    int index = currentInstruction[1].u.operand;
+    int skip = currentInstruction[2].u.operand;
+    int value = currentInstruction[3].u.operand;
+
+    emitLoad(value, regT1, regT0);
+
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), TrustedImm32(JSValue::EmptyValueTag));
+        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
+        activationNotCreated.link(this);
+    }
+    while (skip--)
+        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
+
+    loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT3);
+    emitStore(index, regT1, regT0, regT3);
+    emitWriteBarrier(regT2, regT1, regT0, regT1, ShouldFilterImmediates, WriteBarrierForVariableAccess);
+}
+
+void JIT::emit_op_get_global_var(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    JSGlobalObject* globalObject = m_codeBlock->globalObject();
+    ASSERT(globalObject->isGlobalObject());
+    int index = currentInstruction[2].u.operand;
+
+    loadPtr(&globalObject->m_registers, regT2);
+
+    emitLoad(index, regT1, regT0, regT2);
+    emitValueProfilingSite();
+    emitStore(dst, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_global_var), dst, regT1, regT0);
+}
+
+void JIT::emit_op_put_global_var(Instruction* currentInstruction)
+{
+    int index = currentInstruction[1].u.operand;
+    int value = currentInstruction[2].u.operand;
+
+    JSGlobalObject* globalObject = m_codeBlock->globalObject();
+
+    emitLoad(value, regT1, regT0);
+    move(TrustedImmPtr(globalObject), regT2);
+
+    emitWriteBarrier(globalObject, regT1, regT3, ShouldFilterImmediates, WriteBarrierForVariableAccess);
+
+    loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2);
+    emitStore(index, regT1, regT0, regT2);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_put_global_var), value, regT1, regT0);
+}
+
+void JIT::resetPatchGetById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo)
+{
+    repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_get_by_id);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.get.structureToCompare), reinterpret_cast<void*>(-1));
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel1), 0);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel2), 0);
+    repatchBuffer.relink(stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck), stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin));
+}
+
+void JIT::resetPatchPutById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo)
+{
+    if (isDirectPutById(stubInfo))
+        repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_put_by_id_direct);
+    else
+        repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_put_by_id);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.put.structureToCompare), reinterpret_cast<void*>(-1));
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(stubInfo->patch.baseline.u.put.displacementLabel1), 0);
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(stubInfo->patch.baseline.u.put.displacementLabel2), 0);
+}
+
 } // namespace JSC
 
 #endif // USE(JSVALUE32_64)
 } // namespace JSC
 
 #endif // USE(JSVALUE32_64)
index a0341d6b44cb7c4228ce2b6c76fcd06ba16a1fae..a525ff22750e098b952ec58575132511bd5dacd7 100644 (file)
@@ -104,12 +104,24 @@ namespace JSC {
             m_jit->poke(argument, m_stackIndex);
             m_stackIndex += stackIndexStep;
         }
             m_jit->poke(argument, m_stackIndex);
             m_stackIndex += stackIndexStep;
         }
+        
+        void addArgument(JIT::Imm32 argument)
+        {
+            m_jit->poke(argument, m_stackIndex);
+            m_stackIndex += stackIndexStep;
+        }
 
         void addArgument(JIT::TrustedImmPtr argument)
         {
             m_jit->poke(argument, m_stackIndex);
             m_stackIndex += stackIndexStep;
         }
 
         void addArgument(JIT::TrustedImmPtr argument)
         {
             m_jit->poke(argument, m_stackIndex);
             m_stackIndex += stackIndexStep;
         }
+        
+        void addArgument(JIT::ImmPtr argument)
+        {
+            m_jit->poke(argument, m_stackIndex);
+            m_stackIndex += stackIndexStep;
+        }
 
         void addArgument(JIT::RegisterID argument)
         {
 
         void addArgument(JIT::RegisterID argument)
         {
@@ -172,6 +184,7 @@ namespace JSC {
 #endif
 
             m_jit->restoreArgumentReference();
 #endif
 
             m_jit->restoreArgumentReference();
+            m_jit->updateTopCallFrame();
             JIT::Call call = m_jit->call();
             m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeOffset, m_stub.value()));
 
             JIT::Call call = m_jit->call();
             m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeOffset, m_stub.value()));
 
@@ -199,6 +212,21 @@ namespace JSC {
                 m_jit->emitStoreCell(dst, JIT::returnValueRegister);
             return call;
         }
                 m_jit->emitStoreCell(dst, JIT::returnValueRegister);
             return call;
         }
+        
+        JIT::Call callWithValueProfiling(unsigned dst)
+        {
+            ASSERT(m_returnType == Value || m_returnType == Cell);
+            JIT::Call call = this->call();
+            ASSERT(JIT::returnValueRegister == JIT::regT0);
+            if (m_returnType == Cell)
+                m_jit->move(JIT::TrustedImm32(JSValue::CellTag), JIT::regT1);
+            m_jit->emitValueProfilingSite();
+            if (m_returnType == Value)
+                m_jit->emitStore(dst, JIT::regT1, JIT::regT0);
+            else
+                m_jit->emitStoreCell(dst, JIT::returnValueRegister);
+            return call;
+        }
 #else
         JIT::Call call(unsigned dst) // dst is a virtual register.
         {
 #else
         JIT::Call call(unsigned dst) // dst is a virtual register.
         {
@@ -207,6 +235,16 @@ namespace JSC {
             m_jit->emitPutVirtualRegister(dst);
             return call;
         }
             m_jit->emitPutVirtualRegister(dst);
             return call;
         }
+        
+        JIT::Call callWithValueProfiling(unsigned dst)
+        {
+            ASSERT(m_returnType == VoidPtr || m_returnType == Cell);
+            JIT::Call call = this->call();
+            ASSERT(JIT::returnValueRegister == JIT::regT0);
+            m_jit->emitValueProfilingSite();
+            m_jit->emitPutVirtualRegister(dst);
+            return call;
+        }
 #endif
 
         JIT::Call call(JIT::RegisterID dst) // dst is a machine register.
 #endif
 
         JIT::Call call(JIT::RegisterID dst) // dst is a machine register.
index 2aee6a1b7765a059fc0e6658ac55d65118c0ae27..d81e68aaecc23d52464b089320d5f612351bc3a9 100644 (file)
 #if ENABLE(JIT)
 #include "JITStubs.h"
 
 #if ENABLE(JIT)
 #include "JITStubs.h"
 
+#include "CommonSlowPaths.h"
 #include "Arguments.h"
 #include "CallFrame.h"
 #include "CodeBlock.h"
 #include "Arguments.h"
 #include "CallFrame.h"
 #include "CodeBlock.h"
-#include "Heap.h"
+#include "CodeProfiling.h"
+#include "DFGOSREntry.h"
 #include "Debugger.h"
 #include "ExceptionHelpers.h"
 #include "GetterSetter.h"
 #include "Debugger.h"
 #include "ExceptionHelpers.h"
 #include "GetterSetter.h"
-#include "Strong.h"
+#include "Heap.h"
+#include <wtf/InlineASM.h>
 #include "JIT.h"
 #include "JIT.h"
+#include "JITExceptions.h"
 #include "JSActivation.h"
 #include "JSArray.h"
 #include "JSActivation.h"
 #include "JSArray.h"
-#include "JSByteArray.h"
 #include "JSFunction.h"
 #include "JSGlobalObjectFunctions.h"
 #include "JSNotAnObject.h"
 #include "JSFunction.h"
 #include "JSGlobalObjectFunctions.h"
 #include "JSNotAnObject.h"
@@ -59,6 +62,7 @@
 #include "RegExpPrototype.h"
 #include "Register.h"
 #include "SamplingTool.h"
 #include "RegExpPrototype.h"
 #include "Register.h"
 #include "SamplingTool.h"
+#include "Strong.h"
 #include <wtf/StdLibExtras.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <wtf/StdLibExtras.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -67,47 +71,6 @@ using namespace std;
 
 namespace JSC {
 
 
 namespace JSC {
 
-#if OS(DARWIN) || (OS(WINDOWS) && CPU(X86))
-#define SYMBOL_STRING(name) "_" #name
-#else
-#define SYMBOL_STRING(name) #name
-#endif
-
-#if OS(IOS)
-#define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name)
-#else
-#define THUMB_FUNC_PARAM(name)
-#endif
-
-#if (OS(LINUX) || OS(FREEBSD)) && CPU(X86_64)
-#define SYMBOL_STRING_RELOCATION(name) #name "@plt"
-#elif OS(DARWIN) || (CPU(X86_64) && COMPILER(MINGW) && !GCC_VERSION_AT_LEAST(4, 5, 0))
-#define SYMBOL_STRING_RELOCATION(name) "_" #name
-#elif CPU(X86) && COMPILER(MINGW)
-#define SYMBOL_STRING_RELOCATION(name) "@" #name "@4"
-#else
-#define SYMBOL_STRING_RELOCATION(name) #name
-#endif
-
-#if OS(DARWIN)
-    // Mach-O platform
-#define HIDE_SYMBOL(name) ".private_extern _" #name
-#elif OS(AIX)
-    // IBM's own file format
-#define HIDE_SYMBOL(name) ".lglobl " #name
-#elif   OS(LINUX)               \
-     || OS(FREEBSD)             \
-     || OS(OPENBSD)             \
-     || OS(SOLARIS)             \
-     || (OS(HPUX) && CPU(IA64)) \
-     || OS(SYMBIAN)             \
-     || OS(NETBSD)
-    // ELF platform
-#define HIDE_SYMBOL(name) ".hidden " #name
-#else
-#define HIDE_SYMBOL(name)
-#endif
-
 #if USE(JSVALUE32_64)
 
 #if COMPILER(GCC) && CPU(X86)
 #if USE(JSVALUE32_64)
 
 #if COMPILER(GCC) && CPU(X86)
@@ -130,7 +93,6 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "pushl %edi" "\n"
     "pushl %ebx" "\n"
     "subl $0x3c, %esp" "\n"
     "pushl %edi" "\n"
     "pushl %ebx" "\n"
     "subl $0x3c, %esp" "\n"
-    "movl $512, %esi" "\n"
     "movl 0x58(%esp), %edi" "\n"
     "call *0x50(%esp)" "\n"
     "addl $0x3c, %esp" "\n"
     "movl 0x58(%esp), %edi" "\n"
     "call *0x50(%esp)" "\n"
     "addl $0x3c, %esp" "\n"
@@ -139,6 +101,9 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "popl %esi" "\n"
     "popl %ebp" "\n"
     "ret" "\n"
     "popl %esi" "\n"
     "popl %ebp" "\n"
     "ret" "\n"
+".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
+HIDE_SYMBOL(ctiTrampolineEnd) "\n"
+SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
 );
 
 asm (
 );
 
 asm (
@@ -196,6 +161,9 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "popq %r12" "\n"
     "popq %rbp" "\n"
     "ret" "\n"
     "popq %r12" "\n"
     "popq %rbp" "\n"
     "ret" "\n"
+".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
+HIDE_SYMBOL(ctiTrampolineEnd) "\n"
+SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
 );
 
 asm (
 );
 
 asm (
@@ -228,10 +196,15 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
 #define PRESERVED_R4_OFFSET              0x40
 #define PRESERVED_R5_OFFSET              0x44
 #define PRESERVED_R6_OFFSET              0x48
 #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
+#define PRESERVED_R7_OFFSET              0x4C
+#define PRESERVED_R8_OFFSET              0x50
+#define PRESERVED_R9_OFFSET              0x54
+#define PRESERVED_R10_OFFSET             0x58
+#define PRESERVED_R11_OFFSET             0x5C
+#define REGISTER_FILE_OFFSET             0x60
+#define CALLFRAME_OFFSET                 0x64
+#define EXCEPTION_OFFSET                 0x64
+#define ENABLE_PROFILER_REFERENCE_OFFSET 0x68
 
 #elif (COMPILER(GCC) || COMPILER(MSVC) || COMPILER(RVCT)) && CPU(ARM_TRADITIONAL)
 
 
 #elif (COMPILER(GCC) || COMPILER(MSVC) || COMPILER(RVCT)) && CPU(ARM_TRADITIONAL)
 
@@ -260,7 +233,6 @@ extern "C" {
             push edi;
             push ebx;
             sub esp, 0x3c;
             push edi;
             push ebx;
             sub esp, 0x3c;
-            mov esi, 512;
             mov ecx, esp;
             mov edi, [esp + 0x58];
             call [esp + 0x50];
             mov ecx, esp;
             mov edi, [esp + 0x58];
             call [esp + 0x50];
@@ -434,6 +406,9 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "popq %r12" "\n"
     "popq %rbp" "\n"
     "ret" "\n"
     "popq %r12" "\n"
     "popq %rbp" "\n"
     "ret" "\n"
+".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
+HIDE_SYMBOL(ctiTrampolineEnd) "\n"
+SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
 );
 
 asm (
 );
 
 asm (
@@ -572,18 +547,34 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "str r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
     "str r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
     "str r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
     "str r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
     "str r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
     "str r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
+    "str r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n"
+    "str r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n"
+    "str r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n"
+    "str r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n"
+    "str r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n"
     "str r1, [sp, #" STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "]" "\n"
     "str r2, [sp, #" STRINGIZE_VALUE_OF(CALLFRAME_OFFSET) "]" "\n"
     "str r3, [sp, #" STRINGIZE_VALUE_OF(EXCEPTION_OFFSET) "]" "\n"
     "str r1, [sp, #" STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "]" "\n"
     "str r2, [sp, #" STRINGIZE_VALUE_OF(CALLFRAME_OFFSET) "]" "\n"
     "str r3, [sp, #" STRINGIZE_VALUE_OF(EXCEPTION_OFFSET) "]" "\n"
-    "cpy r5, r2" "\n"
+    "mov r5, r2" "\n"
     "mov r6, #512" "\n"
     "blx r0" "\n"
     "mov r6, #512" "\n"
     "blx r0" "\n"
+    "ldr r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n"
+    "ldr r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n"
+    "ldr r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n"
+    "ldr r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n"
+    "ldr r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n"
     "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
     "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
     "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
     "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
     "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
     "bx lr" "\n"
     "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
     "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
     "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
     "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n"
     "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n"
     "bx lr" "\n"
+".align 2" "\n"
+".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n"
+HIDE_SYMBOL(ctiTrampolineEnd) "\n"
+".thumb" "\n"
+".thumb_func " THUMB_FUNC_PARAM(ctiTrampolineEnd) "\n"
+SYMBOL_STRING(ctiTrampolineEnd) ":" "\n"
 );
 
 asm (
 );
 
 asm (
@@ -594,8 +585,13 @@ HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 ".thumb" "\n"
 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
 ".thumb" "\n"
 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
-    "cpy r0, sp" "\n"
+    "mov r0, sp" "\n"
     "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
     "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
+    "ldr r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n"
+    "ldr r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n"
+    "ldr r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n"
+    "ldr r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n"
+    "ldr r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n"
     "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
     "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
     "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
     "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
     "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
     "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
@@ -612,6 +608,11 @@ HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 ".thumb" "\n"
 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
 ".thumb" "\n"
 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
+    "ldr r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n"
+    "ldr r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n"
+    "ldr r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n"
+    "ldr r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n"
+    "ldr r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n"
     "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
     "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
     "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
     "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n"
     "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n"
     "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n"
@@ -667,12 +668,22 @@ __asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, P
     str r4, [sp, # PRESERVED_R4_OFFSET ]
     str r5, [sp, # PRESERVED_R5_OFFSET ]
     str r6, [sp, # PRESERVED_R6_OFFSET ]
     str r4, [sp, # PRESERVED_R4_OFFSET ]
     str r5, [sp, # PRESERVED_R5_OFFSET ]
     str r6, [sp, # PRESERVED_R6_OFFSET ]
+    str r7, [sp, # PRESERVED_R7_OFFSET ]
+    str r8, [sp, # PRESERVED_R8_OFFSET ]
+    str r9, [sp, # PRESERVED_R9_OFFSET ]
+    str r10, [sp, # PRESERVED_R10_OFFSET ]
+    str r11, [sp, # PRESERVED_R11_OFFSET ]
     str r1, [sp, # REGISTER_FILE_OFFSET ]
     str r2, [sp, # CALLFRAME_OFFSET ]
     str r3, [sp, # EXCEPTION_OFFSET ]
     str r1, [sp, # REGISTER_FILE_OFFSET ]
     str r2, [sp, # CALLFRAME_OFFSET ]
     str r3, [sp, # EXCEPTION_OFFSET ]
-    cpy r5, r2
+    mov r5, r2
     mov r6, #512
     blx r0
     mov r6, #512
     blx r0
+    ldr r11, [sp, # PRESERVED_R11_OFFSET ]
+    ldr r10, [sp, # PRESERVED_R10_OFFSET ]
+    ldr r9, [sp, # PRESERVED_R9_OFFSET ]
+    ldr r8, [sp, # PRESERVED_R8_OFFSET ]
+    ldr r7, [sp, # PRESERVED_R7_OFFSET ]
     ldr r6, [sp, # PRESERVED_R6_OFFSET ]
     ldr r5, [sp, # PRESERVED_R5_OFFSET ]
     ldr r4, [sp, # PRESERVED_R4_OFFSET ]
     ldr r6, [sp, # PRESERVED_R6_OFFSET ]
     ldr r5, [sp, # PRESERVED_R5_OFFSET ]
     ldr r4, [sp, # PRESERVED_R4_OFFSET ]
@@ -684,8 +695,14 @@ __asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, P
 __asm void ctiVMThrowTrampoline()
 {
     PRESERVE8
 __asm void ctiVMThrowTrampoline()
 {
     PRESERVE8
-    cpy r0, sp
+    mov r0, sp
     bl cti_vm_throw
     bl cti_vm_throw
+    ldr r11, [sp, # PRESERVED_R11_OFFSET ]
+    ldr r10, [sp, # PRESERVED_R10_OFFSET ]
+    ldr r9, [sp, # PRESERVED_R9_OFFSET ]
+    ldr r8, [sp, # PRESERVED_R8_OFFSET ]
+    ldr r7, [sp, # PRESERVED_R7_OFFSET ]
+    ldr r6, [sp, # PRESERVED_R6_OFFSET ]
     ldr r6, [sp, # PRESERVED_R6_OFFSET ]
     ldr r5, [sp, # PRESERVED_R5_OFFSET ]
     ldr r4, [sp, # PRESERVED_R4_OFFSET ]
     ldr r6, [sp, # PRESERVED_R6_OFFSET ]
     ldr r5, [sp, # PRESERVED_R5_OFFSET ]
     ldr r4, [sp, # PRESERVED_R4_OFFSET ]
@@ -697,6 +714,12 @@ __asm void ctiVMThrowTrampoline()
 __asm void ctiOpThrowNotCaught()
 {
     PRESERVE8
 __asm void ctiOpThrowNotCaught()
 {
     PRESERVE8
+    ldr r11, [sp, # PRESERVED_R11_OFFSET ]
+    ldr r10, [sp, # PRESERVED_R10_OFFSET ]
+    ldr r9, [sp, # PRESERVED_R9_OFFSET ]
+    ldr r8, [sp, # PRESERVED_R8_OFFSET ]
+    ldr r7, [sp, # PRESERVED_R7_OFFSET ]
+    ldr r6, [sp, # PRESERVED_R6_OFFSET ]
     ldr r6, [sp, # PRESERVED_R6_OFFSET ]
     ldr r5, [sp, # PRESERVED_R5_OFFSET ]
     ldr r4, [sp, # PRESERVED_R4_OFFSET ]
     ldr r6, [sp, # PRESERVED_R6_OFFSET ]
     ldr r5, [sp, # PRESERVED_R5_OFFSET ]
     ldr r4, [sp, # PRESERVED_R4_OFFSET ]
@@ -754,11 +777,11 @@ __asm void ctiOpThrowNotCaught()
 JITThunks::JITThunks(JSGlobalData* globalData)
     : m_hostFunctionStubMap(adoptPtr(new HostFunctionStubMap))
 {
 JITThunks::JITThunks(JSGlobalData* globalData)
     : m_hostFunctionStubMap(adoptPtr(new HostFunctionStubMap))
 {
-    if (!globalData->executableAllocator.isValid())
+    if (!globalData->canUseJIT())
         return;
 
         return;
 
-    JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_trampolineStructure);
-    ASSERT(m_executablePool);
+    m_executableMemory = JIT::compileCTIMachineTrampolines(globalData, &m_trampolineStructure);
+    ASSERT(!!m_executableMemory);
 #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
@@ -767,6 +790,11 @@ JITThunks::JITThunks(JSGlobalData* globalData)
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVED_R4_OFFSET);
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR5) == PRESERVED_R5_OFFSET);
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR6) == PRESERVED_R6_OFFSET);
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVED_R4_OFFSET);
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR5) == PRESERVED_R5_OFFSET);
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR6) == PRESERVED_R6_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR7) == PRESERVED_R7_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR8) == PRESERVED_R8_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR9) == PRESERVED_R9_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR10) == PRESERVED_R10_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR11) == PRESERVED_R11_OFFSET);
 
     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);
@@ -801,8 +829,6 @@ JITThunks::~JITThunks()
 {
 }
 
 {
 }
 
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-
 NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo, bool direct)
 {
     // The interpreter checks for recursion here; I do not believe this can occur in CTI.
 NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo, bool direct)
 {
     // The interpreter checks for recursion here; I do not believe this can occur in CTI.
@@ -843,7 +869,7 @@ 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(callFrame->globalData(), codeBlock->ownerExecutable(), structure->previousID(), structure, prototypeChain);
+        stubInfo->initPutByIdTransition(callFrame->globalData(), codeBlock->ownerExecutable(), structure->previousID(), structure, prototypeChain, direct);
         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;
     }
@@ -866,12 +892,12 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
     
     JSGlobalData* globalData = &callFrame->globalData();
 
     
     JSGlobalData* globalData = &callFrame->globalData();
 
-    if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
+    if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
         JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
         return;
     }
     
         JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
         return;
     }
     
-    if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
+    if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
         // The tradeoff of compiling an patched inline string length access routine does not seem
         // to pay off, so we currently only do this for arrays.
         ctiPatchCallByReturnAddress(codeBlock, returnAddress, globalData->jitStubs->ctiStringLengthTrampoline());
         // The tradeoff of compiling an patched inline string length access routine does not seem
         // to pay off, so we currently only do this for arrays.
         ctiPatchCallByReturnAddress(codeBlock, returnAddress, globalData->jitStubs->ctiStringLengthTrampoline());
@@ -942,9 +968,7 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
     JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
 }
 
     JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
 }
 
-#endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-
-#ifndef NDEBUG
+#if !defined(NDEBUG)
 
 extern "C" {
 
 
 extern "C" {
 
@@ -962,7 +986,8 @@ struct StackHack {
         : stackFrame(stackFrame)
         , savedReturnAddress(*stackFrame.returnAddressSlot())
     {
         : stackFrame(stackFrame)
         , savedReturnAddress(*stackFrame.returnAddressSlot())
     {
-        *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
+        if (!CodeProfiling::enabled())
+            *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
     }
 
     ALWAYS_INLINE ~StackHack() 
     }
 
     ALWAYS_INLINE ~StackHack() 
@@ -997,12 +1022,6 @@ static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, Retur
     returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline));
 }
 
     returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline));
 }
 
-static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
-{
-    globalData->exception = createStackOverflowError(callFrame);
-    returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot);
-}
-
 #define VM_THROW_EXCEPTION() \
     do { \
         VM_THROW_EXCEPTION_AT_END(); \
 #define VM_THROW_EXCEPTION() \
     do { \
         VM_THROW_EXCEPTION_AT_END(); \
@@ -1031,23 +1050,23 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
         } \
     } while (0)
 
         } \
     } while (0)
 
-struct ExceptionHandler {
-    void* catchRoutine;
-    CallFrame* callFrame;
-};
-static ExceptionHandler jitThrow(JSGlobalData* globalData, CallFrame* callFrame, JSValue exceptionValue, ReturnAddressPtr faultLocation)
+// Helper function for JIT stubs that may throw an exception in the middle of
+// processing a function call. This function rolls back the register file to
+// our caller, so exception processing can proceed from a valid state.
+template<typename T> static T throwExceptionFromOpCall(JITStackFrame& jitStackFrame, CallFrame* newCallFrame, ReturnAddressPtr& returnAddressSlot)
 {
 {
-    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;
+    CallFrame* callFrame = newCallFrame->callerFrame();
+    ASSERT(callFrame->globalData().exception);
+    jitStackFrame.callFrame = callFrame;
+    callFrame->globalData().topCallFrame = callFrame;
+    returnToThrowTrampoline(&callFrame->globalData(), ReturnAddressPtr(newCallFrame->returnPC()), returnAddressSlot);
+    return T();
+}
 
 
-    void* catchRoutine = handler ? handler->nativeCode.executableAddress() : FunctionPtr(ctiOpThrowNotCaught).value();
-    ASSERT(catchRoutine);
-    ExceptionHandler exceptionHandler = { catchRoutine, callFrame };
-    return exceptionHandler;
+template<typename T> static T throwExceptionFromOpCall(JITStackFrame& jitStackFrame, CallFrame* newCallFrame, ReturnAddressPtr& returnAddressSlot, JSValue exception)
+{
+    newCallFrame->callerFrame()->globalData().exception = exception;
+    return throwExceptionFromOpCall<T>(jitStackFrame, newCallFrame, returnAddressSlot);
 }
 
 #if CPU(ARM_THUMB2) && COMPILER(GCC)
 }
 
 #if CPU(ARM_THUMB2) && COMPILER(GCC)
@@ -1091,7 +1110,8 @@ static ExceptionHandler jitThrow(JSGlobalData* globalData, CallFrame* callFrame,
         ".set macro" "\n" \
         "la    $25," SYMBOL_STRING(JITStubThunked_##op) "\n" \
         ".set nomacro" "\n" \
         ".set macro" "\n" \
         "la    $25," SYMBOL_STRING(JITStubThunked_##op) "\n" \
         ".set nomacro" "\n" \
-        "bal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
+        ".reloc 1f,R_MIPS_JALR," SYMBOL_STRING(JITStubThunked_##op) "\n" \
+        "1: jalr $25" "\n" \
         "nop" "\n" \
         "lw    $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
         "jr    $31" "\n" \
         "nop" "\n" \
         "lw    $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
         "jr    $31" "\n" \
@@ -1260,10 +1280,10 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_this)
     STUB_INIT_STACK_FRAME(stackFrame);
     CallFrame* callFrame = stackFrame.callFrame;
 
     STUB_INIT_STACK_FRAME(stackFrame);
     CallFrame* callFrame = stackFrame.callFrame;
 
-    JSFunction* constructor = asFunction(callFrame->callee());
+    JSFunction* constructor = jsCast<JSFunction*>(callFrame->callee());
 #if !ASSERT_DISABLED
     ConstructData constructData;
 #if !ASSERT_DISABLED
     ConstructData constructData;
-    ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
+    ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
 #endif
 
     Structure* structure;
 #endif
 
     Structure* structure;
@@ -1284,19 +1304,9 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this)
     JSValue v1 = stackFrame.args[0].jsValue();
     CallFrame* callFrame = stackFrame.callFrame;
 
     JSValue v1 = stackFrame.args[0].jsValue();
     CallFrame* callFrame = stackFrame.callFrame;
 
-    JSObject* result = v1.toThisObject(callFrame);
-    CHECK_FOR_EXCEPTION_AT_END();
-    return JSValue::encode(result);
-}
+    ASSERT(v1.isPrimitive());
 
 
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this_strict)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-    
-    JSValue v1 = stackFrame.args[0].jsValue();
-    CallFrame* callFrame = stackFrame.callFrame;
-    ASSERT(v1.asCell()->structure()->typeInfo().needsThisConversion());
-    JSValue result = v1.toStrictThisObject(callFrame);
+    JSObject* result = v1.toThisObject(callFrame);
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -1309,17 +1319,14 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
     JSValue v2 = stackFrame.args[1].jsValue();
     CallFrame* callFrame = stackFrame.callFrame;
 
     JSValue v2 = stackFrame.args[1].jsValue();
     CallFrame* callFrame = stackFrame.callFrame;
 
-    if (v1.isString()) {
-        JSValue result = v2.isString()
-            ? jsString(callFrame, asString(v1), asString(v2))
-            : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
+    if (v1.isString() && !v2.isObject()) {
+        JSValue result = jsString(callFrame, asString(v1), v2.toString(callFrame));
         CHECK_FOR_EXCEPTION_AT_END();
         return JSValue::encode(result);
     }
 
         CHECK_FOR_EXCEPTION_AT_END();
         return JSValue::encode(result);
     }
 
-    double left = 0.0, right;
-    if (v1.getNumber(left) && v2.getNumber(right))
-        return JSValue::encode(jsNumber(left + right));
+    if (v1.isNumber() && v2.isNumber())
+        return JSValue::encode(jsNumber(v1.asNumber() + v2.asNumber()));
 
     // All other cases are pretty uncommon
     JSValue result = jsAddSlowCase(callFrame, v1, v2);
 
     // All other cases are pretty uncommon
     JSValue result = jsAddSlowCase(callFrame, v1, v2);
@@ -1362,31 +1369,12 @@ DEFINE_STUB_FUNCTION(void*, register_file_check)
     STUB_INIT_STACK_FRAME(stackFrame);
     CallFrame* callFrame = stackFrame.callFrame;
 
     STUB_INIT_STACK_FRAME(stackFrame);
     CallFrame* callFrame = stackFrame.callFrame;
 
-    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;
-    }
+    if (UNLIKELY(!stackFrame.registerFile->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters])))
+        return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame()));
 
     return callFrame;
 }
 
 
     return callFrame;
 }
 
-DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    JSValue src1 = stackFrame.args[0].jsValue();
-    JSValue src2 = stackFrame.args[1].jsValue();
-    CallFrame* callFrame = stackFrame.callFrame;
-
-    bool result = jsLessEq(callFrame, src1, src2);
-    CHECK_FOR_EXCEPTION_AT_END();
-    return result;
-}
-
 DEFINE_STUB_FUNCTION(JSObject*, op_new_object)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(JSObject*, op_new_object)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -1408,7 +1396,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
     STUB_INIT_STACK_FRAME(stackFrame);
     
     PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
     STUB_INIT_STACK_FRAME(stackFrame);
     
     PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
-    stackFrame.args[0].jsValue().putDirect(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
+    JSValue baseValue = stackFrame.args[0].jsValue();
+    ASSERT(baseValue.isObject());
+    asObject(baseValue)->putDirect(stackFrame.callFrame->globalData(), stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
     CHECK_FOR_EXCEPTION_AT_END();
 }
 
     CHECK_FOR_EXCEPTION_AT_END();
 }
 
@@ -1427,8 +1417,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
     return JSValue::encode(result);
 }
 
     return JSValue::encode(result);
 }
 
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-
 DEFINE_STUB_FUNCTION(void, op_put_by_id)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(void, op_put_by_id)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -1455,7 +1443,10 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
     Identifier& ident = stackFrame.args[1].identifier();
     
     PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
     Identifier& ident = stackFrame.args[1].identifier();
     
     PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
-    stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
+    JSValue baseValue = stackFrame.args[0].jsValue();
+    ASSERT(baseValue.isObject());
+    
+    asObject(baseValue)->putDirect(callFrame->globalData(), ident, stackFrame.args[2].jsValue(), slot);
     
     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
     
     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
@@ -1488,7 +1479,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
     Identifier& ident = stackFrame.args[1].identifier();
     
     PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
     Identifier& ident = stackFrame.args[1].identifier();
     
     PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
-    stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
+    JSValue baseValue = stackFrame.args[0].jsValue();
+    ASSERT(baseValue.isObject());
+    asObject(baseValue)->putDirect(callFrame->globalData(), ident, stackFrame.args[2].jsValue(), slot);
     
     CHECK_FOR_EXCEPTION_AT_END();
 }
     
     CHECK_FOR_EXCEPTION_AT_END();
 }
@@ -1499,11 +1492,14 @@ DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
 
     JSValue baseValue = stackFrame.args[0].jsValue();
     int32_t oldSize = stackFrame.args[3].int32();
 
     JSValue baseValue = stackFrame.args[0].jsValue();
     int32_t oldSize = stackFrame.args[3].int32();
-    int32_t newSize = stackFrame.args[4].int32();
+    Structure* newStructure = stackFrame.args[4].structure();
+    int32_t newSize = newStructure->propertyStorageCapacity();
 
     ASSERT(baseValue.isObject());
     JSObject* base = asObject(baseValue);
 
     ASSERT(baseValue.isObject());
     JSObject* base = asObject(baseValue);
-    base->allocatePropertyStorage(oldSize, newSize);
+    JSGlobalData& globalData = *stackFrame.globalData;
+    PropertyStorage newStorage = base->growPropertyStorage(globalData, oldSize, newSize);
+    base->setPropertyStorage(globalData, newStorage, newStructure);
 
     return base;
 }
 
     return base;
 }
@@ -1522,6 +1518,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
 
     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
     MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
 
     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
     MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
+    StructureStubInfo& stubInfo = codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
 
     if (!methodCallLinkInfo.seenOnce()) {
         methodCallLinkInfo.setSeen();
 
     if (!methodCallLinkInfo.seenOnce()) {
         methodCallLinkInfo.setSeen();
@@ -1548,7 +1545,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
         && specific
         ) {
 
         && specific
         ) {
 
-        JSObjectWithGlobalObject* callee = (JSObjectWithGlobalObject*)specific;
+        JSObject* callee = asObject(specific);
 
         // Since we're accessing a prototype in a loop, it's a good bet that it
         // should not be treated as a dictionary.
 
         // Since we're accessing a prototype in a loop, it's a good bet that it
         // should not be treated as a dictionary.
@@ -1560,7 +1557,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
 
         // Check to see if the function is on the object's prototype.  Patch up the code to optimize.
         if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
 
         // 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(callFrame->globalData(), codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
+            JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
             return JSValue::encode(result);
         }
 
             return JSValue::encode(result);
         }
 
@@ -1571,7 +1568,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(callFrame->globalData(), codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
+            JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
             return JSValue::encode(result);
         }
     }
             return JSValue::encode(result);
         }
     }
@@ -1581,6 +1578,96 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
     return JSValue::encode(result);
 }
 
     return JSValue::encode(result);
 }
 
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check_update)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+
+    CallFrame* callFrame = stackFrame.callFrame;
+    Identifier& ident = stackFrame.args[1].identifier();
+
+    JSValue baseValue = stackFrame.args[0].jsValue();
+    PropertySlot slot(baseValue);
+    JSValue result = baseValue.get(callFrame, ident, slot);
+    CHECK_FOR_EXCEPTION();
+
+    CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
+    MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
+    StructureStubInfo& stubInfo = codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
+
+    ASSERT(methodCallLinkInfo.seenOnce());
+
+    // If we successfully got something, then the base from which it is being accessed must
+    // be an object.  (Assertion to ensure asObject() call below is safe, which comes after
+    // an isCacheable() chceck.
+    ASSERT(!slot.isCacheableValue() || slot.slotBase().isObject());
+
+    // Check that:
+    //   * We're dealing with a JSCell,
+    //   * the property is cachable,
+    //   * it's not a dictionary
+    //   * there is a function cached.
+    Structure* structure;
+    JSCell* specific;
+    JSObject* slotBaseObject;
+    if (!(baseValue.isCell()
+          && slot.isCacheableValue()
+          && !(structure = baseValue.asCell()->structure())->isUncacheableDictionary()
+          && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific)
+          && specific
+          )
+        || (slot.slotBase() != structure->prototypeForLookup(callFrame)
+            && slot.slotBase() != baseValue)) {
+        // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
+        ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
+        return JSValue::encode(result);
+    }
+    
+    // Now check if the situation has changed sufficiently that we should bail out of
+    // doing method_check optimizations entirely, or if it changed only slightly, in
+    // which case we can just repatch.
+    
+    JSValue proto = structure->prototypeForLookup(callFrame);
+    
+    bool previousWasProto = methodCallLinkInfo.cachedPrototype.get() != codeBlock->globalObject()->methodCallDummy();
+    bool currentIsProto = slot.slotBase() == proto;
+    
+    JSObject* callee = asObject(specific);
+    
+    if (previousWasProto != currentIsProto
+        || !structure->transitivelyTransitionedFrom(methodCallLinkInfo.cachedStructure.get())
+        || (previousWasProto && !slotBaseObject->structure()->transitivelyTransitionedFrom(methodCallLinkInfo.cachedPrototypeStructure.get()))
+        || specific != methodCallLinkInfo.cachedFunction.get()) {
+        ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
+        return JSValue::encode(result);
+    }
+    
+    // It makes sense to simply repatch the method_check.
+    
+    // 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(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() == proto) {
+        JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
+        return JSValue::encode(result);
+    }
+    
+    ASSERT(slot.slotBase() == baseValue);
+    
+    // Since we generate the method-check to check both the structure and a prototype-structure (since this
+    // is the common case) we have a problem - we need to patch the prototype structure check to do something
+    // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler
+    // 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.
+    JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
+    return JSValue::encode(result);
+}
+
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -1630,7 +1717,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(callFrame->globalData(), codeBlock->ownerExecutable(), CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure.get());
+            polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->globalData(), codeBlock->ownerExecutable(), MacroAssemblerCodeRef(), stubInfo->u.getByIdSelf.baseObjectStructure.get(), true);
             stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
         } else {
             polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
             stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
         } else {
             polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
@@ -1655,13 +1742,13 @@ static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(JSG
 
     switch (stubInfo->accessType) {
     case access_get_by_id_proto:
 
     switch (stubInfo->accessType) {
     case access_get_by_id_proto:
-        prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get());
-        stubInfo->stubRoutine = CodeLocationLabel();
+        prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get(), true);
+        stubInfo->stubRoutine = MacroAssemblerCodeRef();
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
     case access_get_by_id_chain:
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
     case access_get_by_id_chain:
-        prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get());
-        stubInfo->stubRoutine = CodeLocationLabel();
+        prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get(), true);
+        stubInfo->stubRoutine = MacroAssemblerCodeRef();
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
     case access_get_by_id_proto_list:
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
     case access_get_by_id_proto_list:
@@ -1687,7 +1774,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_getter_stub)
         return JSValue::encode(jsUndefined());
     JSObject* getter = asObject(getterSetter->getter());
     CallData callData;
         return JSValue::encode(jsUndefined());
     JSObject* getter = asObject(getterSetter->getter());
     CallData callData;
-    CallType callType = getter->getCallData(callData);
+    CallType callType = getter->methodTable()->getCallData(getter, callData);
     JSValue result = call(callFrame, getter, callType, callData, stackFrame.args[1].jsObject(), ArgList());
     if (callFrame->hadException())
         returnToThrowTrampoline(&callFrame->globalData(), stackFrame.args[2].returnAddress(), STUB_RETURN_ADDRESS);
     JSValue result = call(callFrame, getter, callType, callData, stackFrame.args[1].jsObject(), ArgList());
     if (callFrame->hadException())
         returnToThrowTrampoline(&callFrame->globalData(), stackFrame.args[2].returnAddress(), STUB_RETURN_ADDRESS);
@@ -1821,8 +1908,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail)
     return JSValue::encode(result);
 }
 
     return JSValue::encode(result);
 }
 
-#endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-
 DEFINE_STUB_FUNCTION(void, op_check_has_instance)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(void, op_check_has_instance)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -1840,44 +1925,188 @@ DEFINE_STUB_FUNCTION(void, op_check_has_instance)
     VM_THROW_EXCEPTION_AT_END();
 }
 
     VM_THROW_EXCEPTION_AT_END();
 }
 
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
+#if ENABLE(DFG_JIT)
+DEFINE_STUB_FUNCTION(void, optimize_from_loop)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-
+    
     CallFrame* callFrame = stackFrame.callFrame;
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue value = stackFrame.args[0].jsValue();
-    JSValue baseVal = stackFrame.args[1].jsValue();
-    JSValue proto = stackFrame.args[2].jsValue();
+    CodeBlock* codeBlock = callFrame->codeBlock();
+
+    unsigned bytecodeIndex = stackFrame.args[0].int32();
+    
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("%p: Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
+#endif
 
 
-    // At least one of these checks must have failed to get to the slow case.
-    ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell()
-           || !value.isObject() || !baseVal.isObject() || !proto.isObject() 
-           || (asObject(baseVal)->structure()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance);
+    if (!codeBlock->checkIfOptimizationThresholdReached())
+        return;
 
 
+    if (codeBlock->hasOptimizedReplacement()) {
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("Considering loop OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
+#endif
+        if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
+#if ENABLE(JIT_VERBOSE_OSR)
+            dataLog("Triggering reoptimization of %p(%p) (in loop).\n", codeBlock, codeBlock->replacement());
+#endif
+            codeBlock->reoptimize();
+            return;
+        }
+    } else {
+        if (!codeBlock->shouldOptimizeNow()) {
+#if ENABLE(JIT_VERBOSE_OSR)
+            dataLog("Delaying optimization for %p (in loop) because of insufficient profiling.\n", codeBlock);
+#endif
+            return;
+        }
+        
+        ScopeChainNode* scopeChain = callFrame->scopeChain();
+        
+        JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain);
+#if ENABLE(JIT_VERBOSE_OSR)
+        if (error)
+            dataLog("WARNING: optimized compilation from loop failed.\n");
+#else
+        UNUSED_PARAM(error);
+#endif
+        
+        if (codeBlock->replacement() == codeBlock) {
+#if ENABLE(JIT_VERBOSE_OSR)
+            dataLog("Optimizing %p from loop failed.\n", codeBlock);
+#endif
+            
+            ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
+            codeBlock->dontOptimizeAnytimeSoon();
+            return;
+        }
+    }
+    
+    CodeBlock* optimizedCodeBlock = codeBlock->replacement();
+    ASSERT(optimizedCodeBlock->getJITType() == JITCode::DFGJIT);
+    
+    if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) {
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("Optimizing %p from loop succeeded, performing OSR after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
+#endif
 
 
-    // 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).
-    TypeInfo typeInfo(UnspecifiedType);
-    if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) {
-        stackFrame.globalData->exception = createInvalidParamError(stackFrame.callFrame, "instanceof", baseVal);
-        VM_THROW_EXCEPTION();
+        codeBlock->optimizeSoon();
+        optimizedCodeBlock->countSpeculationSuccess();
+        STUB_SET_RETURN_ADDRESS(address);
+        return;
     }
     }
-    ASSERT(typeInfo.type() != UnspecifiedType);
+    
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("Optimizing %p from loop succeeded, OSR failed, after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
+#endif
 
 
-    if (!typeInfo.overridesHasInstance()) {
-        if (!value.isObject())
-            return JSValue::encode(jsBoolean(false));
+    // Count the OSR failure as a speculation failure. If this happens a lot, then
+    // reoptimize.
+    optimizedCodeBlock->countSpeculationFailure();
+    
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("Encountered loop OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
+#endif
 
 
-        if (!proto.isObject()) {
-            throwError(callFrame, createTypeError(callFrame, "instanceof called on an object with an invalid prototype property."));
-            VM_THROW_EXCEPTION();
+    // We are a lot more conservative about triggering reoptimization after OSR failure than
+    // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
+    // already, then we really would like to reoptimize immediately. But this case covers
+    // something else: there weren't many (or any) speculation failures before, but we just
+    // failed to enter the speculative code because some variable had the wrong value or
+    // because the OSR code decided for any spurious reason that it did not want to OSR
+    // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
+    // reoptimization trigger.
+    if (optimizedCodeBlock->shouldReoptimizeNow()) {
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("Triggering reoptimization of %p(%p) (in loop after OSR fail).\n", codeBlock, codeBlock->replacement());
+#endif
+        codeBlock->reoptimize();
+        return;
+    }
+
+    // OSR failed this time, but it might succeed next time! Let the code run a bit
+    // longer and then try again.
+    codeBlock->optimizeAfterWarmUp();
+}
+
+DEFINE_STUB_FUNCTION(void, optimize_from_ret)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+    
+    CallFrame* callFrame = stackFrame.callFrame;
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("Entered optimize_from_ret with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
+#endif
+
+    if (!codeBlock->checkIfOptimizationThresholdReached())
+        return;
+
+    if (codeBlock->hasOptimizedReplacement()) {
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("Returning from old JIT call frame with optimized replacement %p(%p), with success/fail %u/%u", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
+        CallFrame* callerFrame = callFrame->callerFrame();
+        if (callerFrame)
+            dataLog(", callerFrame = %p, returnPC = %p, caller code block = %p", callerFrame, callFrame->returnPC().value(), callerFrame->codeBlock());
+        dataLog("\n");
+#endif
+        if (codeBlock->replacement()->shouldReoptimizeNow()) {
+#if ENABLE(JIT_VERBOSE_OSR)
+            dataLog("Triggering reoptimization of %p(%p) (in return).\n", codeBlock, codeBlock->replacement());
+#endif
+            codeBlock->reoptimize();
         }
         }
+        
+        codeBlock->optimizeSoon();
+        return;
     }
     }
+    
+    if (!codeBlock->shouldOptimizeNow()) {
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("Delaying optimization for %p (in return) because of insufficient profiling.\n", codeBlock);
+#endif
+        return;
+    }
+    
+    ScopeChainNode* scopeChain = callFrame->scopeChain();
 
 
-    JSValue result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto));
-    CHECK_FOR_EXCEPTION_AT_END();
+    JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain);
+    if (error)
+        dataLog("WARNING: optimized compilation from ret failed.\n");
+    
+    if (codeBlock->replacement() == codeBlock) {
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("Optimizing %p from return failed.\n", codeBlock);
+#endif
 
 
-    return JSValue::encode(result);
+        ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
+        codeBlock->dontOptimizeAnytimeSoon();
+        return;
+    }
+    
+    ASSERT(codeBlock->replacement()->getJITType() == JITCode::DFGJIT);
+
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("Optimizing %p from return succeeded after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
+#endif
+    
+    codeBlock->optimizeSoon();
+}
+#endif // ENABLE(DFG_JIT)
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+
+    CallFrame* callFrame = stackFrame.callFrame;
+    JSValue value = stackFrame.args[0].jsValue();
+    JSValue baseVal = stackFrame.args[1].jsValue();
+    JSValue proto = stackFrame.args[2].jsValue();
+    
+    bool result = CommonSlowPaths::opInstanceOfSlow(callFrame, value, baseVal, proto);
+    CHECK_FOR_EXCEPTION_AT_END();
+    return JSValue::encode(jsBoolean(result));
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
@@ -1888,7 +2117,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
     
     JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
 
     
     JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
 
-    bool couldDelete = baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier());
+    bool couldDelete = baseObj->methodTable()->deleteProperty(baseObj, callFrame, stackFrame.args[1].identifier());
     JSValue result = jsBoolean(couldDelete);
     if (!couldDelete && callFrame->codeBlock()->isStrictMode())
         stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
     JSValue result = jsBoolean(couldDelete);
     if (!couldDelete && callFrame->codeBlock()->isStrictMode())
         stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
@@ -1904,10 +2133,8 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul)
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
-    double left;
-    double right;
-    if (src1.getNumber(left) && src2.getNumber(right))
-        return JSValue::encode(jsNumber(left * right));
+    if (src1.isNumber() && src2.isNumber())
+        return JSValue::encode(jsNumber(src1.asNumber() * src2.asNumber()));
 
     CallFrame* callFrame = stackFrame.callFrame;
     JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
 
     CallFrame* callFrame = stackFrame.callFrame;
     JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
@@ -1923,25 +2150,34 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
     return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
 }
 
     return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
 }
 
+inline void* jitCompileFor(CallFrame* callFrame, CodeSpecializationKind kind)
+{
+    JSFunction* function = jsCast<JSFunction*>(callFrame->callee());
+    ASSERT(!function->isHostFunction());
+    FunctionExecutable* executable = function->jsExecutable();
+    ScopeChainNode* callDataScopeChain = function->scope();
+    JSObject* error = executable->compileFor(callFrame, callDataScopeChain, kind);
+    if (!error)
+        return function;
+    callFrame->globalData().exception = error;
+    return 0;
+}
+
 DEFINE_STUB_FUNCTION(void*, op_call_jitCompile)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 #if !ASSERT_DISABLED
     CallData callData;
 DEFINE_STUB_FUNCTION(void*, op_call_jitCompile)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 #if !ASSERT_DISABLED
     CallData callData;
-    ASSERT(stackFrame.callFrame->callee()->getCallData(callData) == CallTypeJS);
+    ASSERT(stackFrame.callFrame->callee()->methodTable()->getCallData(stackFrame.callFrame->callee(), callData) == CallTypeJS);
 #endif
 #endif
+    
+    CallFrame* callFrame = stackFrame.callFrame;
+    void* result = jitCompileFor(callFrame, CodeForCall);
+    if (!result)
+        return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
 
 
-    JSFunction* function = asFunction(stackFrame.callFrame->callee());
-    ASSERT(!function->isHostFunction());
-    FunctionExecutable* executable = function->jsExecutable();
-    ScopeChainNode* callDataScopeChain = function->scope();
-    JSObject* error = executable->compileForCall(stackFrame.callFrame, callDataScopeChain);
-    if (error) {
-        stackFrame.callFrame->globalData().exception = error;
-        return 0;
-    }
-    return function;
+    return result;
 }
 
 DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
 }
 
 DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
@@ -1950,19 +2186,15 @@ DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
 
 #if !ASSERT_DISABLED
     ConstructData constructData;
 
 #if !ASSERT_DISABLED
     ConstructData constructData;
-    ASSERT(asFunction(stackFrame.callFrame->callee())->getConstructData(constructData) == ConstructTypeJS);
+    ASSERT(jsCast<JSFunction*>(stackFrame.callFrame->callee())->methodTable()->getConstructData(stackFrame.callFrame->callee(), constructData) == ConstructTypeJS);
 #endif
 
 #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;
+    CallFrame* callFrame = stackFrame.callFrame;    
+    void* result = jitCompileFor(callFrame, CodeForConstruct);
+    if (!result)
+        return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
+
+    return result;
 }
 
 DEFINE_STUB_FUNCTION(void*, op_call_arityCheck)
 }
 
 DEFINE_STUB_FUNCTION(void*, op_call_arityCheck)
@@ -1970,58 +2202,12 @@ 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(callFrame->callee());
-    ASSERT(!callee->isHostFunction());
-    CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeForCall();
-    int argCount = callFrame->argumentCountIncludingThis();
-    ReturnAddressPtr pc = callFrame->returnPC();
-
-    ASSERT(argCount != newCodeBlock->m_numParameters);
-
-    CallFrame* oldCallFrame = callFrame->callerFrame();
-
-    Register* r;
-    if (argCount > newCodeBlock->m_numParameters) {
-        size_t numParameters = newCodeBlock->m_numParameters;
-        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;
-        }
 
 
-        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());
+    CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForCall);
+    if (!newCallFrame)
+        return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame()));
 
 
-    ASSERT((void*)callFrame <= stackFrame.registerFile->end());
-    return callFrame;
+    return newCallFrame;
 }
 
 DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck)
 }
 
 DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck)
@@ -2029,136 +2215,76 @@ DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
     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();
+    CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForConstruct);
+    if (!newCallFrame)
+        return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(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;
-        }
-
-        Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
-        for (size_t i = 0; i < omittedArgCount; ++i)
-            argv[i] = jsUndefined();
-    }
-
-    ASSERT((void*)callFrame <= stackFrame.registerFile->end());
-    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;
+    return newCallFrame;
 }
 
 }
 
-#if ENABLE(JIT_OPTIMIZE_CALL)
-DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
+inline void* lazyLinkFor(CallFrame* callFrame, CodeSpecializationKind kind)
 {
 {
-    STUB_INIT_STACK_FRAME(stackFrame);
-    CallFrame* callFrame = stackFrame.callFrame;
-    JSFunction* callee = asFunction(callFrame->callee());
+    JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
     ExecutableBase* executable = callee->executable();
 
     MacroAssemblerCodePtr codePtr;
     CodeBlock* codeBlock = 0;
     ExecutableBase* executable = callee->executable();
 
     MacroAssemblerCodePtr codePtr;
     CodeBlock* codeBlock = 0;
+    CallLinkInfo* callLinkInfo = &callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
+
     if (executable->isHostFunction())
     if (executable->isHostFunction())
-        codePtr = executable->generatedJITCodeForCall().addressForCall();
+        codePtr = executable->generatedJITCodeFor(kind).addressForCall();
     else {
         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
     else {
         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
-        JSObject* error = functionExecutable->compileForCall(callFrame, callee->scope());
-        if (error) {
-            callFrame->globalData().exception = createStackOverflowError(callFrame);
+        if (JSObject* error = functionExecutable->compileFor(callFrame, callee->scope(), kind)) {
+            callFrame->globalData().exception = error;
             return 0;
         }
             return 0;
         }
-        codeBlock = &functionExecutable->generatedBytecodeForCall();
-        if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
-            codePtr = functionExecutable->generatedJITCodeForCall().addressForCall();
+        codeBlock = &functionExecutable->generatedBytecodeFor(kind);
+        if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters())
+            || callLinkInfo->callType == CallLinkInfo::CallVarargs)
+            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
         else
         else
-            codePtr = functionExecutable->generatedJITCodeForCallWithArityCheck();
+            codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
     }
     }
-    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, codePtr, callLinkInfo, callFrame->argumentCountIncludingThis(), stackFrame.globalData);
+        JIT::linkFor(callee, callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, &callFrame->globalData(), kind);
 
     return codePtr.executableAddress();
 }
 
 
     return codePtr.executableAddress();
 }
 
-DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
+DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 {
     STUB_INIT_STACK_FRAME(stackFrame);
+
     CallFrame* callFrame = stackFrame.callFrame;
     CallFrame* callFrame = stackFrame.callFrame;
-    JSFunction* callee = asFunction(callFrame->callee());
-    ExecutableBase* executable = callee->executable();
+    void* result = lazyLinkFor(callFrame, CodeForCall);
+    if (!result)
+        return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
 
 
-    MacroAssemblerCodePtr codePtr;
-    CodeBlock* codeBlock = 0;
-    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());
+    return result;
+}
 
 
-    if (!callLinkInfo->seenOnce())
-        callLinkInfo->setSeen();
-    else
-        JIT::linkConstruct(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, callFrame->argumentCountIncludingThis(), stackFrame.globalData);
+DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
 
 
-    return codePtr.executableAddress();
+    CallFrame* callFrame = stackFrame.callFrame;
+    void* result = lazyLinkFor(callFrame, CodeForConstruct);
+    if (!result)
+        return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
+
+    return result;
 }
 }
-#endif // !ENABLE(JIT_OPTIMIZE_CALL)
 
 DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 
 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()));
+    JSActivation* activation = JSActivation::create(stackFrame.callFrame->globalData(), stackFrame.callFrame, static_cast<FunctionExecutable*>(stackFrame.callFrame->codeBlock()->ownerExecutable()));
     stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->push(activation));
     return activation;
 }
     stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->push(activation));
     return activation;
 }
@@ -2167,54 +2293,36 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    JSValue funcVal = stackFrame.args[0].jsValue();
+    CallFrame* callFrame = stackFrame.callFrame;
+    
+    JSValue callee = callFrame->calleeAsValue();
 
     CallData callData;
 
     CallData callData;
-    CallType callType = getCallData(funcVal, callData);
+    CallType callType = getCallData(callee, callData);
 
     ASSERT(callType != CallTypeJS);
 
     ASSERT(callType != CallTypeJS);
+    if (callType != CallTypeHost) {
+        ASSERT(callType == CallTypeNone);
+        return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createNotAFunctionError(callFrame->callerFrame(), callee));
+    }
 
 
-    if (callType == CallTypeHost) {
-        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();
-        }
-
-        callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(funcVal));
-
-        EncodedJSValue returnValue;
-        {
-            SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
-            returnValue = callData.native.function(callFrame);
-        }
-
-        CHECK_FOR_EXCEPTION_AT_END();
-        return returnValue;
+    EncodedJSValue returnValue;
+    {
+        SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
+        returnValue = callData.native.function(callFrame);
     }
 
     }
 
-    ASSERT(callType == CallTypeNone);
+    if (stackFrame.globalData->exception)
+        return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
 
 
-    stackFrame.globalData->exception = createNotAFunctionError(stackFrame.callFrame, funcVal);
-    VM_THROW_EXCEPTION();
+    return returnValue;
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame);
-    return JSValue::encode(JSValue(arguments));
-}
-
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments_no_params)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame, Arguments::NoParameters);
+    Arguments* arguments = Arguments::create(*stackFrame.globalData, stackFrame.callFrame);
     return JSValue::encode(JSValue(arguments));
 }
 
     return JSValue::encode(JSValue(arguments));
 }
 
@@ -2222,29 +2330,29 @@ DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
+    CallFrame* callFrame = stackFrame.callFrame;
+    ASSERT(callFrame->codeBlock()->needsFullScopeChain());
     JSValue activationValue = stackFrame.args[0].jsValue();
     if (!activationValue) {
         if (JSValue v = stackFrame.args[1].jsValue()) {
     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);
+            if (!callFrame->codeBlock()->isStrictMode())
+                asArguments(v)->tearOff(callFrame);
         }
         return;
     }
     JSActivation* activation = asActivation(stackFrame.args[0].jsValue());
         }
         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);
-    }
+    activation->tearOff(*stackFrame.globalData);
+    if (JSValue v = stackFrame.args[1].jsValue())
+        asArguments(v)->didTearOffActivation(*stackFrame.globalData, activation);
 }
 
 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 }
 
 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    ASSERT(stackFrame.callFrame->codeBlock()->usesArguments() && !stackFrame.callFrame->codeBlock()->needsFullScopeChain());
-    asArguments(stackFrame.args[0].jsValue())->copyRegisters(*stackFrame.globalData);
+    CallFrame* callFrame = stackFrame.callFrame;
+    ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
+    asArguments(stackFrame.args[0].jsValue())->tearOff(callFrame);
 }
 
 DEFINE_STUB_FUNCTION(void, op_profile_will_call)
 }
 
 DEFINE_STUB_FUNCTION(void, op_profile_will_call)
@@ -2267,16 +2375,14 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    ArgList argList(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
-    return constructArray(stackFrame.callFrame, argList);
+    return constructArray(stackFrame.callFrame, reinterpret_cast<JSValue*>(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()]), stackFrame.args[1].int32());
 }
 
 DEFINE_STUB_FUNCTION(JSObject*, op_new_array_buffer)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
     
 }
 
 DEFINE_STUB_FUNCTION(JSObject*, op_new_array_buffer)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
     
-    ArgList argList(stackFrame.callFrame->codeBlock()->constantBuffer(stackFrame.args[0].int32()), stackFrame.args[1].int32());
-    return constructArray(stackFrame.callFrame, argList);
+    return constructArray(stackFrame.callFrame, stackFrame.callFrame->codeBlock()->constantBuffer(stackFrame.args[0].int32()), stackFrame.args[1].int32());
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
@@ -2284,64 +2390,38 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
-    ScopeChainNode* scopeChain = callFrame->scopeChain();
-
-    ScopeChainIterator iter = scopeChain->begin();
-    ScopeChainIterator end = scopeChain->end();
-    ASSERT(iter != end);
-
-    Identifier& ident = stackFrame.args[0].identifier();
-    do {
-        JSObject* o = iter->get();
-        PropertySlot slot(o);
-        if (o->getPropertySlot(callFrame, ident, slot)) {
-            JSValue result = slot.getValue(callFrame, ident);
-            CHECK_FOR_EXCEPTION_AT_END();
-            return JSValue::encode(result);
-        }
-    } while (++iter != end);
 
 
-    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
-    VM_THROW_EXCEPTION();
+    JSValue result = CommonSlowPaths::opResolve(callFrame, stackFrame.args[0].identifier());
+    CHECK_FOR_EXCEPTION_AT_END();
+    return JSValue::encode(result);
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    JSValue constrVal = stackFrame.args[0].jsValue();
+    CallFrame* callFrame = stackFrame.callFrame;
+    JSValue callee = callFrame->calleeAsValue();
 
     ConstructData constructData;
 
     ConstructData constructData;
-    ConstructType constructType = getConstructData(constrVal, constructData);
+    ConstructType constructType = getConstructData(callee, constructData);
 
     ASSERT(constructType != ConstructTypeJS);
 
     ASSERT(constructType != ConstructTypeJS);
+    if (constructType != ConstructTypeHost) {
+        ASSERT(constructType == ConstructTypeNone);
+        return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createNotAConstructorError(callFrame->callerFrame(), callee));
+    }
 
 
-    if (constructType == ConstructTypeHost) {
-        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();
-        }
-
-        callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(constrVal));
-
-        EncodedJSValue returnValue;
-        {
-            SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
-            returnValue = constructData.native.function(callFrame);
-        }
-
-        CHECK_FOR_EXCEPTION_AT_END();
-        return returnValue;
+    EncodedJSValue returnValue;
+    {
+        SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
+        returnValue = constructData.native.function(callFrame);
     }
 
     }
 
-    ASSERT(constructType == ConstructTypeNone);
+    if (stackFrame.globalData->exception)
+        return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
 
 
-    stackFrame.globalData->exception = createNotAConstructorError(stackFrame.callFrame, constrVal);
-    VM_THROW_EXCEPTION();
+    return returnValue;
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
@@ -2349,18 +2429,12 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSGlobalData* globalData = stackFrame.globalData;
 
     JSValue baseValue = stackFrame.args[0].jsValue();
     JSValue subscript = stackFrame.args[1].jsValue();
 
     if (LIKELY(baseValue.isCell() && subscript.isString())) {
 
     JSValue baseValue = stackFrame.args[0].jsValue();
     JSValue subscript = stackFrame.args[1].jsValue();
 
     if (LIKELY(baseValue.isCell() && subscript.isString())) {
-        Identifier propertyName(callFrame, asString(subscript)->value(callFrame));
-        PropertySlot slot(baseValue.asCell());
-        // JSString::value may have thrown, but we shouldn't find a property with a null identifier,
-        // so we should miss this case and wind up in the CHECK_FOR_EXCEPTION_AT_END, below.
-        if (baseValue.asCell()->fastGetOwnPropertySlot(callFrame, propertyName, slot)) {
-            JSValue result = slot.getValue(callFrame, propertyName);
+        if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame))) {
             CHECK_FOR_EXCEPTION();
             return JSValue::encode(result);
         }
             CHECK_FOR_EXCEPTION();
             return JSValue::encode(result);
         }
@@ -2368,23 +2442,18 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
 
     if (subscript.isUInt32()) {
         uint32_t i = subscript.asUInt32();
 
     if (subscript.isUInt32()) {
         uint32_t i = subscript.asUInt32();
-        if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) {
+        if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
             JSValue result = asString(baseValue)->getIndex(callFrame, i);
             CHECK_FOR_EXCEPTION();
             return JSValue::encode(result);
         }
             ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
             JSValue result = asString(baseValue)->getIndex(callFrame, i);
             CHECK_FOR_EXCEPTION();
             return JSValue::encode(result);
         }
-        if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
-            // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
-            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
-            return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
-        }
         JSValue result = baseValue.get(callFrame, i);
         CHECK_FOR_EXCEPTION();
         return JSValue::encode(result);
     }
     
         JSValue result = baseValue.get(callFrame, i);
         CHECK_FOR_EXCEPTION();
         return JSValue::encode(result);
     }
     
-    Identifier property(callFrame, subscript.toString(callFrame));
+    Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
     JSValue result = baseValue.get(callFrame, property);
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
     JSValue result = baseValue.get(callFrame, property);
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
@@ -2395,7 +2464,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
     STUB_INIT_STACK_FRAME(stackFrame);
     
     CallFrame* callFrame = stackFrame.callFrame;
     STUB_INIT_STACK_FRAME(stackFrame);
     
     CallFrame* callFrame = stackFrame.callFrame;
-    JSGlobalData* globalData = stackFrame.globalData;
     
     JSValue baseValue = stackFrame.args[0].jsValue();
     JSValue subscript = stackFrame.args[1].jsValue();
     
     JSValue baseValue = stackFrame.args[0].jsValue();
     JSValue subscript = stackFrame.args[1].jsValue();
@@ -2404,15 +2472,15 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
     
     if (LIKELY(subscript.isUInt32())) {
         uint32_t i = subscript.asUInt32();
     
     if (LIKELY(subscript.isUInt32())) {
         uint32_t i = subscript.asUInt32();
-        if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
+        if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
             result = asString(baseValue)->getIndex(callFrame, i);
         else {
             result = baseValue.get(callFrame, i);
             result = asString(baseValue)->getIndex(callFrame, i);
         else {
             result = baseValue.get(callFrame, i);
-            if (!isJSString(globalData, baseValue))
+            if (!isJSString(baseValue))
                 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
         }
     } else {
                 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
         }
     } else {
-        Identifier property(callFrame, subscript.toString(callFrame));
+        Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
         result = baseValue.get(callFrame, property);
     }
     
         result = baseValue.get(callFrame, property);
     }
     
@@ -2420,37 +2488,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
     return JSValue::encode(result);
 }
     
     return JSValue::encode(result);
 }
     
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_byte_array)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-    
-    CallFrame* callFrame = stackFrame.callFrame;
-    JSGlobalData* globalData = stackFrame.globalData;
-    
-    JSValue baseValue = stackFrame.args[0].jsValue();
-    JSValue subscript = stackFrame.args[1].jsValue();
-    
-    JSValue result;
-
-    if (LIKELY(subscript.isUInt32())) {
-        uint32_t i = subscript.asUInt32();
-        if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
-            // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
-            return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
-        }
-
-        result = baseValue.get(callFrame, i);
-        if (!isJSByteArray(globalData, baseValue))
-            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
-    } else {
-        Identifier property(callFrame, subscript.toString(callFrame));
-        result = baseValue.get(callFrame, property);
-    }
-    
-    CHECK_FOR_EXCEPTION_AT_END();
-    return JSValue::encode(result);
-}
-
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -2458,10 +2495,8 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub)
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
-    double left;
-    double right;
-    if (src1.getNumber(left) && src2.getNumber(right))
-        return JSValue::encode(jsNumber(left - right));
+    if (src1.isNumber() && src2.isNumber())
+        return JSValue::encode(jsNumber(src1.asNumber() - src2.asNumber()));
 
     CallFrame* callFrame = stackFrame.callFrame;
     JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
 
     CallFrame* callFrame = stackFrame.callFrame;
     JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
@@ -2482,32 +2517,16 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val)
 
     if (LIKELY(subscript.isUInt32())) {
         uint32_t i = subscript.asUInt32();
 
     if (LIKELY(subscript.isUInt32())) {
         uint32_t i = subscript.asUInt32();
-        if (isJSArray(globalData, baseValue)) {
+        if (isJSArray(baseValue)) {
             JSArray* jsArray = asArray(baseValue);
             if (jsArray->canSetIndex(i))
                 jsArray->setIndex(*globalData, i, value);
             else
             JSArray* jsArray = asArray(baseValue);
             if (jsArray->canSetIndex(i))
                 jsArray->setIndex(*globalData, i, value);
             else
-                jsArray->JSArray::put(callFrame, i, value);
-        } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
-            JSByteArray* jsByteArray = asByteArray(baseValue);
-            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_byte_array));
-            // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
-            if (value.isInt32()) {
-                jsByteArray->setIndex(i, value.asInt32());
-                return;
-            } else {
-                double dValue = 0;
-                if (value.getNumber(dValue)) {
-                    jsByteArray->setIndex(i, dValue);
-                    return;
-                }
-            }
-
-            baseValue.put(callFrame, i, value);
+                JSArray::putByIndex(jsArray, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
         } else
         } else
-            baseValue.put(callFrame, i, value);
+            baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
     } else {
     } else {
-        Identifier property(callFrame, subscript.toString(callFrame));
+        Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
         if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
             PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
             baseValue.put(callFrame, property, value, slot);
         if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
             PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
             baseValue.put(callFrame, property, value, slot);
@@ -2517,47 +2536,14 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val)
     CHECK_FOR_EXCEPTION_AT_END();
 }
 
     CHECK_FOR_EXCEPTION_AT_END();
 }
 
-DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array)
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_less)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-    
-    CallFrame* callFrame = stackFrame.callFrame;
-    JSGlobalData* globalData = stackFrame.globalData;
-    
-    JSValue baseValue = stackFrame.args[0].jsValue();
-    JSValue subscript = stackFrame.args[1].jsValue();
-    JSValue value = stackFrame.args[2].jsValue();
-    
-    if (LIKELY(subscript.isUInt32())) {
-        uint32_t i = subscript.asUInt32();
-        if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
-            JSByteArray* jsByteArray = asByteArray(baseValue);
-            
-            // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
-            if (value.isInt32()) {
-                jsByteArray->setIndex(i, value.asInt32());
-                return;
-            } else {
-                double dValue = 0;                
-                if (value.getNumber(dValue)) {
-                    jsByteArray->setIndex(i, dValue);
-                    return;
-                }
-            }
-        }
 
 
-        if (!isJSByteArray(globalData, baseValue))
-            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
-        baseValue.put(callFrame, i, value);
-    } else {
-        Identifier property(callFrame, subscript.toString(callFrame));
-        if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
-            PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
-            baseValue.put(callFrame, property, value, slot);
-        }
-    }
-    
+    CallFrame* callFrame = stackFrame.callFrame;
+    JSValue result = jsBoolean(jsLess<true>(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
     CHECK_FOR_EXCEPTION_AT_END();
     CHECK_FOR_EXCEPTION_AT_END();
+    return JSValue::encode(result);
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq)
@@ -2565,98 +2551,45 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsBoolean(jsLessEq(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
+    JSValue result = jsBoolean(jsLessEq<true>(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
 
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
 
-DEFINE_STUB_FUNCTION(int, op_load_varargs)
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_greater)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+
+    CallFrame* callFrame = stackFrame.callFrame;
+    JSValue result = jsBoolean(jsLess<false>(callFrame, stackFrame.args[1].jsValue(), stackFrame.args[0].jsValue()));
+    CHECK_FOR_EXCEPTION_AT_END();
+    return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_greatereq)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+
+    CallFrame* callFrame = stackFrame.callFrame;
+    JSValue result = jsBoolean(jsLessEq<false>(callFrame, stackFrame.args[1].jsValue(), stackFrame.args[0].jsValue()));
+    CHECK_FOR_EXCEPTION_AT_END();
+    return JSValue::encode(result);
+}
+
+DEFINE_STUB_FUNCTION(void*, op_load_varargs)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
     RegisterFile* registerFile = stackFrame.registerFile;
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
     RegisterFile* registerFile = stackFrame.registerFile;
-    int argsOffset = stackFrame.args[0].int32();
-    JSValue arguments = callFrame->registers()[argsOffset].jsValue();
-    uint32_t argCount = 0;
-    if (!arguments) {
-        int providedParams = callFrame->registers()[RegisterFile::ArgumentCount].i() - 1;
-        argCount = providedParams;
-        argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
-        int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
-        Register* newEnd = callFrame->registers() + sizeDelta;
-        if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
-            stackFrame.globalData->exception = createStackOverflowError(callFrame);
-            VM_THROW_EXCEPTION();
-        }
-        int32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
-        int32_t inplaceArgs = min(providedParams, expectedParams);
-        
-        Register* inplaceArgsDst = callFrame->registers() + argsOffset;
-
-        Register* inplaceArgsEnd = inplaceArgsDst + inplaceArgs;
-        Register* inplaceArgsEnd2 = inplaceArgsDst + providedParams;
-
-        Register* inplaceArgsSrc = callFrame->registers() - RegisterFile::CallFrameHeaderSize - expectedParams;
-        Register* inplaceArgsSrc2 = inplaceArgsSrc - providedParams - 1 + inplaceArgs;
-        // First step is to copy the "expected" parameters from their normal location relative to the callframe
-        while (inplaceArgsDst < inplaceArgsEnd)
-            *inplaceArgsDst++ = *inplaceArgsSrc++;
-
-        // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
-        while (inplaceArgsDst < inplaceArgsEnd2)
-            *inplaceArgsDst++ = *inplaceArgsSrc2++;
-
-    } else if (!arguments.isUndefinedOrNull()) {
-        if (!arguments.isObject()) {
-            stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
-            VM_THROW_EXCEPTION();
-        }
-        if (asObject(arguments)->classInfo() == &Arguments::s_info) {
-            Arguments* argsObject = asArguments(arguments);
-            argCount = argsObject->numProvidedArguments(callFrame);
-            argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
-            int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
-            Register* newEnd = callFrame->registers() + sizeDelta;
-            if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
-                stackFrame.globalData->exception = createStackOverflowError(callFrame);
-                VM_THROW_EXCEPTION();
-            }
-            argsObject->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
-        } else if (isJSArray(&callFrame->globalData(), arguments)) {
-            JSArray* array = asArray(arguments);
-            argCount = array->length();
-            argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
-            int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
-            Register* newEnd = callFrame->registers() + sizeDelta;
-            if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
-                stackFrame.globalData->exception = createStackOverflowError(callFrame);
-                VM_THROW_EXCEPTION();
-            }
-            array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
-        } 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));
-            int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
-            Register* newEnd = callFrame->registers() + sizeDelta;
-            if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
-                stackFrame.globalData->exception = createStackOverflowError(callFrame);
-                VM_THROW_EXCEPTION();
-            }
-            Register* argsBuffer = callFrame->registers() + argsOffset;
-            for (unsigned i = 0; i < argCount; ++i) {
-                argsBuffer[i] = asObject(arguments)->get(callFrame, i);
-                CHECK_FOR_EXCEPTION();
-            }
-        } else {
-            stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
-            VM_THROW_EXCEPTION();
-        }
-    }
+    JSValue thisValue = stackFrame.args[0].jsValue();
+    JSValue arguments = stackFrame.args[1].jsValue();
+    int firstFreeRegister = stackFrame.args[2].int32();
 
 
-    return argCount + 1;
+    CallFrame* newCallFrame = loadVarargs(callFrame, registerFile, thisValue, arguments, firstFreeRegister);
+    if (!newCallFrame)
+        VM_THROW_EXCEPTION();
+    return newCallFrame;
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate)
@@ -2665,9 +2598,8 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate)
 
     JSValue src = stackFrame.args[0].jsValue();
 
 
     JSValue src = stackFrame.args[0].jsValue();
 
-    double v;
-    if (src.getNumber(v))
-        return JSValue::encode(jsNumber(-v));
+    if (src.isNumber())
+        return JSValue::encode(jsNumber(-src.asNumber()));
 
     CallFrame* callFrame = stackFrame.callFrame;
     JSValue result = jsNumber(-src.toNumber(callFrame));
 
     CallFrame* callFrame = stackFrame.callFrame;
     JSValue result = jsNumber(-src.toNumber(callFrame));
@@ -2712,38 +2644,9 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    CallFrame* callFrame = stackFrame.callFrame;
-    ScopeChainNode* scopeChain = callFrame->scopeChain();
-
-    int skip = stackFrame.args[1].int32();
-
-    ScopeChainIterator iter = scopeChain->begin();
-    ScopeChainIterator end = scopeChain->end();
-    ASSERT(iter != end);
-    CodeBlock* codeBlock = callFrame->codeBlock();
-    bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
-    ASSERT(skip || !checkTopLevel);
-    if (checkTopLevel && skip--) {
-        if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
-            ++iter;
-    }
-    while (skip--) {
-        ++iter;
-        ASSERT(iter != end);
-    }
-    Identifier& ident = stackFrame.args[0].identifier();
-    do {
-        JSObject* o = iter->get();
-        PropertySlot slot(o);
-        if (o->getPropertySlot(callFrame, ident, slot)) {
-            JSValue result = slot.getValue(callFrame, ident);
-            CHECK_FOR_EXCEPTION_AT_END();
-            return JSValue::encode(result);
-        }
-    } while (++iter != end);
-
-    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
-    VM_THROW_EXCEPTION();
+    JSValue result = CommonSlowPaths::opResolveSkip(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].int32());
+    CHECK_FOR_EXCEPTION_AT_END();
+    return JSValue::encode(result);
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global)
@@ -2782,10 +2685,8 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_div)
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
-    double left;
-    double right;
-    if (src1.getNumber(left) && src2.getNumber(right))
-        return JSValue::encode(jsNumber(left / right));
+    if (src1.isNumber() && src2.isNumber())
+        return JSValue::encode(jsNumber(src1.asNumber() / src2.asNumber()));
 
     CallFrame* callFrame = stackFrame.callFrame;
     JSValue result = jsNumber(src1.toNumber(callFrame) / src2.toNumber(callFrame));
 
     CallFrame* callFrame = stackFrame.callFrame;
     JSValue result = jsNumber(src1.toNumber(callFrame) / src2.toNumber(callFrame));
@@ -2813,7 +2714,7 @@ DEFINE_STUB_FUNCTION(int, op_jless)
     JSValue src2 = stackFrame.args[1].jsValue();
     CallFrame* callFrame = stackFrame.callFrame;
 
     JSValue src2 = stackFrame.args[1].jsValue();
     CallFrame* callFrame = stackFrame.callFrame;
 
-    bool result = jsLess(callFrame, src1, src2);
+    bool result = jsLess<true>(callFrame, src1, src2);
     CHECK_FOR_EXCEPTION_AT_END();
     return result;
 }
     CHECK_FOR_EXCEPTION_AT_END();
     return result;
 }
@@ -2826,7 +2727,33 @@ DEFINE_STUB_FUNCTION(int, op_jlesseq)
     JSValue src2 = stackFrame.args[1].jsValue();
     CallFrame* callFrame = stackFrame.callFrame;
 
     JSValue src2 = stackFrame.args[1].jsValue();
     CallFrame* callFrame = stackFrame.callFrame;
 
-    bool result = jsLessEq(callFrame, src1, src2);
+    bool result = jsLessEq<true>(callFrame, src1, src2);
+    CHECK_FOR_EXCEPTION_AT_END();
+    return result;
+}
+
+DEFINE_STUB_FUNCTION(int, op_jgreater)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+
+    JSValue src1 = stackFrame.args[0].jsValue();
+    JSValue src2 = stackFrame.args[1].jsValue();
+    CallFrame* callFrame = stackFrame.callFrame;
+
+    bool result = jsLess<false>(callFrame, src2, src1);
+    CHECK_FOR_EXCEPTION_AT_END();
+    return result;
+}
+
+DEFINE_STUB_FUNCTION(int, op_jgreatereq)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+
+    JSValue src1 = stackFrame.args[0].jsValue();
+    JSValue src2 = stackFrame.args[1].jsValue();
+    CallFrame* callFrame = stackFrame.callFrame;
+
+    bool result = jsLessEq<false>(callFrame, src2, src1);
     CHECK_FOR_EXCEPTION_AT_END();
     return result;
 }
     CHECK_FOR_EXCEPTION_AT_END();
     return result;
 }
@@ -2865,11 +2792,11 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_inc)
 
     CallFrame* callFrame = stackFrame.callFrame;
 
 
     CallFrame* callFrame = stackFrame.callFrame;
 
-    JSValue number = v.toJSNumber(callFrame);
+    double number = v.toNumber(callFrame);
     CHECK_FOR_EXCEPTION_AT_END();
 
     CHECK_FOR_EXCEPTION_AT_END();
 
-    callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number.uncheckedGetNumber() + 1);
-    return JSValue::encode(number);
+    callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number + 1);
+    return JSValue::encode(jsNumber(number));
 }
 
 DEFINE_STUB_FUNCTION(int, op_eq)
 }
 
 DEFINE_STUB_FUNCTION(int, op_eq)
@@ -2935,20 +2862,20 @@ DEFINE_STUB_FUNCTION(int, op_eq)
 
     if (cell1->isString()) {
         if (src2.isInt32())
 
     if (cell1->isString()) {
         if (src2.isInt32())
-            return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32();
+            return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32();
             
         if (src2.isDouble())
             
         if (src2.isDouble())
-            return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble();
+            return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble();
 
         if (src2.isTrue())
 
         if (src2.isTrue())
-            return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0;
+            return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0;
 
         if (src2.isFalse())
 
         if (src2.isFalse())
-            return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0;
+            return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0;
 
         JSCell* cell2 = src2.asCell();
         if (cell2->isString())
 
         JSCell* cell2 = src2.asCell();
         if (cell2->isString())
-            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame) == static_cast<JSString*>(cell2)->value(stackFrame.callFrame);
+            return jsCast<JSString*>(cell1)->value(stackFrame.callFrame) == jsCast<JSString*>(cell2)->value(stackFrame.callFrame);
 
         src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame);
         CHECK_FOR_EXCEPTION();
 
         src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame);
         CHECK_FOR_EXCEPTION();
@@ -3029,51 +2956,24 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_rshift)
     return JSValue::encode(result);
 }
 
     return JSValue::encode(result);
 }
 
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitnot)
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    JSValue src = stackFrame.args[0].jsValue();
-
-    ASSERT(!src.isInt32());
     CallFrame* callFrame = stackFrame.callFrame;
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(~src.toInt32(callFrame));
+    JSValue result = CommonSlowPaths::opResolveWithBase(callFrame, stackFrame.args[0].identifier(), callFrame->registers()[stackFrame.args[1].int32()]);
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
 
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
 
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base)
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_this)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
-    ScopeChainNode* scopeChain = callFrame->scopeChain();
-
-    ScopeChainIterator iter = scopeChain->begin();
-    ScopeChainIterator end = scopeChain->end();
-
-    // FIXME: add scopeDepthIsZero optimization
-
-    ASSERT(iter != end);
-
-    Identifier& ident = stackFrame.args[0].identifier();
-    JSObject* base;
-    do {
-        base = iter->get();
-        PropertySlot slot(base);
-        if (base->getPropertySlot(callFrame, ident, slot)) {
-            JSValue result = slot.getValue(callFrame, ident);
-            CHECK_FOR_EXCEPTION_AT_END();
-
-            callFrame->registers()[stackFrame.args[1].int32()] = JSValue(base);
-            return JSValue::encode(result);
-        }
-        ++iter;
-    } while (iter != end);
-
-    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
-    VM_THROW_EXCEPTION_AT_END();
-    return JSValue::encode(JSValue());
+    JSValue result = CommonSlowPaths::opResolveWithThis(callFrame, stackFrame.args[0].identifier(), callFrame->registers()[stackFrame.args[1].int32()]);
+    CHECK_FOR_EXCEPTION_AT_END();
+    return JSValue::encode(result);
 }
 
 DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
 }
 
 DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
@@ -3093,7 +2993,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
         does not affect the scope enclosing the FunctionExpression.
      */
     if (!function->name().isNull()) {
         does not affect the scope enclosing the FunctionExpression.
      */
     if (!function->name().isNull()) {
-        JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
+        JSStaticScopeObject* functionScopeObject = JSStaticScopeObject::create(callFrame, function->name(), func, ReadOnly | DontDelete);
         func->setScope(callFrame->globalData(), func->scope()->push(functionScopeObject));
     }
 
         func->setScope(callFrame->globalData(), func->scope()->push(functionScopeObject));
     }
 
@@ -3114,16 +3014,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod)
     return JSValue::encode(result);
 }
 
     return JSValue::encode(result);
 }
 
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_less)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsBoolean(jsLess(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue()));
-    CHECK_FOR_EXCEPTION_AT_END();
-    return JSValue::encode(result);
-}
-
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_dec)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_dec)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -3132,11 +3022,11 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_dec)
 
     CallFrame* callFrame = stackFrame.callFrame;
 
 
     CallFrame* callFrame = stackFrame.callFrame;
 
-    JSValue number = v.toJSNumber(callFrame);
+    double number = v.toNumber(callFrame);
     CHECK_FOR_EXCEPTION_AT_END();
 
     CHECK_FOR_EXCEPTION_AT_END();
 
-    callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number.uncheckedGetNumber() - 1);
-    return JSValue::encode(number);
+    callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number - 1);
+    return JSValue::encode(jsNumber(number));
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_urshift)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_urshift)
@@ -3178,7 +3068,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp)
         VM_THROW_EXCEPTION();
     }
 
         VM_THROW_EXCEPTION();
     }
 
-    return new (stackFrame.globalData) RegExpObject(stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), regExp);
+    return RegExpObject::create(*stackFrame.globalData, stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), regExp);
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
@@ -3198,29 +3088,25 @@ 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;
 
     CallFrame* callFrame = stackFrame.callFrame;
-    RegisterFile* registerFile = stackFrame.registerFile;
+    CallFrame* callerFrame = callFrame->callerFrame();
+    ASSERT(callFrame->callerFrame()->codeBlock()->codeType() != FunctionCode
+        || !callFrame->callerFrame()->codeBlock()->needsFullScopeChain()
+        || callFrame->callerFrame()->uncheckedR(callFrame->callerFrame()->codeBlock()->activationRegister()).jsValue());
 
 
-    Interpreter* interpreter = stackFrame.globalData->interpreter;
-    
-    JSValue funcVal = stackFrame.args[0].jsValue();
-    int registerOffset = stackFrame.args[1].int32();
-    int argCount = stackFrame.args[2].int32();
+    callFrame->setScopeChain(callerFrame->scopeChain());
+    callFrame->setReturnPC(static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()));
+    callFrame->setCodeBlock(0);
 
 
-    Register* newCallFrame = callFrame->registers() + registerOffset;
-    Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
-    JSValue baseValue = argv[0].jsValue();
-    JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject.get();
+    if (!isHostFunction(callFrame->calleeAsValue(), globalFuncEval))
+        return JSValue::encode(JSValue());
 
 
-    if (baseValue == globalObject && funcVal == globalObject->evalFunction()) {
-        JSValue result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset);
-        CHECK_FOR_EXCEPTION_AT_END();
-        return JSValue::encode(result);
-    }
+    JSValue result = eval(callFrame);
+    if (stackFrame.globalData->exception)
+        return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
 
 
-    return JSValue::encode(JSValue());
+    return JSValue::encode(result);
 }
 
 DEFINE_STUB_FUNCTION(void*, op_throw)
 }
 
 DEFINE_STUB_FUNCTION(void*, op_throw)
@@ -3279,35 +3165,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_typeof)
     return JSValue::encode(jsTypeStringForValue(stackFrame.callFrame, stackFrame.args[0].jsValue()));
 }
 
     return JSValue::encode(jsTypeStringForValue(stackFrame.callFrame, stackFrame.args[0].jsValue()));
 }
 
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_undefined)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    JSValue v = stackFrame.args[0].jsValue();
-    return JSValue::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()));
-}
-
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_boolean)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isBoolean()));
-}
-
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_number)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isNumber()));
-}
-
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_string)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    return JSValue::encode(jsBoolean(isJSString(stackFrame.globalData, stackFrame.args[0].jsValue())));
-}
-
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -3328,7 +3185,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_stricteq)
 
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
 
     JSValue src1 = stackFrame.args[0].jsValue();
     JSValue src2 = stackFrame.args[1].jsValue();
-
+    
     bool result = JSValue::strictEqual(stackFrame.callFrame, src1, src2);
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(jsBoolean(result));
     bool result = JSValue::strictEqual(stackFrame.callFrame, src1, src2);
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(jsBoolean(result));
@@ -3369,9 +3226,9 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_jsnumber)
     JSValue src = stackFrame.args[0].jsValue();
     CallFrame* callFrame = stackFrame.callFrame;
 
     JSValue src = stackFrame.args[0].jsValue();
     CallFrame* callFrame = stackFrame.callFrame;
 
-    JSValue result = src.toJSNumber(callFrame);
+    double number = src.toNumber(callFrame);
     CHECK_FOR_EXCEPTION_AT_END();
     CHECK_FOR_EXCEPTION_AT_END();
-    return JSValue::encode(result);
+    return JSValue::encode(jsNumber(number));
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_in)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_in)
@@ -3393,7 +3250,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_in)
     if (propName.getUInt32(i))
         return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
 
     if (propName.getUInt32(i))
         return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, i)));
 
-    Identifier property(callFrame, propName.toString(callFrame));
+    Identifier property(callFrame, propName.toString(callFrame)->value(callFrame));
     CHECK_FOR_EXCEPTION();
     return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
 }
     CHECK_FOR_EXCEPTION();
     return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, property)));
 }
@@ -3402,7 +3259,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_push_new_scope)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    JSObject* scope = new (stackFrame.globalData) JSStaticScopeObject(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), DontDelete);
+    JSObject* scope = JSStaticScopeObject::create(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), DontDelete);
 
     CallFrame* callFrame = stackFrame.callFrame;
     callFrame->setScopeChain(callFrame->scopeChain()->push(scope));
 
     CallFrame* callFrame = stackFrame.callFrame;
     callFrame->setScopeChain(callFrame->scopeChain()->push(scope));
@@ -3429,7 +3286,9 @@ DEFINE_STUB_FUNCTION(void, op_put_by_index)
     CallFrame* callFrame = stackFrame.callFrame;
     unsigned property = stackFrame.args[1].int32();
 
     CallFrame* callFrame = stackFrame.callFrame;
     unsigned property = stackFrame.args[1].int32();
 
-    stackFrame.args[0].jsValue().put(callFrame, property, stackFrame.args[2].jsValue());
+    JSValue arrayValue = stackFrame.args[0].jsValue();
+    ASSERT(isJSArray(arrayValue));
+    asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue(), false);
 }
 
 DEFINE_STUB_FUNCTION(void*, op_switch_imm)
 }
 
 DEFINE_STUB_FUNCTION(void*, op_switch_imm)
@@ -3443,14 +3302,9 @@ DEFINE_STUB_FUNCTION(void*, op_switch_imm)
 
     if (scrutinee.isInt32())
         return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress();
 
     if (scrutinee.isInt32())
         return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress();
-    else {
-        double value;
-        int32_t intValue;
-        if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
-            return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(intValue).executableAddress();
-        else
-            return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
-    }
+    if (scrutinee.isDouble() && scrutinee.asDouble() == static_cast<int32_t>(scrutinee.asDouble()))
+            return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(static_cast<int32_t>(scrutinee.asDouble())).executableAddress();
+    return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
 }
 
 DEFINE_STUB_FUNCTION(void*, op_switch_char)
 }
 
 DEFINE_STUB_FUNCTION(void*, op_switch_char)
@@ -3467,7 +3321,7 @@ DEFINE_STUB_FUNCTION(void*, op_switch_char)
     if (scrutinee.isString()) {
         StringImpl* value = asString(scrutinee)->value(callFrame).impl();
         if (value->length() == 1)
     if (scrutinee.isString()) {
         StringImpl* value = asString(scrutinee)->value(callFrame).impl();
         if (value->length() == 1)
-            result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->characters()[0]).executableAddress();
+            result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue((*value)[0]).executableAddress();
     }
 
     CHECK_FOR_EXCEPTION_AT_END();
     }
 
     CHECK_FOR_EXCEPTION_AT_END();
@@ -3507,12 +3361,12 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val)
     bool result;
     uint32_t i;
     if (subscript.getUInt32(i))
     bool result;
     uint32_t i;
     if (subscript.getUInt32(i))
-        result = baseObj->deleteProperty(callFrame, i);
+        result = baseObj->methodTable()->deletePropertyByIndex(baseObj, callFrame, i);
     else {
         CHECK_FOR_EXCEPTION();
     else {
         CHECK_FOR_EXCEPTION();
-        Identifier property(callFrame, subscript.toString(callFrame));
+        Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
         CHECK_FOR_EXCEPTION();
         CHECK_FOR_EXCEPTION();
-        result = baseObj->deleteProperty(callFrame, property);
+        result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, property);
     }
 
     if (!result && callFrame->codeBlock()->isStrictMode())
     }
 
     if (!result && callFrame->codeBlock()->isStrictMode())
@@ -3522,7 +3376,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val)
     return JSValue::encode(jsBoolean(result));
 }
 
     return JSValue::encode(jsBoolean(result));
 }
 
-DEFINE_STUB_FUNCTION(void, op_put_getter)
+DEFINE_STUB_FUNCTION(void, op_put_getter_setter)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
@@ -3530,20 +3384,20 @@ DEFINE_STUB_FUNCTION(void, op_put_getter)
 
     ASSERT(stackFrame.args[0].jsValue().isObject());
     JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
 
     ASSERT(stackFrame.args[0].jsValue().isObject());
     JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
-    ASSERT(stackFrame.args[2].jsValue().isObject());
-    baseObj->defineGetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
-}
 
 
-DEFINE_STUB_FUNCTION(void, op_put_setter)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
+    GetterSetter* accessor = GetterSetter::create(callFrame);
 
 
-    CallFrame* callFrame = stackFrame.callFrame;
+    JSValue getter = stackFrame.args[2].jsValue();
+    JSValue setter = stackFrame.args[3].jsValue();
+    ASSERT(getter.isObject() || getter.isUndefined());
+    ASSERT(setter.isObject() || setter.isUndefined());
+    ASSERT(getter.isObject() || setter.isObject());
 
 
-    ASSERT(stackFrame.args[0].jsValue().isObject());
-    JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
-    ASSERT(stackFrame.args[2].jsValue().isObject());
-    baseObj->defineSetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
+    if (!getter.isUndefined())
+        accessor->setGetter(callFrame->globalData(), asObject(getter));
+    if (!setter.isUndefined())
+        accessor->setSetter(callFrame->globalData(), asObject(setter));
+    baseObj->putDirectAccessor(callFrame->globalData(), stackFrame.args[1].identifier(), accessor, Accessor);
 }
 
 DEFINE_STUB_FUNCTION(void, op_throw_reference_error)
 }
 
 DEFINE_STUB_FUNCTION(void, op_throw_reference_error)
@@ -3551,7 +3405,7 @@ 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;
-    UString message = stackFrame.args[0].jsValue().toString(callFrame);
+    UString message = stackFrame.args[0].jsValue().toString(callFrame)->value(callFrame);
     stackFrame.globalData->exception = createReferenceError(callFrame, message);
     VM_THROW_EXCEPTION_AT_END();
 }
     stackFrame.globalData->exception = createReferenceError(callFrame, message);
     VM_THROW_EXCEPTION_AT_END();
 }
@@ -3586,30 +3440,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));
 }
 
-MacroAssemblerCodePtr JITThunks::ctiStub(JSGlobalData* globalData, ThunkGenerator generator)
+MacroAssemblerCodeRef 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;
+    CTIStubMap::AddResult entry = m_ctiStubMap.add(generator, MacroAssemblerCodeRef());
+    if (entry.isNewEntry)
+        entry.iterator->second = generator(globalData);
+    return entry.iterator->second;
 }
 
 }
 
-NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function)
+NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, NativeFunction constructor)
 {
 {
-    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();
+    HostFunctionStubMap::AddResult result = m_hostFunctionStubMap->add(function, PassWeak<NativeExecutable>());
+    if (!result.iterator->second)
+        result.iterator->second = PassWeak<NativeExecutable>(NativeExecutable::create(*globalData, JIT::compileCTINativeCall(globalData, function), function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct()), constructor, NoIntrinsic));
+    return result.iterator->second.get();
 }
 
 }
 
-NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator)
+NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator, Intrinsic intrinsic)
 {
 {
-    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));
+    HostFunctionStubMap::AddResult entry = m_hostFunctionStubMap->add(function, PassWeak<NativeExecutable>());
+    if (!entry.iterator->second) {
+        MacroAssemblerCodeRef code;
+        if (generator) {
+            if (globalData->canUseJIT())
+                code = generator(globalData);
+            else
+                code = MacroAssemblerCodeRef();
+        } else
+            code = JIT::compileCTINativeCall(globalData, function);
+        entry.iterator->second = PassWeak<NativeExecutable>(NativeExecutable::create(*globalData, code, function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct()), callHostFunctionAsConstructor, intrinsic));
     }
     }
-    return entry.first->second.get();
+    return entry.iterator->second.get();
 }
 
 void JITThunks::clearHostFunctionStubs()
 }
 
 void JITThunks::clearHostFunctionStubs()
index 75fbb089ec9388be1c2022208f3a517109a39011..786353df5db4fa6d294deb0d1f0c6262e73ec561 100644 (file)
 #define JITStubs_h
 
 #include "CallData.h"
 #define JITStubs_h
 
 #include "CallData.h"
+#include "Intrinsic.h"
+#include "LowLevelInterpreter.h"
 #include "MacroAssemblerCodeRef.h"
 #include "Register.h"
 #include "ThunkGenerators.h"
 #include <wtf/HashMap.h>
 
 #include "MacroAssemblerCodeRef.h"
 #include "Register.h"
 #include "ThunkGenerators.h"
 #include <wtf/HashMap.h>
 
-#if ENABLE(JIT)
-
 namespace JSC {
 
 namespace JSC {
 
+#if ENABLE(JIT)
+
     struct StructureStubInfo;
 
     class CodeBlock;
     struct StructureStubInfo;
 
     class CodeBlock;
@@ -58,6 +60,7 @@ namespace JSC {
     class PutPropertySlot;
     class RegisterFile;
     class RegExp;
     class PutPropertySlot;
     class RegisterFile;
     class RegExp;
+    class Structure;
 
     template <typename T> class Weak;
 
 
     template <typename T> class Weak;
 
@@ -68,6 +71,7 @@ namespace JSC {
 
         JSValue jsValue() { return JSValue::decode(asEncodedJSValue); }
         JSObject* jsObject() { return static_cast<JSObject*>(asPointer); }
 
         JSValue jsValue() { return JSValue::decode(asEncodedJSValue); }
         JSObject* jsObject() { return static_cast<JSObject*>(asPointer); }
+        Register* reg() { return static_cast<Register*>(asPointer); }
         Identifier& identifier() { return *static_cast<Identifier*>(asPointer); }
         int32_t int32() { return asInt32; }
         CodeBlock* codeBlock() { return static_cast<CodeBlock*>(asPointer); }
         Identifier& identifier() { return *static_cast<Identifier*>(asPointer); }
         int32_t int32() { return asInt32; }
         CodeBlock* codeBlock() { return static_cast<CodeBlock*>(asPointer); }
@@ -76,6 +80,7 @@ namespace JSC {
         JSPropertyNameIterator* propertyNameIterator() { return static_cast<JSPropertyNameIterator*>(asPointer); }
         JSGlobalObject* globalObject() { return static_cast<JSGlobalObject*>(asPointer); }
         JSString* jsString() { return static_cast<JSString*>(asPointer); }
         JSPropertyNameIterator* propertyNameIterator() { return static_cast<JSPropertyNameIterator*>(asPointer); }
         JSGlobalObject* globalObject() { return static_cast<JSGlobalObject*>(asPointer); }
         JSString* jsString() { return static_cast<JSString*>(asPointer); }
+        Structure* structure() { return static_cast<Structure*>(asPointer); }
         ReturnAddressPtr returnAddress() { return ReturnAddressPtr(asPointer); }
     };
     
         ReturnAddressPtr returnAddress() { return ReturnAddressPtr(asPointer); }
     };
     
@@ -87,7 +92,6 @@ namespace JSC {
         MacroAssemblerCodePtr ctiVirtualConstruct;
         MacroAssemblerCodePtr ctiNativeCall;
         MacroAssemblerCodePtr ctiNativeConstruct;
         MacroAssemblerCodePtr ctiVirtualConstruct;
         MacroAssemblerCodePtr ctiNativeCall;
         MacroAssemblerCodePtr ctiNativeConstruct;
-        MacroAssemblerCodePtr ctiSoftModulo;
     };
 
 #if CPU(X86_64)
     };
 
 #if CPU(X86_64)
@@ -149,9 +153,6 @@ namespace JSC {
     struct JITStackFrame {
         JITStubArg reserved; // Unused
         JITStubArg args[6];
     struct JITStackFrame {
         JITStubArg reserved; // Unused
         JITStubArg args[6];
-#if USE(JSVALUE64)
-        void* padding; // Maintain 16-byte stack alignment.
-#endif
 
         ReturnAddressPtr thunkReturnAddress;
 
 
         ReturnAddressPtr thunkReturnAddress;
 
@@ -159,11 +160,15 @@ namespace JSC {
         void* preservedR4;
         void* preservedR5;
         void* preservedR6;
         void* preservedR4;
         void* preservedR5;
         void* preservedR6;
+        void* preservedR7;
+        void* preservedR8;
+        void* preservedR9;
+        void* preservedR10;
+        void* preservedR11;
 
         // 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;
-        void* unused1;
 
         // These arguments passed on the stack.
         Profiler** enabledProfilerReference;
 
         // These arguments passed on the stack.
         Profiler** enabledProfilerReference;
@@ -266,6 +271,8 @@ namespace JSC {
     #define JIT_STUB __fastcall
     #elif COMPILER(GCC)
     #define JIT_STUB  __attribute__ ((fastcall))
     #define JIT_STUB __fastcall
     #elif COMPILER(GCC)
     #define JIT_STUB  __attribute__ ((fastcall))
+    #elif COMPILER(SUNCC)
+    #define JIT_STUB
     #else
     #error "JIT_STUB function calls require fastcall conventions on x86, add appropriate directive/attribute here for your compiler!"
     #endif
     #else
     #error "JIT_STUB function calls require fastcall conventions on x86, add appropriate directive/attribute here for your compiler!"
     #endif
@@ -276,6 +283,15 @@ namespace JSC {
     extern "C" void ctiVMThrowTrampoline();
     extern "C" void ctiOpThrowNotCaught();
     extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*);
     extern "C" void ctiVMThrowTrampoline();
     extern "C" void ctiOpThrowNotCaught();
     extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*);
+#if ENABLE(DFG_JIT)
+    extern "C" void ctiTrampolineEnd();
+
+    inline bool returnAddressIsInCtiTrampoline(ReturnAddressPtr returnAddress)
+    {
+        return returnAddress.value() >= bitwise_cast<void*>(&ctiTrampoline)
+            && returnAddress.value() < bitwise_cast<void*>(&ctiTrampolineEnd);
+    }
+#endif
 
     class JITThunks {
     public:
 
     class JITThunks {
     public:
@@ -290,23 +306,36 @@ namespace JSC {
         MacroAssemblerCodePtr ctiVirtualConstructLink() { return m_trampolineStructure.ctiVirtualConstructLink; }
         MacroAssemblerCodePtr ctiVirtualCall() { return m_trampolineStructure.ctiVirtualCall; }
         MacroAssemblerCodePtr ctiVirtualConstruct() { return m_trampolineStructure.ctiVirtualConstruct; }
         MacroAssemblerCodePtr ctiVirtualConstructLink() { return m_trampolineStructure.ctiVirtualConstructLink; }
         MacroAssemblerCodePtr ctiVirtualCall() { return m_trampolineStructure.ctiVirtualCall; }
         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 ctiNativeCall()
+        {
+#if ENABLE(LLINT)
+            if (!m_executableMemory)
+                return MacroAssemblerCodePtr::createLLIntCodePtr(llint_native_call_trampoline);
+#endif
+            return m_trampolineStructure.ctiNativeCall;
+        }
+        MacroAssemblerCodePtr ctiNativeConstruct()
+        {
+#if ENABLE(LLINT)
+            if (!m_executableMemory)
+                return MacroAssemblerCodePtr::createLLIntCodePtr(llint_native_construct_trampoline);
+#endif
+            return m_trampolineStructure.ctiNativeConstruct;
+        }
 
 
-        MacroAssemblerCodePtr ctiStub(JSGlobalData* globalData, ThunkGenerator generator);
+        MacroAssemblerCodeRef ctiStub(JSGlobalData*, ThunkGenerator);
 
 
-        NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction);
-        NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction, ThunkGenerator);
+        NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction, NativeFunction constructor);
+        NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction, ThunkGenerator, Intrinsic);
 
         void clearHostFunctionStubs();
 
     private:
 
         void clearHostFunctionStubs();
 
     private:
-        typedef HashMap<ThunkGenerator, MacroAssemblerCodePtr> CTIStubMap;
+        typedef HashMap<ThunkGenerator, MacroAssemblerCodeRef> CTIStubMap;
         CTIStubMap m_ctiStubMap;
         typedef HashMap<NativeFunction, Weak<NativeExecutable> > HostFunctionStubMap;
         OwnPtr<HostFunctionStubMap> m_hostFunctionStubMap;
         CTIStubMap m_ctiStubMap;
         typedef HashMap<NativeFunction, Weak<NativeExecutable> > HostFunctionStubMap;
         OwnPtr<HostFunctionStubMap> m_hostFunctionStubMap;
-        RefPtr<ExecutablePool> m_executablePool;
+        RefPtr<ExecutableMemoryHandle> m_executableMemory;
 
         TrampolineStructure m_trampolineStructure;
     };
 
         TrampolineStructure m_trampolineStructure;
     };
@@ -314,7 +343,6 @@ namespace JSC {
 extern "C" {
     EncodedJSValue JIT_STUB cti_op_add(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_bitand(STUB_ARGS_DECLARATION);
 extern "C" {
     EncodedJSValue JIT_STUB cti_op_add(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_bitand(STUB_ARGS_DECLARATION);
-    EncodedJSValue JIT_STUB cti_op_bitnot(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_bitor(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_bitxor(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_bitor(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_bitxor(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS_DECLARATION);
@@ -322,9 +350,7 @@ extern "C" {
     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_construct_NotJSConstruct(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_create_this(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION);
-    EncodedJSValue JIT_STUB cti_op_convert_this_strict(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_create_arguments(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_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);
@@ -334,13 +360,13 @@ extern "C" {
     EncodedJSValue JIT_STUB cti_op_get_by_id_generic(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_getter_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_generic(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_getter_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_method_check_update(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_self_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_val(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_self_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_val(STUB_ARGS_DECLARATION);
-    EncodedJSValue JIT_STUB cti_op_get_by_val_byte_array(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_val_string(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_in(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_instanceof(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_val_string(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_in(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_instanceof(STUB_ARGS_DECLARATION);
@@ -352,6 +378,8 @@ extern "C" {
     EncodedJSValue JIT_STUB cti_op_is_undefined(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_less(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_lesseq(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_is_undefined(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_less(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_lesseq(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_op_greater(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_op_greatereq(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_lshift(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_mod(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_mul(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_lshift(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_mod(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_mul(STUB_ARGS_DECLARATION);
@@ -370,6 +398,7 @@ extern "C" {
     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_with_base(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_with_base(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_op_resolve_with_this(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_rshift(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_rshift(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_strcat(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_stricteq(STUB_ARGS_DECLARATION);
@@ -394,9 +423,10 @@ extern "C" {
     int JIT_STUB cti_op_eq_strings(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_jless(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_jlesseq(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_jlesseq(STUB_ARGS_DECLARATION);
+    int JIT_STUB cti_op_jgreater(STUB_ARGS_DECLARATION);
+    int JIT_STUB cti_op_jgreatereq(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION);
-    int JIT_STUB cti_op_load_varargs(STUB_ARGS_DECLARATION);
-    int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION);
+    void* JIT_STUB cti_op_load_varargs(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_check_has_instance(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_check_has_instance(STUB_ARGS_DECLARATION);
@@ -414,12 +444,14 @@ extern "C" {
     void JIT_STUB cti_op_put_by_id_direct_generic(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_id_direct_generic(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_by_val(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_put_getter_setter(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_throw_reference_error(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_throw_reference_error(STUB_ARGS_DECLARATION);
+#if ENABLE(DFG_JIT)
+    void JIT_STUB cti_optimize_from_loop(STUB_ARGS_DECLARATION);
+    void JIT_STUB cti_optimize_from_ret(STUB_ARGS_DECLARATION);
+#endif
     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_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);
@@ -434,8 +466,8 @@ extern "C" {
     void* JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
 } // extern "C"
 
     void* JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
 } // extern "C"
 
-} // namespace JSC
-
 #endif // ENABLE(JIT)
 
 #endif // ENABLE(JIT)
 
+} // namespace JSC
+
 #endif // JITStubs_h
 #endif // JITStubs_h
index 10e07100186eeddacf34a3603da6918ec8a42881..81a3653a0c0bb5d3a7fbf1c64d180f713c75606b 100644 (file)
@@ -69,6 +69,7 @@ public:
     }
     
     void clear() { clear(0); }
     }
     
     void clear() { clear(0); }
+    void clearToMaxUnsigned() { clear(reinterpret_cast<void*>(-1)); }
 
 protected:
     JITWriteBarrierBase()
 
 protected:
     JITWriteBarrierBase()
@@ -121,6 +122,10 @@ public:
         validateCell(value);
         JITWriteBarrierBase::set(globalData, location, owner, value);
     }
         validateCell(value);
         JITWriteBarrierBase::set(globalData, location, owner, value);
     }
+    void set(JSGlobalData& globalData, JSCell* owner, T* value)
+    {
+        set(globalData, location(), owner, value);
+    }
     T* get() const
     {
         T* result = static_cast<T*>(JITWriteBarrierBase::get());
     T* get() const
     {
         T* result = static_cast<T*>(JITWriteBarrierBase::get());
index e1d9353cbb6f2b68db03a7ca6a544aff220c5eb8..05d1ce5ad8cdaafc1891747821f33577ebf2a298 100644 (file)
 #ifndef JSInterfaceJIT_h
 #define JSInterfaceJIT_h
 
 #ifndef JSInterfaceJIT_h
 #define JSInterfaceJIT_h
 
+#include "BytecodeConventions.h"
 #include "JITCode.h"
 #include "JITStubs.h"
 #include "JITCode.h"
 #include "JITStubs.h"
+#include "JSString.h"
 #include "JSValue.h"
 #include "MacroAssembler.h"
 #include "RegisterFile.h"
 #include "JSValue.h"
 #include "MacroAssembler.h"
 #include "RegisterFile.h"
@@ -55,6 +57,10 @@ namespace JSC {
         static const RegisterID cachedResultRegister = X86Registers::eax;
         static const RegisterID firstArgumentRegister = X86Registers::edi;
         
         static const RegisterID cachedResultRegister = X86Registers::eax;
         static const RegisterID firstArgumentRegister = X86Registers::edi;
         
+#if ENABLE(VALUE_PROFILER)
+        static const RegisterID bucketCounterRegister = X86Registers::r10;
+#endif
+        
         static const RegisterID timeoutCheckRegister = X86Registers::r12;
         static const RegisterID callFrameRegister = X86Registers::r13;
         static const RegisterID tagTypeNumberRegister = X86Registers::r14;
         static const RegisterID timeoutCheckRegister = X86Registers::r12;
         static const RegisterID callFrameRegister = X86Registers::r13;
         static const RegisterID tagTypeNumberRegister = X86Registers::r14;
@@ -76,7 +82,7 @@ namespace JSC {
         // OS X if might make more sense to just use regparm.
         static const RegisterID firstArgumentRegister = X86Registers::ecx;
         
         // OS X if might make more sense to just use regparm.
         static const RegisterID firstArgumentRegister = X86Registers::ecx;
         
-        static const RegisterID timeoutCheckRegister = X86Registers::esi;
+        static const RegisterID bucketCounterRegister = X86Registers::esi;
         static const RegisterID callFrameRegister = X86Registers::edi;
         
         static const RegisterID regT0 = X86Registers::eax;
         static const RegisterID callFrameRegister = X86Registers::edi;
         
         static const RegisterID regT0 = X86Registers::eax;
@@ -92,7 +98,11 @@ namespace JSC {
         static const RegisterID returnValueRegister = ARMRegisters::r0;
         static const RegisterID cachedResultRegister = ARMRegisters::r0;
         static const RegisterID firstArgumentRegister = ARMRegisters::r0;
         static const RegisterID returnValueRegister = ARMRegisters::r0;
         static const RegisterID cachedResultRegister = ARMRegisters::r0;
         static const RegisterID firstArgumentRegister = ARMRegisters::r0;
-        
+
+#if ENABLE(VALUE_PROFILER)
+        static const RegisterID bucketCounterRegister = ARMRegisters::r7;
+#endif
+
         static const RegisterID regT0 = ARMRegisters::r0;
         static const RegisterID regT1 = ARMRegisters::r1;
         static const RegisterID regT2 = ARMRegisters::r2;
         static const RegisterID regT0 = ARMRegisters::r0;
         static const RegisterID regT1 = ARMRegisters::r1;
         static const RegisterID regT2 = ARMRegisters::r2;
@@ -193,11 +203,6 @@ namespace JSC {
         inline Jump emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst);
         inline Jump emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch);
 
         inline Jump emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst);
         inline Jump emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch);
 
-        inline void storePtrWithWriteBarrier(TrustedImmPtr ptr, RegisterID /* owner */, Address dest)
-        {
-            storePtr(ptr, dest);
-        }
-
 #if USE(JSVALUE32_64)
         inline Jump emitJumpIfNotJSCell(unsigned virtualRegisterIndex);
         inline Address tagFor(int index, RegisterID base = callFrameRegister);
 #if USE(JSVALUE32_64)
         inline Jump emitJumpIfNotJSCell(unsigned virtualRegisterIndex);
         inline Address tagFor(int index, RegisterID base = callFrameRegister);
@@ -216,6 +221,8 @@ namespace JSC {
     };
 
     struct ThunkHelpers {
     };
 
     struct ThunkHelpers {
+        static unsigned stringImplFlagsOffset() { return StringImpl::flagsOffset(); }
+        static unsigned stringImpl8BitFlag() { return StringImpl::flagIs8Bit(); }
         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 stringImplDataOffset() { return StringImpl::dataOffset(); }
         static unsigned jsStringLengthOffset() { return OBJECT_OFFSETOF(JSString, m_length); }
         static unsigned jsStringValueOffset() { return OBJECT_OFFSETOF(JSString, m_value); }
@@ -276,7 +283,8 @@ namespace JSC {
         loadDouble(addressFor(virtualRegisterIndex), dst);
         done.link(this);
         return notInt;
         loadDouble(addressFor(virtualRegisterIndex), dst);
         done.link(this);
         return notInt;
-    }    
+    }
+
 #endif
 
 #if USE(JSVALUE64)
 #endif
 
 #if USE(JSVALUE64)
@@ -315,7 +323,7 @@ namespace JSC {
         done.link(this);
         return notNumber;
     }
         done.link(this);
         return notNumber;
     }
-    
+
     ALWAYS_INLINE void JSInterfaceJIT::emitFastArithImmToInt(RegisterID)
     {
     }
     ALWAYS_INLINE void JSInterfaceJIT::emitFastArithImmToInt(RegisterID)
     {
     }
index 13a5c2eee6e9afe31e8896571b492c01dbb76062..74e94ea3c70ca767fb2e45b3b58d96c50e04aa1f 100644 (file)
@@ -37,37 +37,35 @@ namespace JSC {
     class SpecializedThunkJIT : public JSInterfaceJIT {
     public:
         static const int ThisArgument = -1;
     class SpecializedThunkJIT : public JSInterfaceJIT {
     public:
         static const int ThisArgument = -1;
-        SpecializedThunkJIT(int expectedArgCount, JSGlobalData* globalData, ExecutablePool* pool)
+        SpecializedThunkJIT(int expectedArgCount, JSGlobalData* globalData)
             : m_expectedArgCount(expectedArgCount)
             , m_globalData(globalData)
             : m_expectedArgCount(expectedArgCount)
             , m_globalData(globalData)
-            , m_pool(pool)
         {
             // Check that we have the expected number of arguments
         {
             // Check that we have the expected number of arguments
-            m_failures.append(branch32(NotEqual, Address(callFrameRegister, RegisterFile::ArgumentCount * (int)sizeof(Register)), TrustedImm32(expectedArgCount + 1)));
+            m_failures.append(branch32(NotEqual, payloadFor(RegisterFile::ArgumentCount), TrustedImm32(expectedArgCount + 1)));
         }
         
         void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch)
         {
         }
         
         void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch)
         {
-            unsigned src = argumentToVirtualRegister(argument);
+            unsigned src = CallFrame::argumentOffset(argument);
             m_failures.append(emitLoadDouble(src, dst, scratch));
         }
         
         void loadCellArgument(int argument, RegisterID dst)
         {
             m_failures.append(emitLoadDouble(src, dst, scratch));
         }
         
         void loadCellArgument(int argument, RegisterID dst)
         {
-            unsigned src = argumentToVirtualRegister(argument);
+            unsigned src = CallFrame::argumentOffset(argument);
             m_failures.append(emitLoadJSCell(src, dst));
         }
         
         void loadJSStringArgument(int argument, RegisterID dst)
         {
             loadCellArgument(argument, dst);
             m_failures.append(emitLoadJSCell(src, dst));
         }
         
         void loadJSStringArgument(int argument, RegisterID dst)
         {
             loadCellArgument(argument, dst);
-            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(branchPtr(NotEqual, Address(dst, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
         }
         
         void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget)
         {
         }
         
         void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget)
         {
-            unsigned src = argumentToVirtualRegister(argument);
+            unsigned src = CallFrame::argumentOffset(argument);
             failTarget = emitLoadInt32(src, dst);
         }
         
             failTarget = emitLoadInt32(src, dst);
         }
         
@@ -95,11 +93,22 @@ namespace JSC {
         {
 #if USE(JSVALUE64)
             moveDoubleToPtr(src, regT0);
         {
 #if USE(JSVALUE64)
             moveDoubleToPtr(src, regT0);
+            Jump zero = branchTestPtr(Zero, regT0);
             subPtr(tagTypeNumberRegister, regT0);
             subPtr(tagTypeNumberRegister, regT0);
+            Jump done = jump();
+            zero.link(this);
+            move(tagTypeNumberRegister, regT0);
+            done.link(this);
 #else
             storeDouble(src, Address(stackPointerRegister, -(int)sizeof(double)));
             loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.tag) - sizeof(double)), regT1);
             loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.payload) - sizeof(double)), regT0);
 #else
             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);
+            Jump lowNonZero = branchTestPtr(NonZero, regT1);
+            Jump highNonZero = branchTestPtr(NonZero, regT0);
+            move(TrustedImm32(0), regT0);
+            move(TrustedImm32(Int32Tag), regT1);
+            lowNonZero.link(this);
+            highNonZero.link(this);
 #endif
             loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
             ret();
 #endif
             loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
             ret();
@@ -123,19 +132,24 @@ namespace JSC {
             ret();
         }
         
             ret();
         }
         
-        MacroAssemblerCodePtr finalize(JSGlobalData& globalData, MacroAssemblerCodePtr fallback)
+        MacroAssemblerCodeRef finalize(JSGlobalData& globalData, MacroAssemblerCodePtr fallback)
         {
         {
-            LinkBuffer patchBuffer(globalData, this, m_pool.get());
+            LinkBuffer patchBuffer(globalData, this, GLOBAL_THUNK_ID);
             patchBuffer.link(m_failures, CodeLocationLabel(fallback));
             patchBuffer.link(m_failures, CodeLocationLabel(fallback));
-            return patchBuffer.finalizeCode().m_code;
+            for (unsigned i = 0; i < m_calls.size(); i++)
+                patchBuffer.link(m_calls[i].first, m_calls[i].second);
+            return patchBuffer.finalizeCode();
         }
         }
-        
-    private:
-        int argumentToVirtualRegister(unsigned argument)
+
+        // Assumes that the target function uses fpRegister0 as the first argument
+        // and return value. Like any sensible architecture would.
+        void callDoubleToDouble(FunctionPtr function)
         {
         {
-            return -static_cast<int>(RegisterFile::CallFrameHeaderSize + (m_expectedArgCount - argument));
+            m_calls.append(std::make_pair(call(), function));
         }
 
         }
 
+    private:
+
         void tagReturnAsInt32()
         {
 #if USE(JSVALUE64)
         void tagReturnAsInt32()
         {
 #if USE(JSVALUE64)
@@ -154,8 +168,8 @@ namespace JSC {
         
         int m_expectedArgCount;
         JSGlobalData* m_globalData;
         
         int m_expectedArgCount;
         JSGlobalData* m_globalData;
-        RefPtr<ExecutablePool> m_pool;
         MacroAssembler::JumpList m_failures;
         MacroAssembler::JumpList m_failures;
+        Vector<std::pair<Call, FunctionPtr> > m_calls;
     };
 
 }
     };
 
 }
index d60fd4d9f6cc5971550dbe346ee5961bcc6acf24..371aff2f95b59ab3aa3c5ed274f7885a09a75b83 100644 (file)
@@ -27,8 +27,9 @@
 #include "ThunkGenerators.h"
 
 #include "CodeBlock.h"
 #include "ThunkGenerators.h"
 
 #include "CodeBlock.h"
-#include <wtf/text/StringImpl.h>
+#include <wtf/InlineASM.h>
 #include "SpecializedThunkJIT.h"
 #include "SpecializedThunkJIT.h"
+#include <wtf/text/StringImpl.h>
 
 #if ENABLE(JIT)
 
 
 #if ENABLE(JIT)
 
@@ -38,12 +39,11 @@ static void stringCharLoad(SpecializedThunkJIT& jit)
 {
     // load string
     jit.loadJSStringArgument(SpecializedThunkJIT::ThisArgument, SpecializedThunkJIT::regT0);
 {
     // load string
     jit.loadJSStringArgument(SpecializedThunkJIT::ThisArgument, SpecializedThunkJIT::regT0);
-    // regT0 now contains this, and is a non-rope JSString*
 
     // Load string length to regT2, and start the process of loading the data pointer into regT0
     jit.load32(MacroAssembler::Address(SpecializedThunkJIT::regT0, ThunkHelpers::jsStringLengthOffset()), SpecializedThunkJIT::regT2);
     jit.loadPtr(MacroAssembler::Address(SpecializedThunkJIT::regT0, ThunkHelpers::jsStringValueOffset()), SpecializedThunkJIT::regT0);
 
     // Load string length to regT2, and start the process of loading the data pointer into regT0
     jit.load32(MacroAssembler::Address(SpecializedThunkJIT::regT0, ThunkHelpers::jsStringLengthOffset()), SpecializedThunkJIT::regT2);
     jit.loadPtr(MacroAssembler::Address(SpecializedThunkJIT::regT0, ThunkHelpers::jsStringValueOffset()), SpecializedThunkJIT::regT0);
-    jit.loadPtr(MacroAssembler::Address(SpecializedThunkJIT::regT0, ThunkHelpers::stringImplDataOffset()), SpecializedThunkJIT::regT0);
+    jit.appendFailure(jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0));
 
     // load index
     jit.loadInt32Argument(0, SpecializedThunkJIT::regT1); // regT1 contains the index
 
     // load index
     jit.loadInt32Argument(0, SpecializedThunkJIT::regT1); // regT1 contains the index
@@ -52,7 +52,17 @@ static void stringCharLoad(SpecializedThunkJIT& jit)
     jit.appendFailure(jit.branch32(MacroAssembler::AboveOrEqual, SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT2));
 
     // Load the character
     jit.appendFailure(jit.branch32(MacroAssembler::AboveOrEqual, SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT2));
 
     // Load the character
+    SpecializedThunkJIT::JumpList is16Bit;
+    SpecializedThunkJIT::JumpList cont8Bit;
+    // Load the string flags
+    jit.loadPtr(MacroAssembler::Address(SpecializedThunkJIT::regT0, ThunkHelpers::stringImplFlagsOffset()), SpecializedThunkJIT::regT2);
+    jit.loadPtr(MacroAssembler::Address(SpecializedThunkJIT::regT0, ThunkHelpers::stringImplDataOffset()), SpecializedThunkJIT::regT0);
+    is16Bit.append(jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT2, MacroAssembler::TrustedImm32(ThunkHelpers::stringImpl8BitFlag())));
+    jit.load8(MacroAssembler::BaseIndex(SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1, MacroAssembler::TimesOne, 0), SpecializedThunkJIT::regT0);
+    cont8Bit.append(jit.jump());
+    is16Bit.link(&jit);
     jit.load16(MacroAssembler::BaseIndex(SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1, MacroAssembler::TimesTwo, 0), SpecializedThunkJIT::regT0);
     jit.load16(MacroAssembler::BaseIndex(SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1, MacroAssembler::TimesTwo, 0), SpecializedThunkJIT::regT0);
+    cont8Bit.link(&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)
@@ -63,26 +73,26 @@ static void charToString(SpecializedThunkJIT& jit, JSGlobalData* globalData, Mac
     jit.appendFailure(jit.branchTestPtr(MacroAssembler::Zero, dst));
 }
 
     jit.appendFailure(jit.branchTestPtr(MacroAssembler::Zero, dst));
 }
 
-MacroAssemblerCodePtr charCodeAtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+MacroAssemblerCodeRef charCodeAtThunkGenerator(JSGlobalData* globalData)
 {
 {
-    SpecializedThunkJIT jit(1, globalData, pool);
+    SpecializedThunkJIT jit(1, globalData);
     stringCharLoad(jit);
     jit.returnInt32(SpecializedThunkJIT::regT0);
     return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
     stringCharLoad(jit);
     jit.returnInt32(SpecializedThunkJIT::regT0);
     return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
-MacroAssemblerCodePtr charAtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+MacroAssemblerCodeRef charAtThunkGenerator(JSGlobalData* globalData)
 {
 {
-    SpecializedThunkJIT jit(1, globalData, pool);
+    SpecializedThunkJIT jit(1, globalData);
     stringCharLoad(jit);
     charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
     jit.returnJSCell(SpecializedThunkJIT::regT0);
     return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
     stringCharLoad(jit);
     charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
     jit.returnJSCell(SpecializedThunkJIT::regT0);
     return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
-MacroAssemblerCodePtr fromCharCodeThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+MacroAssemblerCodeRef fromCharCodeThunkGenerator(JSGlobalData* globalData)
 {
 {
-    SpecializedThunkJIT jit(1, globalData, pool);
+    SpecializedThunkJIT jit(1, globalData);
     // load char code
     jit.loadInt32Argument(0, SpecializedThunkJIT::regT0);
     charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
     // load char code
     jit.loadInt32Argument(0, SpecializedThunkJIT::regT0);
     charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
@@ -90,11 +100,11 @@ MacroAssemblerCodePtr fromCharCodeThunkGenerator(JSGlobalData* globalData, Execu
     return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
     return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
-MacroAssemblerCodePtr sqrtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+MacroAssemblerCodeRef sqrtThunkGenerator(JSGlobalData* globalData)
 {
 {
-    SpecializedThunkJIT jit(1, globalData, pool);
+    SpecializedThunkJIT jit(1, globalData);
     if (!jit.supportsFloatingPointSqrt())
     if (!jit.supportsFloatingPointSqrt())
-        return globalData->jitStubs->ctiNativeCall();
+        return MacroAssemblerCodeRef::createSelfManagedCodeRef(globalData->jitStubs->ctiNativeCall());
 
     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
     jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
 
     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
     jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
@@ -102,14 +112,180 @@ MacroAssemblerCodePtr sqrtThunkGenerator(JSGlobalData* globalData, ExecutablePoo
     return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
     return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
+
+#define UnaryDoubleOpWrapper(function) function##Wrapper
+enum MathThunkCallingConvention { };
+typedef MathThunkCallingConvention(*MathThunk)(MathThunkCallingConvention);
+extern "C" {
+
+double jsRound(double);
+double jsRound(double d)
+{
+    double integer = ceil(d);
+    return integer - (integer - d > 0.5);
+}
+
+}
+    
+#if CPU(X86_64) && COMPILER(GCC) && (PLATFORM(MAC) || OS(LINUX))
+
+#define defineUnaryDoubleOpWrapper(function) \
+    asm( \
+        ".text\n" \
+        ".globl " SYMBOL_STRING(function##Thunk) "\n" \
+        HIDE_SYMBOL(function##Thunk) "\n" \
+        SYMBOL_STRING(function##Thunk) ":" "\n" \
+        "call " SYMBOL_STRING_RELOCATION(function) "\n" \
+        "ret\n" \
+    );\
+    extern "C" { \
+        MathThunkCallingConvention function##Thunk(MathThunkCallingConvention); \
+    } \
+    static MathThunk UnaryDoubleOpWrapper(function) = &function##Thunk;
+
+#elif CPU(X86) && COMPILER(GCC) && (PLATFORM(MAC) || OS(LINUX))
+#define defineUnaryDoubleOpWrapper(function) \
+    asm( \
+        ".text\n" \
+        ".globl " SYMBOL_STRING(function##Thunk) "\n" \
+        HIDE_SYMBOL(function##Thunk) "\n" \
+        SYMBOL_STRING(function##Thunk) ":" "\n" \
+        "subl $8, %esp\n" \
+        "movsd %xmm0, (%esp) \n" \
+        "call " SYMBOL_STRING_RELOCATION(function) "\n" \
+        "fstpl (%esp) \n" \
+        "movsd (%esp), %xmm0 \n" \
+        "addl $8, %esp\n" \
+        "ret\n" \
+    );\
+    extern "C" { \
+        MathThunkCallingConvention function##Thunk(MathThunkCallingConvention); \
+    } \
+    static MathThunk UnaryDoubleOpWrapper(function) = &function##Thunk;
+
+#else
+
+#define defineUnaryDoubleOpWrapper(function) \
+    static MathThunk UnaryDoubleOpWrapper(function) = 0
+#endif
+
+defineUnaryDoubleOpWrapper(jsRound);
+defineUnaryDoubleOpWrapper(exp);
+defineUnaryDoubleOpWrapper(log);
+defineUnaryDoubleOpWrapper(floor);
+defineUnaryDoubleOpWrapper(ceil);
+
+MacroAssemblerCodeRef floorThunkGenerator(JSGlobalData* globalData)
+{
+    SpecializedThunkJIT jit(1, globalData);
+    MacroAssembler::Jump nonIntJump;
+    if (!UnaryDoubleOpWrapper(floor) || !jit.supportsFloatingPoint())
+        return MacroAssemblerCodeRef::createSelfManagedCodeRef(globalData->jitStubs->ctiNativeCall());
+    jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
+    jit.returnInt32(SpecializedThunkJIT::regT0);
+    nonIntJump.link(&jit);
+    jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+    jit.callDoubleToDouble(UnaryDoubleOpWrapper(floor));
+    SpecializedThunkJIT::JumpList doubleResult;
+    jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1);
+    jit.returnInt32(SpecializedThunkJIT::regT0);
+    doubleResult.link(&jit);
+    jit.returnDouble(SpecializedThunkJIT::fpRegT0);
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+}
+
+MacroAssemblerCodeRef ceilThunkGenerator(JSGlobalData* globalData)
+{
+    SpecializedThunkJIT jit(1, globalData);
+    if (!UnaryDoubleOpWrapper(ceil) || !jit.supportsFloatingPoint())
+        return MacroAssemblerCodeRef::createSelfManagedCodeRef(globalData->jitStubs->ctiNativeCall());
+    MacroAssembler::Jump nonIntJump;
+    jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
+    jit.returnInt32(SpecializedThunkJIT::regT0);
+    nonIntJump.link(&jit);
+    jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+    jit.callDoubleToDouble(UnaryDoubleOpWrapper(ceil));
+    SpecializedThunkJIT::JumpList doubleResult;
+    jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1);
+    jit.returnInt32(SpecializedThunkJIT::regT0);
+    doubleResult.link(&jit);
+    jit.returnDouble(SpecializedThunkJIT::fpRegT0);
+    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;
+    
+MacroAssemblerCodeRef roundThunkGenerator(JSGlobalData* globalData)
+{
+    SpecializedThunkJIT jit(1, globalData);
+    if (!UnaryDoubleOpWrapper(jsRound) || !jit.supportsFloatingPoint())
+        return MacroAssemblerCodeRef::createSelfManagedCodeRef(globalData->jitStubs->ctiNativeCall());
+    MacroAssembler::Jump nonIntJump;
+    jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
+    jit.returnInt32(SpecializedThunkJIT::regT0);
+    nonIntJump.link(&jit);
+    jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+    jit.callDoubleToDouble(UnaryDoubleOpWrapper(jsRound));
+    SpecializedThunkJIT::JumpList doubleResult;
+    jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1);
+    jit.returnInt32(SpecializedThunkJIT::regT0);
+    doubleResult.link(&jit);
+    jit.returnDouble(SpecializedThunkJIT::fpRegT0);
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+}
+
+MacroAssemblerCodeRef expThunkGenerator(JSGlobalData* globalData)
+{
+    if (!UnaryDoubleOpWrapper(exp))
+        return MacroAssemblerCodeRef::createSelfManagedCodeRef(globalData->jitStubs->ctiNativeCall());
+    SpecializedThunkJIT jit(1, globalData);
+    if (!jit.supportsFloatingPoint())
+        return MacroAssemblerCodeRef::createSelfManagedCodeRef(globalData->jitStubs->ctiNativeCall());
+    jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+    jit.callDoubleToDouble(UnaryDoubleOpWrapper(exp));
+    jit.returnDouble(SpecializedThunkJIT::fpRegT0);
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+}
+
+MacroAssemblerCodeRef logThunkGenerator(JSGlobalData* globalData)
+{
+    if (!UnaryDoubleOpWrapper(log))
+        return MacroAssemblerCodeRef::createSelfManagedCodeRef(globalData->jitStubs->ctiNativeCall());
+    SpecializedThunkJIT jit(1, globalData);
+    if (!jit.supportsFloatingPoint())
+        return MacroAssemblerCodeRef::createSelfManagedCodeRef(globalData->jitStubs->ctiNativeCall());
+    jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+    jit.callDoubleToDouble(UnaryDoubleOpWrapper(log));
+    jit.returnDouble(SpecializedThunkJIT::fpRegT0);
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+}
+
+MacroAssemblerCodeRef absThunkGenerator(JSGlobalData* globalData)
+{
+    SpecializedThunkJIT jit(1, globalData);
+    if (!jit.supportsFloatingPointAbs())
+        return MacroAssemblerCodeRef::createSelfManagedCodeRef(globalData->jitStubs->ctiNativeCall());
+    MacroAssembler::Jump nonIntJump;
+    jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntJump);
+    jit.rshift32(SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(31), SpecializedThunkJIT::regT1);
+    jit.add32(SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT0);
+    jit.xor32(SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT0);
+    jit.appendFailure(jit.branch32(MacroAssembler::Equal, SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(1 << 31)));
+    jit.returnInt32(SpecializedThunkJIT::regT0);
+    nonIntJump.link(&jit);
+    // Shame about the double int conversion here.
+    jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+    jit.absDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1);
+    jit.returnDouble(SpecializedThunkJIT::fpRegT1);
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
+}
 
 
-MacroAssemblerCodePtr powThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+MacroAssemblerCodeRef powThunkGenerator(JSGlobalData* globalData)
 {
 {
-    SpecializedThunkJIT jit(2, globalData, pool);
+    SpecializedThunkJIT jit(2, globalData);
     if (!jit.supportsFloatingPoint())
     if (!jit.supportsFloatingPoint())
-        return globalData->jitStubs->ctiNativeCall();
+        return MacroAssemblerCodeRef::createSelfManagedCodeRef(globalData->jitStubs->ctiNativeCall());
 
     jit.loadDouble(&oneConstant, SpecializedThunkJIT::fpRegT1);
     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
 
     jit.loadDouble(&oneConstant, SpecializedThunkJIT::fpRegT1);
     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
index 15261f78be4b637c3f72b89c739ebe5dd954527f..b251f6be85f18334875f1a327c28034b540957d8 100644 (file)
@@ -31,14 +31,20 @@ namespace JSC {
     class ExecutablePool;
     class JSGlobalData;
     class NativeExecutable;
     class ExecutablePool;
     class JSGlobalData;
     class NativeExecutable;
-    class MacroAssemblerCodePtr;
+    class MacroAssemblerCodeRef;
 
 
-    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*);
+    typedef MacroAssemblerCodeRef (*ThunkGenerator)(JSGlobalData*);
+    MacroAssemblerCodeRef charCodeAtThunkGenerator(JSGlobalData*);
+    MacroAssemblerCodeRef charAtThunkGenerator(JSGlobalData*);
+    MacroAssemblerCodeRef fromCharCodeThunkGenerator(JSGlobalData*);
+    MacroAssemblerCodeRef absThunkGenerator(JSGlobalData*);
+    MacroAssemblerCodeRef ceilThunkGenerator(JSGlobalData*);
+    MacroAssemblerCodeRef expThunkGenerator(JSGlobalData*);
+    MacroAssemblerCodeRef floorThunkGenerator(JSGlobalData*);
+    MacroAssemblerCodeRef logThunkGenerator(JSGlobalData*);
+    MacroAssemblerCodeRef roundThunkGenerator(JSGlobalData*);
+    MacroAssemblerCodeRef sqrtThunkGenerator(JSGlobalData*);
+    MacroAssemblerCodeRef powThunkGenerator(JSGlobalData*);
 }
 #endif
 
 }
 #endif
 
diff --git a/jsc.cpp b/jsc.cpp
index 85ed56b3f3bd086dce1319a06ff7b9b79f322b6d..95bc3343faaa39290d683df97e6e1068bdfab43e 100644 (file)
--- a/jsc.cpp
+++ b/jsc.cpp
 
 #include "BytecodeGenerator.h"
 #include "Completion.h"
 
 #include "BytecodeGenerator.h"
 #include "Completion.h"
-#include "CurrentTime.h"
+#include <wtf/CurrentTime.h>
 #include "ExceptionHelpers.h"
 #include "InitializeThreading.h"
 #include "ExceptionHelpers.h"
 #include "InitializeThreading.h"
+#include "Interpreter.h"
 #include "JSArray.h"
 #include "JSArray.h"
+#include "JSCTypedArrayStubs.h"
 #include "JSFunction.h"
 #include "JSLock.h"
 #include "JSString.h"
 #include "JSFunction.h"
 #include "JSLock.h"
 #include "JSString.h"
+#include <wtf/MainThread.h>
 #include "SamplingTool.h"
 #include <math.h>
 #include <stdio.h>
 #include "SamplingTool.h"
 #include <math.h>
 #include <stdio.h>
 #endif
 
 #if HAVE(READLINE)
 #endif
 
 #if HAVE(READLINE)
+// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
+// We #define it to something else to avoid this conflict.
+#define Function ReadlineFunction
 #include <readline/history.h>
 #include <readline/readline.h>
 #include <readline/history.h>
 #include <readline/readline.h>
+#undef Function
 #endif
 
 #if HAVE(SYS_TIME_H)
 #endif
 
 #if HAVE(SYS_TIME_H)
 #include <QDateTime>
 #endif
 
 #include <QDateTime>
 #endif
 
+#if CPU(ARM_THUMB2)
+#include <fenv.h>
+#include <arm/arch.h>
+#endif
+
 using namespace JSC;
 using namespace WTF;
 
 using namespace JSC;
 using namespace WTF;
 
-static void cleanupGlobalData(JSGlobalData*);
 static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer);
 
 static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
 static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer);
 
 static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
 #ifndef NDEBUG
 static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
 #ifndef NDEBUG
 static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
@@ -82,6 +94,7 @@ 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 EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
 static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
 
 #if ENABLE(SAMPLING_FLAGS)
 static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
 
 #if ENABLE(SAMPLING_FLAGS)
@@ -100,8 +113,8 @@ struct Script {
     }
 };
 
     }
 };
 
-struct Options {
-    Options()
+struct CommandLine {
+    CommandLine()
         : interactive(false)
         , dump(false)
     {
         : interactive(false)
         , dump(false)
     {
@@ -114,7 +127,6 @@ struct Options {
 };
 
 static const char interactivePrompt[] = "> ";
 };
 
 static const char interactivePrompt[] = "> ";
-static const UString interpreterName("Interpreter");
 
 class StopWatch {
 public:
 
 class StopWatch {
 public:
@@ -143,38 +155,105 @@ long StopWatch::getElapsedMS()
 }
 
 class GlobalObject : public JSGlobalObject {
 }
 
 class GlobalObject : public JSGlobalObject {
+private:
+    GlobalObject(JSGlobalData&, Structure*);
+
 public:
 public:
-    GlobalObject(JSGlobalData&, Structure*, const Vector<UString>& arguments);
-    virtual UString className() const { return "global"; }
+    typedef JSGlobalObject Base;
+
+    static GlobalObject* create(JSGlobalData& globalData, Structure* structure, const Vector<UString>& arguments)
+    {
+        GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(globalData.heap)) GlobalObject(globalData, structure);
+        object->finishCreation(globalData, arguments);
+        return object;
+    }
+
+    static const ClassInfo s_info;
+
+    static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+    {
+        return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
+    }
+
+protected:
+    void finishCreation(JSGlobalData& globalData, const Vector<UString>& arguments)
+    {
+        Base::finishCreation(globalData);
+        
+        addFunction(globalData, "debug", functionDebug, 1);
+        addFunction(globalData, "print", functionPrint, 1);
+        addFunction(globalData, "quit", functionQuit, 0);
+        addFunction(globalData, "gc", functionGC, 0);
+#ifndef NDEBUG
+        addFunction(globalData, "releaseExecutableMemory", functionReleaseExecutableMemory, 0);
+#endif
+        addFunction(globalData, "version", functionVersion, 1);
+        addFunction(globalData, "run", functionRun, 1);
+        addFunction(globalData, "load", functionLoad, 1);
+        addFunction(globalData, "checkSyntax", functionCheckSyntax, 1);
+        addFunction(globalData, "jscStack", functionJSCStack, 1);
+        addFunction(globalData, "readline", functionReadline, 0);
+        addFunction(globalData, "preciseTime", functionPreciseTime, 0);
+#if ENABLE(SAMPLING_FLAGS)
+        addFunction(globalData, "setSamplingFlags", functionSetSamplingFlags, 1);
+        addFunction(globalData, "clearSamplingFlags", functionClearSamplingFlags, 1);
+#endif
+        
+        addConstructableFunction(globalData, "Uint8Array", constructJSUint8Array, 1);
+        addConstructableFunction(globalData, "Uint8ClampedArray", constructJSUint8ClampedArray, 1);
+        addConstructableFunction(globalData, "Uint16Array", constructJSUint16Array, 1);
+        addConstructableFunction(globalData, "Uint32Array", constructJSUint32Array, 1);
+        addConstructableFunction(globalData, "Int8Array", constructJSInt8Array, 1);
+        addConstructableFunction(globalData, "Int16Array", constructJSInt16Array, 1);
+        addConstructableFunction(globalData, "Int32Array", constructJSInt32Array, 1);
+        addConstructableFunction(globalData, "Float32Array", constructJSFloat32Array, 1);
+        addConstructableFunction(globalData, "Float64Array", constructJSFloat64Array, 1);
+
+        JSArray* array = constructEmptyArray(globalExec());
+        for (size_t i = 0; i < arguments.size(); ++i)
+            array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]), false);
+        putDirect(globalData, Identifier(globalExec(), "arguments"), array);
+    }
+
+    void addFunction(JSGlobalData& globalData, const char* name, NativeFunction function, unsigned arguments)
+    {
+        Identifier identifier(globalExec(), name);
+        putDirect(globalData, identifier, JSFunction::create(globalExec(), this, arguments, identifier, function));
+    }
+    
+    void addConstructableFunction(JSGlobalData& globalData, const char* name, NativeFunction function, unsigned arguments)
+    {
+        Identifier identifier(globalExec(), name);
+        putDirect(globalData, identifier, JSFunction::create(globalExec(), this, arguments, identifier, function, NoIntrinsic, function));
+    }
 };
 COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
 ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
 
 };
 COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
 ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
 
-GlobalObject::GlobalObject(JSGlobalData& globalData, Structure* structure, const Vector<UString>& arguments)
+const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
+
+GlobalObject::GlobalObject(JSGlobalData& globalData, Structure* structure)
     : JSGlobalObject(globalData, structure)
 {
     : JSGlobalObject(globalData, structure)
 {
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug));
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "print"), functionPrint));
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "quit"), functionQuit));
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "gc"), functionGC));
-#ifndef NDEBUG
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "releaseExecutableMemory"), functionReleaseExecutableMemory));
-#endif
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "version"), functionVersion));
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "run"), functionRun));
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "load"), functionLoad));
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "checkSyntax"), functionCheckSyntax));
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "readline"), functionReadline));
-
-#if ENABLE(SAMPLING_FLAGS)
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "setSamplingFlags"), functionSetSamplingFlags));
-    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "clearSamplingFlags"), functionClearSamplingFlags));
-#endif
+}
 
 
-    JSObject* array = constructEmptyArray(globalExec());
-    for (size_t i = 0; i < arguments.size(); ++i)
-        array->put(globalExec(), i, jsString(globalExec(), arguments[i]));
-    putDirect(globalExec()->globalData(), Identifier(globalExec(), "arguments"), array);
+static inline SourceCode jscSource(const char* utf8, const UString& filename)
+{
+    // Find the the first non-ascii character, or nul.
+    const char* pos = utf8;
+    while (*pos > 0)
+        pos++;
+    size_t asciiLength = pos - utf8;
+
+    // Fast case - string is all ascii.
+    if (!*pos)
+        return makeSource(UString(utf8, asciiLength), filename);
+
+    // Slow case - contains non-ascii characters, use fromUTF8WithLatin1Fallback.
+    ASSERT(*pos < 0);
+    ASSERT(strlen(utf8) == asciiLength + strlen(pos));
+    String source = String::fromUTF8WithLatin1Fallback(utf8, asciiLength + strlen(pos));
+    return makeSource(source.impl(), filename);
 }
 
 EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
@@ -183,7 +262,7 @@ EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
         if (i)
             putchar(' ');
 
         if (i)
             putchar(' ');
 
-        printf("%s", exec->argument(i).toString(exec).utf8().data());
+        printf("%s", exec->argument(i).toString(exec)->value(exec).utf8().data());
     }
 
     putchar('\n');
     }
 
     putchar('\n');
@@ -193,13 +272,29 @@ EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
 {
 
 EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
 {
-    fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec).utf8().data());
+    fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data());
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
+{
+    String trace = "--> Stack trace:\n";
+    Vector<StackFrame> stackTrace;
+    Interpreter::getStackTrace(&exec->globalData(), stackTrace);
+    int i = 0;
+
+    for (Vector<StackFrame>::iterator iter = stackTrace.begin(); iter < stackTrace.end(); iter++) {
+        StackFrame level = *iter;
+        trace += String::format("    %i   %s\n", i, level.toString(exec).utf8().data());
+        i++;
+    }
+    fprintf(stderr, "%s", trace.utf8().data());
     return JSValue::encode(jsUndefined());
 }
 
 EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
 {
     return JSValue::encode(jsUndefined());
 }
 
 EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
 {
-    JSLock lock(SilenceAssertionsOnly);
+    JSLockHolder lock(exec);
     exec->heap()->collectAllGarbage();
     return JSValue::encode(jsUndefined());
 }
     exec->heap()->collectAllGarbage();
     return JSValue::encode(jsUndefined());
 }
@@ -207,7 +302,7 @@ EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
 #ifndef NDEBUG
 EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
 {
 #ifndef NDEBUG
 EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
 {
-    JSLock lock(SilenceAssertionsOnly);
+    JSLockHolder lock(exec);
     exec->globalData().releaseExecutableMemory();
     return JSValue::encode(jsUndefined());
 }
     exec->globalData().releaseExecutableMemory();
     return JSValue::encode(jsUndefined());
 }
@@ -222,38 +317,46 @@ EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
 
 EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
 {
 
 EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
 {
-    UString fileName = exec->argument(0).toString(exec);
+    UString fileName = exec->argument(0).toString(exec)->value(exec);
     Vector<char> script;
     if (!fillBufferWithContentsOfFile(fileName, script))
         return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
 
     Vector<char> script;
     if (!fillBufferWithContentsOfFile(fileName, script))
         return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
 
-    GlobalObject* globalObject = new (&exec->globalData()) GlobalObject(exec->globalData(), GlobalObject::createStructure(exec->globalData(), jsNull()), Vector<UString>());
+    GlobalObject* globalObject = GlobalObject::create(exec->globalData(), GlobalObject::createStructure(exec->globalData(), jsNull()), Vector<UString>());
 
 
+    JSValue exception;
     StopWatch stopWatch;
     stopWatch.start();
     StopWatch stopWatch;
     stopWatch.start();
-    evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
+    evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(script.data(), fileName), JSValue(), &exception);
     stopWatch.stop();
 
     stopWatch.stop();
 
+    if (!!exception) {
+        throwError(globalObject->globalExec(), exception);
+        return JSValue::encode(jsUndefined());
+    }
+    
     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
 }
 
 EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
 {
     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
 }
 
 EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
 {
-    UString fileName = exec->argument(0).toString(exec);
+    UString fileName = exec->argument(0).toString(exec)->value(exec);
     Vector<char> script;
     if (!fillBufferWithContentsOfFile(fileName, script))
         return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     Vector<char> script;
     if (!fillBufferWithContentsOfFile(fileName, script))
         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)
-        throwError(exec, result.value());
-    return JSValue::encode(result.value());
+    
+    JSValue evaluationException;
+    JSValue result = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(script.data(), fileName), JSValue(), &evaluationException);
+    if (evaluationException)
+        throwError(exec, evaluationException);
+    return JSValue::encode(result);
 }
 
 EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
 {
 }
 
 EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
 {
-    UString fileName = exec->argument(0).toString(exec);
+    UString fileName = exec->argument(0).toString(exec)->value(exec);
     Vector<char> script;
     if (!fillBufferWithContentsOfFile(fileName, script))
         return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
     Vector<char> script;
     if (!fillBufferWithContentsOfFile(fileName, script))
         return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
@@ -262,11 +365,13 @@ EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
 
     StopWatch stopWatch;
     stopWatch.start();
 
     StopWatch stopWatch;
     stopWatch.start();
-    Completion result = checkSyntax(globalObject->globalExec(), makeSource(script.data(), fileName));
+
+    JSValue syntaxException;
+    bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script.data(), fileName), &syntaxException);
     stopWatch.stop();
 
     stopWatch.stop();
 
-    if (result.complType() == Throw)
-        throwError(exec, result.value());
+    if (!validSyntax)
+        throwError(exec, syntaxException);
     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
 }
 
     return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
 }
 
@@ -306,14 +411,13 @@ EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
     return JSValue::encode(jsString(exec, line.data()));
 }
 
     return JSValue::encode(jsString(exec, line.data()));
 }
 
-EncodedJSValue JSC_HOST_CALL functionQuit(ExecState* exec)
+EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
 {
 {
-    // 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
-    // we pretend that execution has terminated to avoid ASSERTs, then tear down the heap.
-    exec->globalData().dynamicGlobalObject = 0;
+    return JSValue::encode(jsNumber(currentTime()));
+}
 
 
-    cleanupGlobalData(&exec->globalData());
+EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
+{
     exit(EXIT_SUCCESS);
 
 #if COMPILER(MSVC) && OS(WINCE)
     exit(EXIT_SUCCESS);
 
 #if COMPILER(MSVC) && OS(WINCE)
@@ -327,7 +431,7 @@ EncodedJSValue JSC_HOST_CALL functionQuit(ExecState* exec)
 // 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) && !OS(WINCE)
+#if COMPILER(MSVC) && !COMPILER(INTEL) && !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
@@ -335,10 +439,18 @@ EncodedJSValue JSC_HOST_CALL functionQuit(ExecState* exec)
 #define EXCEPT(x)
 #endif
 
 #define EXCEPT(x)
 #endif
 
-int jscmain(int argc, char** argv, JSGlobalData*);
+int jscmain(int argc, char** argv);
 
 int main(int argc, char** argv)
 {
 
 int main(int argc, char** argv)
 {
+#if CPU(ARM_THUMB2)
+    // Enabled IEEE754 denormal support.
+    fenv_t env;
+    fegetenv( &env );
+    env.__fpscr &= ~0x01000000u;
+    fesetenv( &env );
+#endif
+
 #if OS(WINDOWS)
 #if !OS(WINCE)
     // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
 #if OS(WINDOWS)
 #if !OS(WINCE)
     // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
@@ -364,31 +476,21 @@ int main(int argc, char** argv)
 #endif
 
     // Initialize JSC before getting JSGlobalData.
 #endif
 
     // Initialize JSC before getting JSGlobalData.
+    WTF::initializeMainThread();
     JSC::initializeThreading();
 
     // We can't use destructors in the following code because it uses Windows
     // Structured Exception Handling
     int res = 0;
     JSC::initializeThreading();
 
     // We can't use destructors in the following code because it uses Windows
     // Structured Exception Handling
     int res = 0;
-    JSGlobalData* globalData = JSGlobalData::create(ThreadStackTypeLarge).leakRef();
     TRY
     TRY
-        res = jscmain(argc, argv, globalData);
+        res = jscmain(argc, argv);
     EXCEPT(res = 3)
     EXCEPT(res = 3)
-
-    cleanupGlobalData(globalData);
     return res;
 }
 
     return res;
 }
 
-static void cleanupGlobalData(JSGlobalData* globalData)
-{
-    JSLock lock(SilenceAssertionsOnly);
-    globalData->clearBuiltinStructures();
-    globalData->heap.destroy();
-    globalData->deref();
-}
-
 static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
 {
 static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
 {
-    UString script;
+    const char* script;
     UString fileName;
     Vector<char> scriptBuffer;
 
     UString fileName;
     Vector<char> scriptBuffer;
 
@@ -415,13 +517,17 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
 
         globalData.startSampling();
 
 
         globalData.startSampling();
 
-        Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script, fileName));
-        success = success && completion.complType() != Throw;
-        if (dump) {
-            if (completion.complType() == Throw)
-                printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
-            else
-                printf("End: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
+        JSValue evaluationException;
+        JSValue returnValue = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(script, fileName), JSValue(), &evaluationException);
+        success = success && !evaluationException;
+        if (dump && !evaluationException)
+            printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
+        if (evaluationException) {
+            printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
+            Identifier stackID(globalObject->globalExec(), "stack");
+            JSValue stackValue = evaluationException.get(globalObject->globalExec(), stackID);
+            if (!stackValue.isUndefinedOrNull())
+                printf("%s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
         }
 
         globalData.stopSampling();
         }
 
         globalData.stopSampling();
@@ -430,6 +536,9 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
 
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::stop();
 
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::stop();
+#endif
+#if ENABLE(SAMPLING_REGIONS)
+    SamplingRegion::dump();
 #endif
     globalData.dumpSampleData(globalObject->globalExec());
 #if ENABLE(SAMPLING_COUNTERS)
 #endif
     globalData.dumpSampleData(globalObject->globalExec());
 #if ENABLE(SAMPLING_COUNTERS)
@@ -445,6 +554,8 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
 
 static void runInteractive(GlobalObject* globalObject)
 {
 
 static void runInteractive(GlobalObject* globalObject)
 {
+    UString interpreterName("Interpreter");
+
     while (true) {
 #if HAVE(READLINE) && !RUNNING_FROM_XCODE
         char* line = readline(interactivePrompt);
     while (true) {
 #if HAVE(READLINE) && !RUNNING_FROM_XCODE
         char* line = readline(interactivePrompt);
@@ -452,7 +563,8 @@ static void runInteractive(GlobalObject* globalObject)
             break;
         if (line[0])
             add_history(line);
             break;
         if (line[0])
             add_history(line);
-        Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line, interpreterName));
+        JSValue evaluationException;
+        JSValue returnValue = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(line, interpreterName), JSValue(), &evaluationException);
         free(line);
 #else
         printf("%s", interactivePrompt);
         free(line);
 #else
         printf("%s", interactivePrompt);
@@ -467,19 +579,21 @@ static void runInteractive(GlobalObject* globalObject)
         if (line.isEmpty())
             break;
         line.append('\0');
         if (line.isEmpty())
             break;
         line.append('\0');
-        Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line.data(), interpreterName));
+
+        JSValue evaluationException;
+        JSValue returnValue = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(line.data(), interpreterName), JSValue(), &evaluationException);
 #endif
 #endif
-        if (completion.complType() == Throw)
-            printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
+        if (evaluationException)
+            printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
         else
         else
-            printf("%s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
+            printf("%s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
 
         globalObject->globalExec()->clearException();
     }
     printf("\n");
 }
 
 
         globalObject->globalExec()->clearException();
     }
     printf("\n");
 }
 
-static NO_RETURN void printUsageStatement(JSGlobalData* globalData, bool help = false)
+static NO_RETURN void printUsageStatement(bool help = false)
 {
     fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
     fprintf(stderr, "  -d         Dumps bytecode (debug builds only)\n");
 {
     fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
     fprintf(stderr, "  -d         Dumps bytecode (debug builds only)\n");
@@ -491,24 +605,23 @@ static NO_RETURN void printUsageStatement(JSGlobalData* globalData, bool help =
     fprintf(stderr, "  -s         Installs signal handlers that exit on a crash (Unix platforms only)\n");
 #endif
 
     fprintf(stderr, "  -s         Installs signal handlers that exit on a crash (Unix platforms only)\n");
 #endif
 
-    cleanupGlobalData(globalData);
     exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
     exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
 }
 
-static void parseArguments(int argc, char** argv, Options& options, JSGlobalData* globalData)
+static void parseArguments(int argc, char** argv, CommandLine& options)
 {
     int i = 1;
     for (; i < argc; ++i) {
         const char* arg = argv[i];
         if (!strcmp(arg, "-f")) {
             if (++i == argc)
 {
     int i = 1;
     for (; i < argc; ++i) {
         const char* arg = argv[i];
         if (!strcmp(arg, "-f")) {
             if (++i == argc)
-                printUsageStatement(globalData);
+                printUsageStatement();
             options.scripts.append(Script(true, argv[i]));
             continue;
         }
         if (!strcmp(arg, "-e")) {
             if (++i == argc)
             options.scripts.append(Script(true, argv[i]));
             continue;
         }
         if (!strcmp(arg, "-e")) {
             if (++i == argc)
-                printUsageStatement(globalData);
+                printUsageStatement();
             options.scripts.append(Script(false, argv[i]));
             continue;
         }
             options.scripts.append(Script(false, argv[i]));
             continue;
         }
@@ -534,7 +647,7 @@ static void parseArguments(int argc, char** argv, Options& options, JSGlobalData
             break;
         }
         if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
             break;
         }
         if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
-            printUsageStatement(globalData, true);
+            printUsageStatement(true);
         options.scripts.append(Script(true, argv[i]));
     }
 
         options.scripts.append(Script(true, argv[i]));
     }
 
@@ -545,14 +658,16 @@ static void parseArguments(int argc, char** argv, Options& options, JSGlobalData
         options.arguments.append(argv[i]);
 }
 
         options.arguments.append(argv[i]);
 }
 
-int jscmain(int argc, char** argv, JSGlobalData* globalData)
+int jscmain(int argc, char** argv)
 {
 {
-    JSLock lock(SilenceAssertionsOnly);
+    
+    RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap);
+    JSLockHolder lock(globalData.get());
 
 
-    Options options;
-    parseArguments(argc, argv, options, globalData);
+    CommandLine options;
+    parseArguments(argc, argv, options);
 
 
-    GlobalObject* globalObject = new (globalData) GlobalObject(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.arguments);
+    GlobalObject* globalObject = GlobalObject::create(*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);
diff --git a/jsc.pro b/jsc.pro
index 21ffeeacbdcc2f5cfc16e752a46ad5c5b270f9d8..123362faaed233ae202b8fb03dc010839e4101e8 100644 (file)
--- a/jsc.pro
+++ b/jsc.pro
@@ -1,27 +1,23 @@
+# -------------------------------------------------------------------
+# Project file for the jsc binary (interactive interpreter)
+#
+# See 'Tools/qmake/README' for an overview of the build system
+# -------------------------------------------------------------------
+
 TEMPLATE = app
 TEMPLATE = app
+
 TARGET = jsc
 TARGET = jsc
-DESTDIR = .
-SOURCES = jsc.cpp
+DESTDIR = $${ROOT_BUILD_DIR}/bin
+
 QT -= gui
 QT -= gui
-CONFIG -= app_bundle
-CONFIG += building-libs
+
 win32-*: CONFIG += console
 win32-msvc*: CONFIG += exceptions_off stl_off
 win32-*: CONFIG += console
 win32-msvc*: CONFIG += exceptions_off stl_off
+win32-msvc*|win32-icc: INCLUDEPATH += $$ROOT_WEBKIT_DIR/Source/JavaScriptCore/os-win32
 
 
-isEmpty(OUTPUT_DIR): OUTPUT_DIR= ..
-include($$PWD/../WebKit.pri)
-
-unix:!mac:!symbian:CONFIG += link_pkgconfig
+WEBKIT += javascriptcore wtf
 
 
-QMAKE_RPATHDIR += $$OUTPUT_DIR/lib
-
-OBJECTS_DIR_WTR = $$OBJECTS_DIR$${QMAKE_DIR_SEP}
-include($$PWD/JavaScriptCore.pri)
-prependJavaScriptCoreLib(.)
-
-symbian {
-    TARGET.CAPABILITY = ReadUserData WriteUserData NetworkServices
-}
+SOURCES = jsc.cpp
 
 mac {
     LIBS_PRIVATE += -framework AppKit
 
 mac {
     LIBS_PRIVATE += -framework AppKit
@@ -38,3 +34,4 @@ wince* {
 # 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
 # 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/llint/LLIntCommon.h b/llint/LLIntCommon.h
new file mode 100644 (file)
index 0000000..6b908ea
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef LLIntCommon_h
+#define LLIntCommon_h
+
+// Print every instruction executed.
+#define LLINT_EXECUTION_TRACING 0
+
+// Print some information for some of the more subtle slow paths.
+#define LLINT_SLOW_PATH_TRACING 0
+
+// Disable inline allocation in the interpreter. This is great if you're changing
+// how the GC allocates.
+#define LLINT_ALWAYS_ALLOCATE_SLOW 0
+
+// Enable OSR into the JIT. Disabling this while the LLInt is enabled effectively
+// turns off all JIT'ing, since in LLInt's parlance, OSR subsumes any form of JIT
+// invocation.
+#if ENABLE(JIT)
+#define LLINT_OSR_TO_JIT 1
+#else
+#define LLINT_OSR_TO_JIT 0
+#endif
+
+#endif // LLIntCommon_h
+
diff --git a/llint/LLIntData.cpp b/llint/LLIntData.cpp
new file mode 100644 (file)
index 0000000..983a7d7
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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 "LLIntData.h"
+
+#if ENABLE(LLINT)
+
+#include "BytecodeConventions.h"
+#include "CodeType.h"
+#include "Instruction.h"
+#include "LowLevelInterpreter.h"
+#include "Opcode.h"
+
+namespace JSC { namespace LLInt {
+
+Data::Data()
+    : m_exceptionInstructions(new Instruction[maxOpcodeLength + 1])
+    , m_opcodeMap(new Opcode[numOpcodeIDs])
+{
+    for (int i = 0; i < maxOpcodeLength + 1; ++i)
+        m_exceptionInstructions[i].u.pointer = bitwise_cast<void*>(&llint_throw_from_slow_path_trampoline);
+#define OPCODE_ENTRY(opcode, length) m_opcodeMap[opcode] = bitwise_cast<void*>(&llint_##opcode);
+    FOR_EACH_OPCODE_ID(OPCODE_ENTRY);
+#undef OPCODE_ENTRY
+}
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+#endif
+void Data::performAssertions(JSGlobalData& globalData)
+{
+    UNUSED_PARAM(globalData);
+    
+    // Assertions to match LowLevelInterpreter.asm.  If you change any of this code, be
+    // prepared to change LowLevelInterpreter.asm as well!!
+    ASSERT(RegisterFile::CallFrameHeaderSize * 8 == 48);
+    ASSERT(RegisterFile::ArgumentCount * 8 == -48);
+    ASSERT(RegisterFile::CallerFrame * 8 == -40);
+    ASSERT(RegisterFile::Callee * 8 == -32);
+    ASSERT(RegisterFile::ScopeChain * 8 == -24);
+    ASSERT(RegisterFile::ReturnPC * 8 == -16);
+    ASSERT(RegisterFile::CodeBlock * 8 == -8);
+    ASSERT(CallFrame::argumentOffsetIncludingThis(0) == -RegisterFile::CallFrameHeaderSize - 1);
+#if CPU(BIG_ENDIAN)
+    ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) == 0);
+    ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) == 4);
+#else
+    ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) == 4);
+    ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) == 0);
+#endif
+#if USE(JSVALUE32_64)
+    ASSERT(JSValue::Int32Tag == -1);
+    ASSERT(JSValue::BooleanTag == -2);
+    ASSERT(JSValue::NullTag == -3);
+    ASSERT(JSValue::UndefinedTag == -4);
+    ASSERT(JSValue::CellTag == -5);
+    ASSERT(JSValue::EmptyValueTag == -6);
+    ASSERT(JSValue::DeletedValueTag == -7);
+    ASSERT(JSValue::LowestTag == -7);
+#else
+    ASSERT(TagBitTypeOther == 0x2);
+    ASSERT(TagBitBool == 0x4);
+    ASSERT(TagBitUndefined == 0x8);
+    ASSERT(ValueEmpty == 0x0);
+    ASSERT(ValueFalse == (TagBitTypeOther | TagBitBool));
+    ASSERT(ValueTrue == (TagBitTypeOther | TagBitBool | 1));
+    ASSERT(ValueUndefined == (TagBitTypeOther | TagBitUndefined));
+    ASSERT(ValueNull == TagBitTypeOther);
+#endif
+    ASSERT(StringType == 5);
+    ASSERT(ObjectType == 13);
+    ASSERT(MasqueradesAsUndefined == 1);
+    ASSERT(ImplementsHasInstance == 2);
+    ASSERT(ImplementsDefaultHasInstance == 8);
+#if USE(JSVALUE64)
+    ASSERT(&globalData.heap.allocatorForObjectWithoutDestructor(sizeof(JSFinalObject)) - &globalData.heap.firstAllocatorWithoutDestructors() == 1);
+#else
+    ASSERT(&globalData.heap.allocatorForObjectWithoutDestructor(sizeof(JSFinalObject)) - &globalData.heap.firstAllocatorWithoutDestructors() == 3);
+#endif
+    ASSERT(FirstConstantRegisterIndex == 0x40000000);
+    ASSERT(GlobalCode == 0);
+    ASSERT(EvalCode == 1);
+    ASSERT(FunctionCode == 2);
+    
+    // FIXME: make these assertions less horrible.
+#if !ASSERT_DISABLED
+    Vector<int> testVector;
+    testVector.resize(42);
+    ASSERT(bitwise_cast<size_t*>(&testVector)[0] == 42);
+    ASSERT(bitwise_cast<int**>(&testVector)[1] == testVector.begin());
+#endif
+
+    ASSERT(StringImpl::s_hashFlag8BitBuffer == 64);
+}
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+
+Data::~Data()
+{
+    delete[] m_exceptionInstructions;
+    delete[] m_opcodeMap;
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
diff --git a/llint/LLIntData.h b/llint/LLIntData.h
new file mode 100644 (file)
index 0000000..ba8daed
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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 LLIntData_h
+#define LLIntData_h
+
+#include "Opcode.h"
+#include <wtf/Platform.h>
+
+namespace JSC {
+
+class JSGlobalData;
+struct Instruction;
+
+namespace LLInt {
+
+#if ENABLE(LLINT)
+class Data {
+public:
+    Data();
+    ~Data();
+    
+    void performAssertions(JSGlobalData&);
+    
+    Instruction* exceptionInstructions()
+    {
+        return m_exceptionInstructions;
+    }
+    
+    Opcode* opcodeMap()
+    {
+        return m_opcodeMap;
+    }
+private:
+    Instruction* m_exceptionInstructions;
+    Opcode* m_opcodeMap;
+};
+#else // ENABLE(LLINT)
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+#endif
+
+class Data {
+public:
+    void performAssertions(JSGlobalData&) { }
+
+    Instruction* exceptionInstructions()
+    {
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+    
+    Opcode* opcodeMap()
+    {
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+};
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+
+#endif // ENABLE(LLINT)
+
+} } // namespace JSC::LLInt
+
+#endif // LLIntData_h
+
diff --git a/llint/LLIntEntrypoints.cpp b/llint/LLIntEntrypoints.cpp
new file mode 100644 (file)
index 0000000..dd7d943
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "LLIntEntrypoints.h"
+
+#if ENABLE(LLINT)
+
+#include "JITCode.h"
+#include "JSGlobalData.h"
+#include "JSObject.h"
+#include "LLIntThunks.h"
+#include "LowLevelInterpreter.h"
+#include "ScopeChain.h"
+
+namespace JSC { namespace LLInt {
+
+void getFunctionEntrypoint(JSGlobalData& globalData, CodeSpecializationKind kind, JITCode& jitCode, MacroAssemblerCodePtr& arityCheck)
+{
+    if (!globalData.canUseJIT()) {
+        if (kind == CodeForCall) {
+            jitCode = JITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_call_prologue), JITCode::InterpreterThunk);
+            arityCheck = MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_call_arity_check);
+            return;
+        }
+
+        ASSERT(kind == CodeForConstruct);
+        jitCode = JITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_function_for_construct_prologue), JITCode::InterpreterThunk);
+        arityCheck = MacroAssemblerCodePtr::createLLIntCodePtr(llint_function_for_construct_arity_check);
+        return;
+    }
+    
+    if (kind == CodeForCall) {
+        jitCode = JITCode(globalData.getCTIStub(functionForCallEntryThunkGenerator), JITCode::InterpreterThunk);
+        arityCheck = globalData.getCTIStub(functionForCallArityCheckThunkGenerator).code();
+        return;
+    }
+
+    ASSERT(kind == CodeForConstruct);
+    jitCode = JITCode(globalData.getCTIStub(functionForConstructEntryThunkGenerator), JITCode::InterpreterThunk);
+    arityCheck = globalData.getCTIStub(functionForConstructArityCheckThunkGenerator).code();
+}
+
+void getEvalEntrypoint(JSGlobalData& globalData, JITCode& jitCode)
+{
+    if (!globalData.canUseJIT()) {
+        jitCode = JITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_eval_prologue), JITCode::InterpreterThunk);
+        return;
+    }
+    
+    jitCode = JITCode(globalData.getCTIStub(evalEntryThunkGenerator), JITCode::InterpreterThunk);
+}
+
+void getProgramEntrypoint(JSGlobalData& globalData, JITCode& jitCode)
+{
+    if (!globalData.canUseJIT()) {
+        jitCode = JITCode(MacroAssemblerCodeRef::createLLIntCodeRef(llint_program_prologue), JITCode::InterpreterThunk);
+        return;
+    }
+    
+    jitCode = JITCode(globalData.getCTIStub(programEntryThunkGenerator), JITCode::InterpreterThunk);
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
diff --git a/llint/LLIntEntrypoints.h b/llint/LLIntEntrypoints.h
new file mode 100644 (file)
index 0000000..dd7c277
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef LLIntEntrypoints_h
+#define LLIntEntrypoints_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(LLINT)
+
+#include "CodeSpecializationKind.h"
+
+namespace JSC {
+
+class EvalCodeBlock;
+class JITCode;
+class JSGlobalData;
+class MacroAssemblerCodePtr;
+class MacroAssemblerCodeRef;
+class ProgramCodeBlock;
+
+namespace LLInt {
+
+void getFunctionEntrypoint(JSGlobalData&, CodeSpecializationKind, JITCode&, MacroAssemblerCodePtr& arityCheck);
+void getEvalEntrypoint(JSGlobalData&, JITCode&);
+void getProgramEntrypoint(JSGlobalData&, JITCode&);
+
+inline void getEntrypoint(JSGlobalData& globalData, EvalCodeBlock*, JITCode& jitCode)
+{
+    getEvalEntrypoint(globalData, jitCode);
+}
+
+inline void getEntrypoint(JSGlobalData& globalData, ProgramCodeBlock*, JITCode& jitCode)
+{
+    getProgramEntrypoint(globalData, jitCode);
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
+
+#endif // LLIntEntrypoints_h
diff --git a/llint/LLIntExceptions.cpp b/llint/LLIntExceptions.cpp
new file mode 100644 (file)
index 0000000..20b0db3
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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 "LLIntExceptions.h"
+
+#if ENABLE(LLINT)
+
+#include "CallFrame.h"
+#include "CodeBlock.h"
+#include "Instruction.h"
+#include "JITExceptions.h"
+#include "LLIntCommon.h"
+#include "LowLevelInterpreter.h"
+
+namespace JSC { namespace LLInt {
+
+void interpreterThrowInCaller(ExecState* exec, ReturnAddressPtr pc)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Throwing exception %s.\n", globalData->exception.description());
+#endif
+    genericThrow(
+        globalData, exec, globalData->exception,
+        exec->codeBlock()->bytecodeOffset(exec, pc));
+}
+
+Instruction* returnToThrowForThrownException(ExecState* exec)
+{
+    return exec->globalData().llintData.exceptionInstructions();
+}
+
+Instruction* returnToThrow(ExecState* exec, Instruction* pc)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Throwing exception %s (returnToThrow).\n", globalData->exception.description());
+#endif
+    genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
+    
+    return globalData->llintData.exceptionInstructions();
+}
+
+void* callToThrow(ExecState* exec, Instruction* pc)
+{
+    JSGlobalData* globalData = &exec->globalData();
+    NativeCallFrameTracer tracer(globalData, exec);
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Throwing exception %s (callToThrow).\n", globalData->exception.description());
+#endif
+    genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
+    
+    return bitwise_cast<void*>(&llint_throw_during_call_trampoline);
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
diff --git a/llint/LLIntExceptions.h b/llint/LLIntExceptions.h
new file mode 100644 (file)
index 0000000..3baa3f4
--- /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. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED 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 LLIntExceptions_h
+#define LLIntExceptions_h
+
+#include <wtf/Platform.h>
+#include <wtf/StdLibExtras.h>
+
+#if ENABLE(LLINT)
+
+#include "MacroAssemblerCodeRef.h"
+
+namespace JSC {
+
+class ExecState;
+struct Instruction;
+
+namespace LLInt {
+
+// Throw the currently active exception in the context of the caller's call frame.
+void interpreterThrowInCaller(ExecState* callerFrame, ReturnAddressPtr);
+
+// Tells you where to jump to if you want to return-to-throw, after you've already
+// set up all information needed to throw the exception.
+Instruction* returnToThrowForThrownException(ExecState*);
+
+// Saves the current PC in the global data for safe-keeping, and gives you a PC
+// that you can tell the interpreter to go to, which when advanced between 1
+// and 9 slots will give you an "instruction" that threads to the interpreter's
+// exception handler. Note that if you give it the PC for exception handling,
+// it's smart enough to just return that PC without doing anything else; this
+// lets you thread exception handling through common helper functions used by
+// other helpers.
+Instruction* returnToThrow(ExecState*, Instruction*);
+
+// Use this when you're throwing to a call thunk.
+void* callToThrow(ExecState*, Instruction*);
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
+
+#endif // LLIntExceptions_h
diff --git a/llint/LLIntOfflineAsmConfig.h b/llint/LLIntOfflineAsmConfig.h
new file mode 100644 (file)
index 0000000..afb062a
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef LLIntOfflineAsmConfig_h
+#define LLIntOfflineAsmConfig_h
+
+#include "LLIntCommon.h"
+#include <wtf/Assertions.h>
+#include <wtf/InlineASM.h>
+#include <wtf/Platform.h>
+
+#if CPU(X86)
+#define OFFLINE_ASM_X86 1
+#else
+#define OFFLINE_ASM_X86 0
+#endif
+
+#if CPU(ARM_THUMB2)
+#define OFFLINE_ASM_ARMv7 1
+#else
+#define OFFLINE_ASM_ARMv7 0
+#endif
+
+#if CPU(X86_64)
+#define OFFLINE_ASM_X86_64 1
+#else
+#define OFFLINE_ASM_X86_64 0
+#endif
+
+#if USE(JSVALUE64)
+#define OFFLINE_ASM_JSVALUE64 1
+#else
+#define OFFLINE_ASM_JSVALUE64 0
+#endif
+
+#if !ASSERT_DISABLED
+#define OFFLINE_ASM_ASSERT_ENABLED 1
+#else
+#define OFFLINE_ASM_ASSERT_ENABLED 0
+#endif
+
+#if CPU(BIG_ENDIAN)
+#define OFFLINE_ASM_BIG_ENDIAN 1
+#else
+#define OFFLINE_ASM_BIG_ENDIAN 0
+#endif
+
+#if LLINT_OSR_TO_JIT
+#define OFFLINE_ASM_JIT_ENABLED 1
+#else
+#define OFFLINE_ASM_JIT_ENABLED 0
+#endif
+
+#if LLINT_EXECUTION_TRACING
+#define OFFLINE_ASM_EXECUTION_TRACING 1
+#else
+#define OFFLINE_ASM_EXECUTION_TRACING 0
+#endif
+
+#if LLINT_ALWAYS_ALLOCATE_SLOW
+#define OFFLINE_ASM_ALWAYS_ALLOCATE_SLOW 1
+#else
+#define OFFLINE_ASM_ALWAYS_ALLOCATE_SLOW 0
+#endif
+
+#if ENABLE(VALUE_PROFILER)
+#define OFFLINE_ASM_VALUE_PROFILER 1
+#else
+#define OFFLINE_ASM_VALUE_PROFILER 0
+#endif
+
+#ifdef __ARM_ARCH_7S__
+#define OFFLINE_ASM_ARMv7s 1
+#else
+#define OFFLINE_ASM_ARMv7s 0
+#endif
+
+#if CPU(ARM_THUMB2)
+#define OFFLINE_ASM_GLOBAL_LABEL(label)          \
+    ".globl " SYMBOL_STRING(label) "\n"          \
+    HIDE_SYMBOL(name) "\n"                       \
+    ".thumb\n"                                   \
+    ".thumb_func " THUMB_FUNC_PARAM(label) "\n"  \
+    SYMBOL_STRING(label) ":\n"
+#else
+#define OFFLINE_ASM_GLOBAL_LABEL(label)         \
+    ".globl " SYMBOL_STRING(label) "\n"         \
+    HIDE_SYMBOL(name) "\n"                      \
+    SYMBOL_STRING(label) ":\n"
+#endif
+
+#endif // LLIntOfflineAsmConfig_h
diff --git a/llint/LLIntOffsetsExtractor.cpp b/llint/LLIntOffsetsExtractor.cpp
new file mode 100644 (file)
index 0000000..f863cb2
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+
+#include "CodeBlock.h"
+#include "Executable.h"
+#include "Heap.h"
+#include "Interpreter.h"
+#include "JITStubs.h"
+#include "JSArray.h"
+#include "JSCell.h"
+#include "JSFunction.h"
+#include "JSGlobalData.h"
+#include "JSGlobalObject.h"
+#include "JSObject.h"
+#include "JSPropertyNameIterator.h"
+#include "JSString.h"
+#include "JSTypeInfo.h"
+#include "JSVariableObject.h"
+#include "JumpTable.h"
+#include "LLIntOfflineAsmConfig.h"
+#include "MarkedSpace.h"
+#include "RegisterFile.h"
+#include "ScopeChain.h"
+#include "Structure.h"
+#include "StructureChain.h"
+#include "ValueProfile.h"
+#include <wtf/text/StringImpl.h>
+
+namespace JSC {
+
+#define OFFLINE_ASM_OFFSETOF(clazz, field) OBJECT_OFFSETOF(clazz, field)
+
+class LLIntOffsetsExtractor {
+public:
+    static const unsigned* dummy();
+};
+
+const unsigned* LLIntOffsetsExtractor::dummy()
+{
+#if ENABLE(JIT)
+// This is a file generated by offlineasm/generate_offsets_extractor.rb, and contains code
+// to create a table of offsets, sizes, and a header identifying what combination of
+// Platform.h macros we have set. We include it inside of a method on LLIntOffsetsExtractor
+// because the fields whose offsets we're extracting are mostly private. So we make their
+// classes friends with LLIntOffsetsExtractor, and include the header here, to get the C++
+// compiler to kindly step aside and yield to our best intentions.
+#include "LLIntDesiredOffsets.h"
+    return extractorTable;
+#else
+    return 0;
+#endif
+}
+
+} // namespace JSC
+
+int main(int, char**)
+{
+    // Out of an abundance of caution, make sure that LLIntOffsetsExtractor::dummy() is live,
+    // and the extractorTable is live, too.
+    printf("%p\n", JSC::LLIntOffsetsExtractor::dummy());
+    return 0;
+}
+
+
diff --git a/llint/LLIntSlowPaths.cpp b/llint/LLIntSlowPaths.cpp
new file mode 100644 (file)
index 0000000..120484e
--- /dev/null
@@ -0,0 +1,1562 @@
+/*
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "LLIntSlowPaths.h"
+
+#if ENABLE(LLINT)
+
+#include "Arguments.h"
+#include "CallFrame.h"
+#include "CommonSlowPaths.h"
+#include "GetterSetter.h"
+#include "HostCallReturnValue.h"
+#include "Interpreter.h"
+#include "JIT.h"
+#include "JITDriver.h"
+#include "JSActivation.h"
+#include "JSGlobalObjectFunctions.h"
+#include "JSPropertyNameIterator.h"
+#include "JSStaticScopeObject.h"
+#include "JSString.h"
+#include "JSValue.h"
+#include "LLIntCommon.h"
+#include "LLIntExceptions.h"
+#include "LowLevelInterpreter.h"
+#include "Operations.h"
+
+namespace JSC { namespace LLInt {
+
+#define LLINT_BEGIN_NO_SET_PC() \
+    JSGlobalData& globalData = exec->globalData();      \
+    NativeCallFrameTracer tracer(&globalData, exec)
+
+#ifndef NDEBUG
+#define LLINT_SET_PC_FOR_STUBS() do { \
+        exec->codeBlock()->bytecodeOffset(pc); \
+        exec->setCurrentVPC(pc + 1); \
+    } while (false)
+#else
+#define LLINT_SET_PC_FOR_STUBS() do { \
+        exec->setCurrentVPC(pc + 1); \
+    } while (false)
+#endif
+
+#define LLINT_BEGIN()                           \
+    LLINT_BEGIN_NO_SET_PC();                    \
+    LLINT_SET_PC_FOR_STUBS()
+
+#define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand))
+#define LLINT_OP_C(index) (exec->r(pc[index].u.operand))
+
+#define LLINT_RETURN_TWO(first, second) do {       \
+        return encodeResult(first, second);        \
+    } while (false)
+
+#define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, exec)
+
+#define LLINT_THROW(exceptionToThrow) do {                        \
+        globalData.exception = (exceptionToThrow);                \
+        pc = returnToThrow(exec, pc);                             \
+        LLINT_END_IMPL();                                         \
+    } while (false)
+
+#define LLINT_CHECK_EXCEPTION() do {                    \
+        if (UNLIKELY(globalData.exception)) {           \
+            pc = returnToThrow(exec, pc);               \
+            LLINT_END_IMPL();                           \
+        }                                               \
+    } while (false)
+
+#define LLINT_END() do {                        \
+        LLINT_CHECK_EXCEPTION();                \
+        LLINT_END_IMPL();                       \
+    } while (false)
+
+#define LLINT_BRANCH(opcode, condition) do {                      \
+        bool __b_condition = (condition);                         \
+        LLINT_CHECK_EXCEPTION();                                  \
+        if (__b_condition)                                        \
+            pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand;        \
+        else                                                      \
+            pc += OPCODE_LENGTH(opcode);                          \
+        LLINT_END_IMPL();                                         \
+    } while (false)
+
+#define LLINT_RETURN(value) do {                \
+        JSValue __r_returnValue = (value);      \
+        LLINT_CHECK_EXCEPTION();                \
+        LLINT_OP(1) = __r_returnValue;          \
+        LLINT_END_IMPL();                       \
+    } while (false)
+
+#if ENABLE(VALUE_PROFILER)
+#define LLINT_RETURN_PROFILED(opcode, value) do {               \
+        JSValue __rp_returnValue = (value);                     \
+        LLINT_CHECK_EXCEPTION();                                \
+        LLINT_OP(1) = __rp_returnValue;                         \
+        pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
+            JSValue::encode(__rp_returnValue);                  \
+        LLINT_END_IMPL();                                       \
+    } while (false)
+#else // ENABLE(VALUE_PROFILER)
+#define LLINT_RETURN_PROFILED(opcode, value) LLINT_RETURN(value)
+#endif // ENABLE(VALUE_PROFILER)
+
+#define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
+
+#define LLINT_CALL_THROW(exec, pc, exceptionToThrow) do {               \
+        ExecState* __ct_exec = (exec);                                  \
+        Instruction* __ct_pc = (pc);                                    \
+        globalData.exception = (exceptionToThrow);                      \
+        LLINT_CALL_END_IMPL(__ct_exec, callToThrow(__ct_exec, __ct_pc)); \
+    } while (false)
+
+#define LLINT_CALL_CHECK_EXCEPTION(exec, pc) do {                       \
+        ExecState* __cce_exec = (exec);                                 \
+        Instruction* __cce_pc = (pc);                                   \
+        if (UNLIKELY(globalData.exception))                              \
+            LLINT_CALL_END_IMPL(__cce_exec, callToThrow(__cce_exec, __cce_pc)); \
+    } while (false)
+
+#define LLINT_CALL_RETURN(exec, pc, callTarget) do {                    \
+        ExecState* __cr_exec = (exec);                                  \
+        Instruction* __cr_pc = (pc);                                    \
+        void* __cr_callTarget = (callTarget);                           \
+        LLINT_CALL_CHECK_EXCEPTION(__cr_exec->callerFrame(), __cr_pc);  \
+        LLINT_CALL_END_IMPL(__cr_exec, __cr_callTarget);                \
+    } while (false)
+
+extern "C" SlowPathReturnType llint_trace_operand(ExecState* exec, Instruction* pc, int fromWhere, int operand)
+{
+    LLINT_BEGIN();
+    dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n",
+            exec->codeBlock(),
+            exec,
+            static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
+            exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
+            fromWhere,
+            operand,
+            pc[operand].u.operand);
+    LLINT_END();
+}
+
+extern "C" SlowPathReturnType llint_trace_value(ExecState* exec, Instruction* pc, int fromWhere, int operand)
+{
+    JSValue value = LLINT_OP_C(operand).jsValue();
+    union {
+        struct {
+            uint32_t tag;
+            uint32_t payload;
+        } bits;
+        EncodedJSValue asValue;
+    } u;
+    u.asValue = JSValue::encode(value);
+    dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n",
+            exec->codeBlock(),
+            exec,
+            static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
+            exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
+            fromWhere,
+            operand,
+            pc[operand].u.operand,
+            u.bits.tag,
+            u.bits.payload,
+            value.description());
+    LLINT_END_IMPL();
+}
+
+LLINT_SLOW_PATH_DECL(trace_prologue)
+{
+    dataLog("%p / %p: in prologue.\n", exec->codeBlock(), exec);
+    LLINT_END_IMPL();
+}
+
+static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpecializationKind kind)
+{
+    JSFunction* callee = jsCast<JSFunction*>(exec->callee());
+    FunctionExecutable* executable = callee->jsExecutable();
+    CodeBlock* codeBlock = &executable->generatedBytecodeFor(kind);
+    dataLog("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u, caller = %p.\n",
+            codeBlock, exec, comment, callee, executable,
+            codeBlock->m_numVars, codeBlock->numParameters(), codeBlock->m_numCalleeRegisters,
+            exec->callerFrame());
+}
+
+LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call)
+{
+    traceFunctionPrologue(exec, "call prologue", CodeForCall);
+    LLINT_END_IMPL();
+}
+
+LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct)
+{
+    traceFunctionPrologue(exec, "construct prologue", CodeForConstruct);
+    LLINT_END_IMPL();
+}
+
+LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call)
+{
+    traceFunctionPrologue(exec, "call arity check", CodeForCall);
+    LLINT_END_IMPL();
+}
+
+LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct)
+{
+    traceFunctionPrologue(exec, "construct arity check", CodeForConstruct);
+    LLINT_END_IMPL();
+}
+
+LLINT_SLOW_PATH_DECL(trace)
+{
+    dataLog("%p / %p: executing bc#%zu, %s, scope %p\n",
+            exec->codeBlock(),
+            exec,
+            static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
+            opcodeNames[exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode)],
+            exec->scopeChain());
+    if (exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode) == op_ret) {
+        dataLog("Will be returning to %p\n", exec->returnPC().value());
+        dataLog("The new cfr will be %p\n", exec->callerFrame());
+    }
+    LLINT_END_IMPL();
+}
+
+LLINT_SLOW_PATH_DECL(special_trace)
+{
+    dataLog("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
+            exec->codeBlock(),
+            exec,
+            static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
+            exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
+            exec->returnPC().value());
+    LLINT_END_IMPL();
+}
+
+inline bool shouldJIT(ExecState* exec)
+{
+    // You can modify this to turn off JITting without rebuilding the world.
+    return exec->globalData().canUseJIT();
+}
+
+// Returns true if we should try to OSR.
+inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec)
+{
+    if (!codeBlock->checkIfJITThresholdReached()) {
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("    JIT threshold should be lifted.\n");
+#endif
+        return false;
+    }
+        
+    CodeBlock::JITCompilationResult result = codeBlock->jitCompile(exec->globalData());
+    switch (result) {
+    case CodeBlock::AlreadyCompiled:
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("    Code was already compiled.\n");
+#endif
+        codeBlock->jitSoon();
+        return true;
+    case CodeBlock::CouldNotCompile:
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("    JIT compilation failed.\n");
+#endif
+        codeBlock->dontJITAnytimeSoon();
+        return false;
+    case CodeBlock::CompiledSuccessfully:
+#if ENABLE(JIT_VERBOSE_OSR)
+        dataLog("    JIT compilation successful.\n");
+#endif
+        codeBlock->jitSoon();
+        return true;
+    }
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+enum EntryKind { Prologue, ArityCheck };
+static SlowPathReturnType entryOSR(ExecState* exec, Instruction* pc, CodeBlock* codeBlock, const char *name, EntryKind kind)
+{
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("%p: Entered %s with executeCounter = %d\n", codeBlock, name, codeBlock->llintExecuteCounter());
+#endif
+    
+    if (!shouldJIT(exec)) {
+        codeBlock->dontJITAnytimeSoon();
+        LLINT_RETURN_TWO(0, exec);
+    }
+    if (!jitCompileAndSetHeuristics(codeBlock, exec))
+        LLINT_RETURN_TWO(0, exec);
+    
+    if (kind == Prologue)
+        LLINT_RETURN_TWO(codeBlock->getJITCode().executableAddressAtOffset(0), exec);
+    ASSERT(kind == ArityCheck);
+    LLINT_RETURN_TWO(codeBlock->getJITCodeWithArityCheck().executableAddress(), exec);
+}
+
+LLINT_SLOW_PATH_DECL(entry_osr)
+{
+    return entryOSR(exec, pc, exec->codeBlock(), "entry_osr", Prologue);
+}
+
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_call)
+{
+    return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call", Prologue);
+}
+
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct)
+{
+    return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct", Prologue);
+}
+
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck)
+{
+    return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call_arityCheck", ArityCheck);
+}
+
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck)
+{
+    return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct_arityCheck", ArityCheck);
+}
+
+LLINT_SLOW_PATH_DECL(loop_osr)
+{
+    CodeBlock* codeBlock = exec->codeBlock();
+    
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("%p: Entered loop_osr with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
+#endif
+    
+    if (!shouldJIT(exec)) {
+        codeBlock->dontJITAnytimeSoon();
+        LLINT_RETURN_TWO(0, exec);
+    }
+    
+    if (!jitCompileAndSetHeuristics(codeBlock, exec))
+        LLINT_RETURN_TWO(0, exec);
+    
+    ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
+    
+    Vector<BytecodeAndMachineOffset> map;
+    codeBlock->jitCodeMap()->decode(map);
+    BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned, BytecodeAndMachineOffset::getBytecodeIndex>(map.begin(), map.size(), pc - codeBlock->instructions().begin());
+    ASSERT(mapping);
+    ASSERT(mapping->m_bytecodeIndex == static_cast<unsigned>(pc - codeBlock->instructions().begin()));
+    
+    void* jumpTarget = codeBlock->getJITCode().executableAddressAtOffset(mapping->m_machineCodeOffset);
+    ASSERT(jumpTarget);
+    
+    LLINT_RETURN_TWO(jumpTarget, exec);
+}
+
+LLINT_SLOW_PATH_DECL(replace)
+{
+    CodeBlock* codeBlock = exec->codeBlock();
+    
+#if ENABLE(JIT_VERBOSE_OSR)
+    dataLog("%p: Entered replace with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
+#endif
+    
+    if (shouldJIT(exec))
+        jitCompileAndSetHeuristics(codeBlock, exec);
+    else
+        codeBlock->dontJITAnytimeSoon();
+    LLINT_END_IMPL();
+}
+
+LLINT_SLOW_PATH_DECL(register_file_check)
+{
+    LLINT_BEGIN();
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Checking stack height with exec = %p.\n", exec);
+    dataLog("CodeBlock = %p.\n", exec->codeBlock());
+    dataLog("Num callee registers = %u.\n", exec->codeBlock()->m_numCalleeRegisters);
+    dataLog("Num vars = %u.\n", exec->codeBlock()->m_numVars);
+    dataLog("Current end is at %p.\n", exec->globalData().interpreter->registerFile().end());
+#endif
+    ASSERT(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters] > exec->globalData().interpreter->registerFile().end());
+    if (UNLIKELY(!globalData.interpreter->registerFile().grow(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters]))) {
+        ReturnAddressPtr returnPC = exec->returnPC();
+        exec = exec->callerFrame();
+        globalData.exception = createStackOverflowError(exec);
+        interpreterThrowInCaller(exec, returnPC);
+        pc = returnToThrowForThrownException(exec);
+    }
+    LLINT_END_IMPL();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_call_arityCheck)
+{
+    LLINT_BEGIN();
+    ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &globalData.interpreter->registerFile(), CodeForCall);
+    if (!newExec) {
+        ReturnAddressPtr returnPC = exec->returnPC();
+        exec = exec->callerFrame();
+        globalData.exception = createStackOverflowError(exec);
+        interpreterThrowInCaller(exec, returnPC);
+        LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
+    }
+    LLINT_RETURN_TWO(0, newExec);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_construct_arityCheck)
+{
+    LLINT_BEGIN();
+    ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &globalData.interpreter->registerFile(), CodeForConstruct);
+    if (!newExec) {
+        ReturnAddressPtr returnPC = exec->returnPC();
+        exec = exec->callerFrame();
+        globalData.exception = createStackOverflowError(exec);
+        interpreterThrowInCaller(exec, returnPC);
+        LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
+    }
+    LLINT_RETURN_TWO(0, newExec);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_create_activation)
+{
+    LLINT_BEGIN();
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Creating an activation, exec = %p!\n", exec);
+#endif
+    JSActivation* activation = JSActivation::create(globalData, exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable()));
+    exec->setScopeChain(exec->scopeChain()->push(activation));
+    LLINT_RETURN(JSValue(activation));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_create_arguments)
+{
+    LLINT_BEGIN();
+    JSValue arguments = JSValue(Arguments::create(globalData, exec));
+    LLINT_CHECK_EXCEPTION();
+    exec->uncheckedR(pc[1].u.operand) = arguments;
+    exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)) = arguments;
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_create_this)
+{
+    LLINT_BEGIN();
+    JSFunction* constructor = jsCast<JSFunction*>(exec->callee());
+    
+#if !ASSERT_DISABLED
+    ConstructData constructData;
+    ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
+#endif
+    
+    Structure* structure;
+    JSValue proto = LLINT_OP(2).jsValue();
+    if (proto.isObject())
+        structure = asObject(proto)->inheritorID(globalData);
+    else
+        structure = constructor->scope()->globalObject->emptyObjectStructure();
+    
+    LLINT_RETURN(constructEmptyObject(exec, structure));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_convert_this)
+{
+    LLINT_BEGIN();
+    JSValue v1 = LLINT_OP(1).jsValue();
+    ASSERT(v1.isPrimitive());
+    LLINT_RETURN(v1.toThisObject(exec));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_object)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(constructEmptyObject(exec));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_array)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(constructArray(exec, bitwise_cast<JSValue*>(&LLINT_OP(2)), pc[3].u.operand));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(constructArray(exec, exec->codeBlock()->constantBuffer(pc[2].u.operand), pc[3].u.operand));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_regexp)
+{
+    LLINT_BEGIN();
+    RegExp* regExp = exec->codeBlock()->regexp(pc[2].u.operand);
+    if (!regExp->isValid())
+        LLINT_THROW(createSyntaxError(exec, "Invalid flag supplied to RegExp constructor."));
+    LLINT_RETURN(RegExpObject::create(globalData, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_not)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(!LLINT_OP_C(2).jsValue().toBoolean(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_eq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_neq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(!JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_stricteq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_nstricteq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(!JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_less)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsLess<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_lesseq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsLessEq<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_greater)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsLess<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_greatereq)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsLessEq<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_pre_inc)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) + 1));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_pre_dec)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) - 1));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_post_inc)
+{
+    LLINT_BEGIN();
+    double result = LLINT_OP(2).jsValue().toNumber(exec);
+    LLINT_OP(2) = jsNumber(result + 1);
+    LLINT_RETURN(jsNumber(result));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_post_dec)
+{
+    LLINT_BEGIN();
+    double result = LLINT_OP(2).jsValue().toNumber(exec);
+    LLINT_OP(2) = jsNumber(result - 1);
+    LLINT_RETURN(jsNumber(result));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_to_jsnumber)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_negate)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(-LLINT_OP_C(2).jsValue().toNumber(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_add)
+{
+    LLINT_BEGIN();
+    JSValue v1 = LLINT_OP_C(2).jsValue();
+    JSValue v2 = LLINT_OP_C(3).jsValue();
+    
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Trying to add %s", v1.description());
+    dataLog(" to %s.\n", v2.description());
+#endif
+    
+    if (v1.isString() && !v2.isObject())
+        LLINT_RETURN(jsString(exec, asString(v1), v2.toString(exec)));
+    
+    if (v1.isNumber() && v2.isNumber())
+        LLINT_RETURN(jsNumber(v1.asNumber() + v2.asNumber()));
+    
+    LLINT_RETURN(jsAddSlowCase(exec, v1, v2));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_mul)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) * LLINT_OP_C(3).jsValue().toNumber(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_sub)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) - LLINT_OP_C(3).jsValue().toNumber(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_div)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) / LLINT_OP_C(3).jsValue().toNumber(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_mod)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(fmod(LLINT_OP_C(2).jsValue().toNumber(exec), LLINT_OP_C(3).jsValue().toNumber(exec))));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_lshift)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) << (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_rshift)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_urshift)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toUInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_bitand)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) & LLINT_OP_C(3).jsValue().toInt32(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_bitor)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) | LLINT_OP_C(3).jsValue().toInt32(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_bitxor)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) ^ LLINT_OP_C(3).jsValue().toInt32(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_check_has_instance)
+{
+    LLINT_BEGIN();
+    JSValue baseVal = LLINT_OP_C(1).jsValue();
+#ifndef NDEBUG
+    TypeInfo typeInfo(UnspecifiedType);
+    ASSERT(!baseVal.isObject()
+           || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance());
+#endif
+    LLINT_THROW(createInvalidParamError(exec, "instanceof", baseVal));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_instanceof)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(CommonSlowPaths::opInstanceOfSlow(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_typeof)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsTypeStringForValue(exec, LLINT_OP_C(2).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_is_object)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsIsObjectType(LLINT_OP_C(2).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_is_function)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(jsIsFunctionType(LLINT_OP_C(2).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_in)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsBoolean(CommonSlowPaths::opIn(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(op_resolve, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_skip)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(
+        op_resolve_skip,
+        CommonSlowPaths::opResolveSkip(
+            exec,
+            exec->codeBlock()->identifier(pc[2].u.operand),
+            pc[3].u.operand));
+}
+
+static JSValue resolveGlobal(ExecState* exec, Instruction* pc)
+{
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSGlobalObject* globalObject = codeBlock->globalObject();
+    ASSERT(globalObject->isGlobalObject());
+    int property = pc[2].u.operand;
+    Structure* structure = pc[3].u.structure.get();
+    
+    ASSERT_UNUSED(structure, structure != globalObject->structure());
+    
+    Identifier& ident = codeBlock->identifier(property);
+    PropertySlot slot(globalObject);
+    
+    if (globalObject->getPropertySlot(exec, ident, slot)) {
+        JSValue result = slot.getValue(exec, ident);
+        if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary()
+            && slot.slotBase() == globalObject) {
+            pc[3].u.structure.set(
+                exec->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
+            pc[4] = slot.cachedOffset();
+        }
+        
+        return result;
+    }
+    
+    exec->globalData().exception = createUndefinedVariableError(exec, ident);
+    return JSValue();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_global)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(op_resolve_global, resolveGlobal(exec, pc));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_global_dynamic)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(op_resolve_global_dynamic, resolveGlobal(exec, pc));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_for_resolve_global_dynamic)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(op_resolve_global_dynamic, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_base)
+{
+    LLINT_BEGIN();
+    Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
+    if (pc[3].u.operand) {
+        JSValue base = JSC::resolveBase(exec, ident, exec->scopeChain(), true);
+        if (!base)
+            LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
+        LLINT_RETURN(base);
+    }
+    
+    LLINT_RETURN_PROFILED(op_resolve_base, JSC::resolveBase(exec, ident, exec->scopeChain(), false));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_ensure_property_exists)
+{
+    LLINT_BEGIN();
+    JSObject* object = asObject(LLINT_OP(1).jsValue());
+    PropertySlot slot(object);
+    Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
+    if (!object->getPropertySlot(exec, ident, slot))
+        LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_with_base)
+{
+    LLINT_BEGIN();
+    JSValue result = CommonSlowPaths::opResolveWithBase(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
+    LLINT_CHECK_EXCEPTION();
+    LLINT_OP(2) = result;
+    // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this)
+{
+    LLINT_BEGIN();
+    JSValue result = CommonSlowPaths::opResolveWithThis(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
+    LLINT_CHECK_EXCEPTION();
+    LLINT_OP(2) = result;
+    // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    Identifier& ident = codeBlock->identifier(pc[3].u.operand);
+    JSValue baseValue = LLINT_OP_C(2).jsValue();
+    PropertySlot slot(baseValue);
+
+    JSValue result = baseValue.get(exec, ident, slot);
+    LLINT_CHECK_EXCEPTION();
+    LLINT_OP(1) = result;
+
+    if (baseValue.isCell()
+        && slot.isCacheable()
+        && slot.slotBase() == baseValue
+        && slot.cachedPropertyType() == PropertySlot::Value) {
+        
+        JSCell* baseCell = baseValue.asCell();
+        Structure* structure = baseCell->structure();
+        
+        if (!structure->isUncacheableDictionary()
+            && !structure->typeInfo().prohibitsPropertyCaching()) {
+            pc[4].u.structure.set(
+                globalData, codeBlock->ownerExecutable(), structure);
+            pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
+        }
+    }
+
+#if ENABLE(VALUE_PROFILER)    
+    pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result);
+#endif
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    Identifier& ident = codeBlock->identifier(pc[3].u.operand);
+    JSValue baseValue = LLINT_OP(2).jsValue();
+    PropertySlot slot(baseValue);
+    LLINT_RETURN(baseValue.get(exec, ident, slot));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    Identifier& ident = codeBlock->identifier(pc[2].u.operand);
+    
+    JSValue baseValue = LLINT_OP_C(1).jsValue();
+    PutPropertySlot slot(codeBlock->isStrictMode());
+    if (pc[8].u.operand)
+        asObject(baseValue)->putDirect(globalData, ident, LLINT_OP_C(3).jsValue(), slot);
+    else
+        baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
+    LLINT_CHECK_EXCEPTION();
+    
+    if (baseValue.isCell()
+        && slot.isCacheable()) {
+        
+        JSCell* baseCell = baseValue.asCell();
+        Structure* structure = baseCell->structure();
+        
+        if (!structure->isUncacheableDictionary()
+            && !structure->typeInfo().prohibitsPropertyCaching()
+            && baseCell == slot.base()) {
+            
+            if (slot.type() == PutPropertySlot::NewProperty) {
+                if (!structure->isDictionary() && structure->previousID()->propertyStorageCapacity() == structure->propertyStorageCapacity()) {
+                    // This is needed because some of the methods we call
+                    // below may GC.
+                    pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
+
+                    normalizePrototypeChain(exec, baseCell);
+                    
+                    ASSERT(structure->previousID()->isObject());
+                    pc[4].u.structure.set(
+                        globalData, codeBlock->ownerExecutable(), structure->previousID());
+                    pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
+                    pc[6].u.structure.set(
+                        globalData, codeBlock->ownerExecutable(), structure);
+                    StructureChain* chain = structure->prototypeChain(exec);
+                    ASSERT(chain);
+                    pc[7].u.structureChain.set(
+                        globalData, codeBlock->ownerExecutable(), chain);
+                    
+                    if (pc[8].u.operand)
+                        pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_direct);
+                    else
+                        pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_normal);
+                }
+            } else {
+                pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
+                pc[4].u.structure.set(
+                    globalData, codeBlock->ownerExecutable(), structure);
+                pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
+            }
+        }
+    }
+    
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_del_by_id)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSObject* baseObject = LLINT_OP_C(2).jsValue().toObject(exec);
+    bool couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, codeBlock->identifier(pc[3].u.operand));
+    LLINT_CHECK_EXCEPTION();
+    if (!couldDelete && codeBlock->isStrictMode())
+        LLINT_THROW(createTypeError(exec, "Unable to delete property."));
+    LLINT_RETURN(jsBoolean(couldDelete));
+}
+
+inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript)
+{
+    if (LIKELY(baseValue.isCell() && subscript.isString())) {
+        if (JSValue result = baseValue.asCell()->fastGetOwnProperty(exec, asString(subscript)->value(exec)))
+            return result;
+    }
+    
+    if (subscript.isUInt32()) {
+        uint32_t i = subscript.asUInt32();
+        if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
+            return asString(baseValue)->getIndex(exec, i);
+        
+        return baseValue.get(exec, i);
+    }
+    
+    Identifier property(exec, subscript.toString(exec)->value(exec));
+    return baseValue.get(exec, property);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_by_val)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN_PROFILED(op_get_by_val, getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val)
+{
+    LLINT_BEGIN();
+    JSValue arguments = LLINT_OP(2).jsValue();
+    if (!arguments) {
+        arguments = Arguments::create(globalData, exec);
+        LLINT_CHECK_EXCEPTION();
+        LLINT_OP(2) = arguments;
+        exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)) = arguments;
+    }
+    
+    LLINT_RETURN(getByVal(exec, arguments, LLINT_OP_C(3).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_by_pname)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_put_by_val)
+{
+    LLINT_BEGIN();
+    
+    JSValue baseValue = LLINT_OP_C(1).jsValue();
+    JSValue subscript = LLINT_OP_C(2).jsValue();
+    JSValue value = LLINT_OP_C(3).jsValue();
+    
+    if (LIKELY(subscript.isUInt32())) {
+        uint32_t i = subscript.asUInt32();
+        if (isJSArray(baseValue)) {
+            JSArray* jsArray = asArray(baseValue);
+            if (jsArray->canSetIndex(i))
+                jsArray->setIndex(globalData, i, value);
+            else
+                JSArray::putByIndex(jsArray, exec, i, value, exec->codeBlock()->isStrictMode());
+            LLINT_END();
+        }
+        baseValue.putByIndex(exec, i, value, exec->codeBlock()->isStrictMode());
+        LLINT_END();
+    }
+    
+    Identifier property(exec, subscript.toString(exec)->value(exec));
+    LLINT_CHECK_EXCEPTION();
+    PutPropertySlot slot(exec->codeBlock()->isStrictMode());
+    baseValue.put(exec, property, value, slot);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_del_by_val)
+{
+    LLINT_BEGIN();
+    JSValue baseValue = LLINT_OP_C(2).jsValue();
+    JSObject* baseObject = baseValue.toObject(exec);
+    
+    JSValue subscript = LLINT_OP_C(3).jsValue();
+    
+    bool couldDelete;
+    
+    uint32_t i;
+    if (subscript.getUInt32(i))
+        couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
+    else {
+        LLINT_CHECK_EXCEPTION();
+        Identifier property(exec, subscript.toString(exec)->value(exec));
+        LLINT_CHECK_EXCEPTION();
+        couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
+    }
+    
+    if (!couldDelete && exec->codeBlock()->isStrictMode())
+        LLINT_THROW(createTypeError(exec, "Unable to delete property."));
+    
+    LLINT_RETURN(jsBoolean(couldDelete));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_put_by_index)
+{
+    LLINT_BEGIN();
+    JSValue arrayValue = LLINT_OP_C(1).jsValue();
+    ASSERT(isJSArray(arrayValue));
+    asArray(arrayValue)->putDirectIndex(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue(), false);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter)
+{
+    LLINT_BEGIN();
+    ASSERT(LLINT_OP(1).jsValue().isObject());
+    JSObject* baseObj = asObject(LLINT_OP(1).jsValue());
+    
+    GetterSetter* accessor = GetterSetter::create(exec);
+    LLINT_CHECK_EXCEPTION();
+    
+    JSValue getter = LLINT_OP(3).jsValue();
+    JSValue setter = LLINT_OP(4).jsValue();
+    ASSERT(getter.isObject() || getter.isUndefined());
+    ASSERT(setter.isObject() || setter.isUndefined());
+    ASSERT(getter.isObject() || setter.isObject());
+    
+    if (!getter.isUndefined())
+        accessor->setGetter(globalData, asObject(getter));
+    if (!setter.isUndefined())
+        accessor->setSetter(globalData, asObject(setter));
+    baseObj->putDirectAccessor(
+        globalData,
+        exec->codeBlock()->identifier(pc[2].u.operand),
+        accessor, Accessor);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jmp_scopes)
+{
+    LLINT_BEGIN();
+    unsigned count = pc[1].u.operand;
+    ScopeChainNode* tmp = exec->scopeChain();
+    while (count--)
+        tmp = tmp->pop();
+    exec->setScopeChain(tmp);
+    pc += pc[2].u.operand;
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jtrue)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean(exec));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jfalse)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean(exec));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jless)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jless, jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jnless)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jnless, !jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jgreater)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jgreater, jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jngreater)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jngreater, !jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jlesseq)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jlesseq, jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jnlesseq)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jnlesseq, !jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jgreatereq)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jgreatereq, jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_jngreatereq)
+{
+    LLINT_BEGIN();
+    LLINT_BRANCH(op_jngreatereq, !jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_switch_imm)
+{
+    LLINT_BEGIN();
+    JSValue scrutinee = LLINT_OP_C(3).jsValue();
+    ASSERT(scrutinee.isDouble());
+    double value = scrutinee.asDouble();
+    int32_t intValue = static_cast<int32_t>(value);
+    int defaultOffset = pc[2].u.operand;
+    if (value == intValue) {
+        CodeBlock* codeBlock = exec->codeBlock();
+        pc += codeBlock->immediateSwitchJumpTable(pc[1].u.operand).offsetForValue(intValue, defaultOffset);
+    } else
+        pc += defaultOffset;
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_switch_char)
+{
+    LLINT_BEGIN();
+    JSValue scrutinee = LLINT_OP_C(3).jsValue();
+    ASSERT(scrutinee.isString());
+    JSString* string = asString(scrutinee);
+    ASSERT(string->length() == 1);
+    int defaultOffset = pc[2].u.operand;
+    StringImpl* impl = string->value(exec).impl();
+    CodeBlock* codeBlock = exec->codeBlock();
+    pc += codeBlock->characterSwitchJumpTable(pc[1].u.operand).offsetForValue((*impl)[0], defaultOffset);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_switch_string)
+{
+    LLINT_BEGIN();
+    JSValue scrutinee = LLINT_OP_C(3).jsValue();
+    int defaultOffset = pc[2].u.operand;
+    if (!scrutinee.isString())
+        pc += defaultOffset;
+    else {
+        CodeBlock* codeBlock = exec->codeBlock();
+        pc += codeBlock->stringSwitchJumpTable(pc[1].u.operand).offsetForValue(asString(scrutinee)->value(exec).impl(), defaultOffset);
+    }
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_func)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    ASSERT(codeBlock->codeType() != FunctionCode
+           || !codeBlock->needsFullScopeChain()
+           || exec->uncheckedR(codeBlock->activationRegister()).jsValue());
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Creating function!\n");
+#endif
+    LLINT_RETURN(codeBlock->functionDecl(pc[2].u.operand)->make(exec, exec->scopeChain()));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_new_func_exp)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    FunctionExecutable* function = codeBlock->functionExpr(pc[2].u.operand);
+    JSFunction* func = function->make(exec, exec->scopeChain());
+    
+    if (!function->name().isNull()) {
+        JSStaticScopeObject* functionScopeObject = JSStaticScopeObject::create(exec, function->name(), func, ReadOnly | DontDelete);
+        func->setScope(globalData, func->scope()->push(functionScopeObject));
+    }
+    
+    LLINT_RETURN(func);
+}
+
+static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, JSValue callee, CodeSpecializationKind kind)
+{
+    ExecState* exec = execCallee->callerFrame();
+    JSGlobalData& globalData = exec->globalData();
+
+    execCallee->setScopeChain(exec->scopeChain());
+    execCallee->setCodeBlock(0);
+    execCallee->clearReturnPC();
+
+    if (kind == CodeForCall) {
+        CallData callData;
+        CallType callType = getCallData(callee, callData);
+    
+        ASSERT(callType != CallTypeJS);
+    
+        if (callType == CallTypeHost) {
+            NativeCallFrameTracer tracer(&globalData, execCallee);
+            execCallee->setCallee(asObject(callee));
+            globalData.hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
+            
+            LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
+        }
+        
+#if LLINT_SLOW_PATH_TRACING
+        dataLog("Call callee is not a function: %s\n", callee.description());
+#endif
+
+        ASSERT(callType == CallTypeNone);
+        LLINT_CALL_THROW(exec, pc, createNotAFunctionError(exec, callee));
+    }
+
+    ASSERT(kind == CodeForConstruct);
+    
+    ConstructData constructData;
+    ConstructType constructType = getConstructData(callee, constructData);
+    
+    ASSERT(constructType != ConstructTypeJS);
+    
+    if (constructType == ConstructTypeHost) {
+        NativeCallFrameTracer tracer(&globalData, execCallee);
+        execCallee->setCallee(asObject(callee));
+        globalData.hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
+
+        LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
+    }
+    
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Constructor callee is not a function: %s\n", callee.description());
+#endif
+
+    ASSERT(constructType == ConstructTypeNone);
+    LLINT_CALL_THROW(exec, pc, createNotAConstructorError(exec, callee));
+}
+
+inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, CodeSpecializationKind kind, JSValue calleeAsValue, LLIntCallLinkInfo* callLinkInfo = 0)
+{
+#if LLINT_SLOW_PATH_TRACING
+    dataLog("Performing call with recorded PC = %p\n", execCallee->callerFrame()->currentVPC());
+#endif
+
+    JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
+    if (!calleeAsFunctionCell)
+        return handleHostCall(execCallee, pc, calleeAsValue, kind);
+    
+    JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
+    ScopeChainNode* scope = callee->scopeUnchecked();
+    JSGlobalData& globalData = *scope->globalData;
+    execCallee->setScopeChain(scope);
+    ExecutableBase* executable = callee->executable();
+    
+    MacroAssemblerCodePtr codePtr;
+    CodeBlock* codeBlock = 0;
+    if (executable->isHostFunction())
+        codePtr = executable->generatedJITCodeFor(kind).addressForCall();
+    else {
+        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
+        JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
+        if (error)
+            LLINT_CALL_THROW(execCallee->callerFrame(), pc, error);
+        codeBlock = &functionExecutable->generatedBytecodeFor(kind);
+        ASSERT(codeBlock);
+        if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
+            codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
+        else
+            codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
+    }
+    
+    if (callLinkInfo) {
+        if (callLinkInfo->isOnList())
+            callLinkInfo->remove();
+        ExecState* execCaller = execCallee->callerFrame();
+        callLinkInfo->callee.set(globalData, execCaller->codeBlock()->ownerExecutable(), callee);
+        callLinkInfo->lastSeenCallee.set(globalData, execCaller->codeBlock()->ownerExecutable(), callee);
+        callLinkInfo->machineCodeTarget = codePtr;
+        if (codeBlock)
+            codeBlock->linkIncomingCall(callLinkInfo);
+    }
+    
+    LLINT_CALL_RETURN(execCallee, pc, codePtr.executableAddress());
+}
+
+inline SlowPathReturnType genericCall(ExecState* exec, Instruction* pc, CodeSpecializationKind kind)
+{
+    // This needs to:
+    // - Set up a call frame.
+    // - Figure out what to call and compile it if necessary.
+    // - If possible, link the call's inline cache.
+    // - Return a tuple of machine code address to call and the new call frame.
+    
+    JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
+    
+    ExecState* execCallee = exec + pc[3].u.operand;
+    
+    execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
+    execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
+    execCallee->setCallerFrame(exec);
+    
+    ASSERT(pc[4].u.callLinkInfo);
+    return setUpCall(execCallee, pc, kind, calleeAsValue, pc[4].u.callLinkInfo);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_call)
+{
+    LLINT_BEGIN_NO_SET_PC();
+    return genericCall(exec, pc, CodeForCall);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_construct)
+{
+    LLINT_BEGIN_NO_SET_PC();
+    return genericCall(exec, pc, CodeForConstruct);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_call_varargs)
+{
+    LLINT_BEGIN();
+    // This needs to:
+    // - Set up a call frame while respecting the variable arguments.
+    // - Figure out what to call and compile it if necessary.
+    // - Return a tuple of machine code address to call and the new call frame.
+    
+    JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
+    
+    ExecState* execCallee = loadVarargs(
+        exec, &globalData.interpreter->registerFile(),
+        LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), pc[4].u.operand);
+    LLINT_CALL_CHECK_EXCEPTION(exec, pc);
+    
+    execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
+    execCallee->setCallerFrame(exec);
+    exec->setCurrentVPC(pc + OPCODE_LENGTH(op_call_varargs));
+    
+    return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_call_eval)
+{
+    LLINT_BEGIN_NO_SET_PC();
+    JSValue calleeAsValue = LLINT_OP(1).jsValue();
+    
+    ExecState* execCallee = exec + pc[3].u.operand;
+    
+    execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
+    execCallee->setCallerFrame(exec);
+    execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
+    execCallee->setScopeChain(exec->scopeChain());
+    execCallee->setReturnPC(bitwise_cast<Instruction*>(&llint_generic_return_point));
+    execCallee->setCodeBlock(0);
+    exec->setCurrentVPC(pc + OPCODE_LENGTH(op_call_eval));
+    
+    if (!isHostFunction(calleeAsValue, globalFuncEval))
+        return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
+    
+    globalData.hostCallReturnValue = eval(execCallee);
+    LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation)
+{
+    LLINT_BEGIN();
+    ASSERT(exec->codeBlock()->needsFullScopeChain());
+    JSValue activationValue = LLINT_OP(1).jsValue();
+    if (!activationValue) {
+        if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue()) {
+            if (!exec->codeBlock()->isStrictMode())
+                asArguments(v)->tearOff(exec);
+        }
+        LLINT_END();
+    }
+    JSActivation* activation = asActivation(activationValue);
+    activation->tearOff(globalData);
+    if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue())
+        asArguments(v)->didTearOffActivation(globalData, activation);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments)
+{
+    LLINT_BEGIN();
+    ASSERT(exec->codeBlock()->usesArguments() && !exec->codeBlock()->needsFullScopeChain());
+    asArguments(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue())->tearOff(exec);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_strcat)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(jsString(exec, &LLINT_OP(2), pc[3].u.operand));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_to_primitive)
+{
+    LLINT_BEGIN();
+    LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_get_pnames)
+{
+    LLINT_BEGIN();
+    JSValue v = LLINT_OP(2).jsValue();
+    if (v.isUndefinedOrNull()) {
+        pc += pc[5].u.operand;
+        LLINT_END();
+    }
+    
+    JSObject* o = v.toObject(exec);
+    Structure* structure = o->structure();
+    JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
+    if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(exec))
+        jsPropertyNameIterator = JSPropertyNameIterator::create(exec, o);
+    
+    LLINT_OP(1) = JSValue(jsPropertyNameIterator);
+    LLINT_OP(2) = JSValue(o);
+    LLINT_OP(3) = Register::withInt(0);
+    LLINT_OP(4) = Register::withInt(jsPropertyNameIterator->size());
+    
+    pc += OPCODE_LENGTH(op_get_pnames);
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_next_pname)
+{
+    LLINT_BEGIN();
+    JSObject* base = asObject(LLINT_OP(2).jsValue());
+    JSString* property = asString(LLINT_OP(1).jsValue());
+    if (base->hasProperty(exec, Identifier(exec, property->value(exec)))) {
+        // Go to target.
+        pc += pc[6].u.operand;
+    } // Else, don't change the PC, so the interpreter will reloop.
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_push_scope)
+{
+    LLINT_BEGIN();
+    JSValue v = LLINT_OP(1).jsValue();
+    JSObject* o = v.toObject(exec);
+    LLINT_CHECK_EXCEPTION();
+    
+    LLINT_OP(1) = o;
+    exec->setScopeChain(exec->scopeChain()->push(o));
+    
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_pop_scope)
+{
+    LLINT_BEGIN();
+    exec->setScopeChain(exec->scopeChain()->pop());
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_push_new_scope)
+{
+    LLINT_BEGIN();
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSObject* scope = JSStaticScopeObject::create(exec, codeBlock->identifier(pc[2].u.operand), LLINT_OP(3).jsValue(), DontDelete);
+    exec->setScopeChain(exec->scopeChain()->push(scope));
+    LLINT_RETURN(scope);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_throw)
+{
+    LLINT_BEGIN();
+    LLINT_THROW(LLINT_OP_C(1).jsValue());
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_throw_reference_error)
+{
+    LLINT_BEGIN();
+    LLINT_THROW(createReferenceError(exec, LLINT_OP_C(1).jsValue().toString(exec)->value(exec)));
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_debug)
+{
+    LLINT_BEGIN();
+    int debugHookID = pc[1].u.operand;
+    int firstLine = pc[2].u.operand;
+    int lastLine = pc[3].u.operand;
+    
+    globalData.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
+    
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_profile_will_call)
+{
+    LLINT_BEGIN();
+    (*Profiler::enabledProfilerReference())->willExecute(exec, LLINT_OP(1).jsValue());
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_profile_did_call)
+{
+    LLINT_BEGIN();
+    (*Profiler::enabledProfilerReference())->didExecute(exec, LLINT_OP(1).jsValue());
+    LLINT_END();
+}
+
+LLINT_SLOW_PATH_DECL(throw_from_native_call)
+{
+    LLINT_BEGIN();
+    ASSERT(globalData.exception);
+    LLINT_END();
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
diff --git a/llint/LLIntSlowPaths.h b/llint/LLIntSlowPaths.h
new file mode 100644 (file)
index 0000000..a91cf79
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * 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 LLIntSlowPaths_h
+#define LLIntSlowPaths_h
+
+#include <wtf/Platform.h>
+#include <wtf/StdLibExtras.h>
+
+#if ENABLE(LLINT)
+
+namespace JSC {
+
+class ExecState;
+struct Instruction;
+
+namespace LLInt {
+
+#if USE(JSVALUE64)
+// According to C++ rules, a type used for the return signature of function with C linkage (i.e.
+// 'extern "C"') needs to be POD; hence putting any constructors into it could cause either compiler
+// warnings, or worse, a change in the ABI used to return these types.
+struct SlowPathReturnType {
+    void* a;
+    void* b;
+};
+
+inline SlowPathReturnType encodeResult(void* a, void* b)
+{
+    SlowPathReturnType result;
+    result.a = a;
+    result.b = b;
+    return result;
+}
+#else
+typedef int64_t SlowPathReturnType;
+
+inline SlowPathReturnType encodeResult(void* a, void* b)
+{
+    union {
+        struct {
+            void* a;
+            void* b;
+        } pair;
+        int64_t i;
+    } u;
+    u.pair.a = a;
+    u.pair.b = b;
+    return u.i;
+}
+#endif
+
+extern "C" SlowPathReturnType llint_trace_operand(ExecState*, Instruction*, int fromWhere, int operand);
+extern "C" SlowPathReturnType llint_trace_value(ExecState*, Instruction*, int fromWhere, int operand);
+
+#define LLINT_SLOW_PATH_DECL(name) \
+    extern "C" SlowPathReturnType llint_##name(ExecState* exec, Instruction* pc)
+
+LLINT_SLOW_PATH_DECL(trace_prologue);
+LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call);
+LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct);
+LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call);
+LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct);
+LLINT_SLOW_PATH_DECL(trace);
+LLINT_SLOW_PATH_DECL(special_trace);
+LLINT_SLOW_PATH_DECL(entry_osr);
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_call);
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct);
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck);
+LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck);
+LLINT_SLOW_PATH_DECL(loop_osr);
+LLINT_SLOW_PATH_DECL(replace);
+LLINT_SLOW_PATH_DECL(register_file_check);
+LLINT_SLOW_PATH_DECL(slow_path_call_arityCheck);
+LLINT_SLOW_PATH_DECL(slow_path_construct_arityCheck);
+LLINT_SLOW_PATH_DECL(slow_path_create_activation);
+LLINT_SLOW_PATH_DECL(slow_path_create_arguments);
+LLINT_SLOW_PATH_DECL(slow_path_create_this);
+LLINT_SLOW_PATH_DECL(slow_path_convert_this);
+LLINT_SLOW_PATH_DECL(slow_path_new_object);
+LLINT_SLOW_PATH_DECL(slow_path_new_array);
+LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer);
+LLINT_SLOW_PATH_DECL(slow_path_new_regexp);
+LLINT_SLOW_PATH_DECL(slow_path_not);
+LLINT_SLOW_PATH_DECL(slow_path_eq);
+LLINT_SLOW_PATH_DECL(slow_path_neq);
+LLINT_SLOW_PATH_DECL(slow_path_stricteq);
+LLINT_SLOW_PATH_DECL(slow_path_nstricteq);
+LLINT_SLOW_PATH_DECL(slow_path_less);
+LLINT_SLOW_PATH_DECL(slow_path_lesseq);
+LLINT_SLOW_PATH_DECL(slow_path_greater);
+LLINT_SLOW_PATH_DECL(slow_path_greatereq);
+LLINT_SLOW_PATH_DECL(slow_path_pre_inc);
+LLINT_SLOW_PATH_DECL(slow_path_pre_dec);
+LLINT_SLOW_PATH_DECL(slow_path_post_inc);
+LLINT_SLOW_PATH_DECL(slow_path_post_dec);
+LLINT_SLOW_PATH_DECL(slow_path_to_jsnumber);
+LLINT_SLOW_PATH_DECL(slow_path_negate);
+LLINT_SLOW_PATH_DECL(slow_path_add);
+LLINT_SLOW_PATH_DECL(slow_path_mul);
+LLINT_SLOW_PATH_DECL(slow_path_sub);
+LLINT_SLOW_PATH_DECL(slow_path_div);
+LLINT_SLOW_PATH_DECL(slow_path_mod);
+LLINT_SLOW_PATH_DECL(slow_path_lshift);
+LLINT_SLOW_PATH_DECL(slow_path_rshift);
+LLINT_SLOW_PATH_DECL(slow_path_urshift);
+LLINT_SLOW_PATH_DECL(slow_path_bitand);
+LLINT_SLOW_PATH_DECL(slow_path_bitor);
+LLINT_SLOW_PATH_DECL(slow_path_bitxor);
+LLINT_SLOW_PATH_DECL(slow_path_check_has_instance);
+LLINT_SLOW_PATH_DECL(slow_path_instanceof);
+LLINT_SLOW_PATH_DECL(slow_path_typeof);
+LLINT_SLOW_PATH_DECL(slow_path_is_object);
+LLINT_SLOW_PATH_DECL(slow_path_is_function);
+LLINT_SLOW_PATH_DECL(slow_path_in);
+LLINT_SLOW_PATH_DECL(slow_path_resolve);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_skip);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_global);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_global_dynamic);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_for_resolve_global_dynamic);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_base);
+LLINT_SLOW_PATH_DECL(slow_path_ensure_property_exists);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_with_base);
+LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this);
+LLINT_SLOW_PATH_DECL(slow_path_get_by_id);
+LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length);
+LLINT_SLOW_PATH_DECL(slow_path_put_by_id);
+LLINT_SLOW_PATH_DECL(slow_path_del_by_id);
+LLINT_SLOW_PATH_DECL(slow_path_get_by_val);
+LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val);
+LLINT_SLOW_PATH_DECL(slow_path_get_by_pname);
+LLINT_SLOW_PATH_DECL(slow_path_put_by_val);
+LLINT_SLOW_PATH_DECL(slow_path_del_by_val);
+LLINT_SLOW_PATH_DECL(slow_path_put_by_index);
+LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter);
+LLINT_SLOW_PATH_DECL(slow_path_jmp_scopes);
+LLINT_SLOW_PATH_DECL(slow_path_jtrue);
+LLINT_SLOW_PATH_DECL(slow_path_jfalse);
+LLINT_SLOW_PATH_DECL(slow_path_jless);
+LLINT_SLOW_PATH_DECL(slow_path_jnless);
+LLINT_SLOW_PATH_DECL(slow_path_jgreater);
+LLINT_SLOW_PATH_DECL(slow_path_jngreater);
+LLINT_SLOW_PATH_DECL(slow_path_jlesseq);
+LLINT_SLOW_PATH_DECL(slow_path_jnlesseq);
+LLINT_SLOW_PATH_DECL(slow_path_jgreatereq);
+LLINT_SLOW_PATH_DECL(slow_path_jngreatereq);
+LLINT_SLOW_PATH_DECL(slow_path_switch_imm);
+LLINT_SLOW_PATH_DECL(slow_path_switch_char);
+LLINT_SLOW_PATH_DECL(slow_path_switch_string);
+LLINT_SLOW_PATH_DECL(slow_path_new_func);
+LLINT_SLOW_PATH_DECL(slow_path_new_func_exp);
+LLINT_SLOW_PATH_DECL(slow_path_call);
+LLINT_SLOW_PATH_DECL(slow_path_construct);
+LLINT_SLOW_PATH_DECL(slow_path_call_varargs);
+LLINT_SLOW_PATH_DECL(slow_path_call_eval);
+LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation);
+LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments);
+LLINT_SLOW_PATH_DECL(slow_path_strcat);
+LLINT_SLOW_PATH_DECL(slow_path_to_primitive);
+LLINT_SLOW_PATH_DECL(slow_path_get_pnames);
+LLINT_SLOW_PATH_DECL(slow_path_next_pname);
+LLINT_SLOW_PATH_DECL(slow_path_push_scope);
+LLINT_SLOW_PATH_DECL(slow_path_pop_scope);
+LLINT_SLOW_PATH_DECL(slow_path_push_new_scope);
+LLINT_SLOW_PATH_DECL(slow_path_throw);
+LLINT_SLOW_PATH_DECL(slow_path_throw_reference_error);
+LLINT_SLOW_PATH_DECL(slow_path_debug);
+LLINT_SLOW_PATH_DECL(slow_path_profile_will_call);
+LLINT_SLOW_PATH_DECL(slow_path_profile_did_call);
+LLINT_SLOW_PATH_DECL(throw_from_native_call);
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
+
+#endif // LLIntSlowPaths_h
+
diff --git a/llint/LLIntThunks.cpp b/llint/LLIntThunks.cpp
new file mode 100644 (file)
index 0000000..b4d0264
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "LLIntThunks.h"
+
+#if ENABLE(LLINT)
+
+#include "JSInterfaceJIT.h"
+#include "JSObject.h"
+#include "LinkBuffer.h"
+#include "LowLevelInterpreter.h"
+#include "ScopeChain.h"
+
+namespace JSC { namespace LLInt {
+
+static MacroAssemblerCodeRef generateThunkWithJumpTo(JSGlobalData* globalData, void (*target)())
+{
+    JSInterfaceJIT jit;
+    
+    // FIXME: there's probably a better way to do it on X86, but I'm not sure I care.
+    jit.move(JSInterfaceJIT::TrustedImmPtr(bitwise_cast<void*>(target)), JSInterfaceJIT::regT0);
+    jit.jump(JSInterfaceJIT::regT0);
+    
+    LinkBuffer patchBuffer(*globalData, &jit, GLOBAL_THUNK_ID);
+    return patchBuffer.finalizeCode();
+}
+
+MacroAssemblerCodeRef functionForCallEntryThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_function_for_call_prologue);
+}
+
+MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_function_for_construct_prologue);
+}
+
+MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_function_for_call_arity_check);
+}
+
+MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_function_for_construct_arity_check);
+}
+
+MacroAssemblerCodeRef evalEntryThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_eval_prologue);
+}
+
+MacroAssemblerCodeRef programEntryThunkGenerator(JSGlobalData* globalData)
+{
+    return generateThunkWithJumpTo(globalData, llint_program_prologue);
+}
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
diff --git a/llint/LLIntThunks.h b/llint/LLIntThunks.h
new file mode 100644 (file)
index 0000000..ee119e0
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef LLIntThunks_h
+#define LLIntThunks_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(LLINT)
+
+#include "MacroAssemblerCodeRef.h"
+
+namespace JSC {
+
+class JSGlobalData;
+
+namespace LLInt {
+
+MacroAssemblerCodeRef functionForCallEntryThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef functionForConstructEntryThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef functionForCallArityCheckThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef functionForConstructArityCheckThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef evalEntryThunkGenerator(JSGlobalData*);
+MacroAssemblerCodeRef programEntryThunkGenerator(JSGlobalData*);
+
+} } // namespace JSC::LLInt
+
+#endif // ENABLE(LLINT)
+
+#endif // LLIntThunks_h
diff --git a/llint/LowLevelInterpreter.asm b/llint/LowLevelInterpreter.asm
new file mode 100644 (file)
index 0000000..0a5f201
--- /dev/null
@@ -0,0 +1,833 @@
+# Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. 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.
+
+# Work-around for the fact that the toolchain's awareness of armv7s results in
+# a separate slab in the fat binary, yet the offlineasm doesn't know to expect
+# it.
+if ARMv7s
+end
+
+# First come the common protocols that both interpreters use. Note that each
+# of these must have an ASSERT() in LLIntData.cpp
+
+# These declarations must match interpreter/RegisterFile.h.
+const CallFrameHeaderSize = 48
+const ArgumentCount = -48
+const CallerFrame = -40
+const Callee = -32
+const ScopeChain = -24
+const ReturnPC = -16
+const CodeBlock = -8
+
+const ThisArgumentOffset = -CallFrameHeaderSize - 8
+
+# Some register conventions.
+if JSVALUE64
+    # - Use a pair of registers to represent the PC: one register for the
+    #   base of the register file, and one register for the index.
+    # - The PC base (or PB for short) should be stored in the csr. It will
+    #   get clobbered on calls to other JS code, but will get saved on calls
+    #   to C functions.
+    # - C calls are still given the Instruction* rather than the PC index.
+    #   This requires an add before the call, and a sub after.
+    const PC = t4
+    const PB = t6
+    const tagTypeNumber = csr1
+    const tagMask = csr2
+else
+    const PC = t4
+end
+
+# Constants for reasoning about value representation.
+if BIG_ENDIAN
+    const TagOffset = 0
+    const PayloadOffset = 4
+else
+    const TagOffset = 4
+    const PayloadOffset = 0
+end
+
+# Type constants.
+const StringType = 5
+const ObjectType = 13
+
+# Type flags constants.
+const MasqueradesAsUndefined = 1
+const ImplementsHasInstance = 2
+const ImplementsDefaultHasInstance = 8
+
+# Bytecode operand constants.
+const FirstConstantRegisterIndex = 0x40000000
+
+# Code type constants.
+const GlobalCode = 0
+const EvalCode = 1
+const FunctionCode = 2
+
+# The interpreter steals the tag word of the argument count.
+const LLIntReturnPC = ArgumentCount + TagOffset
+
+# String flags.
+const HashFlags8BitBuffer = 64
+
+# Allocation constants
+if JSVALUE64
+    const JSFinalObjectSizeClassIndex = 1
+else
+    const JSFinalObjectSizeClassIndex = 3
+end
+
+# This must match wtf/Vector.h
+if JSVALUE64
+    const VectorSizeOffset = 0
+    const VectorBufferOffset = 8
+else
+    const VectorSizeOffset = 0
+    const VectorBufferOffset = 4
+end
+
+
+# Some common utilities.
+macro crash()
+    storei 0, 0xbbadbeef[]
+    move 0, t0
+    call t0
+end
+
+macro assert(assertion)
+    if ASSERT_ENABLED
+        assertion(.ok)
+        crash()
+    .ok:
+    end
+end
+
+macro preserveReturnAddressAfterCall(destinationRegister)
+    if ARMv7
+        move lr, destinationRegister
+    elsif X86 or X86_64
+        pop destinationRegister
+    else
+        error
+    end
+end
+
+macro restoreReturnAddressBeforeReturn(sourceRegister)
+    if ARMv7
+        move sourceRegister, lr
+    elsif X86 or X86_64
+        push sourceRegister
+    else
+        error
+    end
+end
+
+macro traceExecution()
+    if EXECUTION_TRACING
+        callSlowPath(_llint_trace)
+    end
+end
+
+macro slowPathForCall(advance, slowPath)
+    callCallSlowPath(
+        advance,
+        slowPath,
+        macro (callee)
+            call callee
+            dispatchAfterCall()
+        end)
+end
+
+macro checkSwitchToJIT(increment, action)
+    if JIT_ENABLED
+        loadp CodeBlock[cfr], t0
+        baddis increment, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t0], .continue
+        action()
+    .continue:
+    end
+end
+
+macro checkSwitchToJITForEpilogue()
+    checkSwitchToJIT(
+        10,
+        macro ()
+            callSlowPath(_llint_replace)
+        end)
+end
+
+macro assertNotConstant(index)
+    assert(macro (ok) bilt index, FirstConstantRegisterIndex, ok end)
+end
+
+macro functionForCallCodeBlockGetter(targetRegister)
+    loadp Callee[cfr], targetRegister
+    loadp JSFunction::m_executable[targetRegister], targetRegister
+    loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister
+end
+
+macro functionForConstructCodeBlockGetter(targetRegister)
+    loadp Callee[cfr], targetRegister
+    loadp JSFunction::m_executable[targetRegister], targetRegister
+    loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister
+end
+
+macro notFunctionCodeBlockGetter(targetRegister)
+    loadp CodeBlock[cfr], targetRegister
+end
+
+macro functionCodeBlockSetter(sourceRegister)
+    storep sourceRegister, CodeBlock[cfr]
+end
+
+macro notFunctionCodeBlockSetter(sourceRegister)
+    # Nothing to do!
+end
+
+# Do the bare minimum required to execute code. Sets up the PC, leave the CodeBlock*
+# in t1. May also trigger prologue entry OSR.
+macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
+    preserveReturnAddressAfterCall(t2)
+    
+    # Set up the call frame and check if we should OSR.
+    storep t2, ReturnPC[cfr]
+    if EXECUTION_TRACING
+        callSlowPath(traceSlowPath)
+    end
+    codeBlockGetter(t1)
+    if JIT_ENABLED
+        baddis 5, CodeBlock::m_llintExecuteCounter + ExecutionCounter::m_counter[t1], .continue
+        cCall2(osrSlowPath, cfr, PC)
+        move t1, cfr
+        btpz t0, .recover
+        loadp ReturnPC[cfr], t2
+        restoreReturnAddressBeforeReturn(t2)
+        jmp t0
+    .recover:
+        codeBlockGetter(t1)
+    .continue:
+    end
+    codeBlockSetter(t1)
+    
+    # Set up the PC.
+    if JSVALUE64
+        loadp CodeBlock::m_instructions[t1], PB
+        move 0, PC
+    else
+        loadp CodeBlock::m_instructions[t1], PC
+    end
+end
+
+# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
+# Must call dispatch(0) after calling this.
+macro functionInitialization(profileArgSkip)
+    if VALUE_PROFILER
+        # Profile the arguments. Unfortunately, we have no choice but to do this. This
+        # code is pretty horrendous because of the difference in ordering between
+        # arguments and value profiles, the desire to have a simple loop-down-to-zero
+        # loop, and the desire to use only three registers so as to preserve the PC and
+        # the code block. It is likely that this code should be rewritten in a more
+        # optimal way for architectures that have more than five registers available
+        # for arbitrary use in the interpreter.
+        loadi CodeBlock::m_numParameters[t1], t0
+        addp -profileArgSkip, t0 # Use addi because that's what has the peephole
+        assert(macro (ok) bpgteq t0, 0, ok end)
+        btpz t0, .argumentProfileDone
+        loadp CodeBlock::m_argumentValueProfiles + VectorBufferOffset[t1], t3
+        mulp sizeof ValueProfile, t0, t2 # Aaaaahhhh! Need strength reduction!
+        negp t0
+        lshiftp 3, t0
+        addp t2, t3
+    .argumentProfileLoop:
+        if JSVALUE64
+            loadp ThisArgumentOffset + 8 - profileArgSkip * 8[cfr, t0], t2
+            subp sizeof ValueProfile, t3
+            storep t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets[t3]
+        else
+            loadi ThisArgumentOffset + TagOffset + 8 - profileArgSkip * 8[cfr, t0], t2
+            subp sizeof ValueProfile, t3
+            storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + TagOffset[t3]
+            loadi ThisArgumentOffset + PayloadOffset + 8 - profileArgSkip * 8[cfr, t0], t2
+            storei t2, profileArgSkip * sizeof ValueProfile + ValueProfile::m_buckets + PayloadOffset[t3]
+        end
+        baddpnz 8, t0, .argumentProfileLoop
+    .argumentProfileDone:
+    end
+        
+    # Check stack height.
+    loadi CodeBlock::m_numCalleeRegisters[t1], t0
+    loadp CodeBlock::m_globalData[t1], t2
+    loadp JSGlobalData::interpreter[t2], t2   # FIXME: Can get to the RegisterFile from the JITStackFrame
+    lshifti 3, t0
+    addp t0, cfr, t0
+    bpaeq Interpreter::m_registerFile + RegisterFile::m_end[t2], t0, .stackHeightOK
+
+    # Stack height check failed - need to call a slow_path.
+    callSlowPath(_llint_register_file_check)
+.stackHeightOK:
+end
+
+macro allocateBasicJSObject(sizeClassIndex, classInfoOffset, structure, result, scratch1, scratch2, slowCase)
+    if ALWAYS_ALLOCATE_SLOW
+        jmp slowCase
+    else
+        const offsetOfMySizeClass =
+            JSGlobalData::heap +
+            Heap::m_objectSpace +
+            MarkedSpace::m_normalSpace +
+            MarkedSpace::Subspace::preciseAllocators +
+            sizeClassIndex * sizeof MarkedAllocator
+        
+        const offsetOfFirstFreeCell = 
+            MarkedAllocator::m_freeList + 
+            MarkedBlock::FreeList::head
+
+        # FIXME: we can get the global data in one load from the stack.
+        loadp CodeBlock[cfr], scratch1
+        loadp CodeBlock::m_globalData[scratch1], scratch1
+        
+        # Get the object from the free list.   
+        loadp offsetOfMySizeClass + offsetOfFirstFreeCell[scratch1], result
+        btpz result, slowCase
+        
+        # Remove the object from the free list.
+        loadp [result], scratch2
+        storep scratch2, offsetOfMySizeClass + offsetOfFirstFreeCell[scratch1]
+    
+        # Initialize the object.
+        loadp classInfoOffset[scratch1], scratch2
+        storep scratch2, [result]
+        storep structure, JSCell::m_structure[result]
+        storep 0, JSObject::m_inheritorID[result]
+        addp sizeof JSObject, result, scratch1
+        storep scratch1, JSObject::m_propertyStorage[result]
+    end
+end
+
+macro doReturn()
+    loadp ReturnPC[cfr], t2
+    loadp CallerFrame[cfr], cfr
+    restoreReturnAddressBeforeReturn(t2)
+    ret
+end
+
+
+# Indicate the beginning of LLInt.
+_llint_begin:
+    crash()
+
+
+_llint_program_prologue:
+    prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
+    dispatch(0)
+
+
+_llint_eval_prologue:
+    prologue(notFunctionCodeBlockGetter, notFunctionCodeBlockSetter, _llint_entry_osr, _llint_trace_prologue)
+    dispatch(0)
+
+
+_llint_function_for_call_prologue:
+    prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call, _llint_trace_prologue_function_for_call)
+.functionForCallBegin:
+    functionInitialization(0)
+    dispatch(0)
+    
+
+_llint_function_for_construct_prologue:
+    prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct, _llint_trace_prologue_function_for_construct)
+.functionForConstructBegin:
+    functionInitialization(1)
+    dispatch(0)
+    
+
+_llint_function_for_call_arity_check:
+    prologue(functionForCallCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_call_arityCheck, _llint_trace_arityCheck_for_call)
+    functionArityCheck(.functionForCallBegin, _llint_slow_path_call_arityCheck)
+
+
+_llint_function_for_construct_arity_check:
+    prologue(functionForConstructCodeBlockGetter, functionCodeBlockSetter, _llint_entry_osr_function_for_construct_arityCheck, _llint_trace_arityCheck_for_construct)
+    functionArityCheck(.functionForConstructBegin, _llint_slow_path_construct_arityCheck)
+
+
+# Value-representation-specific code.
+if JSVALUE64
+    include LowLevelInterpreter64
+else
+    include LowLevelInterpreter32_64
+end
+
+
+# Value-representation-agnostic code.
+_llint_op_new_array:
+    traceExecution()
+    callSlowPath(_llint_slow_path_new_array)
+    dispatch(4)
+
+
+_llint_op_new_array_buffer:
+    traceExecution()
+    callSlowPath(_llint_slow_path_new_array_buffer)
+    dispatch(4)
+
+
+_llint_op_new_regexp:
+    traceExecution()
+    callSlowPath(_llint_slow_path_new_regexp)
+    dispatch(3)
+
+
+_llint_op_less:
+    traceExecution()
+    callSlowPath(_llint_slow_path_less)
+    dispatch(4)
+
+
+_llint_op_lesseq:
+    traceExecution()
+    callSlowPath(_llint_slow_path_lesseq)
+    dispatch(4)
+
+
+_llint_op_greater:
+    traceExecution()
+    callSlowPath(_llint_slow_path_greater)
+    dispatch(4)
+
+
+_llint_op_greatereq:
+    traceExecution()
+    callSlowPath(_llint_slow_path_greatereq)
+    dispatch(4)
+
+
+_llint_op_mod:
+    traceExecution()
+    callSlowPath(_llint_slow_path_mod)
+    dispatch(4)
+
+
+_llint_op_typeof:
+    traceExecution()
+    callSlowPath(_llint_slow_path_typeof)
+    dispatch(3)
+
+
+_llint_op_is_object:
+    traceExecution()
+    callSlowPath(_llint_slow_path_is_object)
+    dispatch(3)
+
+
+_llint_op_is_function:
+    traceExecution()
+    callSlowPath(_llint_slow_path_is_function)
+    dispatch(3)
+
+
+_llint_op_in:
+    traceExecution()
+    callSlowPath(_llint_slow_path_in)
+    dispatch(4)
+
+
+_llint_op_resolve:
+    traceExecution()
+    callSlowPath(_llint_slow_path_resolve)
+    dispatch(4)
+
+
+_llint_op_resolve_skip:
+    traceExecution()
+    callSlowPath(_llint_slow_path_resolve_skip)
+    dispatch(5)
+
+
+_llint_op_resolve_base:
+    traceExecution()
+    callSlowPath(_llint_slow_path_resolve_base)
+    dispatch(5)
+
+
+_llint_op_ensure_property_exists:
+    traceExecution()
+    callSlowPath(_llint_slow_path_ensure_property_exists)
+    dispatch(3)
+
+
+_llint_op_resolve_with_base:
+    traceExecution()
+    callSlowPath(_llint_slow_path_resolve_with_base)
+    dispatch(5)
+
+
+_llint_op_resolve_with_this:
+    traceExecution()
+    callSlowPath(_llint_slow_path_resolve_with_this)
+    dispatch(5)
+
+
+_llint_op_del_by_id:
+    traceExecution()
+    callSlowPath(_llint_slow_path_del_by_id)
+    dispatch(4)
+
+
+_llint_op_del_by_val:
+    traceExecution()
+    callSlowPath(_llint_slow_path_del_by_val)
+    dispatch(4)
+
+
+_llint_op_put_by_index:
+    traceExecution()
+    callSlowPath(_llint_slow_path_put_by_index)
+    dispatch(4)
+
+
+_llint_op_put_getter_setter:
+    traceExecution()
+    callSlowPath(_llint_slow_path_put_getter_setter)
+    dispatch(5)
+
+
+_llint_op_jmp_scopes:
+    traceExecution()
+    callSlowPath(_llint_slow_path_jmp_scopes)
+    dispatch(0)
+
+
+_llint_op_loop_if_true:
+    jmp _llint_op_jtrue
+_llint_op_jtrue:
+    traceExecution()
+    jumpTrueOrFalse(
+        macro (value, target) btinz value, target end,
+        _llint_slow_path_jtrue)
+
+
+_llint_op_loop_if_false:
+   jmp _llint_op_jfalse
+_llint_op_jfalse:
+    traceExecution()
+    jumpTrueOrFalse(
+        macro (value, target) btiz value, target end,
+        _llint_slow_path_jfalse)
+
+
+_llint_op_loop_if_less:
+    jmp _llint_op_jless
+_llint_op_jless:
+    traceExecution()
+    compare(
+        macro (left, right, target) bilt left, right, target end,
+        macro (left, right, target) bdlt left, right, target end,
+        _llint_slow_path_jless)
+
+
+_llint_op_jnless:
+    traceExecution()
+    compare(
+        macro (left, right, target) bigteq left, right, target end,
+        macro (left, right, target) bdgtequn left, right, target end,
+        _llint_slow_path_jnless)
+
+
+_llint_op_loop_if_greater:
+    jmp _llint_op_jgreater
+_llint_op_jgreater:
+    traceExecution()
+    compare(
+        macro (left, right, target) bigt left, right, target end,
+        macro (left, right, target) bdgt left, right, target end,
+        _llint_slow_path_jgreater)
+
+
+_llint_op_jngreater:
+    traceExecution()
+    compare(
+        macro (left, right, target) bilteq left, right, target end,
+        macro (left, right, target) bdltequn left, right, target end,
+        _llint_slow_path_jngreater)
+
+
+_llint_op_loop_if_lesseq:
+    jmp _llint_op_jlesseq
+_llint_op_jlesseq:
+    traceExecution()
+    compare(
+        macro (left, right, target) bilteq left, right, target end,
+        macro (left, right, target) bdlteq left, right, target end,
+        _llint_slow_path_jlesseq)
+
+
+_llint_op_jnlesseq:
+    traceExecution()
+    compare(
+        macro (left, right, target) bigt left, right, target end,
+        macro (left, right, target) bdgtun left, right, target end,
+        _llint_slow_path_jnlesseq)
+
+
+_llint_op_loop_if_greatereq:
+    jmp _llint_op_jgreatereq
+_llint_op_jgreatereq:
+    traceExecution()
+    compare(
+        macro (left, right, target) bigteq left, right, target end,
+        macro (left, right, target) bdgteq left, right, target end,
+        _llint_slow_path_jgreatereq)
+
+
+_llint_op_jngreatereq:
+    traceExecution()
+    compare(
+        macro (left, right, target) bilt left, right, target end,
+        macro (left, right, target) bdltun left, right, target end,
+        _llint_slow_path_jngreatereq)
+
+
+_llint_op_loop_hint:
+    traceExecution()
+    checkSwitchToJITForLoop()
+    dispatch(1)
+
+
+_llint_op_switch_string:
+    traceExecution()
+    callSlowPath(_llint_slow_path_switch_string)
+    dispatch(0)
+
+
+_llint_op_new_func_exp:
+    traceExecution()
+    callSlowPath(_llint_slow_path_new_func_exp)
+    dispatch(3)
+
+
+_llint_op_call:
+    traceExecution()
+    doCall(_llint_slow_path_call)
+
+
+_llint_op_construct:
+    traceExecution()
+    doCall(_llint_slow_path_construct)
+
+
+_llint_op_call_varargs:
+    traceExecution()
+    slowPathForCall(6, _llint_slow_path_call_varargs)
+
+
+_llint_op_call_eval:
+    traceExecution()
+    
+    # Eval is executed in one of two modes:
+    #
+    # 1) We find that we're really invoking eval() in which case the
+    #    execution is perfomed entirely inside the slow_path, and it
+    #    returns the PC of a function that just returns the return value
+    #    that the eval returned.
+    #
+    # 2) We find that we're invoking something called eval() that is not
+    #    the real eval. Then the slow_path returns the PC of the thing to
+    #    call, and we call it.
+    #
+    # This allows us to handle two cases, which would require a total of
+    # up to four pieces of state that cannot be easily packed into two
+    # registers (C functions can return up to two registers, easily):
+    #
+    # - The call frame register. This may or may not have been modified
+    #   by the slow_path, but the convention is that it returns it. It's not
+    #   totally clear if that's necessary, since the cfr is callee save.
+    #   But that's our style in this here interpreter so we stick with it.
+    #
+    # - A bit to say if the slow_path successfully executed the eval and has
+    #   the return value, or did not execute the eval but has a PC for us
+    #   to call.
+    #
+    # - Either:
+    #   - The JS return value (two registers), or
+    #
+    #   - The PC to call.
+    #
+    # It turns out to be easier to just always have this return the cfr
+    # and a PC to call, and that PC may be a dummy thunk that just
+    # returns the JS value that the eval returned.
+    
+    slowPathForCall(4, _llint_slow_path_call_eval)
+
+
+_llint_generic_return_point:
+    dispatchAfterCall()
+
+
+_llint_op_strcat:
+    traceExecution()
+    callSlowPath(_llint_slow_path_strcat)
+    dispatch(4)
+
+
+_llint_op_method_check:
+    traceExecution()
+    # We ignore method checks and use normal get_by_id optimizations.
+    dispatch(1)
+
+
+_llint_op_get_pnames:
+    traceExecution()
+    callSlowPath(_llint_slow_path_get_pnames)
+    dispatch(0) # The slow_path either advances the PC or jumps us to somewhere else.
+
+
+_llint_op_push_scope:
+    traceExecution()
+    callSlowPath(_llint_slow_path_push_scope)
+    dispatch(2)
+
+
+_llint_op_pop_scope:
+    traceExecution()
+    callSlowPath(_llint_slow_path_pop_scope)
+    dispatch(1)
+
+
+_llint_op_push_new_scope:
+    traceExecution()
+    callSlowPath(_llint_slow_path_push_new_scope)
+    dispatch(4)
+
+
+_llint_op_throw:
+    traceExecution()
+    callSlowPath(_llint_slow_path_throw)
+    dispatch(2)
+
+
+_llint_op_throw_reference_error:
+    traceExecution()
+    callSlowPath(_llint_slow_path_throw_reference_error)
+    dispatch(2)
+
+
+_llint_op_profile_will_call:
+    traceExecution()
+    loadp JITStackFrame::enabledProfilerReference[sp], t0
+    btpz [t0], .opProfileWillCallDone
+    callSlowPath(_llint_slow_path_profile_will_call)
+.opProfileWillCallDone:
+    dispatch(2)
+
+
+_llint_op_profile_did_call:
+    traceExecution()
+    loadp JITStackFrame::enabledProfilerReference[sp], t0
+    btpz [t0], .opProfileWillCallDone
+    callSlowPath(_llint_slow_path_profile_did_call)
+.opProfileDidCallDone:
+    dispatch(2)
+
+
+_llint_op_debug:
+    traceExecution()
+    callSlowPath(_llint_slow_path_debug)
+    dispatch(4)
+
+
+_llint_native_call_trampoline:
+    nativeCallTrampoline(NativeExecutable::m_function)
+
+
+_llint_native_construct_trampoline:
+    nativeCallTrampoline(NativeExecutable::m_constructor)
+
+
+# Lastly, make sure that we can link even though we don't support all opcodes.
+# These opcodes should never arise when using LLInt or either JIT. We assert
+# as much.
+
+macro notSupported()
+    if ASSERT_ENABLED
+        crash()
+    else
+        # We should use whatever the smallest possible instruction is, just to
+        # ensure that there is a gap between instruction labels. If multiple
+        # smallest instructions exist, we should pick the one that is most
+        # likely result in execution being halted. Currently that is the break
+        # instruction on all architectures we're interested in. (Break is int3
+        # on Intel, which is 1 byte, and bkpt on ARMv7, which is 2 bytes.)
+        break
+    end
+end
+
+_llint_op_get_array_length:
+    notSupported()
+
+_llint_op_get_by_id_chain:
+    notSupported()
+
+_llint_op_get_by_id_custom_chain:
+    notSupported()
+
+_llint_op_get_by_id_custom_proto:
+    notSupported()
+
+_llint_op_get_by_id_custom_self:
+    notSupported()
+
+_llint_op_get_by_id_generic:
+    notSupported()
+
+_llint_op_get_by_id_getter_chain:
+    notSupported()
+
+_llint_op_get_by_id_getter_proto:
+    notSupported()
+
+_llint_op_get_by_id_getter_self:
+    notSupported()
+
+_llint_op_get_by_id_proto:
+    notSupported()
+
+_llint_op_get_by_id_self:
+    notSupported()
+
+_llint_op_get_string_length:
+    notSupported()
+
+_llint_op_put_by_id_generic:
+    notSupported()
+
+_llint_op_put_by_id_replace:
+    notSupported()
+
+_llint_op_put_by_id_transition:
+    notSupported()
+
+
+# Indicate the end of LLInt.
+_llint_end:
+    crash()
+
diff --git a/llint/LowLevelInterpreter.cpp b/llint/LowLevelInterpreter.cpp
new file mode 100644 (file)
index 0000000..b95a500
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "LowLevelInterpreter.h"
+
+#if ENABLE(LLINT)
+
+#include "LLIntOfflineAsmConfig.h"
+#include <wtf/InlineASM.h>
+
+// This is a file generated by offlineasm, which contains all of the assembly code
+// for the interpreter, as compiled from LowLevelInterpreter.asm.
+#include "LLIntAssembly.h"
+
+#endif // ENABLE(LLINT)
diff --git a/llint/LowLevelInterpreter.h b/llint/LowLevelInterpreter.h
new file mode 100644 (file)
index 0000000..6383757
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef LowLevelInterpreter_h
+#define LowLevelInterpreter_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(LLINT)
+
+#include "Opcode.h"
+
+#define LLINT_INSTRUCTION_DECL(opcode, length) extern "C" void llint_##opcode();
+    FOR_EACH_OPCODE_ID(LLINT_INSTRUCTION_DECL);
+#undef LLINT_INSTRUCTION_DECL
+
+extern "C" void llint_begin();
+extern "C" void llint_end();
+extern "C" void llint_program_prologue();
+extern "C" void llint_eval_prologue();
+extern "C" void llint_function_for_call_prologue();
+extern "C" void llint_function_for_construct_prologue();
+extern "C" void llint_function_for_call_arity_check();
+extern "C" void llint_function_for_construct_arity_check();
+extern "C" void llint_generic_return_point();
+extern "C" void llint_throw_from_slow_path_trampoline();
+extern "C" void llint_throw_during_call_trampoline();
+
+// Native call trampolines
+extern "C" void llint_native_call_trampoline();
+extern "C" void llint_native_construct_trampoline();
+
+#endif // ENABLE(LLINT)
+
+#endif // LowLevelInterpreter_h
diff --git a/llint/LowLevelInterpreter32_64.asm b/llint/LowLevelInterpreter32_64.asm
new file mode 100644 (file)
index 0000000..1a089bd
--- /dev/null
@@ -0,0 +1,1717 @@
+# Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. 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.
+
+
+# Crash course on the language that this is written in (which I just call
+# "assembly" even though it's more than that):
+#
+# - Mostly gas-style operand ordering. The last operand tends to be the
+#   destination. So "a := b" is written as "mov b, a". But unlike gas,
+#   comparisons are in-order, so "if (a < b)" is written as
+#   "bilt a, b, ...".
+#
+# - "b" = byte, "h" = 16-bit word, "i" = 32-bit word, "p" = pointer.
+#   Currently this is just 32-bit so "i" and "p" are interchangeable
+#   except when an op supports one but not the other.
+#
+# - In general, valid operands for macro invocations and instructions are
+#   registers (eg "t0"), addresses (eg "4[t0]"), base-index addresses
+#   (eg "7[t0, t1, 2]"), absolute addresses (eg "0xa0000000[]"), or labels
+#   (eg "_foo" or ".foo"). Macro invocations can also take anonymous
+#   macros as operands. Instructions cannot take anonymous macros.
+#
+# - Labels must have names that begin with either "_" or ".".  A "." label
+#   is local and gets renamed before code gen to minimize namespace
+#   pollution. A "_" label is an extern symbol (i.e. ".globl"). The "_"
+#   may or may not be removed during code gen depending on whether the asm
+#   conventions for C name mangling on the target platform mandate a "_"
+#   prefix.
+#
+# - A "macro" is a lambda expression, which may be either anonymous or
+#   named. But this has caveats. "macro" can take zero or more arguments,
+#   which may be macros or any valid operands, but it can only return
+#   code. But you can do Turing-complete things via continuation passing
+#   style: "macro foo (a, b) b(a) end foo(foo, foo)". Actually, don't do
+#   that, since you'll just crash the assembler.
+#
+# - An "if" is a conditional on settings. Any identifier supplied in the
+#   predicate of an "if" is assumed to be a #define that is available
+#   during code gen. So you can't use "if" for computation in a macro, but
+#   you can use it to select different pieces of code for different
+#   platforms.
+#
+# - Arguments to macros follow lexical scoping rather than dynamic scoping.
+#   Const's also follow lexical scoping and may override (hide) arguments
+#   or other consts. All variables (arguments and constants) can be bound
+#   to operands. Additionally, arguments (but not constants) can be bound
+#   to macros.
+
+
+# Below we have a bunch of constant declarations. Each constant must have
+# a corresponding ASSERT() in LLIntData.cpp.
+
+
+# Value representation constants.
+const Int32Tag = -1
+const BooleanTag = -2
+const NullTag = -3
+const UndefinedTag = -4
+const CellTag = -5
+const EmptyValueTag = -6
+const DeletedValueTag = -7
+const LowestTag = DeletedValueTag
+
+
+# Utilities
+macro dispatch(advance)
+    addp advance * 4, PC
+    jmp [PC]
+end
+
+macro dispatchBranchWithOffset(pcOffset)
+    lshifti 2, pcOffset
+    addp pcOffset, PC
+    jmp [PC]
+end
+
+macro dispatchBranch(pcOffset)
+    loadi pcOffset, t0
+    dispatchBranchWithOffset(t0)
+end
+
+macro dispatchAfterCall()
+    loadi ArgumentCount + TagOffset[cfr], PC
+    jmp [PC]
+end
+
+macro cCall2(function, arg1, arg2)
+    if ARMv7
+        move arg1, t0
+        move arg2, t1
+    elsif X86
+        poke arg1, 0
+        poke arg2, 1
+    else
+        error
+    end
+    call function
+end
+
+# This barely works. arg3 and arg4 should probably be immediates.
+macro cCall4(function, arg1, arg2, arg3, arg4)
+    if ARMv7
+        move arg1, t0
+        move arg2, t1
+        move arg3, t2
+        move arg4, t3
+    elsif X86
+        poke arg1, 0
+        poke arg2, 1
+        poke arg3, 2
+        poke arg4, 3
+    else
+        error
+    end
+    call function
+end
+
+macro callSlowPath(slowPath)
+    cCall2(slowPath, cfr, PC)
+    move t0, PC
+    move t1, cfr
+end
+
+# Debugging operation if you'd like to print an operand in the instruction stream. fromWhere
+# should be an immediate integer - any integer you like; use it to identify the place you're
+# debugging from. operand should likewise be an immediate, and should identify the operand
+# in the instruction stream you'd like to print out.
+macro traceOperand(fromWhere, operand)
+    cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
+    move t0, PC
+    move t1, cfr
+end
+
+# Debugging operation if you'd like to print the value of an operand in the instruction
+# stream. Same as traceOperand(), but assumes that the operand is a register, and prints its
+# value.
+macro traceValue(fromWhere, operand)
+    cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
+    move t0, PC
+    move t1, cfr
+end
+
+# Call a slowPath for call opcodes.
+macro callCallSlowPath(advance, slowPath, action)
+    addp advance * 4, PC, t0
+    storep t0, ArgumentCount + TagOffset[cfr]
+    cCall2(slowPath, cfr, PC)
+    move t1, cfr
+    action(t0)
+end
+
+macro checkSwitchToJITForLoop()
+    checkSwitchToJIT(
+        1,
+        macro ()
+            storei PC, ArgumentCount + TagOffset[cfr]
+            cCall2(_llint_loop_osr, cfr, PC)
+            move t1, cfr
+            btpz t0, .recover
+            jmp t0
+        .recover:
+            loadi ArgumentCount + TagOffset[cfr], PC
+        end)
+end
+
+# Index, tag, and payload must be different registers. Index is not
+# changed.
+macro loadConstantOrVariable(index, tag, payload)
+    bigteq index, FirstConstantRegisterIndex, .constant
+    loadi TagOffset[cfr, index, 8], tag
+    loadi PayloadOffset[cfr, index, 8], payload
+    jmp .done
+.constant:
+    loadp CodeBlock[cfr], payload
+    loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
+    # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
+    # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
+    loadp TagOffset[payload, index, 8], tag
+    loadp PayloadOffset[payload, index, 8], payload
+.done:
+end
+
+macro loadConstantOrVariableTag(index, tag)
+    bigteq index, FirstConstantRegisterIndex, .constant
+    loadi TagOffset[cfr, index, 8], tag
+    jmp .done
+.constant:
+    loadp CodeBlock[cfr], tag
+    loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag
+    # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
+    # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
+    loadp TagOffset[tag, index, 8], tag
+.done:
+end
+
+# Index and payload may be the same register. Index may be clobbered.
+macro loadConstantOrVariable2Reg(index, tag, payload)
+    bigteq index, FirstConstantRegisterIndex, .constant
+    loadi TagOffset[cfr, index, 8], tag
+    loadi PayloadOffset[cfr, index, 8], payload
+    jmp .done
+.constant:
+    loadp CodeBlock[cfr], tag
+    loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag
+    # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
+    # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
+    lshifti 3, index
+    addp index, tag
+    loadp PayloadOffset[tag], payload
+    loadp TagOffset[tag], tag
+.done:
+end
+
+macro loadConstantOrVariablePayloadTagCustom(index, tagCheck, payload)
+    bigteq index, FirstConstantRegisterIndex, .constant
+    tagCheck(TagOffset[cfr, index, 8])
+    loadi PayloadOffset[cfr, index, 8], payload
+    jmp .done
+.constant:
+    loadp CodeBlock[cfr], payload
+    loadp CodeBlock::m_constantRegisters + VectorBufferOffset[payload], payload
+    # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex,
+    # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3.
+    tagCheck(TagOffset[payload, index, 8])
+    loadp PayloadOffset[payload, index, 8], payload
+.done:
+end
+
+# Index and payload must be different registers. Index is not mutated. Use
+# this if you know what the tag of the variable should be. Doing the tag
+# test as part of loading the variable reduces register use, but may not
+# be faster than doing loadConstantOrVariable followed by a branch on the
+# tag.
+macro loadConstantOrVariablePayload(index, expectedTag, payload, slow)
+    loadConstantOrVariablePayloadTagCustom(
+        index,
+        macro (actualTag) bineq actualTag, expectedTag, slow end,
+        payload)
+end
+
+macro loadConstantOrVariablePayloadUnchecked(index, payload)
+    loadConstantOrVariablePayloadTagCustom(
+        index,
+        macro (actualTag) end,
+        payload)
+end
+
+macro writeBarrier(tag, payload)
+    # Nothing to do, since we don't have a generational or incremental collector.
+end
+
+macro valueProfile(tag, payload, profile)
+    if VALUE_PROFILER
+        storei tag, ValueProfile::m_buckets + TagOffset[profile]
+        storei payload, ValueProfile::m_buckets + PayloadOffset[profile]
+    end
+end
+
+
+# Entrypoints into the interpreter
+
+# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
+macro functionArityCheck(doneLabel, slow_path)
+    loadi PayloadOffset + ArgumentCount[cfr], t0
+    biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
+    cCall2(slow_path, cfr, PC)   # This slow_path has a simple protocol: t0 = 0 => no error, t0 != 0 => error
+    move t1, cfr
+    btiz t0, .continue
+    loadp JITStackFrame::globalData[sp], t1
+    loadp JSGlobalData::callFrameForThrow[t1], t0
+    jmp JSGlobalData::targetMachinePCForThrow[t1]
+.continue:
+    # Reload CodeBlock and PC, since the slow_path clobbered it.
+    loadp CodeBlock[cfr], t1
+    loadp CodeBlock::m_instructions[t1], PC
+    jmp doneLabel
+end
+
+
+# Instruction implementations
+
+_llint_op_enter:
+    traceExecution()
+    loadp CodeBlock[cfr], t2
+    loadi CodeBlock::m_numVars[t2], t2
+    btiz t2, .opEnterDone
+    move UndefinedTag, t0
+    move 0, t1
+.opEnterLoop:
+    subi 1, t2
+    storei t0, TagOffset[cfr, t2, 8]
+    storei t1, PayloadOffset[cfr, t2, 8]
+    btinz t2, .opEnterLoop
+.opEnterDone:
+    dispatch(1)
+
+
+_llint_op_create_activation:
+    traceExecution()
+    loadi 4[PC], t0
+    bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateActivationDone
+    callSlowPath(_llint_slow_path_create_activation)
+.opCreateActivationDone:
+    dispatch(2)
+
+
+_llint_op_init_lazy_reg:
+    traceExecution()
+    loadi 4[PC], t0
+    storei EmptyValueTag, TagOffset[cfr, t0, 8]
+    storei 0, PayloadOffset[cfr, t0, 8]
+    dispatch(2)
+
+
+_llint_op_create_arguments:
+    traceExecution()
+    loadi 4[PC], t0
+    bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opCreateArgumentsDone
+    callSlowPath(_llint_slow_path_create_arguments)
+.opCreateArgumentsDone:
+    dispatch(2)
+
+
+_llint_op_create_this:
+    traceExecution()
+    loadi 8[PC], t0
+    assertNotConstant(t0)
+    bineq TagOffset[cfr, t0, 8], CellTag, .opCreateThisSlow
+    loadi PayloadOffset[cfr, t0, 8], t0
+    loadp JSCell::m_structure[t0], t1
+    bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
+    loadp JSObject::m_inheritorID[t0], t2
+    btpz t2, .opCreateThisSlow
+    allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
+    loadi 4[PC], t1
+    storei CellTag, TagOffset[cfr, t1, 8]
+    storei t0, PayloadOffset[cfr, t1, 8]
+    dispatch(3)
+
+.opCreateThisSlow:
+    callSlowPath(_llint_slow_path_create_this)
+    dispatch(3)
+
+
+_llint_op_get_callee:
+    traceExecution()
+    loadi 4[PC], t0
+    loadp PayloadOffset + Callee[cfr], t1
+    storei CellTag, TagOffset[cfr, t0, 8]
+    storei t1, PayloadOffset[cfr, t0, 8]
+    dispatch(2)
+
+
+_llint_op_convert_this:
+    traceExecution()
+    loadi 4[PC], t0
+    bineq TagOffset[cfr, t0, 8], CellTag, .opConvertThisSlow
+    loadi PayloadOffset[cfr, t0, 8], t0
+    loadp JSCell::m_structure[t0], t0
+    bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
+    dispatch(2)
+
+.opConvertThisSlow:
+    callSlowPath(_llint_slow_path_convert_this)
+    dispatch(2)
+
+
+_llint_op_new_object:
+    traceExecution()
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_globalObject[t0], t0
+    loadp JSGlobalObject::m_emptyObjectStructure[t0], t1
+    allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t1, t0, t2, t3, .opNewObjectSlow)
+    loadi 4[PC], t1
+    storei CellTag, TagOffset[cfr, t1, 8]
+    storei t0, PayloadOffset[cfr, t1, 8]
+    dispatch(2)
+
+.opNewObjectSlow:
+    callSlowPath(_llint_slow_path_new_object)
+    dispatch(2)
+
+
+_llint_op_mov:
+    traceExecution()
+    loadi 8[PC], t1
+    loadi 4[PC], t0
+    loadConstantOrVariable(t1, t2, t3)
+    storei t2, TagOffset[cfr, t0, 8]
+    storei t3, PayloadOffset[cfr, t0, 8]
+    dispatch(3)
+
+
+_llint_op_not:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t1
+    loadConstantOrVariable(t0, t2, t3)
+    bineq t2, BooleanTag, .opNotSlow
+    xori 1, t3
+    storei t2, TagOffset[cfr, t1, 8]
+    storei t3, PayloadOffset[cfr, t1, 8]
+    dispatch(3)
+
+.opNotSlow:
+    callSlowPath(_llint_slow_path_not)
+    dispatch(3)
+
+
+_llint_op_eq:
+    traceExecution()
+    loadi 12[PC], t2
+    loadi 8[PC], t0
+    loadConstantOrVariable(t2, t3, t1)
+    loadConstantOrVariable2Reg(t0, t2, t0)
+    bineq t2, t3, .opEqSlow
+    bieq t2, CellTag, .opEqSlow
+    bib t2, LowestTag, .opEqSlow
+    loadi 4[PC], t2
+    cieq t0, t1, t0
+    storei BooleanTag, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    dispatch(4)
+
+.opEqSlow:
+    callSlowPath(_llint_slow_path_eq)
+    dispatch(4)
+
+
+_llint_op_eq_null:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t3
+    assertNotConstant(t0)
+    loadi TagOffset[cfr, t0, 8], t1
+    loadi PayloadOffset[cfr, t0, 8], t0
+    bineq t1, CellTag, .opEqNullImmediate
+    loadp JSCell::m_structure[t0], t1
+    tbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1
+    jmp .opEqNullNotImmediate
+.opEqNullImmediate:
+    cieq t1, NullTag, t2
+    cieq t1, UndefinedTag, t1
+    ori t2, t1
+.opEqNullNotImmediate:
+    storei BooleanTag, TagOffset[cfr, t3, 8]
+    storei t1, PayloadOffset[cfr, t3, 8]
+    dispatch(3)
+
+
+_llint_op_neq:
+    traceExecution()
+    loadi 12[PC], t2
+    loadi 8[PC], t0
+    loadConstantOrVariable(t2, t3, t1)
+    loadConstantOrVariable2Reg(t0, t2, t0)
+    bineq t2, t3, .opNeqSlow
+    bieq t2, CellTag, .opNeqSlow
+    bib t2, LowestTag, .opNeqSlow
+    loadi 4[PC], t2
+    cineq t0, t1, t0
+    storei BooleanTag, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    dispatch(4)
+
+.opNeqSlow:
+    callSlowPath(_llint_slow_path_neq)
+    dispatch(4)
+    
+
+_llint_op_neq_null:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t3
+    assertNotConstant(t0)
+    loadi TagOffset[cfr, t0, 8], t1
+    loadi PayloadOffset[cfr, t0, 8], t0
+    bineq t1, CellTag, .opNeqNullImmediate
+    loadp JSCell::m_structure[t0], t1
+    tbz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1
+    jmp .opNeqNullNotImmediate
+.opNeqNullImmediate:
+    cineq t1, NullTag, t2
+    cineq t1, UndefinedTag, t1
+    andi t2, t1
+.opNeqNullNotImmediate:
+    storei BooleanTag, TagOffset[cfr, t3, 8]
+    storei t1, PayloadOffset[cfr, t3, 8]
+    dispatch(3)
+
+
+macro strictEq(equalityOperation, slowPath)
+    loadi 12[PC], t2
+    loadi 8[PC], t0
+    loadConstantOrVariable(t2, t3, t1)
+    loadConstantOrVariable2Reg(t0, t2, t0)
+    bineq t2, t3, .slow
+    bib t2, LowestTag, .slow
+    bineq t2, CellTag, .notString
+    loadp JSCell::m_structure[t0], t2
+    loadp JSCell::m_structure[t1], t3
+    bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .notString
+    bbeq Structure::m_typeInfo + TypeInfo::m_type[t3], StringType, .slow
+.notString:
+    loadi 4[PC], t2
+    equalityOperation(t0, t1, t0)
+    storei BooleanTag, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    dispatch(4)
+
+.slow:
+    callSlowPath(slowPath)
+    dispatch(4)
+end
+
+_llint_op_stricteq:
+    traceExecution()
+    strictEq(macro (left, right, result) cieq left, right, result end, _llint_slow_path_stricteq)
+
+
+_llint_op_nstricteq:
+    traceExecution()
+    strictEq(macro (left, right, result) cineq left, right, result end, _llint_slow_path_nstricteq)
+
+
+_llint_op_pre_inc:
+    traceExecution()
+    loadi 4[PC], t0
+    bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreIncSlow
+    loadi PayloadOffset[cfr, t0, 8], t1
+    baddio 1, t1, .opPreIncSlow
+    storei t1, PayloadOffset[cfr, t0, 8]
+    dispatch(2)
+
+.opPreIncSlow:
+    callSlowPath(_llint_slow_path_pre_inc)
+    dispatch(2)
+
+
+_llint_op_pre_dec:
+    traceExecution()
+    loadi 4[PC], t0
+    bineq TagOffset[cfr, t0, 8], Int32Tag, .opPreDecSlow
+    loadi PayloadOffset[cfr, t0, 8], t1
+    bsubio 1, t1, .opPreDecSlow
+    storei t1, PayloadOffset[cfr, t0, 8]
+    dispatch(2)
+
+.opPreDecSlow:
+    callSlowPath(_llint_slow_path_pre_dec)
+    dispatch(2)
+
+
+_llint_op_post_inc:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t1
+    bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostIncSlow
+    bieq t0, t1, .opPostIncDone
+    loadi PayloadOffset[cfr, t0, 8], t2
+    move t2, t3
+    baddio 1, t3, .opPostIncSlow
+    storei Int32Tag, TagOffset[cfr, t1, 8]
+    storei t2, PayloadOffset[cfr, t1, 8]
+    storei t3, PayloadOffset[cfr, t0, 8]
+.opPostIncDone:
+    dispatch(3)
+
+.opPostIncSlow:
+    callSlowPath(_llint_slow_path_post_inc)
+    dispatch(3)
+
+
+_llint_op_post_dec:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t1
+    bineq TagOffset[cfr, t0, 8], Int32Tag, .opPostDecSlow
+    bieq t0, t1, .opPostDecDone
+    loadi PayloadOffset[cfr, t0, 8], t2
+    move t2, t3
+    bsubio 1, t3, .opPostDecSlow
+    storei Int32Tag, TagOffset[cfr, t1, 8]
+    storei t2, PayloadOffset[cfr, t1, 8]
+    storei t3, PayloadOffset[cfr, t0, 8]
+.opPostDecDone:
+    dispatch(3)
+
+.opPostDecSlow:
+    callSlowPath(_llint_slow_path_post_dec)
+    dispatch(3)
+
+
+_llint_op_to_jsnumber:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t1
+    loadConstantOrVariable(t0, t2, t3)
+    bieq t2, Int32Tag, .opToJsnumberIsInt
+    biaeq t2, EmptyValueTag, .opToJsnumberSlow
+.opToJsnumberIsInt:
+    storei t2, TagOffset[cfr, t1, 8]
+    storei t3, PayloadOffset[cfr, t1, 8]
+    dispatch(3)
+
+.opToJsnumberSlow:
+    callSlowPath(_llint_slow_path_to_jsnumber)
+    dispatch(3)
+
+
+_llint_op_negate:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t3
+    loadConstantOrVariable(t0, t1, t2)
+    bineq t1, Int32Tag, .opNegateSrcNotInt
+    btiz t2, 0x7fffffff, .opNegateSlow
+    negi t2
+    storei Int32Tag, TagOffset[cfr, t3, 8]
+    storei t2, PayloadOffset[cfr, t3, 8]
+    dispatch(3)
+.opNegateSrcNotInt:
+    bia t1, LowestTag, .opNegateSlow
+    xori 0x80000000, t1
+    storei t1, TagOffset[cfr, t3, 8]
+    storei t2, PayloadOffset[cfr, t3, 8]
+    dispatch(3)
+
+.opNegateSlow:
+    callSlowPath(_llint_slow_path_negate)
+    dispatch(3)
+
+
+macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath)
+    loadi 12[PC], t2
+    loadi 8[PC], t0
+    loadConstantOrVariable(t2, t3, t1)
+    loadConstantOrVariable2Reg(t0, t2, t0)
+    bineq t2, Int32Tag, .op1NotInt
+    bineq t3, Int32Tag, .op2NotInt
+    loadi 4[PC], t2
+    integerOperationAndStore(t3, t1, t0, .slow, t2)
+    dispatch(5)
+
+.op1NotInt:
+    # First operand is definitely not an int, the second operand could be anything.
+    bia t2, LowestTag, .slow
+    bib t3, LowestTag, .op1NotIntOp2Double
+    bineq t3, Int32Tag, .slow
+    ci2d t1, ft1
+    jmp .op1NotIntReady
+.op1NotIntOp2Double:
+    fii2d t1, t3, ft1
+.op1NotIntReady:
+    loadi 4[PC], t1
+    fii2d t0, t2, ft0
+    doubleOperation(ft1, ft0)
+    stored ft0, [cfr, t1, 8]
+    dispatch(5)
+
+.op2NotInt:
+    # First operand is definitely an int, the second operand is definitely not.
+    loadi 4[PC], t2
+    bia t3, LowestTag, .slow
+    ci2d t0, ft0
+    fii2d t1, t3, ft1
+    doubleOperation(ft1, ft0)
+    stored ft0, [cfr, t2, 8]
+    dispatch(5)
+
+.slow:
+    callSlowPath(slowPath)
+    dispatch(5)
+end
+
+macro binaryOp(integerOperation, doubleOperation, slowPath)
+    binaryOpCustomStore(
+        macro (int32Tag, left, right, slow, index)
+            integerOperation(left, right, slow)
+            storei int32Tag, TagOffset[cfr, index, 8]
+            storei right, PayloadOffset[cfr, index, 8]
+        end,
+        doubleOperation, slowPath)
+end
+
+_llint_op_add:
+    traceExecution()
+    binaryOp(
+        macro (left, right, slow) baddio left, right, slow end,
+        macro (left, right) addd left, right end,
+        _llint_slow_path_add)
+
+
+_llint_op_mul:
+    traceExecution()
+    binaryOpCustomStore(
+        macro (int32Tag, left, right, slow, index)
+            const scratch = int32Tag   # We know that we can reuse the int32Tag register since it has a constant.
+            move right, scratch
+            bmulio left, scratch, slow
+            btinz scratch, .done
+            bilt left, 0, slow
+            bilt right, 0, slow
+        .done:
+            storei Int32Tag, TagOffset[cfr, index, 8]
+            storei scratch, PayloadOffset[cfr, index, 8]
+        end,
+        macro (left, right) muld left, right end,
+        _llint_slow_path_mul)
+
+
+_llint_op_sub:
+    traceExecution()
+    binaryOp(
+        macro (left, right, slow) bsubio left, right, slow end,
+        macro (left, right) subd left, right end,
+        _llint_slow_path_sub)
+
+
+_llint_op_div:
+    traceExecution()
+    binaryOpCustomStore(
+        macro (int32Tag, left, right, slow, index)
+            ci2d left, ft0
+            ci2d right, ft1
+            divd ft0, ft1
+            bcd2i ft1, right, .notInt
+            storei int32Tag, TagOffset[cfr, index, 8]
+            storei right, PayloadOffset[cfr, index, 8]
+            jmp .done
+        .notInt:
+            stored ft1, [cfr, index, 8]
+        .done:
+        end,
+        macro (left, right) divd left, right end,
+        _llint_slow_path_div)
+
+
+macro bitOp(operation, slowPath, advance)
+    loadi 12[PC], t2
+    loadi 8[PC], t0
+    loadConstantOrVariable(t2, t3, t1)
+    loadConstantOrVariable2Reg(t0, t2, t0)
+    bineq t3, Int32Tag, .slow
+    bineq t2, Int32Tag, .slow
+    loadi 4[PC], t2
+    operation(t1, t0, .slow)
+    storei t3, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    dispatch(advance)
+
+.slow:
+    callSlowPath(slowPath)
+    dispatch(advance)
+end
+
+_llint_op_lshift:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) lshifti left, right end,
+        _llint_slow_path_lshift,
+        4)
+
+
+_llint_op_rshift:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) rshifti left, right end,
+        _llint_slow_path_rshift,
+        4)
+
+
+_llint_op_urshift:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow)
+            urshifti left, right
+            bilt right, 0, slow
+        end,
+        _llint_slow_path_urshift,
+        4)
+
+
+_llint_op_bitand:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) andi left, right end,
+        _llint_slow_path_bitand,
+        5)
+
+
+_llint_op_bitxor:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) xori left, right end,
+        _llint_slow_path_bitxor,
+        5)
+
+
+_llint_op_bitor:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) ori left, right end,
+        _llint_slow_path_bitor,
+        5)
+
+
+_llint_op_check_has_instance:
+    traceExecution()
+    loadi 4[PC], t1
+    loadConstantOrVariablePayload(t1, CellTag, t0, .opCheckHasInstanceSlow)
+    loadp JSCell::m_structure[t0], t0
+    btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsHasInstance, .opCheckHasInstanceSlow
+    dispatch(2)
+
+.opCheckHasInstanceSlow:
+    callSlowPath(_llint_slow_path_check_has_instance)
+    dispatch(2)
+
+
+_llint_op_instanceof:
+    traceExecution()
+    # Check that baseVal implements the default HasInstance behavior.
+    # FIXME: This should be deprecated.
+    loadi 12[PC], t1
+    loadConstantOrVariablePayloadUnchecked(t1, t0)
+    loadp JSCell::m_structure[t0], t0
+    btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsDefaultHasInstance, .opInstanceofSlow
+    
+    # Actually do the work.
+    loadi 16[PC], t0
+    loadi 4[PC], t3
+    loadConstantOrVariablePayload(t0, CellTag, t1, .opInstanceofSlow)
+    loadp JSCell::m_structure[t1], t2
+    bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opInstanceofSlow
+    loadi 8[PC], t0
+    loadConstantOrVariablePayload(t0, CellTag, t2, .opInstanceofSlow)
+    
+    # Register state: t1 = prototype, t2 = value
+    move 1, t0
+.opInstanceofLoop:
+    loadp JSCell::m_structure[t2], t2
+    loadi Structure::m_prototype + PayloadOffset[t2], t2
+    bpeq t2, t1, .opInstanceofDone
+    btinz t2, .opInstanceofLoop
+
+    move 0, t0
+.opInstanceofDone:
+    storei BooleanTag, TagOffset[cfr, t3, 8]
+    storei t0, PayloadOffset[cfr, t3, 8]
+    dispatch(5)
+
+.opInstanceofSlow:
+    callSlowPath(_llint_slow_path_instanceof)
+    dispatch(5)
+
+
+_llint_op_is_undefined:
+    traceExecution()
+    loadi 8[PC], t1
+    loadi 4[PC], t0
+    loadConstantOrVariable(t1, t2, t3)
+    storei BooleanTag, TagOffset[cfr, t0, 8]
+    bieq t2, CellTag, .opIsUndefinedCell
+    cieq t2, UndefinedTag, t3
+    storei t3, PayloadOffset[cfr, t0, 8]
+    dispatch(3)
+.opIsUndefinedCell:
+    loadp JSCell::m_structure[t3], t1
+    tbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1
+    storei t1, PayloadOffset[cfr, t0, 8]
+    dispatch(3)
+
+
+_llint_op_is_boolean:
+    traceExecution()
+    loadi 8[PC], t1
+    loadi 4[PC], t2
+    loadConstantOrVariableTag(t1, t0)
+    cieq t0, BooleanTag, t0
+    storei BooleanTag, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    dispatch(3)
+
+
+_llint_op_is_number:
+    traceExecution()
+    loadi 8[PC], t1
+    loadi 4[PC], t2
+    loadConstantOrVariableTag(t1, t0)
+    storei BooleanTag, TagOffset[cfr, t2, 8]
+    addi 1, t0
+    cib t0, LowestTag + 1, t1
+    storei t1, PayloadOffset[cfr, t2, 8]
+    dispatch(3)
+
+
+_llint_op_is_string:
+    traceExecution()
+    loadi 8[PC], t1
+    loadi 4[PC], t2
+    loadConstantOrVariable(t1, t0, t3)
+    storei BooleanTag, TagOffset[cfr, t2, 8]
+    bineq t0, CellTag, .opIsStringNotCell
+    loadp JSCell::m_structure[t3], t0
+    cbeq Structure::m_typeInfo + TypeInfo::m_type[t0], StringType, t1
+    storei t1, PayloadOffset[cfr, t2, 8]
+    dispatch(3)
+.opIsStringNotCell:
+    storep 0, PayloadOffset[cfr, t2, 8]
+    dispatch(3)
+
+
+macro resolveGlobal(size, slow)
+    # Operands are as follows:
+    # 4[PC]   Destination for the load.
+    # 8[PC]   Property identifier index in the code block.
+    # 12[PC]  Structure pointer, initialized to 0 by bytecode generator.
+    # 16[PC]  Offset in global object, initialized to 0 by bytecode generator.
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_globalObject[t0], t0
+    loadp JSCell::m_structure[t0], t1
+    bpneq t1, 12[PC], slow
+    loadi 16[PC], t1
+    loadp JSObject::m_propertyStorage[t0], t0
+    loadi TagOffset[t0, t1, 8], t2
+    loadi PayloadOffset[t0, t1, 8], t3
+    loadi 4[PC], t0
+    storei t2, TagOffset[cfr, t0, 8]
+    storei t3, PayloadOffset[cfr, t0, 8]
+    loadi (size - 1) * 4[PC], t0
+    valueProfile(t2, t3, t0)
+end
+
+_llint_op_resolve_global:
+    traceExecution()
+    resolveGlobal(6, .opResolveGlobalSlow)
+    dispatch(6)
+
+.opResolveGlobalSlow:
+    callSlowPath(_llint_slow_path_resolve_global)
+    dispatch(6)
+
+
+# Gives you the scope in t0, while allowing you to optionally perform additional checks on the
+# scopes as they are traversed. scopeCheck() is called with two arguments: the register
+# holding the scope, and a register that can be used for scratch. Note that this does not
+# use t3, so you can hold stuff in t3 if need be.
+macro getScope(deBruijinIndexOperand, scopeCheck)
+    loadp ScopeChain + PayloadOffset[cfr], t0
+    loadi deBruijinIndexOperand, t2
+    
+    btiz t2, .done
+    
+    loadp CodeBlock[cfr], t1
+    bineq CodeBlock::m_codeType[t1], FunctionCode, .loop
+    btbz CodeBlock::m_needsFullScopeChain[t1], .loop
+    
+    loadi CodeBlock::m_activationRegister[t1], t1
+
+    # Need to conditionally skip over one scope.
+    bieq TagOffset[cfr, t1, 8], EmptyValueTag, .noActivation
+    scopeCheck(t0, t1)
+    loadp ScopeChainNode::next[t0], t0
+.noActivation:
+    subi 1, t2
+    
+    btiz t2, .done
+.loop:
+    scopeCheck(t0, t1)
+    loadp ScopeChainNode::next[t0], t0
+    subi 1, t2
+    btinz t2, .loop
+
+.done:
+end
+
+_llint_op_resolve_global_dynamic:
+    traceExecution()
+    loadp JITStackFrame::globalData[sp], t3
+    loadp JSGlobalData::activationStructure[t3], t3
+    getScope(
+        20[PC],
+        macro (scope, scratch)
+            loadp ScopeChainNode::object[scope], scratch
+            bpneq JSCell::m_structure[scratch], t3, .opResolveGlobalDynamicSuperSlow
+        end)
+    resolveGlobal(7, .opResolveGlobalDynamicSlow)
+    dispatch(7)
+
+.opResolveGlobalDynamicSuperSlow:
+    callSlowPath(_llint_slow_path_resolve_for_resolve_global_dynamic)
+    dispatch(7)
+
+.opResolveGlobalDynamicSlow:
+    callSlowPath(_llint_slow_path_resolve_global_dynamic)
+    dispatch(7)
+
+
+_llint_op_get_scoped_var:
+    traceExecution()
+    # Operands are as follows:
+    # 4[PC]   Destination for the load.
+    # 8[PC]   Index of register in the scope.
+    # 12[PC]  De Bruijin index.
+    getScope(12[PC], macro (scope, scratch) end)
+    loadi 4[PC], t1
+    loadi 8[PC], t2
+    loadp ScopeChainNode::object[t0], t0
+    loadp JSVariableObject::m_registers[t0], t0
+    loadi TagOffset[t0, t2, 8], t3
+    loadi PayloadOffset[t0, t2, 8], t0
+    storei t3, TagOffset[cfr, t1, 8]
+    storei t0, PayloadOffset[cfr, t1, 8]
+    loadi 16[PC], t1
+    valueProfile(t3, t0, t1)
+    dispatch(5)
+
+
+_llint_op_put_scoped_var:
+    traceExecution()
+    getScope(8[PC], macro (scope, scratch) end)
+    loadi 12[PC], t1
+    loadConstantOrVariable(t1, t3, t2)
+    loadi 4[PC], t1
+    writeBarrier(t3, t2)
+    loadp ScopeChainNode::object[t0], t0
+    loadp JSVariableObject::m_registers[t0], t0
+    storei t3, TagOffset[t0, t1, 8]
+    storei t2, PayloadOffset[t0, t1, 8]
+    dispatch(4)
+
+
+_llint_op_get_global_var:
+    traceExecution()
+    loadi 8[PC], t1
+    loadi 4[PC], t3
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_globalObject[t0], t0
+    loadp JSGlobalObject::m_registers[t0], t0
+    loadi TagOffset[t0, t1, 8], t2
+    loadi PayloadOffset[t0, t1, 8], t1
+    storei t2, TagOffset[cfr, t3, 8]
+    storei t1, PayloadOffset[cfr, t3, 8]
+    loadi 12[PC], t3
+    valueProfile(t2, t1, t3)
+    dispatch(4)
+
+
+_llint_op_put_global_var:
+    traceExecution()
+    loadi 8[PC], t1
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_globalObject[t0], t0
+    loadp JSGlobalObject::m_registers[t0], t0
+    loadConstantOrVariable(t1, t2, t3)
+    loadi 4[PC], t1
+    writeBarrier(t2, t3)
+    storei t2, TagOffset[t0, t1, 8]
+    storei t3, PayloadOffset[t0, t1, 8]
+    dispatch(3)
+
+
+_llint_op_get_by_id:
+    traceExecution()
+    # We only do monomorphic get_by_id caching for now, and we do not modify the
+    # opcode. We do, however, allow for the cache to change anytime if fails, since
+    # ping-ponging is free. At best we get lucky and the get_by_id will continue
+    # to take fast path on the new cache. At worst we take slow path, which is what
+    # we would have been doing anyway.
+    loadi 8[PC], t0
+    loadi 16[PC], t1
+    loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow)
+    loadi 20[PC], t2
+    loadp JSObject::m_propertyStorage[t3], t0
+    bpneq JSCell::m_structure[t3], t1, .opGetByIdSlow
+    loadi 4[PC], t1
+    loadi TagOffset[t0, t2], t3
+    loadi PayloadOffset[t0, t2], t2
+    storei t3, TagOffset[cfr, t1, 8]
+    storei t2, PayloadOffset[cfr, t1, 8]
+    loadi 32[PC], t1
+    valueProfile(t3, t2, t1)
+    dispatch(9)
+
+.opGetByIdSlow:
+    callSlowPath(_llint_slow_path_get_by_id)
+    dispatch(9)
+
+
+_llint_op_get_arguments_length:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 4[PC], t1
+    bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentsLengthSlow
+    loadi ArgumentCount + PayloadOffset[cfr], t2
+    subi 1, t2
+    storei Int32Tag, TagOffset[cfr, t1, 8]
+    storei t2, PayloadOffset[cfr, t1, 8]
+    dispatch(4)
+
+.opGetArgumentsLengthSlow:
+    callSlowPath(_llint_slow_path_get_arguments_length)
+    dispatch(4)
+
+
+_llint_op_put_by_id:
+    traceExecution()
+    loadi 4[PC], t3
+    loadi 16[PC], t1
+    loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
+    loadi 12[PC], t2
+    loadp JSObject::m_propertyStorage[t0], t3
+    bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
+    loadi 20[PC], t1
+    loadConstantOrVariable2Reg(t2, t0, t2)
+    writeBarrier(t0, t2)
+    storei t0, TagOffset[t3, t1]
+    storei t2, PayloadOffset[t3, t1]
+    dispatch(9)
+
+.opPutByIdSlow:
+    callSlowPath(_llint_slow_path_put_by_id)
+    dispatch(9)
+
+
+macro putByIdTransition(additionalChecks)
+    traceExecution()
+    loadi 4[PC], t3
+    loadi 16[PC], t1
+    loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
+    loadi 12[PC], t2
+    bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
+    additionalChecks(t1, t3, .opPutByIdSlow)
+    loadi 20[PC], t1
+    loadp JSObject::m_propertyStorage[t0], t3
+    addp t1, t3
+    loadConstantOrVariable2Reg(t2, t1, t2)
+    writeBarrier(t1, t2)
+    storei t1, TagOffset[t3]
+    loadi 24[PC], t1
+    storei t2, PayloadOffset[t3]
+    storep t1, JSCell::m_structure[t0]
+    dispatch(9)
+end
+
+_llint_op_put_by_id_transition_direct:
+    putByIdTransition(macro (oldStructure, scratch, slow) end)
+
+
+_llint_op_put_by_id_transition_normal:
+    putByIdTransition(
+        macro (oldStructure, scratch, slow)
+            const protoCell = oldStructure   # Reusing the oldStructure register for the proto
+        
+            loadp 28[PC], scratch
+            assert(macro (ok) btpnz scratch, ok end)
+            loadp StructureChain::m_vector[scratch], scratch
+            assert(macro (ok) btpnz scratch, ok end)
+            bieq Structure::m_prototype + TagOffset[oldStructure], NullTag, .done
+        .loop:
+            loadi Structure::m_prototype + PayloadOffset[oldStructure], protoCell
+            loadp JSCell::m_structure[protoCell], oldStructure
+            bpneq oldStructure, [scratch], slow
+            addp 4, scratch
+            bineq Structure::m_prototype + TagOffset[oldStructure], NullTag, .loop
+        .done:
+        end)
+
+
+_llint_op_get_by_val:
+    traceExecution()
+    loadp CodeBlock[cfr], t1
+    loadi 8[PC], t2
+    loadi 12[PC], t3
+    loadp CodeBlock::m_globalData[t1], t1
+    loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow)
+    loadp JSGlobalData::jsArrayClassInfo[t1], t2
+    loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow)
+    bpneq [t0], t2, .opGetByValSlow
+    loadp JSArray::m_storage[t0], t3
+    biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow
+    loadi 4[PC], t0
+    loadi ArrayStorage::m_vector + TagOffset[t3, t1, 8], t2
+    loadi ArrayStorage::m_vector + PayloadOffset[t3, t1, 8], t1
+    bieq t2, EmptyValueTag, .opGetByValSlow
+    storei t2, TagOffset[cfr, t0, 8]
+    storei t1, PayloadOffset[cfr, t0, 8]
+    loadi 16[PC], t0
+    valueProfile(t2, t1, t0)
+    dispatch(5)
+
+.opGetByValSlow:
+    callSlowPath(_llint_slow_path_get_by_val)
+    dispatch(5)
+
+
+_llint_op_get_argument_by_val:
+    traceExecution()
+    loadi 8[PC], t0
+    loadi 12[PC], t1
+    bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opGetArgumentByValSlow
+    loadConstantOrVariablePayload(t1, Int32Tag, t2, .opGetArgumentByValSlow)
+    addi 1, t2
+    loadi ArgumentCount + PayloadOffset[cfr], t1
+    biaeq t2, t1, .opGetArgumentByValSlow
+    negi t2
+    loadi 4[PC], t3
+    loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0
+    loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t1
+    storei t0, TagOffset[cfr, t3, 8]
+    storei t1, PayloadOffset[cfr, t3, 8]
+    dispatch(5)
+
+.opGetArgumentByValSlow:
+    callSlowPath(_llint_slow_path_get_argument_by_val)
+    dispatch(5)
+
+
+_llint_op_get_by_pname:
+    traceExecution()
+    loadi 12[PC], t0
+    loadConstantOrVariablePayload(t0, CellTag, t1, .opGetByPnameSlow)
+    loadi 16[PC], t0
+    bpneq t1, PayloadOffset[cfr, t0, 8], .opGetByPnameSlow
+    loadi 8[PC], t0
+    loadConstantOrVariablePayload(t0, CellTag, t2, .opGetByPnameSlow)
+    loadi 20[PC], t0
+    loadi PayloadOffset[cfr, t0, 8], t3
+    loadp JSCell::m_structure[t2], t0
+    bpneq t0, JSPropertyNameIterator::m_cachedStructure[t3], .opGetByPnameSlow
+    loadi 24[PC], t0
+    loadi [cfr, t0, 8], t0
+    subi 1, t0
+    biaeq t0, JSPropertyNameIterator::m_numCacheableSlots[t3], .opGetByPnameSlow
+    loadp JSObject::m_propertyStorage[t2], t2
+    loadi TagOffset[t2, t0, 8], t1
+    loadi PayloadOffset[t2, t0, 8], t3
+    loadi 4[PC], t0
+    storei t1, TagOffset[cfr, t0, 8]
+    storei t3, PayloadOffset[cfr, t0, 8]
+    dispatch(7)
+
+.opGetByPnameSlow:
+    callSlowPath(_llint_slow_path_get_by_pname)
+    dispatch(7)
+
+
+_llint_op_put_by_val:
+    traceExecution()
+    loadi 4[PC], t0
+    loadConstantOrVariablePayload(t0, CellTag, t1, .opPutByValSlow)
+    loadi 8[PC], t0
+    loadConstantOrVariablePayload(t0, Int32Tag, t2, .opPutByValSlow)
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_globalData[t0], t0
+    loadp JSGlobalData::jsArrayClassInfo[t0], t0
+    bpneq [t1], t0, .opPutByValSlow
+    biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow
+    loadp JSArray::m_storage[t1], t0
+    bieq ArrayStorage::m_vector + TagOffset[t0, t2, 8], EmptyValueTag, .opPutByValEmpty
+.opPutByValStoreResult:
+    loadi 12[PC], t3
+    loadConstantOrVariable2Reg(t3, t1, t3)
+    writeBarrier(t1, t3)
+    storei t1, ArrayStorage::m_vector + TagOffset[t0, t2, 8]
+    storei t3, ArrayStorage::m_vector + PayloadOffset[t0, t2, 8]
+    dispatch(4)
+
+.opPutByValEmpty:
+    addi 1, ArrayStorage::m_numValuesInVector[t0]
+    bib t2, ArrayStorage::m_length[t0], .opPutByValStoreResult
+    addi 1, t2, t1
+    storei t1, ArrayStorage::m_length[t0]
+    jmp .opPutByValStoreResult
+
+.opPutByValSlow:
+    callSlowPath(_llint_slow_path_put_by_val)
+    dispatch(4)
+
+
+_llint_op_loop:
+    jmp _llint_op_jmp
+_llint_op_jmp:
+    traceExecution()
+    dispatchBranch(4[PC])
+
+
+macro jumpTrueOrFalse(conditionOp, slow)
+    loadi 4[PC], t1
+    loadConstantOrVariablePayload(t1, BooleanTag, t0, .slow)
+    conditionOp(t0, .target)
+    dispatch(3)
+
+.target:
+    dispatchBranch(8[PC])
+
+.slow:
+    callSlowPath(slow)
+    dispatch(0)
+end
+
+
+macro equalNull(cellHandler, immediateHandler)
+    loadi 4[PC], t0
+    assertNotConstant(t0)
+    loadi TagOffset[cfr, t0, 8], t1
+    loadi PayloadOffset[cfr, t0, 8], t0
+    bineq t1, CellTag, .immediate
+    loadp JSCell::m_structure[t0], t2
+    cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target)
+    dispatch(3)
+
+.target:
+    dispatchBranch(8[PC])
+
+.immediate:
+    ori 1, t1
+    immediateHandler(t1, .target)
+    dispatch(3)
+end
+
+_llint_op_jeq_null:
+    traceExecution()
+    equalNull(
+        macro (value, target) btbnz value, MasqueradesAsUndefined, target end,
+        macro (value, target) bieq value, NullTag, target end)
+    
+
+_llint_op_jneq_null:
+    traceExecution()
+    equalNull(
+        macro (value, target) btbz value, MasqueradesAsUndefined, target end,
+        macro (value, target) bineq value, NullTag, target end)
+
+
+_llint_op_jneq_ptr:
+    traceExecution()
+    loadi 4[PC], t0
+    loadi 8[PC], t1
+    bineq TagOffset[cfr, t0, 8], CellTag, .opJneqPtrBranch
+    bpeq PayloadOffset[cfr, t0, 8], t1, .opJneqPtrFallThrough
+.opJneqPtrBranch:
+    dispatchBranch(12[PC])
+.opJneqPtrFallThrough:
+    dispatch(4)
+
+
+macro compare(integerCompare, doubleCompare, slowPath)
+    loadi 4[PC], t2
+    loadi 8[PC], t3
+    loadConstantOrVariable(t2, t0, t1)
+    loadConstantOrVariable2Reg(t3, t2, t3)
+    bineq t0, Int32Tag, .op1NotInt
+    bineq t2, Int32Tag, .op2NotInt
+    integerCompare(t1, t3, .jumpTarget)
+    dispatch(4)
+
+.op1NotInt:
+    bia t0, LowestTag, .slow
+    bib t2, LowestTag, .op1NotIntOp2Double
+    bineq t2, Int32Tag, .slow
+    ci2d t3, ft1
+    jmp .op1NotIntReady
+.op1NotIntOp2Double:
+    fii2d t3, t2, ft1
+.op1NotIntReady:
+    fii2d t1, t0, ft0
+    doubleCompare(ft0, ft1, .jumpTarget)
+    dispatch(4)
+
+.op2NotInt:
+    ci2d t1, ft0
+    bia t2, LowestTag, .slow
+    fii2d t3, t2, ft1
+    doubleCompare(ft0, ft1, .jumpTarget)
+    dispatch(4)
+
+.jumpTarget:
+    dispatchBranch(12[PC])
+
+.slow:
+    callSlowPath(slowPath)
+    dispatch(0)
+end
+
+
+_llint_op_switch_imm:
+    traceExecution()
+    loadi 12[PC], t2
+    loadi 4[PC], t3
+    loadConstantOrVariable(t2, t1, t0)
+    loadp CodeBlock[cfr], t2
+    loadp CodeBlock::m_rareData[t2], t2
+    muli sizeof SimpleJumpTable, t3   # FIXME: would be nice to peephole this!
+    loadp CodeBlock::RareData::m_immediateSwitchJumpTables + VectorBufferOffset[t2], t2
+    addp t3, t2
+    bineq t1, Int32Tag, .opSwitchImmNotInt
+    subi SimpleJumpTable::min[t2], t0
+    biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
+    loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
+    loadi [t3, t0, 4], t1
+    btiz t1, .opSwitchImmFallThrough
+    dispatchBranchWithOffset(t1)
+
+.opSwitchImmNotInt:
+    bib t1, LowestTag, .opSwitchImmSlow  # Go to slow path if it's a double.
+.opSwitchImmFallThrough:
+    dispatchBranch(8[PC])
+
+.opSwitchImmSlow:
+    callSlowPath(_llint_slow_path_switch_imm)
+    dispatch(0)
+
+
+_llint_op_switch_char:
+    traceExecution()
+    loadi 12[PC], t2
+    loadi 4[PC], t3
+    loadConstantOrVariable(t2, t1, t0)
+    loadp CodeBlock[cfr], t2
+    loadp CodeBlock::m_rareData[t2], t2
+    muli sizeof SimpleJumpTable, t3
+    loadp CodeBlock::RareData::m_characterSwitchJumpTables + VectorBufferOffset[t2], t2
+    addp t3, t2
+    bineq t1, CellTag, .opSwitchCharFallThrough
+    loadp JSCell::m_structure[t0], t1
+    bbneq Structure::m_typeInfo + TypeInfo::m_type[t1], StringType, .opSwitchCharFallThrough
+    bineq JSString::m_length[t0], 1, .opSwitchCharFallThrough
+    loadp JSString::m_value[t0], t0
+    btpz  t0, .opSwitchOnRope
+    loadp StringImpl::m_data8[t0], t1
+    btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
+    loadh [t1], t0
+    jmp .opSwitchCharReady
+.opSwitchChar8Bit:
+    loadb [t1], t0
+.opSwitchCharReady:
+    subi SimpleJumpTable::min[t2], t0
+    biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
+    loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
+    loadi [t2, t0, 4], t1
+    btiz t1, .opSwitchCharFallThrough
+    dispatchBranchWithOffset(t1)
+
+.opSwitchCharFallThrough:
+    dispatchBranch(8[PC])
+
+.opSwitchOnRope:
+    callSlowPath(_llint_slow_path_switch_char)
+    dispatch(0)
+
+
+_llint_op_new_func:
+    traceExecution()
+    btiz 12[PC], .opNewFuncUnchecked
+    loadi 4[PC], t1
+    bineq TagOffset[cfr, t1, 8], EmptyValueTag, .opNewFuncDone
+.opNewFuncUnchecked:
+    callSlowPath(_llint_slow_path_new_func)
+.opNewFuncDone:
+    dispatch(4)
+
+
+macro doCall(slowPath)
+    loadi 4[PC], t0
+    loadi 16[PC], t1
+    loadp LLIntCallLinkInfo::callee[t1], t2
+    loadConstantOrVariablePayload(t0, CellTag, t3, .opCallSlow)
+    bineq t3, t2, .opCallSlow
+    loadi 12[PC], t3
+    addp 24, PC
+    lshifti 3, t3
+    addp cfr, t3  # t3 contains the new value of cfr
+    loadp JSFunction::m_scopeChain[t2], t0
+    storei t2, Callee + PayloadOffset[t3]
+    storei t0, ScopeChain + PayloadOffset[t3]
+    loadi 8 - 24[PC], t2
+    storei PC, ArgumentCount + TagOffset[cfr]
+    storep cfr, CallerFrame[t3]
+    storei t2, ArgumentCount + PayloadOffset[t3]
+    storei CellTag, Callee + TagOffset[t3]
+    storei CellTag, ScopeChain + TagOffset[t3]
+    move t3, cfr
+    call LLIntCallLinkInfo::machineCodeTarget[t1]
+    dispatchAfterCall()
+
+.opCallSlow:
+    slowPathForCall(6, slowPath)
+end
+
+
+_llint_op_tear_off_activation:
+    traceExecution()
+    loadi 4[PC], t0
+    loadi 8[PC], t1
+    bineq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffActivationCreated
+    bieq TagOffset[cfr, t1, 8], EmptyValueTag, .opTearOffActivationNotCreated
+.opTearOffActivationCreated:
+    callSlowPath(_llint_slow_path_tear_off_activation)
+.opTearOffActivationNotCreated:
+    dispatch(3)
+
+
+_llint_op_tear_off_arguments:
+    traceExecution()
+    loadi 4[PC], t0
+    subi 1, t0   # Get the unmodifiedArgumentsRegister
+    bieq TagOffset[cfr, t0, 8], EmptyValueTag, .opTearOffArgumentsNotCreated
+    callSlowPath(_llint_slow_path_tear_off_arguments)
+.opTearOffArgumentsNotCreated:
+    dispatch(2)
+
+
+_llint_op_ret:
+    traceExecution()
+    checkSwitchToJITForEpilogue()
+    loadi 4[PC], t2
+    loadConstantOrVariable(t2, t1, t0)
+    doReturn()
+
+
+_llint_op_call_put_result:
+    loadi 4[PC], t2
+    loadi 8[PC], t3
+    storei t1, TagOffset[cfr, t2, 8]
+    storei t0, PayloadOffset[cfr, t2, 8]
+    valueProfile(t1, t0, t3)
+    traceExecution() # Needs to be here because it would clobber t1, t0
+    dispatch(3)
+
+
+_llint_op_ret_object_or_this:
+    traceExecution()
+    checkSwitchToJITForEpilogue()
+    loadi 4[PC], t2
+    loadConstantOrVariable(t2, t1, t0)
+    bineq t1, CellTag, .opRetObjectOrThisNotObject
+    loadp JSCell::m_structure[t0], t2
+    bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opRetObjectOrThisNotObject
+    doReturn()
+
+.opRetObjectOrThisNotObject:
+    loadi 8[PC], t2
+    loadConstantOrVariable(t2, t1, t0)
+    doReturn()
+
+
+_llint_op_to_primitive:
+    traceExecution()
+    loadi 8[PC], t2
+    loadi 4[PC], t3
+    loadConstantOrVariable(t2, t1, t0)
+    bineq t1, CellTag, .opToPrimitiveIsImm
+    loadp JSCell::m_structure[t0], t2
+    bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .opToPrimitiveSlowCase
+.opToPrimitiveIsImm:
+    storei t1, TagOffset[cfr, t3, 8]
+    storei t0, PayloadOffset[cfr, t3, 8]
+    dispatch(3)
+
+.opToPrimitiveSlowCase:
+    callSlowPath(_llint_slow_path_to_primitive)
+    dispatch(3)
+
+
+_llint_op_next_pname:
+    traceExecution()
+    loadi 12[PC], t1
+    loadi 16[PC], t2
+    loadi PayloadOffset[cfr, t1, 8], t0
+    bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd
+    loadi 20[PC], t2
+    loadi PayloadOffset[cfr, t2, 8], t2
+    loadp JSPropertyNameIterator::m_jsStrings[t2], t3
+    loadi [t3, t0, 8], t3
+    addi 1, t0
+    storei t0, PayloadOffset[cfr, t1, 8]
+    loadi 4[PC], t1
+    storei CellTag, TagOffset[cfr, t1, 8]
+    storei t3, PayloadOffset[cfr, t1, 8]
+    loadi 8[PC], t3
+    loadi PayloadOffset[cfr, t3, 8], t3
+    loadp JSCell::m_structure[t3], t1
+    bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow
+    loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0
+    loadp StructureChain::m_vector[t0], t0
+    btpz [t0], .opNextPnameTarget
+.opNextPnameCheckPrototypeLoop:
+    bieq Structure::m_prototype + TagOffset[t1], NullTag, .opNextPnameSlow
+    loadp Structure::m_prototype + PayloadOffset[t1], t2
+    loadp JSCell::m_structure[t2], t1
+    bpneq t1, [t0], .opNextPnameSlow
+    addp 4, t0
+    btpnz [t0], .opNextPnameCheckPrototypeLoop
+.opNextPnameTarget:
+    dispatchBranch(24[PC])
+
+.opNextPnameEnd:
+    dispatch(7)
+
+.opNextPnameSlow:
+    callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target.
+    dispatch(0)
+
+
+_llint_op_catch:
+    # This is where we end up from the JIT's throw trampoline (because the
+    # machine code return address will be set to _llint_op_catch), and from
+    # the interpreter's throw trampoline (see _llint_throw_trampoline).
+    # The JIT throwing protocol calls for the cfr to be in t0. The throwing
+    # code must have known that we were throwing to the interpreter, and have
+    # set JSGlobalData::targetInterpreterPCForThrow.
+    move t0, cfr
+    loadp JITStackFrame::globalData[sp], t3
+    loadi JSGlobalData::targetInterpreterPCForThrow[t3], PC
+    loadi JSGlobalData::exception + PayloadOffset[t3], t0
+    loadi JSGlobalData::exception + TagOffset[t3], t1
+    storei 0, JSGlobalData::exception + PayloadOffset[t3]
+    storei EmptyValueTag, JSGlobalData::exception + TagOffset[t3]       
+    loadi 4[PC], t2
+    storei t0, PayloadOffset[cfr, t2, 8]
+    storei t1, TagOffset[cfr, t2, 8]
+    traceExecution()  # This needs to be here because we don't want to clobber t0, t1, t2, t3 above.
+    dispatch(2)
+
+
+_llint_op_end:
+    traceExecution()
+    checkSwitchToJITForEpilogue()
+    loadi 4[PC], t0
+    assertNotConstant(t0)
+    loadi TagOffset[cfr, t0, 8], t1
+    loadi PayloadOffset[cfr, t0, 8], t0
+    doReturn()
+
+
+_llint_throw_from_slow_path_trampoline:
+    # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
+    # the throw target is not necessarily interpreted code, we come to here.
+    # This essentially emulates the JIT's throwing protocol.
+    loadp JITStackFrame::globalData[sp], t1
+    loadp JSGlobalData::callFrameForThrow[t1], t0
+    jmp JSGlobalData::targetMachinePCForThrow[t1]
+
+
+_llint_throw_during_call_trampoline:
+    preserveReturnAddressAfterCall(t2)
+    loadp JITStackFrame::globalData[sp], t1
+    loadp JSGlobalData::callFrameForThrow[t1], t0
+    jmp JSGlobalData::targetMachinePCForThrow[t1]
+
+
+macro nativeCallTrampoline(executableOffsetToFunction)
+    storep 0, CodeBlock[cfr]
+    loadp CallerFrame[cfr], t0
+    loadi ScopeChain + PayloadOffset[t0], t1
+    storei CellTag, ScopeChain + TagOffset[cfr]
+    storei t1, ScopeChain + PayloadOffset[cfr]
+    if X86
+        loadp JITStackFrame::globalData + 4[sp], t3 # Additional offset for return address
+        storep cfr, JSGlobalData::topCallFrame[t3]
+        peek 0, t1
+        storep t1, ReturnPC[cfr]
+        move cfr, t2  # t2 = ecx
+        subp 16 - 4, sp
+        loadi Callee + PayloadOffset[cfr], t1
+        loadp JSFunction::m_executable[t1], t1
+        move t0, cfr
+        call executableOffsetToFunction[t1]
+        addp 16 - 4, sp
+        loadp JITStackFrame::globalData + 4[sp], t3
+    elsif ARMv7
+        loadp JITStackFrame::globalData[sp], t3
+        storep cfr, JSGlobalData::topCallFrame[t3]
+        move t0, t2
+        preserveReturnAddressAfterCall(t3)
+        storep t3, ReturnPC[cfr]
+        move cfr, t0
+        loadi Callee + PayloadOffset[cfr], t1
+        loadp JSFunction::m_executable[t1], t1
+        move t2, cfr
+        call executableOffsetToFunction[t1]
+        restoreReturnAddressBeforeReturn(t3)
+        loadp JITStackFrame::globalData[sp], t3
+    else  
+        error
+    end
+    bineq JSGlobalData::exception + TagOffset[t3], EmptyValueTag, .exception
+    ret
+.exception:
+    preserveReturnAddressAfterCall(t1) # This is really only needed on X86
+    loadi ArgumentCount + TagOffset[cfr], PC
+    callSlowPath(_llint_throw_from_native_call)
+    jmp _llint_throw_from_slow_path_trampoline
+end
+
diff --git a/llint/LowLevelInterpreter64.asm b/llint/LowLevelInterpreter64.asm
new file mode 100644 (file)
index 0000000..2b79b85
--- /dev/null
@@ -0,0 +1,1548 @@
+# Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. 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.
+
+
+# Some value representation constants.
+const TagBitTypeOther = 0x2
+const TagBitBool      = 0x4
+const TagBitUndefined = 0x8
+const ValueEmpty      = 0x0
+const ValueFalse      = TagBitTypeOther | TagBitBool
+const ValueTrue       = TagBitTypeOther | TagBitBool | 1
+const ValueUndefined  = TagBitTypeOther | TagBitUndefined
+const ValueNull       = TagBitTypeOther
+
+# Utilities.
+macro dispatch(advance)
+    addp advance, PC
+    jmp [PB, PC, 8]
+end
+
+macro dispatchInt(advance)
+    addi advance, PC
+    jmp [PB, PC, 8]
+end
+
+macro dispatchAfterCall()
+    loadi ArgumentCount + TagOffset[cfr], PC
+    loadp CodeBlock[cfr], PB
+    loadp CodeBlock::m_instructions[PB], PB
+    jmp [PB, PC, 8]
+end
+
+macro cCall2(function, arg1, arg2)
+    move arg1, t5
+    move arg2, t4
+    call function
+end
+
+# This barely works. arg3 and arg4 should probably be immediates.
+macro cCall4(function, arg1, arg2, arg3, arg4)
+    move arg1, t5
+    move arg2, t4
+    move arg3, t1
+    move arg4, t2
+    call function
+end
+
+macro prepareStateForCCall()
+    leap [PB, PC, 8], PC
+    move PB, t3
+end
+
+macro restoreStateAfterCCall()
+    move t0, PC
+    move t1, cfr
+    move t3, PB
+    subp PB, PC
+    urshiftp 3, PC
+end
+
+macro callSlowPath(slowPath)
+    prepareStateForCCall()
+    cCall2(slowPath, cfr, PC)
+    restoreStateAfterCCall()
+end
+
+macro traceOperand(fromWhere, operand)
+    prepareStateForCCall()
+    cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
+    restoreStateAfterCCall()
+end
+
+macro traceValue(fromWhere, operand)
+    prepareStateForCCall()
+    cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
+    restoreStateAfterCCall()
+end
+
+# Call a slow path for call call opcodes.
+macro callCallSlowPath(advance, slowPath, action)
+    addi advance, PC, t0
+    storei t0, ArgumentCount + TagOffset[cfr]
+    prepareStateForCCall()
+    cCall2(slowPath, cfr, PC)
+    move t1, cfr
+    action(t0)
+end
+
+macro checkSwitchToJITForLoop()
+    checkSwitchToJIT(
+        1,
+        macro()
+            storei PC, ArgumentCount + TagOffset[cfr]
+            prepareStateForCCall()
+            cCall2(_llint_loop_osr, cfr, PC)
+            move t1, cfr
+            btpz t0, .recover
+            jmp t0
+        .recover:
+            move t3, PB
+            loadi ArgumentCount + TagOffset[cfr], PC
+        end)
+end
+
+# Index and value must be different registers. Index may be clobbered.
+macro loadConstantOrVariable(index, value)
+    bpgteq index, FirstConstantRegisterIndex, .constant
+    loadp [cfr, index, 8], value
+    jmp .done
+.constant:
+    loadp CodeBlock[cfr], value
+    loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
+    subp FirstConstantRegisterIndex, index
+    loadp [value, index, 8], value
+.done:
+end
+
+macro loadConstantOrVariableInt32(index, value, slow)
+    loadConstantOrVariable(index, value)
+    bpb value, tagTypeNumber, slow
+end
+
+macro loadConstantOrVariableCell(index, value, slow)
+    loadConstantOrVariable(index, value)
+    btpnz value, tagMask, slow
+end
+
+macro writeBarrier(value)
+    # Nothing to do, since we don't have a generational or incremental collector.
+end
+
+macro valueProfile(value, profile)
+    if VALUE_PROFILER
+        storep value, ValueProfile::m_buckets[profile]
+    end
+end
+
+
+# Entrypoints into the interpreter.
+
+# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
+macro functionArityCheck(doneLabel, slow_path)
+    loadi PayloadOffset + ArgumentCount[cfr], t0
+    biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
+    prepareStateForCCall()
+    cCall2(slow_path, cfr, PC)   # This slow_path has a simple protocol: t0 = 0 => no error, t0 != 0 => error
+    move t1, cfr
+    btiz t0, .continue
+    loadp JITStackFrame::globalData[sp], t1
+    loadp JSGlobalData::callFrameForThrow[t1], t0
+    jmp JSGlobalData::targetMachinePCForThrow[t1]
+.continue:
+    # Reload CodeBlock and reset PC, since the slow_path clobbered them.
+    loadp CodeBlock[cfr], t1
+    loadp CodeBlock::m_instructions[t1], PB
+    move 0, PC
+    jmp doneLabel
+end
+
+
+# Instruction implementations
+
+_llint_op_enter:
+    traceExecution()
+    loadp CodeBlock[cfr], t2
+    loadi CodeBlock::m_numVars[t2], t2
+    btiz t2, .opEnterDone
+    move ValueUndefined, t0
+.opEnterLoop:
+    subi 1, t2
+    storep t0, [cfr, t2, 8]
+    btinz t2, .opEnterLoop
+.opEnterDone:
+    dispatch(1)
+
+
+_llint_op_create_activation:
+    traceExecution()
+    loadis 8[PB, PC, 8], t0
+    bpneq [cfr, t0, 8], ValueEmpty, .opCreateActivationDone
+    callSlowPath(_llint_slow_path_create_activation)
+.opCreateActivationDone:
+    dispatch(2)
+
+
+_llint_op_init_lazy_reg:
+    traceExecution()
+    loadis 8[PB, PC, 8], t0
+    storep ValueEmpty, [cfr, t0, 8]
+    dispatch(2)
+
+
+_llint_op_create_arguments:
+    traceExecution()
+    loadis 8[PB, PC, 8], t0
+    bpneq [cfr, t0, 8], ValueEmpty, .opCreateArgumentsDone
+    callSlowPath(_llint_slow_path_create_arguments)
+.opCreateArgumentsDone:
+    dispatch(2)
+
+
+_llint_op_create_this:
+    traceExecution()
+    loadis 16[PB, PC, 8], t0
+    assertNotConstant(t0)
+    loadp [cfr, t0, 8], t0
+    btpnz t0, tagMask, .opCreateThisSlow
+    loadp JSCell::m_structure[t0], t1
+    bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
+    loadp JSObject::m_inheritorID[t0], t2
+    btpz t2, .opCreateThisSlow
+    allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
+    loadis 8[PB, PC, 8], t1
+    storep t0, [cfr, t1, 8]
+    dispatch(3)
+
+.opCreateThisSlow:
+    callSlowPath(_llint_slow_path_create_this)
+    dispatch(3)
+
+
+_llint_op_get_callee:
+    traceExecution()
+    loadis 8[PB, PC, 8], t0
+    loadp Callee[cfr], t1
+    storep t1, [cfr, t0, 8]
+    dispatch(2)
+
+
+_llint_op_convert_this:
+    traceExecution()
+    loadis 8[PB, PC, 8], t0
+    loadp [cfr, t0, 8], t0
+    btpnz t0, tagMask, .opConvertThisSlow
+    loadp JSCell::m_structure[t0], t0
+    bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
+    dispatch(2)
+
+.opConvertThisSlow:
+    callSlowPath(_llint_slow_path_convert_this)
+    dispatch(2)
+
+
+_llint_op_new_object:
+    traceExecution()
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_globalObject[t0], t0
+    loadp JSGlobalObject::m_emptyObjectStructure[t0], t1
+    allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t1, t0, t2, t3, .opNewObjectSlow)
+    loadis 8[PB, PC, 8], t1
+    storep t0, [cfr, t1, 8]
+    dispatch(2)
+
+.opNewObjectSlow:
+    callSlowPath(_llint_slow_path_new_object)
+    dispatch(2)
+
+
+_llint_op_mov:
+    traceExecution()
+    loadis 16[PB, PC, 8], t1
+    loadis 8[PB, PC, 8], t0
+    loadConstantOrVariable(t1, t2)
+    storep t2, [cfr, t0, 8]
+    dispatch(3)
+
+
+_llint_op_not:
+    traceExecution()
+    loadis 16[PB, PC, 8], t0
+    loadis 8[PB, PC, 8], t1
+    loadConstantOrVariable(t0, t2)
+    xorp ValueFalse, t2
+    btpnz t2, ~1, .opNotSlow
+    xorp ValueTrue, t2
+    storep t2, [cfr, t1, 8]
+    dispatch(3)
+
+.opNotSlow:
+    callSlowPath(_llint_slow_path_not)
+    dispatch(3)
+
+
+macro equalityComparison(integerComparison, slowPath)
+    traceExecution()
+    loadis 24[PB, PC, 8], t0
+    loadis 16[PB, PC, 8], t2
+    loadis 8[PB, PC, 8], t3
+    loadConstantOrVariableInt32(t0, t1, .slow)
+    loadConstantOrVariableInt32(t2, t0, .slow)
+    integerComparison(t0, t1, t0)
+    orp ValueFalse, t0
+    storep t0, [cfr, t3, 8]
+    dispatch(4)
+
+.slow:
+    callSlowPath(slowPath)
+    dispatch(4)
+end
+
+_llint_op_eq:
+    equalityComparison(
+        macro (left, right, result) cieq left, right, result end,
+        _llint_slow_path_eq)
+
+
+_llint_op_neq:
+    equalityComparison(
+        macro (left, right, result) cineq left, right, result end,
+        _llint_slow_path_neq)
+
+
+macro equalNullComparison()
+    loadis 16[PB, PC, 8], t0
+    loadp [cfr, t0, 8], t0
+    btpnz t0, tagMask, .immediate
+    loadp JSCell::m_structure[t0], t2
+    tbnz Structure::m_typeInfo + TypeInfo::m_flags[t2], MasqueradesAsUndefined, t0
+    jmp .done
+.immediate:
+    andp ~TagBitUndefined, t0
+    cpeq t0, ValueNull, t0
+.done:
+end
+
+_llint_op_eq_null:
+    traceExecution()
+    equalNullComparison()
+    loadis 8[PB, PC, 8], t1
+    orp ValueFalse, t0
+    storep t0, [cfr, t1, 8]
+    dispatch(3)
+
+
+_llint_op_neq_null:
+    traceExecution()
+    equalNullComparison()
+    loadis 8[PB, PC, 8], t1
+    xorp ValueTrue, t0
+    storep t0, [cfr, t1, 8]
+    dispatch(3)
+
+
+macro strictEq(equalityOperation, slowPath)
+    traceExecution()
+    loadis 24[PB, PC, 8], t0
+    loadis 16[PB, PC, 8], t2
+    loadConstantOrVariable(t0, t1)
+    loadConstantOrVariable(t2, t0)
+    move t0, t2
+    orp t1, t2
+    btpz t2, tagMask, .slow
+    bpaeq t0, tagTypeNumber, .leftOK
+    btpnz t0, tagTypeNumber, .slow
+.leftOK:
+    bpaeq t1, tagTypeNumber, .rightOK
+    btpnz t1, tagTypeNumber, .slow
+.rightOK:
+    equalityOperation(t0, t1, t0)
+    loadis 8[PB, PC, 8], t1
+    orp ValueFalse, t0
+    storep t0, [cfr, t1, 8]
+    dispatch(4)
+
+.slow:
+    callSlowPath(slowPath)
+    dispatch(4)
+end
+
+_llint_op_stricteq:
+    strictEq(
+        macro (left, right, result) cpeq left, right, result end,
+        _llint_slow_path_stricteq)
+
+
+_llint_op_nstricteq:
+    strictEq(
+        macro (left, right, result) cpneq left, right, result end,
+        _llint_slow_path_nstricteq)
+
+
+macro preOp(arithmeticOperation, slowPath)
+    traceExecution()
+    loadis 8[PB, PC, 8], t0
+    loadp [cfr, t0, 8], t1
+    bpb t1, tagTypeNumber, .slow
+    arithmeticOperation(t1, .slow)
+    orp tagTypeNumber, t1
+    storep t1, [cfr, t0, 8]
+    dispatch(2)
+
+.slow:
+    callSlowPath(slowPath)
+    dispatch(2)
+end
+
+_llint_op_pre_inc:
+    preOp(
+        macro (value, slow) baddio 1, value, slow end,
+        _llint_slow_path_pre_inc)
+
+
+_llint_op_pre_dec:
+    preOp(
+        macro (value, slow) bsubio 1, value, slow end,
+        _llint_slow_path_pre_dec)
+
+
+macro postOp(arithmeticOperation, slowPath)
+    traceExecution()
+    loadis 16[PB, PC, 8], t0
+    loadis 8[PB, PC, 8], t1
+    loadp [cfr, t0, 8], t2
+    bieq t0, t1, .done
+    bpb t2, tagTypeNumber, .slow
+    move t2, t3
+    arithmeticOperation(t3, .slow)
+    orp tagTypeNumber, t3
+    storep t2, [cfr, t1, 8]
+    storep t3, [cfr, t0, 8]
+.done:
+    dispatch(3)
+
+.slow:
+    callSlowPath(slowPath)
+    dispatch(3)
+end
+
+_llint_op_post_inc:
+    postOp(
+        macro (value, slow) baddio 1, value, slow end,
+        _llint_slow_path_post_inc)
+
+
+_llint_op_post_dec:
+    postOp(
+        macro (value, slow) bsubio 1, value, slow end,
+        _llint_slow_path_post_dec)
+
+
+_llint_op_to_jsnumber:
+    traceExecution()
+    loadis 16[PB, PC, 8], t0
+    loadis 8[PB, PC, 8], t1
+    loadConstantOrVariable(t0, t2)
+    bpaeq t2, tagTypeNumber, .opToJsnumberIsImmediate
+    btpz t2, tagTypeNumber, .opToJsnumberSlow
+.opToJsnumberIsImmediate:
+    storep t2, [cfr, t1, 8]
+    dispatch(3)
+
+.opToJsnumberSlow:
+    callSlowPath(_llint_slow_path_to_jsnumber)
+    dispatch(3)
+
+
+_llint_op_negate:
+    traceExecution()
+    loadis 16[PB, PC, 8], t0
+    loadis 8[PB, PC, 8], t1
+    loadConstantOrVariable(t0, t2)
+    bpb t2, tagTypeNumber, .opNegateNotInt
+    btiz t2, 0x7fffffff, .opNegateSlow
+    negi t2
+    orp tagTypeNumber, t2
+    storep t2, [cfr, t1, 8]
+    dispatch(3)
+.opNegateNotInt:
+    btpz t2, tagTypeNumber, .opNegateSlow
+    xorp 0x8000000000000000, t2
+    storep t2, [cfr, t1, 8]
+    dispatch(3)
+
+.opNegateSlow:
+    callSlowPath(_llint_slow_path_negate)
+    dispatch(3)
+
+
+macro binaryOpCustomStore(integerOperationAndStore, doubleOperation, slowPath)
+    loadis 24[PB, PC, 8], t0
+    loadis 16[PB, PC, 8], t2
+    loadConstantOrVariable(t0, t1)
+    loadConstantOrVariable(t2, t0)
+    bpb t0, tagTypeNumber, .op1NotInt
+    bpb t1, tagTypeNumber, .op2NotInt
+    loadis 8[PB, PC, 8], t2
+    integerOperationAndStore(t1, t0, .slow, t2)
+    dispatch(5)
+
+.op1NotInt:
+    # First operand is definitely not an int, the second operand could be anything.
+    btpz t0, tagTypeNumber, .slow
+    bpaeq t1, tagTypeNumber, .op1NotIntOp2Int
+    btpz t1, tagTypeNumber, .slow
+    addp tagTypeNumber, t1
+    fp2d t1, ft1
+    jmp .op1NotIntReady
+.op1NotIntOp2Int:
+    ci2d t1, ft1
+.op1NotIntReady:
+    loadis 8[PB, PC, 8], t2
+    addp tagTypeNumber, t0
+    fp2d t0, ft0
+    doubleOperation(ft1, ft0)
+    fd2p ft0, t0
+    subp tagTypeNumber, t0
+    storep t0, [cfr, t2, 8]
+    dispatch(5)
+
+.op2NotInt:
+    # First operand is definitely an int, the second is definitely not.
+    loadis 8[PB, PC, 8], t2
+    btpz t1, tagTypeNumber, .slow
+    ci2d t0, ft0
+    addp tagTypeNumber, t1
+    fp2d t1, ft1
+    doubleOperation(ft1, ft0)
+    fd2p ft0, t0
+    subp tagTypeNumber, t0
+    storep t0, [cfr, t2, 8]
+    dispatch(5)
+
+.slow:
+    callSlowPath(slowPath)
+    dispatch(5)
+end
+
+macro binaryOp(integerOperation, doubleOperation, slowPath)
+    binaryOpCustomStore(
+        macro (left, right, slow, index)
+            integerOperation(left, right, slow)
+            orp tagTypeNumber, right
+            storep right, [cfr, index, 8]
+        end,
+        doubleOperation, slowPath)
+end
+
+_llint_op_add:
+    traceExecution()
+    binaryOp(
+        macro (left, right, slow) baddio left, right, slow end,
+        macro (left, right) addd left, right end,
+        _llint_slow_path_add)
+
+
+_llint_op_mul:
+    traceExecution()
+    binaryOpCustomStore(
+        macro (left, right, slow, index)
+            # Assume t3 is scratchable.
+            move right, t3
+            bmulio left, t3, slow
+            btinz t3, .done
+            bilt left, 0, slow
+            bilt right, 0, slow
+        .done:
+            orp tagTypeNumber, t3
+            storep t3, [cfr, index, 8]
+        end,
+        macro (left, right) muld left, right end,
+        _llint_slow_path_mul)
+
+
+_llint_op_sub:
+    traceExecution()
+    binaryOp(
+        macro (left, right, slow) bsubio left, right, slow end,
+        macro (left, right) subd left, right end,
+        _llint_slow_path_sub)
+
+
+_llint_op_div:
+    traceExecution()
+    binaryOpCustomStore(
+        macro (left, right, slow, index)
+            # Assume t3 is scratchable.
+            btiz left, slow
+            bineq left, -1, .notNeg2TwoThe31DivByNeg1
+            bieq right, -2147483648, .slow
+        .notNeg2TwoThe31DivByNeg1:
+            btinz right, .intOK
+            bilt left, 0, slow
+        .intOK:
+            move left, t3
+            move right, t0
+            cdqi
+            idivi t3
+            btinz t1, slow
+            orp tagTypeNumber, t0
+            storep t0, [cfr, index, 8]
+        end,
+        macro (left, right) divd left, right end,
+        _llint_slow_path_div)
+
+
+macro bitOp(operation, slowPath, advance)
+    loadis 24[PB, PC, 8], t0
+    loadis 16[PB, PC, 8], t2
+    loadis 8[PB, PC, 8], t3
+    loadConstantOrVariable(t0, t1)
+    loadConstantOrVariable(t2, t0)
+    bpb t0, tagTypeNumber, .slow
+    bpb t1, tagTypeNumber, .slow
+    operation(t1, t0, .slow)
+    orp tagTypeNumber, t0
+    storep t0, [cfr, t3, 8]
+    dispatch(advance)
+
+.slow:
+    callSlowPath(slowPath)
+    dispatch(advance)
+end
+
+_llint_op_lshift:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) lshifti left, right end,
+        _llint_slow_path_lshift,
+        4)
+
+
+_llint_op_rshift:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) rshifti left, right end,
+        _llint_slow_path_rshift,
+        4)
+
+
+_llint_op_urshift:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow)
+            urshifti left, right
+            bilt right, 0, slow
+        end,
+        _llint_slow_path_urshift,
+        4)
+
+
+_llint_op_bitand:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) andi left, right end,
+        _llint_slow_path_bitand,
+        5)
+
+
+_llint_op_bitxor:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) xori left, right end,
+        _llint_slow_path_bitxor,
+        5)
+
+
+_llint_op_bitor:
+    traceExecution()
+    bitOp(
+        macro (left, right, slow) ori left, right end,
+        _llint_slow_path_bitor,
+        5)
+
+
+_llint_op_check_has_instance:
+    traceExecution()
+    loadis 8[PB, PC, 8], t1
+    loadConstantOrVariableCell(t1, t0, .opCheckHasInstanceSlow)
+    loadp JSCell::m_structure[t0], t0
+    btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsHasInstance, .opCheckHasInstanceSlow
+    dispatch(2)
+
+.opCheckHasInstanceSlow:
+    callSlowPath(_llint_slow_path_check_has_instance)
+    dispatch(2)
+
+
+_llint_op_instanceof:
+    traceExecution()
+    # Check that baseVal implements the default HasInstance behavior.
+    # FIXME: This should be deprecated.
+    loadis 24[PB, PC, 8], t1
+    loadConstantOrVariable(t1, t0)
+    loadp JSCell::m_structure[t0], t0
+    btbz Structure::m_typeInfo + TypeInfo::m_flags[t0], ImplementsDefaultHasInstance, .opInstanceofSlow
+    
+    # Actually do the work.
+    loadis 32[PB, PC, 8], t0
+    loadis 8[PB, PC, 8], t3
+    loadConstantOrVariableCell(t0, t1, .opInstanceofSlow)
+    loadp JSCell::m_structure[t1], t2
+    bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opInstanceofSlow
+    loadis 16[PB, PC, 8], t0
+    loadConstantOrVariableCell(t0, t2, .opInstanceofSlow)
+    
+    # Register state: t1 = prototype, t2 = value
+    move 1, t0
+.opInstanceofLoop:
+    loadp JSCell::m_structure[t2], t2
+    loadp Structure::m_prototype[t2], t2
+    bpeq t2, t1, .opInstanceofDone
+    btpz t2, tagMask, .opInstanceofLoop
+
+    move 0, t0
+.opInstanceofDone:
+    orp ValueFalse, t0
+    storep t0, [cfr, t3, 8]
+    dispatch(5)
+
+.opInstanceofSlow:
+    callSlowPath(_llint_slow_path_instanceof)
+    dispatch(5)
+
+
+_llint_op_is_undefined:
+    traceExecution()
+    loadis 16[PB, PC, 8], t1
+    loadis 8[PB, PC, 8], t2
+    loadConstantOrVariable(t1, t0)
+    btpz t0, tagMask, .opIsUndefinedCell
+    cpeq t0, ValueUndefined, t3
+    orp ValueFalse, t3
+    storep t3, [cfr, t2, 8]
+    dispatch(3)
+.opIsUndefinedCell:
+    loadp JSCell::m_structure[t0], t0
+    tbnz Structure::m_typeInfo + TypeInfo::m_flags[t0], MasqueradesAsUndefined, t1
+    orp ValueFalse, t1
+    storep t1, [cfr, t2, 8]
+    dispatch(3)
+
+
+_llint_op_is_boolean:
+    traceExecution()
+    loadis 16[PB, PC, 8], t1
+    loadis 8[PB, PC, 8], t2
+    loadConstantOrVariable(t1, t0)
+    xorp ValueFalse, t0
+    tpz t0, ~1, t0
+    orp ValueFalse, t0
+    storep t0, [cfr, t2, 8]
+    dispatch(3)
+
+
+_llint_op_is_number:
+    traceExecution()
+    loadis 16[PB, PC, 8], t1
+    loadis 8[PB, PC, 8], t2
+    loadConstantOrVariable(t1, t0)
+    tpnz t0, tagTypeNumber, t1
+    orp ValueFalse, t1
+    storep t1, [cfr, t2, 8]
+    dispatch(3)
+
+
+_llint_op_is_string:
+    traceExecution()
+    loadis 16[PB, PC, 8], t1
+    loadis 8[PB, PC, 8], t2
+    loadConstantOrVariable(t1, t0)
+    btpnz t0, tagMask, .opIsStringNotCell
+    loadp JSCell::m_structure[t0], t0
+    cbeq Structure::m_typeInfo + TypeInfo::m_type[t0], StringType, t1
+    orp ValueFalse, t1
+    storep t1, [cfr, t2, 8]
+    dispatch(3)
+.opIsStringNotCell:
+    storep ValueFalse, [cfr, t2, 8]
+    dispatch(3)
+
+
+macro resolveGlobal(size, slow)
+    # Operands are as follows:
+    # 8[PB, PC, 8]   Destination for the load.
+    # 16[PB, PC, 8]  Property identifier index in the code block.
+    # 24[PB, PC, 8]  Structure pointer, initialized to 0 by bytecode generator.
+    # 32[PB, PC, 8]  Offset in global object, initialized to 0 by bytecode generator.
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_globalObject[t0], t0
+    loadp JSCell::m_structure[t0], t1
+    bpneq t1, 24[PB, PC, 8], slow
+    loadis 32[PB, PC, 8], t1
+    loadp JSObject::m_propertyStorage[t0], t0
+    loadp [t0, t1, 8], t2
+    loadis 8[PB, PC, 8], t0
+    storep t2, [cfr, t0, 8]
+    loadp (size - 1) * 8[PB, PC, 8], t0
+    valueProfile(t2, t0)
+end
+
+_llint_op_resolve_global:
+    traceExecution()
+    resolveGlobal(6, .opResolveGlobalSlow)
+    dispatch(6)
+
+.opResolveGlobalSlow:
+    callSlowPath(_llint_slow_path_resolve_global)
+    dispatch(6)
+
+
+# Gives you the scope in t0, while allowing you to optionally perform additional checks on the
+# scopes as they are traversed. scopeCheck() is called with two arguments: the register
+# holding the scope, and a register that can be used for scratch. Note that this does not
+# use t3, so you can hold stuff in t3 if need be.
+macro getScope(deBruijinIndexOperand, scopeCheck)
+    loadp ScopeChain[cfr], t0
+    loadis deBruijinIndexOperand, t2
+    
+    btiz t2, .done
+    
+    loadp CodeBlock[cfr], t1
+    bineq CodeBlock::m_codeType[t1], FunctionCode, .loop
+    btbz CodeBlock::m_needsFullScopeChain[t1], .loop
+    
+    loadis CodeBlock::m_activationRegister[t1], t1
+
+    # Need to conditionally skip over one scope.
+    btpz [cfr, t1, 8], .noActivation
+    scopeCheck(t0, t1)
+    loadp ScopeChainNode::next[t0], t0
+.noActivation:
+    subi 1, t2
+    
+    btiz t2, .done
+.loop:
+    scopeCheck(t0, t1)
+    loadp ScopeChainNode::next[t0], t0
+    subi 1, t2
+    btinz t2, .loop
+
+.done:
+end
+
+_llint_op_resolve_global_dynamic:
+    traceExecution()
+    loadp JITStackFrame::globalData[sp], t3
+    loadp JSGlobalData::activationStructure[t3], t3
+    getScope(
+        40[PB, PC, 8],
+        macro (scope, scratch)
+            loadp ScopeChainNode::object[scope], scratch
+            bpneq JSCell::m_structure[scratch], t3, .opResolveGlobalDynamicSuperSlow
+        end)
+    resolveGlobal(7, .opResolveGlobalDynamicSlow)
+    dispatch(7)
+
+.opResolveGlobalDynamicSuperSlow:
+    callSlowPath(_llint_slow_path_resolve_for_resolve_global_dynamic)
+    dispatch(7)
+
+.opResolveGlobalDynamicSlow:
+    callSlowPath(_llint_slow_path_resolve_global_dynamic)
+    dispatch(7)
+
+
+_llint_op_get_scoped_var:
+    traceExecution()
+    # Operands are as follows:
+    # 8[PB, PC, 8]   Destination for the load
+    # 16[PB, PC, 8]  Index of register in the scope
+    # 24[PB, PC, 8]  De Bruijin index.
+    getScope(24[PB, PC, 8], macro (scope, scratch) end)
+    loadis 8[PB, PC, 8], t1
+    loadis 16[PB, PC, 8], t2
+    loadp ScopeChainNode::object[t0], t0
+    loadp JSVariableObject::m_registers[t0], t0
+    loadp [t0, t2, 8], t3
+    storep t3, [cfr, t1, 8]
+    loadp 32[PB, PC, 8], t1
+    valueProfile(t3, t1)
+    dispatch(5)
+
+
+_llint_op_put_scoped_var:
+    traceExecution()
+    getScope(16[PB, PC, 8], macro (scope, scratch) end)
+    loadis 24[PB, PC, 8], t1
+    loadConstantOrVariable(t1, t3)
+    loadis 8[PB, PC, 8], t1
+    writeBarrier(t3)
+    loadp ScopeChainNode::object[t0], t0
+    loadp JSVariableObject::m_registers[t0], t0
+    storep t3, [t0, t1, 8]
+    dispatch(4)
+
+
+_llint_op_get_global_var:
+    traceExecution()
+    loadis 16[PB, PC, 8], t1
+    loadis 8[PB, PC, 8], t3
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_globalObject[t0], t0
+    loadp JSGlobalObject::m_registers[t0], t0
+    loadp [t0, t1, 8], t2
+    storep t2, [cfr, t3, 8]
+    loadp 24[PB, PC, 8], t3
+    valueProfile(t2, t3)
+    dispatch(4)
+
+
+_llint_op_put_global_var:
+    traceExecution()
+    loadis 16[PB, PC, 8], t1
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_globalObject[t0], t0
+    loadp JSGlobalObject::m_registers[t0], t0
+    loadConstantOrVariable(t1, t2)
+    loadis 8[PB, PC, 8], t1
+    writeBarrier(t2)
+    storep t2, [t0, t1, 8]
+    dispatch(3)
+
+
+_llint_op_get_by_id:
+    traceExecution()
+    # We only do monomorphic get_by_id caching for now, and we do not modify the
+    # opcode. We do, however, allow for the cache to change anytime if fails, since
+    # ping-ponging is free. At best we get lucky and the get_by_id will continue
+    # to take fast path on the new cache. At worst we take slow path, which is what
+    # we would have been doing anyway.
+    loadis 16[PB, PC, 8], t0
+    loadp 32[PB, PC, 8], t1
+    loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
+    loadis 40[PB, PC, 8], t2
+    loadp JSObject::m_propertyStorage[t3], t0
+    bpneq JSCell::m_structure[t3], t1, .opGetByIdSlow
+    loadis 8[PB, PC, 8], t1
+    loadp [t0, t2], t3
+    storep t3, [cfr, t1, 8]
+    loadp 64[PB, PC, 8], t1
+    valueProfile(t3, t1)
+    dispatch(9)
+
+.opGetByIdSlow:
+    callSlowPath(_llint_slow_path_get_by_id)
+    dispatch(9)
+
+
+_llint_op_get_arguments_length:
+    traceExecution()
+    loadis 16[PB, PC, 8], t0
+    loadis 8[PB, PC, 8], t1
+    btpnz [cfr, t0, 8], .opGetArgumentsLengthSlow
+    loadi ArgumentCount + PayloadOffset[cfr], t2
+    subi 1, t2
+    orp tagTypeNumber, t2
+    storep t2, [cfr, t1, 8]
+    dispatch(4)
+
+.opGetArgumentsLengthSlow:
+    callSlowPath(_llint_slow_path_get_arguments_length)
+    dispatch(4)
+
+
+_llint_op_put_by_id:
+    traceExecution()
+    loadis 8[PB, PC, 8], t3
+    loadp 32[PB, PC, 8], t1
+    loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
+    loadis 24[PB, PC, 8], t2
+    loadp JSObject::m_propertyStorage[t0], t3
+    bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
+    loadis 40[PB, PC, 8], t1
+    loadConstantOrVariable(t2, t0)
+    writeBarrier(t0)
+    storep t0, [t3, t1]
+    dispatch(9)
+
+.opPutByIdSlow:
+    callSlowPath(_llint_slow_path_put_by_id)
+    dispatch(9)
+
+
+macro putByIdTransition(additionalChecks)
+    traceExecution()
+    loadis 8[PB, PC, 8], t3
+    loadp 32[PB, PC, 8], t1
+    loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
+    loadis 24[PB, PC, 8], t2
+    bpneq JSCell::m_structure[t0], t1, .opPutByIdSlow
+    additionalChecks(t1, t3, .opPutByIdSlow)
+    loadis 40[PB, PC, 8], t1
+    loadp JSObject::m_propertyStorage[t0], t3
+    addp t1, t3
+    loadConstantOrVariable(t2, t1)
+    writeBarrier(t1)
+    storep t1, [t3]
+    loadp 48[PB, PC, 8], t1
+    storep t1, JSCell::m_structure[t0]
+    dispatch(9)
+end
+
+_llint_op_put_by_id_transition_direct:
+    putByIdTransition(macro (oldStructure, scratch, slow) end)
+
+
+_llint_op_put_by_id_transition_normal:
+    putByIdTransition(
+        macro (oldStructure, scratch, slow)
+            const protoCell = oldStructure    # Reusing the oldStructure register for the proto
+            loadp 56[PB, PC, 8], scratch
+            assert(macro (ok) btpnz scratch, ok end)
+            loadp StructureChain::m_vector[scratch], scratch
+            assert(macro (ok) btpnz scratch, ok end)
+            bpeq Structure::m_prototype[oldStructure], ValueNull, .done
+        .loop:
+            loadp Structure::m_prototype[oldStructure], protoCell
+            loadp JSCell::m_structure[protoCell], oldStructure
+            bpneq oldStructure, [scratch], slow
+            addp 8, scratch
+            bpneq Structure::m_prototype[oldStructure], ValueNull, .loop
+        .done:
+        end)
+
+
+_llint_op_get_by_val:
+    traceExecution()
+    loadp CodeBlock[cfr], t1
+    loadis 16[PB, PC, 8], t2
+    loadis 24[PB, PC, 8], t3
+    loadp CodeBlock::m_globalData[t1], t1
+    loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
+    loadp JSGlobalData::jsArrayClassInfo[t1], t2
+    loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
+    sxi2p t1, t1
+    bpneq [t0], t2, .opGetByValSlow
+    loadp JSArray::m_storage[t0], t3
+    biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow
+    loadis 8[PB, PC, 8], t0
+    loadp ArrayStorage::m_vector[t3, t1, 8], t2
+    btpz t2, .opGetByValSlow
+    storep t2, [cfr, t0, 8]
+    loadp 32[PB, PC, 8], t0
+    valueProfile(t2, t0)
+    dispatch(5)
+
+.opGetByValSlow:
+    callSlowPath(_llint_slow_path_get_by_val)
+    dispatch(5)
+
+
+_llint_op_get_argument_by_val:
+    traceExecution()
+    loadis 16[PB, PC, 8], t0
+    loadis 24[PB, PC, 8], t1
+    btpnz [cfr, t0, 8], .opGetArgumentByValSlow
+    loadConstantOrVariableInt32(t1, t2, .opGetArgumentByValSlow)
+    addi 1, t2
+    loadi ArgumentCount + PayloadOffset[cfr], t1
+    biaeq t2, t1, .opGetArgumentByValSlow
+    negi t2
+    sxi2p t2, t2
+    loadis 8[PB, PC, 8], t3
+    loadp ThisArgumentOffset[cfr, t2, 8], t0
+    storep t0, [cfr, t3, 8]
+    dispatch(5)
+
+.opGetArgumentByValSlow:
+    callSlowPath(_llint_slow_path_get_argument_by_val)
+    dispatch(5)
+
+
+_llint_op_get_by_pname:
+    traceExecution()
+    loadis 24[PB, PC, 8], t1
+    loadConstantOrVariable(t1, t0)
+    loadis 32[PB, PC, 8], t1
+    assertNotConstant(t1)
+    bpneq t0, [cfr, t1, 8], .opGetByPnameSlow
+    loadis 16[PB, PC, 8], t2
+    loadis 40[PB, PC, 8], t3
+    loadConstantOrVariableCell(t2, t0, .opGetByPnameSlow)
+    assertNotConstant(t3)
+    loadp [cfr, t3, 8], t1
+    loadp JSCell::m_structure[t0], t2
+    bpneq t2, JSPropertyNameIterator::m_cachedStructure[t1], .opGetByPnameSlow
+    loadis 48[PB, PC, 8], t3
+    loadi PayloadOffset[cfr, t3, 8], t3
+    subi 1, t3
+    biaeq t3, JSPropertyNameIterator::m_numCacheableSlots[t1], .opGetByPnameSlow
+    loadp JSObject::m_propertyStorage[t0], t0
+    loadp [t0, t3, 8], t0
+    loadis 8[PB, PC, 8], t1
+    storep t0, [cfr, t1, 8]
+    dispatch(7)
+
+.opGetByPnameSlow:
+    callSlowPath(_llint_slow_path_get_by_pname)
+    dispatch(7)
+
+
+_llint_op_put_by_val:
+    traceExecution()
+    loadis 8[PB, PC, 8], t0
+    loadConstantOrVariableCell(t0, t1, .opPutByValSlow)
+    loadis 16[PB, PC, 8], t0
+    loadConstantOrVariableInt32(t0, t2, .opPutByValSlow)
+    sxi2p t2, t2
+    loadp CodeBlock[cfr], t0
+    loadp CodeBlock::m_globalData[t0], t0
+    loadp JSGlobalData::jsArrayClassInfo[t0], t0
+    bpneq [t1], t0, .opPutByValSlow
+    biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow
+    loadp JSArray::m_storage[t1], t0
+    btpz ArrayStorage::m_vector[t0, t2, 8], .opPutByValEmpty
+.opPutByValStoreResult:
+    loadis 24[PB, PC, 8], t3
+    loadConstantOrVariable(t3, t1)
+    writeBarrier(t1)
+    storep t1, ArrayStorage::m_vector[t0, t2, 8]
+    dispatch(4)
+
+.opPutByValEmpty:
+    addi 1, ArrayStorage::m_numValuesInVector[t0]
+    bib t2, ArrayStorage::m_length[t0], .opPutByValStoreResult
+    addi 1, t2, t1
+    storei t1, ArrayStorage::m_length[t0]
+    jmp .opPutByValStoreResult
+
+.opPutByValSlow:
+    callSlowPath(_llint_slow_path_put_by_val)
+    dispatch(4)
+
+
+_llint_op_loop:
+    nop
+_llint_op_jmp:
+    traceExecution()
+    dispatchInt(8[PB, PC, 8])
+
+
+macro jumpTrueOrFalse(conditionOp, slow)
+    loadis 8[PB, PC, 8], t1
+    loadConstantOrVariable(t1, t0)
+    xorp ValueFalse, t0
+    btpnz t0, -1, .slow
+    conditionOp(t0, .target)
+    dispatch(3)
+
+.target:
+    dispatchInt(16[PB, PC, 8])
+
+.slow:
+    callSlowPath(slow)
+    dispatch(0)
+end
+
+
+macro equalNull(cellHandler, immediateHandler)
+    loadis 8[PB, PC, 8], t0
+    assertNotConstant(t0)
+    loadp [cfr, t0, 8], t0
+    btpnz t0, tagMask, .immediate
+    loadp JSCell::m_structure[t0], t2
+    cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target)
+    dispatch(3)
+
+.target:
+    dispatch(16[PB, PC, 8])
+
+.immediate:
+    andp ~TagBitUndefined, t0
+    immediateHandler(t0, .target)
+    dispatch(3)
+end
+
+_llint_op_jeq_null:
+    traceExecution()
+    equalNull(
+        macro (value, target) btbnz value, MasqueradesAsUndefined, target end,
+        macro (value, target) bpeq value, ValueNull, target end)
+
+
+_llint_op_jneq_null:
+    traceExecution()
+    equalNull(
+        macro (value, target) btbz value, MasqueradesAsUndefined, target end,
+        macro (value, target) bpneq value, ValueNull, target end)
+
+
+_llint_op_jneq_ptr:
+    traceExecution()
+    loadis 8[PB, PC, 8], t0
+    loadp 16[PB, PC, 8], t1
+    bpneq t1, [cfr, t0, 8], .opJneqPtrTarget
+    dispatch(4)
+
+.opJneqPtrTarget:
+    dispatchInt(24[PB, PC, 8])
+
+
+macro compare(integerCompare, doubleCompare, slowPath)
+    loadis 8[PB, PC, 8], t2
+    loadis 16[PB, PC, 8], t3
+    loadConstantOrVariable(t2, t0)
+    loadConstantOrVariable(t3, t1)
+    bpb t0, tagTypeNumber, .op1NotInt
+    bpb t1, tagTypeNumber, .op2NotInt
+    integerCompare(t0, t1, .jumpTarget)
+    dispatch(4)
+
+.op1NotInt:
+    btpz t0, tagTypeNumber, .slow
+    bpb t1, tagTypeNumber, .op1NotIntOp2NotInt
+    ci2d t1, ft1
+    jmp .op1NotIntReady
+.op1NotIntOp2NotInt:
+    btpz t1, tagTypeNumber, .slow
+    addp tagTypeNumber, t1
+    fp2d t1, ft1
+.op1NotIntReady:
+    addp tagTypeNumber, t0
+    fp2d t0, ft0
+    doubleCompare(ft0, ft1, .jumpTarget)
+    dispatch(4)
+
+.op2NotInt:
+    ci2d t0, ft0
+    btpz t1, tagTypeNumber, .slow
+    addp tagTypeNumber, t1
+    fp2d t1, ft1
+    doubleCompare(ft0, ft1, .jumpTarget)
+    dispatch(4)
+
+.jumpTarget:
+    dispatchInt(24[PB, PC, 8])
+
+.slow:
+    callSlowPath(slowPath)
+    dispatch(0)
+end
+
+
+_llint_op_switch_imm:
+    traceExecution()
+    loadis 24[PB, PC, 8], t2
+    loadis 8[PB, PC, 8], t3
+    loadConstantOrVariable(t2, t1)
+    loadp CodeBlock[cfr], t2
+    loadp CodeBlock::m_rareData[t2], t2
+    muli sizeof SimpleJumpTable, t3    # FIXME: would be nice to peephole this!
+    loadp CodeBlock::RareData::m_immediateSwitchJumpTables + VectorBufferOffset[t2], t2
+    addp t3, t2
+    bpb t1, tagTypeNumber, .opSwitchImmNotInt
+    subi SimpleJumpTable::min[t2], t1
+    biaeq t1, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchImmFallThrough
+    loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t3
+    loadis [t3, t1, 4], t1
+    btiz t1, .opSwitchImmFallThrough
+    dispatch(t1)
+
+.opSwitchImmNotInt:
+    btpnz t1, tagTypeNumber, .opSwitchImmSlow   # Go slow if it's a double.
+.opSwitchImmFallThrough:
+    dispatchInt(16[PB, PC, 8])
+
+.opSwitchImmSlow:
+    callSlowPath(_llint_slow_path_switch_imm)
+    dispatch(0)
+
+
+_llint_op_switch_char:
+    traceExecution()
+    loadis 24[PB, PC, 8], t2
+    loadis 8[PB, PC, 8], t3
+    loadConstantOrVariable(t2, t1)
+    loadp CodeBlock[cfr], t2
+    loadp CodeBlock::m_rareData[t2], t2
+    muli sizeof SimpleJumpTable, t3
+    loadp CodeBlock::RareData::m_characterSwitchJumpTables + VectorBufferOffset[t2], t2
+    addp t3, t2
+    btpnz t1, tagMask, .opSwitchCharFallThrough
+    loadp JSCell::m_structure[t1], t0
+    bbneq Structure::m_typeInfo + TypeInfo::m_type[t0], StringType, .opSwitchCharFallThrough
+    bineq JSString::m_length[t1], 1, .opSwitchCharFallThrough
+    loadp JSString::m_value[t1], t0
+    btpz  t0, .opSwitchOnRope
+    loadp StringImpl::m_data8[t0], t1
+    btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
+    loadh [t1], t0
+    jmp .opSwitchCharReady
+.opSwitchChar8Bit:
+    loadb [t1], t0
+.opSwitchCharReady:
+    subi SimpleJumpTable::min[t2], t0
+    biaeq t0, SimpleJumpTable::branchOffsets + VectorSizeOffset[t2], .opSwitchCharFallThrough
+    loadp SimpleJumpTable::branchOffsets + VectorBufferOffset[t2], t2
+    loadis [t2, t0, 4], t1
+    btiz t1, .opSwitchCharFallThrough
+    dispatch(t1)
+
+.opSwitchCharFallThrough:
+    dispatchInt(16[PB, PC, 8])
+
+.opSwitchOnRope:
+    callSlowPath(_llint_slow_path_switch_char)
+    dispatch(0)
+
+
+_llint_op_new_func:
+    traceExecution()
+    btiz 24[PB, PC, 8], .opNewFuncUnchecked
+    loadis 8[PB, PC, 8], t1
+    btpnz [cfr, t1, 8], .opNewFuncDone
+.opNewFuncUnchecked:
+    callSlowPath(_llint_slow_path_new_func)
+.opNewFuncDone:
+    dispatch(4)
+
+
+macro doCall(slowPath)
+    loadis 8[PB, PC, 8], t0
+    loadp 32[PB, PC, 8], t1
+    loadp LLIntCallLinkInfo::callee[t1], t2
+    loadConstantOrVariable(t0, t3)
+    bpneq t3, t2, .opCallSlow
+    loadis 24[PB, PC, 8], t3
+    addi 6, PC
+    lshifti 3, t3
+    addp cfr, t3
+    loadp JSFunction::m_scopeChain[t2], t0
+    storep t2, Callee[t3]
+    storep t0, ScopeChain[t3]
+    loadis 16 - 48[PB, PC, 8], t2
+    storei PC, ArgumentCount + TagOffset[cfr]
+    storep cfr, CallerFrame[t3]
+    storei t2, ArgumentCount + PayloadOffset[t3]
+    move t3, cfr
+    call LLIntCallLinkInfo::machineCodeTarget[t1]
+    dispatchAfterCall()
+
+.opCallSlow:
+    slowPathForCall(6, slowPath)
+end
+
+
+_llint_op_tear_off_activation:
+    traceExecution()
+    loadis 8[PB, PC, 8], t0
+    loadis 16[PB, PC, 8], t1
+    btpnz [cfr, t0, 8], .opTearOffActivationCreated
+    btpz [cfr, t1, 8], .opTearOffActivationNotCreated
+.opTearOffActivationCreated:
+    callSlowPath(_llint_slow_path_tear_off_activation)
+.opTearOffActivationNotCreated:
+    dispatch(3)
+
+
+_llint_op_tear_off_arguments:
+    traceExecution()
+    loadis 8[PB, PC, 8], t0
+    subi 1, t0   # Get the unmodifiedArgumentsRegister
+    btpz [cfr, t0, 8], .opTearOffArgumentsNotCreated
+    callSlowPath(_llint_slow_path_tear_off_arguments)
+.opTearOffArgumentsNotCreated:
+    dispatch(2)
+
+
+_llint_op_ret:
+    traceExecution()
+    checkSwitchToJITForEpilogue()
+    loadis 8[PB, PC, 8], t2
+    loadConstantOrVariable(t2, t0)
+    doReturn()
+
+
+_llint_op_call_put_result:
+    loadis 8[PB, PC, 8], t2
+    loadp 16[PB, PC, 8], t3
+    storep t0, [cfr, t2, 8]
+    valueProfile(t0, t3)
+    traceExecution()
+    dispatch(3)
+
+
+_llint_op_ret_object_or_this:
+    traceExecution()
+    checkSwitchToJITForEpilogue()
+    loadis 8[PB, PC, 8], t2
+    loadConstantOrVariable(t2, t0)
+    btpnz t0, tagMask, .opRetObjectOrThisNotObject
+    loadp JSCell::m_structure[t0], t2
+    bbb Structure::m_typeInfo + TypeInfo::m_type[t2], ObjectType, .opRetObjectOrThisNotObject
+    doReturn()
+
+.opRetObjectOrThisNotObject:
+    loadis 16[PB, PC, 8], t2
+    loadConstantOrVariable(t2, t0)
+    doReturn()
+
+
+_llint_op_to_primitive:
+    traceExecution()
+    loadis 16[PB, PC, 8], t2
+    loadis 8[PB, PC, 8], t3
+    loadConstantOrVariable(t2, t0)
+    btpnz t0, tagMask, .opToPrimitiveIsImm
+    loadp JSCell::m_structure[t0], t2
+    bbneq Structure::m_typeInfo + TypeInfo::m_type[t2], StringType, .opToPrimitiveSlowCase
+.opToPrimitiveIsImm:
+    storep t0, [cfr, t3, 8]
+    dispatch(3)
+
+.opToPrimitiveSlowCase:
+    callSlowPath(_llint_slow_path_to_primitive)
+    dispatch(3)
+
+
+_llint_op_next_pname:
+    traceExecution()
+    loadis 24[PB, PC, 8], t1
+    loadis 32[PB, PC, 8], t2
+    assertNotConstant(t1)
+    assertNotConstant(t2)
+    loadi PayloadOffset[cfr, t1, 8], t0
+    bieq t0, PayloadOffset[cfr, t2, 8], .opNextPnameEnd
+    loadis 40[PB, PC, 8], t2
+    assertNotConstant(t2)
+    loadp [cfr, t2, 8], t2
+    loadp JSPropertyNameIterator::m_jsStrings[t2], t3
+    loadp [t3, t0, 8], t3
+    addi 1, t0
+    storei t0, PayloadOffset[cfr, t1, 8]
+    loadis 8[PB, PC, 8], t1
+    storep t3, [cfr, t1, 8]
+    loadis 16[PB, PC, 8], t3
+    assertNotConstant(t3)
+    loadp [cfr, t3, 8], t3
+    loadp JSCell::m_structure[t3], t1
+    bpneq t1, JSPropertyNameIterator::m_cachedStructure[t2], .opNextPnameSlow
+    loadp JSPropertyNameIterator::m_cachedPrototypeChain[t2], t0
+    loadp StructureChain::m_vector[t0], t0
+    btpz [t0], .opNextPnameTarget
+.opNextPnameCheckPrototypeLoop:
+    bpeq Structure::m_prototype[t1], ValueNull, .opNextPnameSlow
+    loadp Structure::m_prototype[t1], t2
+    loadp JSCell::m_structure[t2], t1
+    bpneq t1, [t0], .opNextPnameSlow
+    addp 8, t0
+    btpnz [t0], .opNextPnameCheckPrototypeLoop
+.opNextPnameTarget:
+    dispatchInt(48[PB, PC, 8])
+
+.opNextPnameEnd:
+    dispatch(7)
+
+.opNextPnameSlow:
+    callSlowPath(_llint_slow_path_next_pname) # This either keeps the PC where it was (causing us to loop) or sets it to target.
+    dispatch(0)
+
+
+_llint_op_catch:
+    # This is where we end up from the JIT's throw trampoline (because the
+    # machine code return address will be set to _llint_op_catch), and from
+    # the interpreter's throw trampoline (see _llint_throw_trampoline).
+    # The JIT throwing protocol calls for the cfr to be in t0. The throwing
+    # code must have known that we were throwing to the interpreter, and have
+    # set JSGlobalData::targetInterpreterPCForThrow.
+    move t0, cfr
+    loadp CodeBlock[cfr], PB
+    loadp CodeBlock::m_instructions[PB], PB
+    loadp JITStackFrame::globalData[sp], t3
+    loadp JSGlobalData::targetInterpreterPCForThrow[t3], PC
+    subp PB, PC
+    urshiftp 3, PC
+    loadp JSGlobalData::exception[t3], t0
+    storep 0, JSGlobalData::exception[t3]
+    loadis 8[PB, PC, 8], t2
+    storep t0, [cfr, t2, 8]
+    traceExecution()
+    dispatch(2)
+
+
+_llint_op_end:
+    traceExecution()
+    checkSwitchToJITForEpilogue()
+    loadis 8[PB, PC, 8], t0
+    assertNotConstant(t0)
+    loadp [cfr, t0, 8], t0
+    doReturn()
+
+
+_llint_throw_from_slow_path_trampoline:
+    # When throwing from the interpreter (i.e. throwing from LLIntSlowPaths), so
+    # the throw target is not necessarily interpreted code, we come to here.
+    # This essentially emulates the JIT's throwing protocol.
+    loadp JITStackFrame::globalData[sp], t1
+    loadp JSGlobalData::callFrameForThrow[t1], t0
+    jmp JSGlobalData::targetMachinePCForThrow[t1]
+
+
+_llint_throw_during_call_trampoline:
+    preserveReturnAddressAfterCall(t2)
+    loadp JITStackFrame::globalData[sp], t1
+    loadp JSGlobalData::callFrameForThrow[t1], t0
+    jmp JSGlobalData::targetMachinePCForThrow[t1]
+
+
+macro nativeCallTrampoline(executableOffsetToFunction)
+    storep 0, CodeBlock[cfr]
+    loadp JITStackFrame::globalData + 8[sp], t0
+    storep cfr, JSGlobalData::topCallFrame[t0]
+    loadp CallerFrame[cfr], t0
+    loadp ScopeChain[t0], t1
+    storep t1, ScopeChain[cfr]
+    peek 0, t1
+    storep t1, ReturnPC[cfr]
+    move cfr, t5  # t5 = rdi
+    subp 16 - 8, sp
+    loadp Callee[cfr], t4 # t4 = rsi
+    loadp JSFunction::m_executable[t4], t1
+    move t0, cfr # Restore cfr to avoid loading from stack
+    call executableOffsetToFunction[t1]
+    addp 16 - 8, sp
+    loadp JITStackFrame::globalData + 8[sp], t3
+    btpnz JSGlobalData::exception[t3], .exception
+    ret
+.exception:
+    preserveReturnAddressAfterCall(t1)
+    loadi ArgumentCount + TagOffset[cfr], PC
+    loadp CodeBlock[cfr], PB
+    loadp CodeBlock::m_instructions[PB], PB
+    loadp JITStackFrame::globalData[sp], t0
+    storep cfr, JSGlobalData::topCallFrame[t0]
+    callSlowPath(_llint_throw_from_native_call)
+    jmp _llint_throw_from_slow_path_trampoline
+end
+
diff --git a/offlineasm/armv7.rb b/offlineasm/armv7.rb
new file mode 100644 (file)
index 0000000..69df51a
--- /dev/null
@@ -0,0 +1,1006 @@
+# 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.
+
+require "ast"
+require "opt"
+
+class Node
+    def armV7Single
+        doubleOperand = armV7Operand
+        raise "Bogus register name #{doubleOperand}" unless doubleOperand =~ /^d/
+        "s" + ($~.post_match.to_i * 2).to_s
+    end
+end
+
+class SpecialRegister < NoChildren
+    def armV7Operand
+        @name
+    end
+end
+
+ARMv7_EXTRA_GPRS = [SpecialRegister.new("r9"), SpecialRegister.new("r8"), SpecialRegister.new("r3")]
+ARMv7_EXTRA_FPRS = [SpecialRegister.new("d7")]
+ARMv7_SCRATCH_FPR = SpecialRegister.new("d8")
+
+def armV7MoveImmediate(value, register)
+    # Currently we only handle the simple cases, and fall back to mov/movt for the complex ones.
+    if value >= 0 && value < 256
+        $asm.puts "movw #{register.armV7Operand}, \##{value}"
+    elsif (~value) >= 0 && (~value) < 256
+        $asm.puts "mvn #{register.armV7Operand}, \##{~value}"
+    else
+        $asm.puts "movw #{register.armV7Operand}, \##{value & 0xffff}"
+        if (value & 0xffff0000) != 0
+            $asm.puts "movt #{register.armV7Operand}, \##{value >> 16}"
+        end
+    end
+end
+
+class RegisterID
+    def armV7Operand
+        case name
+        when "t0", "a0", "r0"
+            "r0"
+        when "t1", "a1", "r1"
+            "r1"
+        when "t2", "a2"
+            "r2"
+        when "a3"
+            "r3"
+        when "t3"
+            "r4"
+        when "t4"
+            "r10"
+        when "cfr"
+            "r5"
+        when "lr"
+            "lr"
+        when "sp"
+            "sp"
+        else
+            raise "Bad register #{name} for ARMv7 at #{codeOriginString}"
+        end
+    end
+end
+
+class FPRegisterID
+    def armV7Operand
+        case name
+        when "ft0", "fr"
+            "d0"
+        when "ft1"
+            "d1"
+        when "ft2"
+            "d2"
+        when "ft3"
+            "d3"
+        when "ft4"
+            "d4"
+        when "ft5"
+            "d5"
+        else
+            raise "Bad register #{name} for ARMv7 at #{codeOriginString}"
+        end
+    end
+end
+
+class Immediate
+    def armV7Operand
+        raise "Invalid immediate #{value} at #{codeOriginString}" if value < 0 or value > 255
+        "\##{value}"
+    end
+end
+
+class Address
+    def armV7Operand
+        raise "Bad offset at #{codeOriginString}" if offset.value < -0xff or offset.value > 0xfff
+        "[#{base.armV7Operand}, \##{offset.value}]"
+    end
+end
+
+class BaseIndex
+    def armV7Operand
+        raise "Bad offset at #{codeOriginString}" if offset.value != 0
+        "[#{base.armV7Operand}, #{index.armV7Operand}, lsl \##{scaleShift}]"
+    end
+end
+
+class AbsoluteAddress
+    def armV7Operand
+        raise "Unconverted absolute address at #{codeOriginString}"
+    end
+end
+
+#
+# Lowering of branch ops. For example:
+#
+# baddiz foo, bar, baz
+#
+# will become:
+#
+# addi foo, bar
+# bz baz
+#
+
+def armV7LowerBranchOps(list)
+    newList = []
+    list.each {
+        | node |
+        if node.is_a? Instruction
+            case node.opcode
+            when /^b(addi|subi|ori|addp)/
+                op = $1
+                branch = "b" + $~.post_match
+                
+                case op
+                when "addi", "addp"
+                    op = "addis"
+                when "subi"
+                    op = "subis"
+                when "ori"
+                    op = "oris"
+                end
+                
+                newList << Instruction.new(node.codeOrigin, op, node.operands[0..-2])
+                newList << Instruction.new(node.codeOrigin, branch, [node.operands[-1]])
+            when "bmulio"
+                tmp1 = Tmp.new(node.codeOrigin, :gpr)
+                tmp2 = Tmp.new(node.codeOrigin, :gpr)
+                newList << Instruction.new(node.codeOrigin, "smulli", [node.operands[0], node.operands[1], node.operands[1], tmp1])
+                newList << Instruction.new(node.codeOrigin, "rshifti", [node.operands[-2], Immediate.new(node.codeOrigin, 31), tmp2])
+                newList << Instruction.new(node.codeOrigin, "bineq", [tmp1, tmp2, node.operands[-1]])
+            when /^bmuli/
+                condition = $~.post_match
+                newList << Instruction.new(node.codeOrigin, "muli", node.operands[0..-2])
+                newList << Instruction.new(node.codeOrigin, "bti" + condition, [node.operands[-2], node.operands[-1]])
+            else
+                newList << node
+            end
+        else
+            newList << node
+        end
+    }
+    newList
+end
+
+#
+# Lowering of shift ops. For example:
+#
+# lshifti foo, bar
+#
+# will become:
+#
+# andi foo, 31, tmp
+# lshifti tmp, bar
+#
+
+def armV7SanitizeShift(operand, list)
+    return operand if operand.immediate?
+    
+    tmp = Tmp.new(operand.codeOrigin, :gpr)
+    list << Instruction.new(operand.codeOrigin, "andi", [operand, Immediate.new(operand.codeOrigin, 31), tmp])
+    tmp
+end
+
+def armV7LowerShiftOps(list)
+    newList = []
+    list.each {
+        | node |
+        if node.is_a? Instruction
+            case node.opcode
+            when "lshifti", "rshifti", "urshifti", "lshiftp", "rshiftp", "urshiftp"
+                if node.operands.size == 2
+                    newList << Instruction.new(node.codeOrigin, node.opcode, [armV7SanitizeShift(node.operands[0], newList), node.operands[1]])
+                else
+                    newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], armV7SanitizeShift(node.operands[1], newList), node.operands[2]])
+                    raise "Wrong number of operands for shift at #{node.codeOriginString}" unless node.operands.size == 3
+                end
+            else
+                newList << node
+            end
+        else
+            newList << node
+        end
+    }
+    newList
+end
+
+#
+# Lowering of malformed addresses. For example:
+#
+# loadp 10000[foo], bar
+#
+# will become:
+#
+# move 10000, tmp
+# addp foo, tmp
+# loadp 0[tmp], bar
+#
+
+class Node
+    def armV7LowerMalformedAddressesRecurse(list)
+        mapChildren {
+            | node |
+            node.armV7LowerMalformedAddressesRecurse(list)
+        }
+    end
+end
+
+class Address
+    def armV7LowerMalformedAddressesRecurse(list)
+        if offset.value < -0xff or offset.value > 0xfff
+            tmp = Tmp.new(codeOrigin, :gpr)
+            list << Instruction.new(codeOrigin, "move", [offset, tmp])
+            list << Instruction.new(codeOrigin, "addp", [base, tmp])
+            Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
+        else
+            self
+        end
+    end
+end
+
+class BaseIndex
+    def armV7LowerMalformedAddressesRecurse(list)
+        if offset.value != 0
+            tmp = Tmp.new(codeOrigin, :gpr)
+            list << Instruction.new(codeOrigin, "move", [offset, tmp])
+            list << Instruction.new(codeOrigin, "addp", [base, tmp])
+            BaseIndex.new(codeOrigin, tmp, index, scale, Immediate.new(codeOrigin, 0))
+        else
+            self
+        end
+    end
+end
+
+class AbsoluteAddress
+    def armV7LowerMalformedAddressesRecurse(list)
+        tmp = Tmp.new(codeOrigin, :gpr)
+        list << Instruction.new(codeOrigin, "move", [address, tmp])
+        Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
+    end
+end
+
+def armV7LowerMalformedAddresses(list)
+    newList = []
+    list.each {
+        | node |
+        newList << node.armV7LowerMalformedAddressesRecurse(newList)
+    }
+    newList
+end
+
+#
+# Lowering of malformed addresses in double loads and stores. For example:
+#
+# loadd [foo, bar, 8], baz
+#
+# becomes:
+#
+# leap [foo, bar, 8], tmp
+# loadd [tmp], baz
+#
+
+class Node
+    def armV7DoubleAddress(list)
+        self
+    end
+end
+
+class BaseIndex
+    def armV7DoubleAddress(list)
+        tmp = Tmp.new(codeOrigin, :gpr)
+        list << Instruction.new(codeOrigin, "leap", [self, tmp])
+        Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
+    end
+end
+
+def armV7LowerMalformedAddressesDouble(list)
+    newList = []
+    list.each {
+        | node |
+        if node.is_a? Instruction
+            case node.opcode
+            when "loadd"
+                newList << Instruction.new(node.codeOrigin, "loadd", [node.operands[0].armV7DoubleAddress(newList), node.operands[1]])
+            when "stored"
+                newList << Instruction.new(node.codeOrigin, "stored", [node.operands[0], node.operands[1].armV7DoubleAddress(newList)])
+            else
+                newList << node
+            end
+        else
+            newList << node
+        end
+    }
+    newList
+end
+
+#
+# Lowering of misplaced immediates. For example:
+#
+# storei 0, [foo]
+#
+# will become:
+#
+# move 0, tmp
+# storei tmp, [foo]
+#
+
+def armV7LowerMisplacedImmediates(list)
+    newList = []
+    list.each {
+        | node |
+        if node.is_a? Instruction
+            case node.opcode
+            when "storei", "storep"
+                operands = node.operands
+                newOperands = []
+                operands.each {
+                    | operand |
+                    if operand.is_a? Immediate
+                        tmp = Tmp.new(operand.codeOrigin, :gpr)
+                        newList << Instruction.new(operand.codeOrigin, "move", [operand, tmp])
+                        newOperands << tmp
+                    else
+                        newOperands << operand
+                    end
+                }
+                newList << Instruction.new(node.codeOrigin, node.opcode, newOperands)
+            else
+                newList << node
+            end
+        else
+            newList << node
+        end
+    }
+    newList
+end
+
+#
+# Lowering of malformed immediates except when used in a "move" instruction.
+# For example:
+#
+# addp 642641, foo
+#
+# will become:
+#
+# move 642641, tmp
+# addp tmp, foo
+#
+
+class Node
+    def armV7LowerMalformedImmediatesRecurse(list)
+        mapChildren {
+            | node |
+            node.armV7LowerMalformedImmediatesRecurse(list)
+        }
+    end
+end
+
+class Address
+    def armV7LowerMalformedImmediatesRecurse(list)
+        self
+    end
+end
+
+class BaseIndex
+    def armV7LowerMalformedImmediatesRecurse(list)
+        self
+    end
+end
+
+class AbsoluteAddress
+    def armV7LowerMalformedImmediatesRecurse(list)
+        self
+    end
+end
+
+class Immediate
+    def armV7LowerMalformedImmediatesRecurse(list)
+        if value < 0 or value > 255
+            tmp = Tmp.new(codeOrigin, :gpr)
+            list << Instruction.new(codeOrigin, "move", [self, tmp])
+            tmp
+        else
+            self
+        end
+    end
+end
+
+def armV7LowerMalformedImmediates(list)
+    newList = []
+    list.each {
+        | node |
+        if node.is_a? Instruction
+            case node.opcode
+            when "move"
+                newList << node
+            when "addi", "addp", "addis", "subi", "subp", "subis"
+                if node.operands[0].is_a? Immediate and
+                        node.operands[0].value < 0 and
+                        node.operands[0].value >= 255 and
+                        node.operands.size == 2
+                    if node.opcode =~ /add/
+                        newOpcode = "sub" + node.opcode[-1..-1]
+                    else
+                        newOpcode = "add" + node.opcode[-1..-1]
+                    end
+                    newList << Instruction.new(node.codeOrigin, newOpcode,
+                                               [Immediate.new(-node.operands[0].value)] + node.operands[1..-1])
+                else
+                    newList << node.armV7LowerMalformedImmediatesRecurse(newList)
+                end
+            when "muli", "mulp"
+                if node.operands[0].is_a? Immediate
+                    tmp = Tmp.new(codeOrigin, :gpr)
+                    newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
+                    newList << Instruction.new(node.codeOrigin, "muli", [tmp] + node.operands[1..-1])
+                else
+                    newList << node.armV7LowerMalformedImmediatesRecurse(newList)
+                end
+            else
+                newList << node.armV7LowerMalformedImmediatesRecurse(newList)
+            end
+        else
+            newList << node
+        end
+    }
+    newList
+end
+
+#
+# Lowering of misplaced addresses. For example:
+#
+# addi foo, [bar]
+#
+# will become:
+#
+# loadi [bar], tmp
+# addi foo, tmp
+# storei tmp, [bar]
+#
+# Another example:
+#
+# addi [foo], bar
+#
+# will become:
+#
+# loadi [foo], tmp
+# addi tmp, bar
+#
+
+def armV7AsRegister(preList, postList, operand, suffix, needStore)
+    return operand unless operand.address?
+    
+    tmp = Tmp.new(operand.codeOrigin, if suffix == "d" then :fpr else :gpr end)
+    preList << Instruction.new(operand.codeOrigin, "load" + suffix, [operand, tmp])
+    if needStore
+        postList << Instruction.new(operand.codeOrigin, "store" + suffix, [tmp, operand])
+    end
+    tmp
+end
+
+def armV7AsRegisters(preList, postList, operands, suffix)
+    newOperands = []
+    operands.each_with_index {
+        | operand, index |
+        newOperands << armV7AsRegister(preList, postList, operand, suffix, index == operands.size - 1)
+    }
+    newOperands
+end
+
+def armV7LowerMisplacedAddresses(list)
+    newList = []
+    list.each {
+        | node |
+        if node.is_a? Instruction
+            postInstructions = []
+            case node.opcode
+            when "addi", "addp", "addis", "andi", "andp", "lshifti", "lshiftp", "muli", "mulp", "negi",
+                "negp", "noti", "ori", "oris", "orp", "rshifti", "urshifti", "rshiftp", "urshiftp", "subi",
+                "subp", "subis", "xori", "xorp", /^bi/, /^bp/, /^bti/, /^btp/, /^ci/, /^cp/, /^ti/
+                newList << Instruction.new(node.codeOrigin,
+                                           node.opcode,
+                                           armV7AsRegisters(newList, postInstructions, node.operands, "i"))
+            when "bbeq", "bbneq", "bba", "bbaeq", "bbb", "bbbeq", "btbo", "btbz", "btbnz", "tbz", "tbnz",
+                "tbo", "cbeq", "cbneq", "cba", "cbaeq", "cbb", "cbbeq"
+                newList << Instruction.new(node.codeOrigin,
+                                           node.opcode,
+                                           armV7AsRegisters(newList, postInstructions, node.operands, "b"))
+            when "bbgt", "bbgteq", "bblt", "bblteq", "btbs", "tbs", "cbgt", "cbgteq", "cblt", "cblteq"
+                newList << Instruction.new(node.codeOrigin,
+                                           node.opcode,
+                                           armV7AsRegisters(newList, postInstructions, node.operands, "bs"))
+            when "addd", "divd", "subd", "muld", "sqrtd", /^bd/
+                newList << Instruction.new(node.codeOrigin,
+                                           node.opcode,
+                                           armV7AsRegisters(newList, postInstructions, node.operands, "d"))
+            when "jmp", "call"
+                newList << Instruction.new(node.codeOrigin,
+                                           node.opcode,
+                                           [armV7AsRegister(newList, postInstructions, node.operands[0], "p", false)])
+            else
+                newList << node
+            end
+            newList += postInstructions
+        else
+            newList << node
+        end
+    }
+    newList
+end
+
+#
+# Lowering of register reuse in compare instructions. For example:
+#
+# cieq t0, t1, t0
+#
+# will become:
+#
+# mov tmp, t0
+# cieq tmp, t1, t0
+#
+
+def armV7LowerRegisterReuse(list)
+    newList = []
+    list.each {
+        | node |
+        if node.is_a? Instruction
+            case node.opcode
+            when "cieq", "cineq", "cia", "ciaeq", "cib", "cibeq", "cigt", "cigteq", "cilt", "cilteq",
+                "cpeq", "cpneq", "cpa", "cpaeq", "cpb", "cpbeq", "cpgt", "cpgteq", "cplt", "cplteq",
+                "tio", "tis", "tiz", "tinz", "tbo", "tbs", "tbz", "tbnz", "tpo", "tps", "tpz", "tpnz",
+                "cbeq", "cbneq", "cba", "cbaeq", "cbb", "cbbeq", "cbgt", "cbgteq", "cblt", "cblteq"
+                if node.operands.size == 2
+                    if node.operands[0] == node.operands[1]
+                        tmp = Tmp.new(node.codeOrigin, :gpr)
+                        newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
+                        newList << Instruction.new(node.codeOrigin, node.opcode, [tmp, node.operands[1]])
+                    else
+                        newList << node
+                    end
+                else
+                    raise "Wrong number of arguments at #{node.codeOriginString}" unless node.operands.size == 3
+                    if node.operands[0] == node.operands[2]
+                        tmp = Tmp.new(node.codeOrigin, :gpr)
+                        newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp])
+                        newList << Instruction.new(node.codeOrigin, node.opcode, [tmp, node.operands[1], node.operands[2]])
+                    elsif node.operands[1] == node.operands[2]
+                        tmp = Tmp.new(node.codeOrigin, :gpr)
+                        newList << Instruction.new(node.codeOrigin, "move", [node.operands[1], tmp])
+                        newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], tmp, node.operands[2]])
+                    else
+                        newList << node
+                    end
+                end
+            else
+                newList << node
+            end
+        else
+            newList << node
+        end
+    }
+    newList
+end
+
+#
+# Lea support.
+#
+
+class Address
+    def armV7EmitLea(destination)
+        if destination == base
+            $asm.puts "adds #{destination.armV7Operand}, \##{offset.value}"
+        else
+            $asm.puts "adds #{destination.armV7Operand}, #{base.armV7Operand}, \##{offset.value}"
+        end
+    end
+end
+
+class BaseIndex
+    def armV7EmitLea(destination)
+        raise "Malformed BaseIndex, offset should be zero at #{codeOriginString}" unless offset.value == 0
+        $asm.puts "add.w #{destination.armV7Operand}, #{base.armV7Operand}, #{index.armV7Operand}, lsl \##{scaleShift}"
+    end
+end
+
+# FIXME: we could support AbsoluteAddress for lea, but we don't.
+
+#
+# Actual lowering code follows.
+#
+
+class Sequence
+    def getModifiedListARMv7
+        myList = @list
+        
+        # Verify that we will only see instructions and labels.
+        myList.each {
+            | node |
+            unless node.is_a? Instruction or
+                    node.is_a? Label or
+                    node.is_a? LocalLabel or
+                    node.is_a? Skip
+                raise "Unexpected #{node.inspect} at #{node.codeOrigin}" 
+            end
+        }
+        
+        myList = armV7LowerBranchOps(myList)
+        myList = armV7LowerShiftOps(myList)
+        myList = armV7LowerMalformedAddresses(myList)
+        myList = armV7LowerMalformedAddressesDouble(myList)
+        myList = armV7LowerMisplacedImmediates(myList)
+        myList = armV7LowerMalformedImmediates(myList)
+        myList = armV7LowerMisplacedAddresses(myList)
+        myList = armV7LowerRegisterReuse(myList)
+        myList = assignRegistersToTemporaries(myList, :gpr, ARMv7_EXTRA_GPRS)
+        myList = assignRegistersToTemporaries(myList, :fpr, ARMv7_EXTRA_FPRS)
+        
+        return myList
+    end
+end
+
+def armV7Operands(operands)
+    operands.map{|v| v.armV7Operand}.join(", ")
+end
+
+def armV7FlippedOperands(operands)
+    armV7Operands([operands[-1]] + operands[0..-2])
+end
+
+def emitArmV7Compact(opcode2, opcode3, operands)
+    if operands.size == 3
+        $asm.puts "#{opcode3} #{armV7FlippedOperands(operands)}"
+    else
+        raise unless operands.size == 2
+        raise unless operands[1].is_a? RegisterID
+        if operands[0].is_a? Immediate
+            $asm.puts "#{opcode3} #{operands[1].armV7Operand}, #{operands[1].armV7Operand}, #{operands[0].armV7Operand}"
+        else
+            $asm.puts "#{opcode2} #{armV7FlippedOperands(operands)}"
+        end
+    end
+end
+
+def emitArmV7(opcode, operands)
+    if operands.size == 3
+        $asm.puts "#{opcode} #{armV7FlippedOperands(operands)}"
+    else
+        raise unless operands.size == 2
+        $asm.puts "#{opcode} #{operands[1].armV7Operand}, #{operands[1].armV7Operand}, #{operands[0].armV7Operand}"
+    end
+end
+
+def emitArmV7DoubleBranch(branchOpcode, operands)
+    $asm.puts "vcmpe.f64 #{armV7Operands(operands[0..1])}"
+    $asm.puts "vmrs apsr_nzcv, fpscr"
+    $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
+end
+
+def emitArmV7Test(operands)
+    value = operands[0]
+    case operands.size
+    when 2
+        mask = Immediate.new(codeOrigin, -1)
+    when 3
+        mask = operands[1]
+    else
+        raise "Expected 2 or 3 operands but got #{operands.size} at #{codeOriginString}"
+    end
+    
+    if mask.is_a? Immediate and mask.value == -1
+        $asm.puts "tst #{value.armV7Operand}, #{value.armV7Operand}"
+    elsif mask.is_a? Immediate
+        $asm.puts "tst.w #{value.armV7Operand}, #{mask.armV7Operand}"
+    else
+        $asm.puts "tst #{value.armV7Operand}, #{mask.armV7Operand}"
+    end
+end
+
+def emitArmV7Compare(operands, code)
+    $asm.puts "movs #{operands[2].armV7Operand}, \#0"
+    $asm.puts "cmp #{operands[0].armV7Operand}, #{operands[1].armV7Operand}"
+    $asm.puts "it #{code}"
+    $asm.puts "mov#{code} #{operands[2].armV7Operand}, \#1"
+end
+
+def emitArmV7TestSet(operands, code)
+    $asm.puts "movs #{operands[-1].armV7Operand}, \#0"
+    emitArmV7Test(operands)
+    $asm.puts "it #{code}"
+    $asm.puts "mov#{code} #{operands[-1].armV7Operand}, \#1"
+end
+
+class Instruction
+    def lowerARMv7
+        $asm.comment codeOriginString
+        case opcode
+        when "addi", "addp", "addis"
+            if opcode == "addis"
+                suffix = "s"
+            else
+                suffix = ""
+            end
+            if operands.size == 3 and operands[0].is_a? Immediate
+                raise unless operands[1].is_a? RegisterID
+                raise unless operands[2].is_a? RegisterID
+                if operands[0].value == 0 and suffix.empty?
+                    unless operands[1] == operands[2]
+                        $asm.puts "mov #{operands[2].armV7Operand}, #{operands[1].armV7Operand}"
+                    end
+                else
+                    $asm.puts "adds #{operands[2].armV7Operand}, #{operands[1].armV7Operand}, #{operands[0].armV7Operand}"
+                end
+            elsif operands.size == 3 and operands[0].is_a? RegisterID
+                raise unless operands[1].is_a? RegisterID
+                raise unless operands[2].is_a? RegisterID
+                $asm.puts "adds #{armV7FlippedOperands(operands)}"
+            else
+                if operands[0].is_a? Immediate
+                    unless Immediate.new(nil, 0) == operands[0]
+                        $asm.puts "adds #{armV7FlippedOperands(operands)}"
+                    end
+                else
+                    $asm.puts "add#{suffix} #{armV7FlippedOperands(operands)}"
+                end
+            end
+        when "andi", "andp"
+            emitArmV7Compact("ands", "and", operands)
+        when "ori", "orp"
+            emitArmV7Compact("orrs", "orr", operands)
+        when "oris"
+            emitArmV7Compact("orrs", "orrs", operands)
+        when "xori", "xorp"
+            emitArmV7Compact("eors", "eor", operands)
+        when "lshifti", "lshiftp"
+            emitArmV7Compact("lsls", "lsls", operands)
+        when "rshifti", "rshiftp"
+            emitArmV7Compact("asrs", "asrs", operands)
+        when "urshifti", "urshiftp"
+            emitArmV7Compact("lsrs", "lsrs", operands)
+        when "muli", "mulp"
+            emitArmV7("mul", operands)
+        when "subi", "subp", "subis"
+            emitArmV7Compact("subs", "subs", operands)
+        when "negi", "negp"
+            $asm.puts "rsbs #{operands[0].armV7Operand}, #{operands[0].armV7Operand}, \#0"
+        when "noti"
+            $asm.puts "mvns #{operands[0].armV7Operand}, #{operands[0].armV7Operand}"
+        when "loadi", "loadis", "loadp"
+            $asm.puts "ldr #{armV7FlippedOperands(operands)}"
+        when "storei", "storep"
+            $asm.puts "str #{armV7Operands(operands)}"
+        when "loadb"
+            $asm.puts "ldrb #{armV7FlippedOperands(operands)}"
+        when "loadbs"
+            $asm.puts "ldrsb.w #{armV7FlippedOperands(operands)}"
+        when "storeb"
+            $asm.puts "strb #{armV7Operands(operands)}"
+        when "loadh"
+            $asm.puts "ldrh #{armV7FlippedOperands(operands)}"
+        when "loadhs"
+            $asm.puts "ldrsh.w #{armV7FlippedOperands(operands)}"
+        when "storeh"
+            $asm.puts "strh #{armV7Operands(operands)}"
+        when "loadd"
+            $asm.puts "vldr.64 #{armV7FlippedOperands(operands)}"
+        when "stored"
+            $asm.puts "vstr.64 #{armV7Operands(operands)}"
+        when "addd"
+            emitArmV7("vadd.f64", operands)
+        when "divd"
+            emitArmV7("vdiv.f64", operands)
+        when "subd"
+            emitArmV7("vsub.f64", operands)
+        when "muld"
+            emitArmV7("vmul.f64", operands)
+        when "sqrtd"
+            $asm.puts "vsqrt.f64 #{armV7FlippedOperands(operands)}"
+        when "ci2d"
+            $asm.puts "vmov #{operands[1].armV7Single}, #{operands[0].armV7Operand}"
+            $asm.puts "vcvt.f64.s32 #{operands[1].armV7Operand}, #{operands[1].armV7Single}"
+        when "bdeq"
+            emitArmV7DoubleBranch("beq", operands)
+        when "bdneq"
+            $asm.puts "vcmpe.f64 #{armV7Operands(operands[0..1])}"
+            $asm.puts "vmrs apsr_nzcv, fpscr"
+            isUnordered = LocalLabel.unique("bdneq")
+            $asm.puts "bvs #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
+            $asm.puts "bne #{operands[2].asmLabel}"
+            isUnordered.lower("ARMv7")
+        when "bdgt"
+            emitArmV7DoubleBranch("bgt", operands)
+        when "bdgteq"
+            emitArmV7DoubleBranch("bge", operands)
+        when "bdlt"
+            emitArmV7DoubleBranch("bmi", operands)
+        when "bdlteq"
+            emitArmV7DoubleBranch("bls", operands)
+        when "bdequn"
+            $asm.puts "vcmpe.f64 #{armV7Operands(operands[0..1])}"
+            $asm.puts "vmrs apsr_nzcv, fpscr"
+            $asm.puts "bvs #{operands[2].asmLabel}"
+            $asm.puts "beq #{operands[2].asmLabel}"
+        when "bdnequn"
+            emitArmV7DoubleBranch("bne", operands)
+        when "bdgtun"
+            emitArmV7DoubleBranch("bhi", operands)
+        when "bdgtequn"
+            emitArmV7DoubleBranch("bpl", operands)
+        when "bdltun"
+            emitArmV7DoubleBranch("blt", operands)
+        when "bdltequn"
+            emitArmV7DoubleBranch("ble", operands)
+        when "btd2i"
+            # FIXME: may be a good idea to just get rid of this instruction, since the interpreter
+            # currently does not use it.
+            raise "ARMv7 does not support this opcode yet, #{codeOrigin}"
+        when "td2i"
+            $asm.puts "vcvt.s32.f64 #{ARMv7_SCRATCH_FPR.armV7Single}, #{operands[0].armV7Operand}"
+            $asm.puts "vmov #{operands[1].armV7Operand}, #{ARMv7_SCRATCH_FPR.armV7Single}"
+        when "bcd2i"
+            $asm.puts "vcvt.s32.f64 #{ARMv7_SCRATCH_FPR.armV7Single}, #{operands[0].armV7Operand}"
+            $asm.puts "vmov #{operands[1].armV7Operand}, #{ARMv7_SCRATCH_FPR.armV7Single}"
+            $asm.puts "vcvt.f64.s32 #{ARMv7_SCRATCH_FPR.armV7Operand}, #{ARMv7_SCRATCH_FPR.armV7Single}"
+            emitArmV7DoubleBranch("bne", [ARMv7_SCRATCH_FPR, operands[0], operands[2]])
+            $asm.puts "tst #{operands[1].armV7Operand}, #{operands[1].armV7Operand}"
+            $asm.puts "beq #{operands[2].asmLabel}"
+        when "movdz"
+            # FIXME: either support this or remove it.
+            raise "ARMv7 does not support this opcode yet, #{codeOrigin}"
+        when "pop"
+            $asm.puts "pop #{operands[0].armV7Operand}"
+        when "push"
+            $asm.puts "push #{operands[0].armV7Operand}"
+        when "move", "sxi2p", "zxi2p"
+            if operands[0].is_a? Immediate
+                armV7MoveImmediate(operands[0].value, operands[1])
+            else
+                $asm.puts "mov #{armV7FlippedOperands(operands)}"
+            end
+        when "nop"
+            $asm.puts "nop"
+        when "bieq", "bpeq", "bbeq"
+            if Immediate.new(nil, 0) == operands[0]
+                $asm.puts "tst #{operands[1].armV7Operand}, #{operands[1].armV7Operand}"
+            elsif Immediate.new(nil, 0) == operands[1]
+                $asm.puts "tst #{operands[0].armV7Operand}, #{operands[0].armV7Operand}"
+            else
+                $asm.puts "cmp #{armV7Operands(operands[0..1])}"
+            end
+            $asm.puts "beq #{operands[2].asmLabel}"
+        when "bineq", "bpneq", "bbneq"
+            if Immediate.new(nil, 0) == operands[0]
+                $asm.puts "tst #{operands[1].armV7Operand}, #{operands[1].armV7Operand}"
+            elsif Immediate.new(nil, 0) == operands[1]
+                $asm.puts "tst #{operands[0].armV7Operand}, #{operands[0].armV7Operand}"
+            else
+                $asm.puts "cmp #{armV7Operands(operands[0..1])}"
+            end
+            $asm.puts "bne #{operands[2].asmLabel}"
+        when "bia", "bpa", "bba"
+            $asm.puts "cmp #{armV7Operands(operands[0..1])}"
+            $asm.puts "bhi #{operands[2].asmLabel}"
+        when "biaeq", "bpaeq", "bbaeq"
+            $asm.puts "cmp #{armV7Operands(operands[0..1])}"
+            $asm.puts "bhs #{operands[2].asmLabel}"
+        when "bib", "bpb", "bbb"
+            $asm.puts "cmp #{armV7Operands(operands[0..1])}"
+            $asm.puts "blo #{operands[2].asmLabel}"
+        when "bibeq", "bpbeq", "bbbeq"
+            $asm.puts "cmp #{armV7Operands(operands[0..1])}"
+            $asm.puts "bls #{operands[2].asmLabel}"
+        when "bigt", "bpgt", "bbgt"
+            $asm.puts "cmp #{armV7Operands(operands[0..1])}"
+            $asm.puts "bgt #{operands[2].asmLabel}"
+        when "bigteq", "bpgteq", "bbgteq"
+            $asm.puts "cmp #{armV7Operands(operands[0..1])}"
+            $asm.puts "bge #{operands[2].asmLabel}"
+        when "bilt", "bplt", "bblt"
+            $asm.puts "cmp #{armV7Operands(operands[0..1])}"
+            $asm.puts "blt #{operands[2].asmLabel}"
+        when "bilteq", "bplteq", "bblteq"
+            $asm.puts "cmp #{armV7Operands(operands[0..1])}"
+            $asm.puts "ble #{operands[2].asmLabel}"
+        when "btiz", "btpz", "btbz"
+            emitArmV7Test(operands)
+            $asm.puts "beq #{operands[-1].asmLabel}"
+        when "btinz", "btpnz", "btbnz"
+            emitArmV7Test(operands)
+            $asm.puts "bne #{operands[-1].asmLabel}"
+        when "btio", "btpo", "btbo"
+            emitArmV7Test(operands)
+            $asm.puts "bvs #{operands[-1].asmLabel}"
+        when "btis", "btps", "btbs"
+            emitArmV7Test(operands)
+            $asm.puts "bmi #{operands[-1].asmLabel}"
+        when "jmp"
+            if operands[0].label?
+                $asm.puts "b #{operands[0].asmLabel}"
+            else
+                $asm.puts "mov pc, #{operands[0].armV7Operand}"
+            end
+        when "call"
+            if operands[0].label?
+                $asm.puts "blx #{operands[0].asmLabel}"
+            else
+                $asm.puts "blx #{operands[0].armV7Operand}"
+            end
+        when "break"
+            $asm.puts "bkpt #0"
+        when "ret"
+            $asm.puts "bx lr"
+        when "cieq", "cpeq", "cbeq"
+            emitArmV7Compare(operands, "eq")
+        when "cineq", "cpneq", "cbneq"
+            emitArmV7Compare(operands, "ne")
+        when "cia", "cpa", "cba"
+            emitArmV7Compare(operands, "hi")
+        when "ciaeq", "cpaeq", "cbaeq"
+            emitArmV7Compare(operands, "hs")
+        when "cib", "cpb", "cbb"
+            emitArmV7Compare(operands, "lo")
+        when "cibeq", "cpbeq", "cbbeq"
+            emitArmV7Compare(operands, "ls")
+        when "cigt", "cpgt", "cbgt"
+            emitArmV7Compare(operands, "gt")
+        when "cigteq", "cpgteq", "cbgteq"
+            emitArmV7Compare(operands, "ge")
+        when "cilt", "cplt", "cblt"
+            emitArmV7Compare(operands, "lt")
+        when "cilteq", "cplteq", "cblteq"
+            emitArmV7Compare(operands, "le")
+        when "tio", "tbo", "tpo"
+            emitArmV7TestSet(operands, "vs")
+        when "tis", "tbs", "tps"
+            emitArmV7TestSet(operands, "mi")
+        when "tiz", "tbz", "tpz"
+            emitArmV7TestSet(operands, "eq")
+        when "tinz", "tbnz", "tpnz"
+            emitArmV7TestSet(operands, "ne")
+        when "peek"
+            $asm.puts "ldr #{operands[1].armV7Operand}, [sp, \##{operands[0].value * 4}]"
+        when "poke"
+            $asm.puts "str #{operands[1].armV7Operand}, [sp, \##{operands[0].value * 4}]"
+        when "fii2d"
+            $asm.puts "vmov #{operands[2].armV7Operand}, #{operands[0].armV7Operand}, #{operands[1].armV7Operand}"
+        when "fd2ii"
+            $asm.puts "vmov #{operands[1].armV7Operand}, #{operands[2].armV7Operand}, #{operands[0].armV7Operand}"
+        when "bo"
+            $asm.puts "bvs #{operands[0].asmLabel}"
+        when "bs"
+            $asm.puts "bmi #{operands[0].asmLabel}"
+        when "bz"
+            $asm.puts "beq #{operands[0].asmLabel}"
+        when "bnz"
+            $asm.puts "bne #{operands[0].asmLabel}"
+        when "leai", "leap"
+            operands[0].armV7EmitLea(operands[1])
+        when "smulli"
+            raise "Wrong number of arguments to smull in #{self.inspect} at #{codeOriginString}" unless operands.length == 4
+            $asm.puts "smull #{operands[2].armV7Operand}, #{operands[3].armV7Operand}, #{operands[0].armV7Operand}, #{operands[1].armV7Operand}"
+        else
+            raise "Unhandled opcode #{opcode} at #{codeOriginString}"
+        end
+    end
+end
+
diff --git a/offlineasm/asm.rb b/offlineasm/asm.rb
new file mode 100644 (file)
index 0000000..12bade0
--- /dev/null
@@ -0,0 +1,181 @@
+#!/usr/bin/env ruby
+
+# 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.
+
+$: << File.dirname(__FILE__)
+
+require "backends"
+require "digest/sha1"
+require "offsets"
+require "parser"
+require "self_hash"
+require "settings"
+require "transform"
+
+class Assembler
+    def initialize(outp)
+        @outp = outp
+        @state = :cpp
+        @commentState = :none
+        @comment = nil
+    end
+    
+    def enterAsm
+        @outp.puts "asm ("
+        @state = :asm
+    end
+    
+    def leaveAsm
+        putsLastComment
+        @outp.puts ");"
+        @state = :cpp
+    end
+    
+    def inAsm
+        enterAsm
+        yield
+        leaveAsm
+    end
+    
+    def lastComment
+        if @comment
+            result = "// #{@comment}"
+        else
+            result = ""
+        end
+        @commentState = :none
+        @comment = nil
+        result
+    end
+    
+    def putsLastComment
+        comment = lastComment
+        unless comment.empty?
+            @outp.puts comment
+        end
+    end
+    
+    def puts(*line)
+        raise unless @state == :asm
+        @outp.puts("\"\\t" + line.join('') + "\\n\" #{lastComment}")
+    end
+    
+    def print(line)
+        raise unless @state == :asm
+        @outp.print("\"" + line + "\"")
+    end
+    
+    def putsLabel(labelName)
+        raise unless @state == :asm
+        @outp.puts("OFFLINE_ASM_GLOBAL_LABEL(#{labelName}) #{lastComment}")
+    end
+    
+    def putsLocalLabel(labelName)
+        raise unless @state == :asm
+        @outp.puts("LOCAL_LABEL_STRING(#{labelName}) \":\\n\" #{lastComment}")
+    end
+    
+    def self.labelReference(labelName)
+        "\" SYMBOL_STRING(#{labelName}) \""
+    end
+    
+    def self.localLabelReference(labelName)
+        "\" LOCAL_LABEL_STRING(#{labelName}) \""
+    end
+    
+    def comment(text)
+        case @commentState
+        when :none
+            @comment = text
+            @commentState = :one
+        when :one
+            @outp.puts "// #{@comment}"
+            @outp.puts "// #{text}"
+            @comment = nil
+            @commentState = :many
+        when :many
+            @outp.puts "// #{text}"
+        else
+            raise
+        end
+    end
+end
+
+asmFile = ARGV.shift
+offsetsFile = ARGV.shift
+outputFlnm = ARGV.shift
+
+$stderr.puts "offlineasm: Parsing #{asmFile} and #{offsetsFile} and creating assembly file #{outputFlnm}."
+
+begin
+    configurationList = offsetsAndConfigurationIndex(offsetsFile)
+rescue MissingMagicValuesException
+    $stderr.puts "offlineasm: No magic values found. Skipping assembly file generation assuming the classic interpreter is enabled."
+    exit 0
+end
+
+inputHash =
+    "// offlineasm input hash: " + parseHash(asmFile) +
+    " " + Digest::SHA1.hexdigest(configurationList.map{|v| (v[0] + [v[1]]).join(' ')}.join(' ')) +
+    " " + selfHash
+
+if FileTest.exist? outputFlnm
+    File.open(outputFlnm, "r") {
+        | inp |
+        firstLine = inp.gets
+        if firstLine and firstLine.chomp == inputHash
+            $stderr.puts "offlineasm: Nothing changed."
+            exit 0
+        end
+    }
+end
+
+File.open(outputFlnm, "w") {
+    | outp |
+    $output = outp
+    $output.puts inputHash
+    
+    $asm = Assembler.new($output)
+    
+    ast = parse(asmFile)
+    
+    configurationList.each {
+        | configuration |
+        offsetsList = configuration[0]
+        configIndex = configuration[1]
+        forSettings(computeSettingsCombinations(ast)[configIndex], ast) {
+            | concreteSettings, lowLevelAST, backend |
+            lowLevelAST = lowLevelAST.resolve(*buildOffsetsMap(lowLevelAST, offsetsList))
+            lowLevelAST.validate
+            emitCodeInConfiguration(concreteSettings, lowLevelAST, backend) {
+                $asm.inAsm {
+                    lowLevelAST.lower(backend)
+                }
+            }
+        }
+    }
+}
+
+$stderr.puts "offlineasm: Assembly file #{outputFlnm} successfully generated."
+
diff --git a/offlineasm/ast.rb b/offlineasm/ast.rb
new file mode 100644 (file)
index 0000000..e555b5d
--- /dev/null
@@ -0,0 +1,1224 @@
+# 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.
+
+#
+# Base utility types for the AST.
+#
+
+# Valid methods for Node:
+#
+# node.children -> Returns an array of immediate children.
+#
+# node.descendents -> Returns an array of all strict descendants (children
+#     and children of children, transitively).
+#
+# node.flatten -> Returns an array containing the strict descendants and
+#     the node itself.
+#
+# node.filter(type) -> Returns an array containing those elements in
+#     node.flatten that are of the given type (is_a? type returns true).
+#
+# node.mapChildren{|v| ...} -> Returns a new node with all children
+#     replaced according to the given block.
+#
+# Examples:
+#
+# node.filter(Setting).uniq -> Returns all of the settings that the AST's
+#     IfThenElse blocks depend on.
+#
+# node.filter(StructOffset).uniq -> Returns all of the structure offsets
+#     that the AST depends on.
+
+class Node
+    attr_reader :codeOrigin
+    
+    def initialize(codeOrigin)
+        @codeOrigin = codeOrigin
+    end
+    
+    def codeOriginString
+        @codeOrigin.to_s
+    end
+    
+    def descendants
+        children.collect{|v| v.flatten}.flatten
+    end
+    
+    def flatten
+        [self] + descendants
+    end
+    
+    def filter(type)
+        flatten.select{|v| v.is_a? type}
+    end
+end
+
+class NoChildren < Node
+    def initialize(codeOrigin)
+        super(codeOrigin)
+    end
+    
+    def children
+        []
+    end
+    
+    def mapChildren
+        self
+    end
+end
+
+class StructOffsetKey
+    attr_reader :struct, :field
+    
+    def initialize(struct, field)
+        @struct = struct
+        @field = field
+    end
+    
+    def hash
+        @struct.hash + @field.hash * 3
+    end
+    
+    def eql?(other)
+        @struct == other.struct and @field == other.field
+    end
+end
+
+#
+# AST nodes.
+#
+
+class StructOffset < NoChildren
+    attr_reader :struct, :field
+    
+    def initialize(codeOrigin, struct, field)
+        super(codeOrigin)
+        @struct = struct
+        @field = field
+    end
+    
+    @@mapping = {}
+    
+    def self.forField(codeOrigin, struct, field)
+        key = StructOffsetKey.new(struct, field)
+        
+        unless @@mapping[key]
+            @@mapping[key] = StructOffset.new(codeOrigin, struct, field)
+        end
+        @@mapping[key]
+    end
+    
+    def dump
+        "#{struct}::#{field}"
+    end
+    
+    def <=>(other)
+        if @struct != other.struct
+            return @struct <=> other.struct
+        end
+        @field <=> other.field
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        true
+    end
+    
+    def register?
+        false
+    end
+end
+
+class Sizeof < NoChildren
+    attr_reader :struct
+    
+    def initialize(codeOrigin, struct)
+        super(codeOrigin)
+        @struct = struct
+    end
+    
+    @@mapping = {}
+    
+    def self.forName(codeOrigin, struct)
+        unless @@mapping[struct]
+            @@mapping[struct] = Sizeof.new(codeOrigin, struct)
+        end
+        @@mapping[struct]
+    end
+    
+    def dump
+        "sizeof #{@struct}"
+    end
+    
+    def <=>(other)
+        @struct <=> other.struct
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        true
+    end
+    
+    def register?
+        false
+    end
+end
+
+class Immediate < NoChildren
+    attr_reader :value
+    
+    def initialize(codeOrigin, value)
+        super(codeOrigin)
+        @value = value
+        raise "Bad immediate value #{value.inspect} at #{codeOriginString}" unless value.is_a? Integer
+    end
+    
+    def dump
+        "#{value}"
+    end
+    
+    def ==(other)
+        other.is_a? Immediate and other.value == @value
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        true
+    end
+    
+    def register?
+        false
+    end
+end
+
+class AddImmediates < Node
+    attr_reader :left, :right
+    
+    def initialize(codeOrigin, left, right)
+        super(codeOrigin)
+        @left = left
+        @right = right
+    end
+    
+    def children
+        [@left, @right]
+    end
+    
+    def mapChildren
+        AddImmediates.new(codeOrigin, (yield @left), (yield @right))
+    end
+    
+    def dump
+        "(#{left.dump} + #{right.dump})"
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        true
+    end
+    
+    def register?
+        false
+    end
+end
+
+class SubImmediates < Node
+    attr_reader :left, :right
+    
+    def initialize(codeOrigin, left, right)
+        super(codeOrigin)
+        @left = left
+        @right = right
+    end
+    
+    def children
+        [@left, @right]
+    end
+    
+    def mapChildren
+        SubImmediates.new(codeOrigin, (yield @left), (yield @right))
+    end
+    
+    def dump
+        "(#{left.dump} - #{right.dump})"
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        true
+    end
+    
+    def register?
+        false
+    end
+end
+
+class MulImmediates < Node
+    attr_reader :left, :right
+    
+    def initialize(codeOrigin, left, right)
+        super(codeOrigin)
+        @left = left
+        @right = right
+    end
+    
+    def children
+        [@left, @right]
+    end
+    
+    def mapChildren
+        MulImmediates.new(codeOrigin, (yield @left), (yield @right))
+    end
+    
+    def dump
+        "(#{left.dump} * #{right.dump})"
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        true
+    end
+    
+    def register?
+        false
+    end
+end
+
+class NegImmediate < Node
+    attr_reader :child
+    
+    def initialize(codeOrigin, child)
+        super(codeOrigin)
+        @child = child
+    end
+    
+    def children
+        [@child]
+    end
+    
+    def mapChildren
+        NegImmediate.new(codeOrigin, (yield @child))
+    end
+    
+    def dump
+        "(-#{@child.dump})"
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        true
+    end
+    
+    def register?
+        false
+    end
+end
+
+class OrImmediates < Node
+    attr_reader :left, :right
+    
+    def initialize(codeOrigin, left, right)
+        super(codeOrigin)
+        @left = left
+        @right = right
+    end
+    
+    def children
+        [@left, @right]
+    end
+    
+    def mapChildren
+        OrImmediates.new(codeOrigin, (yield @left), (yield @right))
+    end
+    
+    def dump
+        "(#{left.dump} | #{right.dump})"
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        true
+    end
+    
+    def register?
+        false
+    end
+end
+
+class AndImmediates < Node
+    attr_reader :left, :right
+    
+    def initialize(codeOrigin, left, right)
+        super(codeOrigin)
+        @left = left
+        @right = right
+    end
+    
+    def children
+        [@left, @right]
+    end
+    
+    def mapChildren
+        AndImmediates.new(codeOrigin, (yield @left), (yield @right))
+    end
+    
+    def dump
+        "(#{left.dump} & #{right.dump})"
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        true
+    end
+    
+    def register?
+        false
+    end
+end
+
+class XorImmediates < Node
+    attr_reader :left, :right
+    
+    def initialize(codeOrigin, left, right)
+        super(codeOrigin)
+        @left = left
+        @right = right
+    end
+    
+    def children
+        [@left, @right]
+    end
+    
+    def mapChildren
+        XorImmediates.new(codeOrigin, (yield @left), (yield @right))
+    end
+    
+    def dump
+        "(#{left.dump} ^ #{right.dump})"
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        true
+    end
+    
+    def register?
+        false
+    end
+end
+
+class BitnotImmediate < Node
+    attr_reader :child
+    
+    def initialize(codeOrigin, child)
+        super(codeOrigin)
+        @child = child
+    end
+    
+    def children
+        [@child]
+    end
+    
+    def mapChildren
+        BitnotImmediate.new(codeOrigin, (yield @child))
+    end
+    
+    def dump
+        "(~#{@child.dump})"
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        true
+    end
+    
+    def register?
+        false
+    end
+end
+
+class RegisterID < NoChildren
+    attr_reader :name
+    
+    def initialize(codeOrigin, name)
+        super(codeOrigin)
+        @name = name
+    end
+    
+    @@mapping = {}
+    
+    def self.forName(codeOrigin, name)
+        unless @@mapping[name]
+            @@mapping[name] = RegisterID.new(codeOrigin, name)
+        end
+        @@mapping[name]
+    end
+    
+    def dump
+        name
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        false
+    end
+    
+    def register?
+        true
+    end
+end
+
+class FPRegisterID < NoChildren
+    attr_reader :name
+    
+    def initialize(codeOrigin, name)
+        super(codeOrigin)
+        @name = name
+    end
+    
+    @@mapping = {}
+    
+    def self.forName(codeOrigin, name)
+        unless @@mapping[name]
+            @@mapping[name] = FPRegisterID.new(codeOrigin, name)
+        end
+        @@mapping[name]
+    end
+    
+    def dump
+        name
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        false
+    end
+    
+    def register?
+        true
+    end
+end
+
+class SpecialRegister < NoChildren
+    def initialize(name)
+        @name = name
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        false
+    end
+    
+    def register?
+        true
+    end
+end
+
+class Variable < NoChildren
+    attr_reader :name
+    
+    def initialize(codeOrigin, name)
+        super(codeOrigin)
+        @name = name
+    end
+    
+    @@mapping = {}
+    
+    def self.forName(codeOrigin, name)
+        unless @@mapping[name]
+            @@mapping[name] = Variable.new(codeOrigin, name)
+        end
+        @@mapping[name]
+    end
+    
+    def dump
+        name
+    end
+    
+    def inspect
+        "<variable #{name} at #{codeOriginString}>"
+    end
+end
+
+class Address < Node
+    attr_reader :base, :offset
+    
+    def initialize(codeOrigin, base, offset)
+        super(codeOrigin)
+        @base = base
+        @offset = offset
+        raise "Bad base for address #{base.inspect} at #{codeOriginString}" unless base.is_a? Variable or base.register?
+        raise "Bad offset for address #{offset.inspect} at #{codeOriginString}" unless offset.is_a? Variable or offset.immediate?
+    end
+    
+    def children
+        [@base, @offset]
+    end
+    
+    def mapChildren
+        Address.new(codeOrigin, (yield @base), (yield @offset))
+    end
+    
+    def dump
+        "#{offset.dump}[#{base.dump}]"
+    end
+    
+    def address?
+        true
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        false
+    end
+    
+    def register?
+        false
+    end
+end
+
+class BaseIndex < Node
+    attr_reader :base, :index, :scale, :offset
+    
+    def initialize(codeOrigin, base, index, scale, offset)
+        super(codeOrigin)
+        @base = base
+        @index = index
+        @scale = scale
+        raise unless [1, 2, 4, 8].member? @scale
+        @offset = offset
+    end
+    
+    def scaleShift
+        case scale
+        when 1
+            0
+        when 2
+            1
+        when 4
+            2
+        when 8
+            3
+        else
+            raise "Bad scale at #{codeOriginString}"
+        end
+    end
+    
+    def children
+        [@base, @index, @offset]
+    end
+    
+    def mapChildren
+        BaseIndex.new(codeOrigin, (yield @base), (yield @index), @scale, (yield @offset))
+    end
+    
+    def dump
+        "#{offset.dump}[#{base.dump}, #{index.dump}, #{scale}]"
+    end
+    
+    def address?
+        true
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        false
+    end
+    
+    def register?
+        false
+    end
+end
+
+class AbsoluteAddress < NoChildren
+    attr_reader :address
+    
+    def initialize(codeOrigin, address)
+        super(codeOrigin)
+        @address = address
+    end
+    
+    def dump
+        "#{address.dump}[]"
+    end
+    
+    def address?
+        true
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        false
+    end
+    
+    def register?
+        false
+    end
+end
+
+class Instruction < Node
+    attr_reader :opcode, :operands
+    
+    def initialize(codeOrigin, opcode, operands)
+        super(codeOrigin)
+        @opcode = opcode
+        @operands = operands
+    end
+    
+    def children
+        operands
+    end
+    
+    def mapChildren(&proc)
+        Instruction.new(codeOrigin, @opcode, @operands.map(&proc))
+    end
+    
+    def dump
+        "\t" + opcode.to_s + " " + operands.collect{|v| v.dump}.join(", ")
+    end
+end
+
+class Error < NoChildren
+    def initialize(codeOrigin)
+        super(codeOrigin)
+    end
+    
+    def dump
+        "\terror"
+    end
+end
+
+class ConstDecl < Node
+    attr_reader :variable, :value
+    
+    def initialize(codeOrigin, variable, value)
+        super(codeOrigin)
+        @variable = variable
+        @value = value
+    end
+    
+    def children
+        [@variable, @value]
+    end
+    
+    def mapChildren
+        ConstDecl.new(codeOrigin, (yield @variable), (yield @value))
+    end
+    
+    def dump
+        "const #{@variable.dump} = #{@value.dump}"
+    end
+end
+
+$labelMapping = {}
+
+class Label < NoChildren
+    attr_reader :name
+    
+    def initialize(codeOrigin, name)
+        super(codeOrigin)
+        @name = name
+    end
+    
+    def self.forName(codeOrigin, name)
+        if $labelMapping[name]
+            raise "Label name collision: #{name}" unless $labelMapping[name].is_a? Label
+        else
+            $labelMapping[name] = Label.new(codeOrigin, name)
+        end
+        $labelMapping[name]
+    end
+    
+    def dump
+        "#{name}:"
+    end
+end
+
+class LocalLabel < NoChildren
+    attr_reader :name
+    
+    def initialize(codeOrigin, name)
+        super(codeOrigin)
+        @name = name
+    end
+
+    @@uniqueNameCounter = 0
+    
+    def self.forName(codeOrigin, name)
+        if $labelMapping[name]
+            raise "Label name collision: #{name}" unless $labelMapping[name].is_a? LocalLabel
+        else
+            $labelMapping[name] = LocalLabel.new(codeOrigin, name)
+        end
+        $labelMapping[name]
+    end
+    
+    def self.unique(comment)
+        newName = "_#{comment}"
+        if $labelMapping[newName]
+            while $labelMapping[newName = "_#{@@uniqueNameCounter}_#{comment}"]
+                @@uniqueNameCounter += 1
+            end
+        end
+        forName(nil, newName)
+    end
+    
+    def cleanName
+        if name =~ /^\./
+            "_" + name[1..-1]
+        else
+            name
+        end
+    end
+    
+    def dump
+        "#{name}:"
+    end
+end
+
+class LabelReference < Node
+    attr_reader :label
+    
+    def initialize(codeOrigin, label)
+        super(codeOrigin)
+        @label = label
+    end
+    
+    def children
+        [@label]
+    end
+    
+    def mapChildren
+        LabelReference.new(codeOrigin, (yield @label))
+    end
+    
+    def name
+        label.name
+    end
+    
+    def dump
+        label.name
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        true
+    end
+    
+    def immediate?
+        false
+    end
+end
+
+class LocalLabelReference < NoChildren
+    attr_reader :label
+    
+    def initialize(codeOrigin, label)
+        super(codeOrigin)
+        @label = label
+    end
+    
+    def children
+        [@label]
+    end
+    
+    def mapChildren
+        LocalLabelReference.new(codeOrigin, (yield @label))
+    end
+    
+    def name
+        label.name
+    end
+    
+    def dump
+        label.name
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        true
+    end
+    
+    def immediate?
+        false
+    end
+end
+
+class Sequence < Node
+    attr_reader :list
+    
+    def initialize(codeOrigin, list)
+        super(codeOrigin)
+        @list = list
+    end
+    
+    def children
+        list
+    end
+    
+    def mapChildren(&proc)
+        Sequence.new(codeOrigin, @list.map(&proc))
+    end
+    
+    def dump
+        list.collect{|v| v.dump}.join("\n")
+    end
+end
+
+class True < NoChildren
+    def initialize
+        super(nil)
+    end
+    
+    @@instance = True.new
+    
+    def self.instance
+        @@instance
+    end
+    
+    def value
+        true
+    end
+    
+    def dump
+        "true"
+    end
+end
+
+class False < NoChildren
+    def initialize
+        super(nil)
+    end
+    
+    @@instance = False.new
+    
+    def self.instance
+        @@instance
+    end
+    
+    def value
+        false
+    end
+    
+    def dump
+        "false"
+    end
+end
+
+class TrueClass
+    def asNode
+        True.instance
+    end
+end
+
+class FalseClass
+    def asNode
+        False.instance
+    end
+end
+
+class Setting < NoChildren
+    attr_reader :name
+    
+    def initialize(codeOrigin, name)
+        super(codeOrigin)
+        @name = name
+    end
+    
+    @@mapping = {}
+    
+    def self.forName(codeOrigin, name)
+        unless @@mapping[name]
+            @@mapping[name] = Setting.new(codeOrigin, name)
+        end
+        @@mapping[name]
+    end
+    
+    def dump
+        name
+    end
+end
+
+class And < Node
+    attr_reader :left, :right
+    
+    def initialize(codeOrigin, left, right)
+        super(codeOrigin)
+        @left = left
+        @right = right
+    end
+    
+    def children
+        [@left, @right]
+    end
+    
+    def mapChildren
+        And.new(codeOrigin, (yield @left), (yield @right))
+    end
+    
+    def dump
+        "(#{left.dump} and #{right.dump})"
+    end
+end
+
+class Or < Node
+    attr_reader :left, :right
+    
+    def initialize(codeOrigin, left, right)
+        super(codeOrigin)
+        @left = left
+        @right = right
+    end
+    
+    def children
+        [@left, @right]
+    end
+    
+    def mapChildren
+        Or.new(codeOrigin, (yield @left), (yield @right))
+    end
+    
+    def dump
+        "(#{left.dump} or #{right.dump})"
+    end
+end
+
+class Not < Node
+    attr_reader :child
+    
+    def initialize(codeOrigin, child)
+        super(codeOrigin)
+        @child = child
+    end
+    
+    def children
+        [@left, @right]
+    end
+    
+    def mapChildren
+        Not.new(codeOrigin, (yield @child))
+    end
+    
+    def dump
+        "(not #{child.dump})"
+    end
+end
+
+class Skip < NoChildren
+    def initialize(codeOrigin)
+        super(codeOrigin)
+    end
+    
+    def dump
+        "\tskip"
+    end
+end
+
+class IfThenElse < Node
+    attr_reader :predicate, :thenCase
+    attr_accessor :elseCase
+    
+    def initialize(codeOrigin, predicate, thenCase)
+        super(codeOrigin)
+        @predicate = predicate
+        @thenCase = thenCase
+        @elseCase = Skip.new(codeOrigin)
+    end
+    
+    def children
+        if @elseCase
+            [@predicate, @thenCase, @elseCase]
+        else
+            [@predicate, @thenCase]
+        end
+    end
+    
+    def mapChildren
+        IfThenElse.new(codeOrigin, (yield @predicate), (yield @thenCase), (yield @elseCase))
+    end
+    
+    def dump
+        "if #{predicate.dump}\n" + thenCase.dump + "\nelse\n" + elseCase.dump + "\nend"
+    end
+end
+
+class Macro < Node
+    attr_reader :name, :variables, :body
+    
+    def initialize(codeOrigin, name, variables, body)
+        super(codeOrigin)
+        @name = name
+        @variables = variables
+        @body = body
+    end
+    
+    def children
+        @variables + [@body]
+    end
+    
+    def mapChildren
+        Macro.new(codeOrigin, @name, @variables.map{|v| yield v}, (yield @body))
+    end
+    
+    def dump
+        "macro #{name}(" + variables.collect{|v| v.dump}.join(", ") + ")\n" + body.dump + "\nend"
+    end
+end
+
+class MacroCall < Node
+    attr_reader :name, :operands
+    
+    def initialize(codeOrigin, name, operands)
+        super(codeOrigin)
+        @name = name
+        @operands = operands
+        raise unless @operands
+        @operands.each{|v| raise unless v}
+    end
+    
+    def children
+        @operands
+    end
+    
+    def mapChildren(&proc)
+        MacroCall.new(codeOrigin, @name, @operands.map(&proc))
+    end
+    
+    def dump
+        "\t#{name}(" + operands.collect{|v| v.dump}.join(", ") + ")"
+    end
+end
+
diff --git a/offlineasm/backends.rb b/offlineasm/backends.rb
new file mode 100644 (file)
index 0000000..db7a1e2
--- /dev/null
@@ -0,0 +1,110 @@
+# 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.
+
+require "armv7"
+require "ast"
+require "x86"
+
+BACKENDS =
+    [
+     "X86",
+     "X86_64",
+     "ARMv7"
+    ]
+
+# Keep the set of working backends separate from the set of backends that might be
+# supported. This is great because the BACKENDS list is almost like a reserved
+# words list, in that it causes settings resolution to treat those words specially.
+# Hence this lets us set aside the name of a backend we might want to support in
+# the future while not actually supporting the backend yet.
+WORKING_BACKENDS =
+    [
+     "X86",
+     "X86_64",
+     "ARMv7"
+    ]
+
+BACKEND_PATTERN = Regexp.new('\\A(' + BACKENDS.join(')|(') + ')\\Z')
+
+class Node
+    def lower(name)
+        begin
+            $activeBackend = name
+            send("lower" + name)
+        rescue => e
+            raise "Got error #{e} at #{codeOriginString}"
+        end
+    end
+end
+
+# Overrides for lower() for those nodes that are backend-agnostic
+
+class Label
+    def lower(name)
+        $asm.putsLabel(self.name[1..-1])
+    end
+end
+
+class LocalLabel
+    def lower(name)
+        $asm.putsLocalLabel "_offlineasm_#{self.name[1..-1]}"
+    end
+end
+
+class LabelReference
+    def asmLabel
+        Assembler.labelReference(name[1..-1])
+    end
+end
+
+class LocalLabelReference
+    def asmLabel
+        Assembler.localLabelReference("_offlineasm_"+name[1..-1])
+    end
+end
+
+class Skip
+    def lower(name)
+    end
+end
+
+class Sequence
+    def lower(name)
+        $activeBackend = name
+        if respond_to? "getModifiedList#{name}"
+            newList = send("getModifiedList#{name}")
+            newList.each {
+                | node |
+                node.lower(name)
+            }
+        elsif respond_to? "lower#{name}"
+            send("lower#{name}")
+        else
+            @list.each {
+                | node |
+                node.lower(name)
+            }
+        end
+    end
+end
+
diff --git a/offlineasm/generate_offset_extractor.rb b/offlineasm/generate_offset_extractor.rb
new file mode 100644 (file)
index 0000000..b2a8c2c
--- /dev/null
@@ -0,0 +1,145 @@
+#!/usr/bin/env ruby
+
+# 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.
+
+$: << File.dirname(__FILE__)
+
+require "backends"
+require "digest/sha1"
+require "offsets"
+require "parser"
+require "self_hash"
+require "settings"
+require "transform"
+
+inputFlnm = ARGV.shift
+outputFlnm = ARGV.shift
+
+$stderr.puts "offlineasm: Parsing #{inputFlnm} and creating offset extractor #{outputFlnm}."
+
+def emitMagicNumber
+    OFFSET_MAGIC_NUMBERS.each {
+        | number |
+        $output.puts "#{number},"
+    }
+end
+
+inputHash = "// offlineasm input hash: #{parseHash(inputFlnm)} #{selfHash}"
+
+if FileTest.exist? outputFlnm
+    File.open(outputFlnm, "r") {
+        | inp |
+        firstLine = inp.gets
+        if firstLine and firstLine.chomp == inputHash
+            $stderr.puts "offlineasm: Nothing changed."
+            exit 0
+        end
+    }
+end
+
+originalAST = parse(inputFlnm)
+
+#
+# Optimize the AST to make configuration extraction faster. This reduces the AST to a form
+# that only contains the things that matter for our purposes: offsets, sizes, and if
+# statements.
+#
+
+class Node
+    def offsetsPruneTo(sequence)
+        children.each {
+            | child |
+            child.offsetsPruneTo(sequence)
+        }
+    end
+    
+    def offsetsPrune
+        result = Sequence.new(codeOrigin, [])
+        offsetsPruneTo(result)
+        result
+    end
+end
+
+class IfThenElse
+    def offsetsPruneTo(sequence)
+        ifThenElse = IfThenElse.new(codeOrigin, predicate, thenCase.offsetsPrune)
+        ifThenElse.elseCase = elseCase.offsetsPrune
+        sequence.list << ifThenElse
+    end
+end
+
+class StructOffset
+    def offsetsPruneTo(sequence)
+        sequence.list << self
+    end
+end
+
+class Sizeof
+    def offsetsPruneTo(sequence)
+        sequence.list << self
+    end
+end
+
+prunedAST = originalAST.offsetsPrune
+
+File.open(outputFlnm, "w") {
+    | outp |
+    $output = outp
+    outp.puts inputHash
+    length = 0
+    emitCodeInAllConfigurations(prunedAST) {
+        | settings, ast, backend, index |
+        offsetsList = ast.filter(StructOffset).uniq.sort
+        sizesList = ast.filter(Sizeof).uniq.sort
+        length += OFFSET_HEADER_MAGIC_NUMBERS.size + (OFFSET_MAGIC_NUMBERS.size + 1) * (1 + offsetsList.size + sizesList.size)
+    }
+    outp.puts "static const unsigned extractorTable[#{length}] = {"
+    emitCodeInAllConfigurations(prunedAST) {
+        | settings, ast, backend, index |
+        OFFSET_HEADER_MAGIC_NUMBERS.each {
+            | number |
+            $output.puts "#{number},"
+        }
+
+        offsetsList = ast.filter(StructOffset).uniq.sort
+        sizesList = ast.filter(Sizeof).uniq.sort
+        
+        emitMagicNumber
+        outp.puts "#{index},"
+        offsetsList.each {
+            | offset |
+            emitMagicNumber
+            outp.puts "OFFLINE_ASM_OFFSETOF(#{offset.struct}, #{offset.field}),"
+        }
+        sizesList.each {
+            | offset |
+            emitMagicNumber
+            outp.puts "sizeof(#{offset.struct}),"
+        }
+    }
+    outp.puts "};"
+}
+
+$stderr.puts "offlineasm: offset extractor #{outputFlnm} successfully generated."
+
diff --git a/offlineasm/instructions.rb b/offlineasm/instructions.rb
new file mode 100644 (file)
index 0000000..67cec6d
--- /dev/null
@@ -0,0 +1,239 @@
+# 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.
+
+# Interesting invariant, which we take advantage of: branching instructions
+# always begin with "b", and no non-branching instructions begin with "b".
+# Terminal instructions are "jmp" and "ret".
+
+MACRO_INSTRUCTIONS =
+    [
+     "addi",
+     "andi",
+     "lshifti",
+     "lshiftp",
+     "muli",
+     "negi",
+     "negp",
+     "noti",
+     "ori",
+     "rshifti",
+     "urshifti",
+     "rshiftp",
+     "urshiftp",
+     "subi",
+     "xori",
+     "loadi",
+     "loadis",
+     "loadb",
+     "loadbs",
+     "loadh",
+     "loadhs",
+     "storei",
+     "storeb",
+     "loadd",
+     "moved",
+     "stored",
+     "addd",
+     "divd",
+     "subd",
+     "muld",
+     "sqrtd",
+     "ci2d",
+     "fii2d", # usage: fii2d <gpr with least significant bits>, <gpr with most significant bits>, <fpr>
+     "fd2ii", # usage: fd2ii <fpr>, <gpr with least significant bits>, <gpr with most significant bits>
+     "fp2d",
+     "fd2p",
+     "bdeq",
+     "bdneq",
+     "bdgt",
+     "bdgteq",
+     "bdlt",
+     "bdlteq",
+     "bdequn",
+     "bdnequn",
+     "bdgtun",
+     "bdgtequn",
+     "bdltun",
+     "bdltequn",
+     "btd2i",
+     "td2i",
+     "bcd2i",
+     "movdz",
+     "pop",
+     "push",
+     "move",
+     "sxi2p",
+     "zxi2p",
+     "nop",
+     "bieq",
+     "bineq",
+     "bia",
+     "biaeq",
+     "bib",
+     "bibeq",
+     "bigt",
+     "bigteq",
+     "bilt",
+     "bilteq",
+     "bbeq",
+     "bbneq",
+     "bba",
+     "bbaeq",
+     "bbb",
+     "bbbeq",
+     "bbgt",
+     "bbgteq",
+     "bblt",
+     "bblteq",
+     "btio",
+     "btis",
+     "btiz",
+     "btinz",
+     "btbo",
+     "btbs",
+     "btbz",
+     "btbnz",
+     "jmp",
+     "baddio",
+     "baddis",
+     "baddiz",
+     "baddinz",
+     "bsubio",
+     "bsubis",
+     "bsubiz",
+     "bsubinz",
+     "bmulio",
+     "bmulis",
+     "bmuliz",
+     "bmulinz",
+     "borio",
+     "boris",
+     "boriz",
+     "borinz",
+     "break",
+     "call",
+     "ret",
+     "cbeq",
+     "cbneq",
+     "cba",
+     "cbaeq",
+     "cbb",
+     "cbbeq",
+     "cbgt",
+     "cbgteq",
+     "cblt",
+     "cblteq",
+     "cieq",
+     "cineq",
+     "cia",
+     "ciaeq",
+     "cib",
+     "cibeq",
+     "cigt",
+     "cigteq",
+     "cilt",
+     "cilteq",
+     "tio",
+     "tis",
+     "tiz",
+     "tinz",
+     "tbo",
+     "tbs",
+     "tbz",
+     "tbnz",
+     "tpo",
+     "tps",
+     "tpz",
+     "tpnz",
+     "peek",
+     "poke",
+     "bpeq",
+     "bpneq",
+     "bpa",
+     "bpaeq",
+     "bpb",
+     "bpbeq",
+     "bpgt",
+     "bpgteq",
+     "bplt",
+     "bplteq",
+     "addp",
+     "mulp",
+     "andp",
+     "orp",
+     "subp",
+     "xorp",
+     "loadp",
+     "cpeq",
+     "cpneq",
+     "cpa",
+     "cpaeq",
+     "cpb",
+     "cpbeq",
+     "cpgt",
+     "cpgteq",
+     "cplt",
+     "cplteq",
+     "storep",
+     "btpo",
+     "btps",
+     "btpz",
+     "btpnz",
+     "baddpo",
+     "baddps",
+     "baddpz",
+     "baddpnz",
+     "bo",
+     "bs",
+     "bz",
+     "bnz",
+     "leai",
+     "leap",
+    ]
+
+X86_INSTRUCTIONS =
+    [
+     "cdqi",
+     "idivi"
+    ]
+
+ARMv7_INSTRUCTIONS =
+    [
+     "smulli",
+     "addis",
+     "subis",
+     "oris"
+    ]
+
+INSTRUCTIONS = MACRO_INSTRUCTIONS + X86_INSTRUCTIONS + ARMv7_INSTRUCTIONS
+
+INSTRUCTION_PATTERN = Regexp.new('\\A((' + INSTRUCTIONS.join(')|(') + '))\\Z')
+
+def isBranch(instruction)
+    instruction =~ /^b/
+end
+
+def hasFallThrough(instruction)
+    instruction != "ret" and instruction != "jmp"
+end
+
diff --git a/offlineasm/offsets.rb b/offlineasm/offsets.rb
new file mode 100644 (file)
index 0000000..63af014
--- /dev/null
@@ -0,0 +1,183 @@
+# 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.
+
+require "ast"
+
+OFFSET_HEADER_MAGIC_NUMBERS = [ 0x9e43fd66, 0x4379bfba ]
+OFFSET_MAGIC_NUMBERS = [ 0xec577ac7, 0x0ff5e755 ]
+
+#
+# MissingMagicValuesException
+#
+# Thrown when magic values are missing from the binary.
+# This is usually an indication that the classic interpreter is enabled.
+#
+
+class MissingMagicValuesException < Exception
+end
+
+#
+# offsetsList(ast)
+# sizesList(ast)
+#
+# Returns a list of offsets and sizes used by the AST.
+#
+
+def offsetsList(ast)
+    ast.filter(StructOffset).uniq.sort
+end
+
+def sizesList(ast)
+    ast.filter(Sizeof).uniq.sort
+end
+
+#
+# offsetsAndConfigurationIndex(ast, file) ->
+#     [[offsets, index], ...]
+#
+# Parses the offsets from a file and returns a list of offsets and the
+# index of the configuration that is valid in this build target.
+#
+
+def offsetsAndConfigurationIndex(file)
+    endiannessMarkerBytes = nil
+    result = []
+    
+    def readInt(endianness, bytes)
+        if endianness == :little
+            # Little endian
+            (bytes[0] << 0 |
+             bytes[1] << 8 |
+             bytes[2] << 16 |
+             bytes[3] << 24)
+        else
+            # Big endian
+            (bytes[0] << 24 |
+             bytes[1] << 16 |
+             bytes[2] << 8 |
+             bytes[3] << 0)
+        end
+    end
+    
+    def prepareMagic(endianness, numbers)
+        magicBytes = []
+        numbers.each {
+            | number |
+            currentBytes = []
+            4.times {
+                currentBytes << (number & 0xff)
+                number >>= 8
+            }
+            if endianness == :big
+                currentBytes.reverse!
+            end
+            magicBytes += currentBytes
+        }
+        magicBytes
+    end
+    
+    fileBytes = []
+    
+    File.open(file, "r") {
+        | inp |
+        loop {
+            byte = inp.getbyte
+            break unless byte
+            fileBytes << byte
+        }
+    }
+    
+    def sliceByteArrays(byteArray, pattern)
+        result = []
+        lastSlicePoint = 0
+        (byteArray.length - pattern.length + 1).times {
+            | index |
+            foundOne = true
+            pattern.length.times {
+                | subIndex |
+                if byteArray[index + subIndex] != pattern[subIndex]
+                    foundOne = false
+                    break
+                end
+            }
+            if foundOne
+                result << byteArray[lastSlicePoint...index]
+                lastSlicePoint = index + pattern.length
+            end
+        }
+        
+        result << byteArray[lastSlicePoint...(byteArray.length)]
+        
+        result
+    end
+    
+    [:little, :big].each {
+        | endianness |
+        headerMagicBytes = prepareMagic(endianness, OFFSET_HEADER_MAGIC_NUMBERS)
+        magicBytes = prepareMagic(endianness, OFFSET_MAGIC_NUMBERS)
+        
+        bigArray = sliceByteArrays(fileBytes, headerMagicBytes)
+        unless bigArray.size <= 1
+            bigArray[1..-1].each {
+                | configArray |
+                array = sliceByteArrays(configArray, magicBytes)
+                index = readInt(endianness, array[1])
+                offsets = []
+                array[2..-1].each {
+                    | data |
+                    offsets << readInt(endianness, data)
+                }
+                result << [offsets, index]
+            }
+        end
+    }
+    
+    raise MissingMagicValuesException unless result.length >= 1
+    raise if result.map{|v| v[1]}.uniq.size < result.map{|v| v[1]}.size
+    
+    result
+end
+
+#
+# buildOffsetsMap(ast, offsetsList) -> [offsets, sizes]
+#
+# Builds a mapping between StructOffset nodes and their values.
+#
+
+def buildOffsetsMap(ast, offsetsList)
+    offsetsMap = {}
+    sizesMap = {}
+    astOffsetsList = offsetsList(ast)
+    astSizesList = sizesList(ast)
+    raise unless astOffsetsList.size + astSizesList.size == offsetsList.size
+    offsetsList(ast).each_with_index {
+        | structOffset, index |
+        offsetsMap[structOffset] = offsetsList.shift
+    }
+    sizesList(ast).each_with_index {
+        | sizeof, index |
+        sizesMap[sizeof] = offsetsList.shift
+    }
+    [offsetsMap, sizesMap]
+end
+
diff --git a/offlineasm/opt.rb b/offlineasm/opt.rb
new file mode 100644 (file)
index 0000000..3170d3a
--- /dev/null
@@ -0,0 +1,134 @@
+# 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.
+
+require "ast"
+
+#
+# "Optimization" passes. These are used to lower the representation for
+# backends that cannot handle some of our higher-level instructions.
+#
+
+#
+# A temporary - a variable that will be allocated to a register after we're
+# done.
+#
+
+class Node
+    def replaceTemporariesWithRegisters(kind)
+        mapChildren {
+            | node |
+            node.replaceTemporariesWithRegisters(kind)
+        }
+    end
+end
+
+class Tmp < NoChildren
+    attr_reader :firstMention, :lastMention
+    attr_reader :kind
+    attr_accessor :register
+
+    def initialize(codeOrigin, kind)
+        super(codeOrigin)
+        @kind = kind
+    end
+    
+    def dump
+        "$tmp#{object_id}"
+    end
+    
+    def mention!(position)
+        if not @firstMention or position < @firstMention
+            @firstMention = position
+        end
+        if not @lastMention or position > @lastMention
+            @lastMention = position
+        end
+    end
+    
+    def replaceTemporariesWithRegisters(kind)
+        if @kind == kind
+            raise "Did not allocate register to temporary at #{codeOriginString}" unless @register
+            @register
+        else
+            self
+        end
+    end
+    
+    def address?
+        false
+    end
+    
+    def label?
+        false
+    end
+    
+    def immediate?
+        false
+    end
+    
+    def register?
+        true
+    end
+end
+
+# Assign registers to temporaries, by finding which temporaries interfere
+# with each other. Note that this relies on temporary live ranges not crossing
+# basic block boundaries.
+
+def assignRegistersToTemporaries(list, kind, registers)
+    list.each_with_index {
+        | node, index |
+        node.filter(Tmp).uniq.each {
+            | tmp |
+            if tmp.kind == kind
+                tmp.mention! index
+            end
+        }
+    }
+    
+    freeRegisters = registers.dup
+    list.each_with_index {
+        | node, index |
+        tmpList = node.filter(Tmp).uniq
+        tmpList.each {
+            | tmp |
+            if tmp.kind == kind and tmp.firstMention == index
+                raise "Could not allocate register to temporary at #{node.codeOriginString}" if freeRegisters.empty?
+                tmp.register = freeRegisters.pop
+            end
+        }
+        tmpList.each {
+            | tmp |
+            if tmp.kind == kind and tmp.lastMention == index
+                freeRegisters.push tmp.register
+                raise "Register allocation inconsistency at #{node.codeOriginString}" if freeRegisters.size > registers.size
+            end
+        }
+    }
+    
+    list.map {
+        | node |
+        node.replaceTemporariesWithRegisters(kind)
+    }
+end
+
diff --git a/offlineasm/parser.rb b/offlineasm/parser.rb
new file mode 100644 (file)
index 0000000..11863c7
--- /dev/null
@@ -0,0 +1,648 @@
+# 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.
+
+require "ast"
+require "instructions"
+require "pathname"
+require "registers"
+require "self_hash"
+
+class CodeOrigin
+    attr_reader :fileName, :lineNumber
+    
+    def initialize(fileName, lineNumber)
+        @fileName = fileName
+        @lineNumber = lineNumber
+    end
+    
+    def to_s
+        "#{fileName}:#{lineNumber}"
+    end
+end
+
+class Token
+    attr_reader :codeOrigin, :string
+    
+    def initialize(codeOrigin, string)
+        @codeOrigin = codeOrigin
+        @string = string
+    end
+    
+    def ==(other)
+        if other.is_a? Token
+            @string == other.string
+        else
+            @string == other
+        end
+    end
+    
+    def =~(other)
+        @string =~ other
+    end
+    
+    def to_s
+        "#{@string.inspect} at #{codeOrigin}"
+    end
+    
+    def parseError(*comment)
+        if comment.empty?
+            raise "Parse error: #{to_s}"
+        else
+            raise "Parse error: #{to_s}: #{comment[0]}"
+        end
+    end
+end
+
+#
+# The lexer. Takes a string and returns an array of tokens.
+#
+
+def lex(str, fileName)
+    fileName = Pathname.new(fileName)
+    result = []
+    lineNumber = 1
+    while not str.empty?
+        case str
+        when /\A\#([^\n]*)/
+            # comment, ignore
+        when /\A\n/
+            result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
+            lineNumber += 1
+        when /\A[a-zA-Z]([a-zA-Z0-9_]*)/
+            result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
+        when /\A\.([a-zA-Z0-9_]*)/
+            result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
+        when /\A_([a-zA-Z0-9_]*)/
+            result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
+        when /\A([ \t]+)/
+            # whitespace, ignore
+        when /\A0x([0-9a-fA-F]+)/
+            result << Token.new(CodeOrigin.new(fileName, lineNumber), $&.hex.to_s)
+        when /\A0([0-7]+)/
+            result << Token.new(CodeOrigin.new(fileName, lineNumber), $&.oct.to_s)
+        when /\A([0-9]+)/
+            result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
+        when /\A::/
+            result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
+        when /\A[:,\(\)\[\]=\+\-~\|&^*]/
+            result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
+        else
+            raise "Lexer error at #{CodeOrigin.new(fileName, lineNumber).to_s}, unexpected sequence #{str[0..20].inspect}"
+        end
+        str = $~.post_match
+    end
+    result
+end
+
+#
+# Token identification.
+#
+
+def isRegister(token)
+    token =~ REGISTER_PATTERN
+end
+
+def isInstruction(token)
+    token =~ INSTRUCTION_PATTERN
+end
+
+def isKeyword(token)
+    token =~ /\A((true)|(false)|(if)|(then)|(else)|(elsif)|(end)|(and)|(or)|(not)|(macro)|(const)|(sizeof)|(error)|(include))\Z/ or
+        token =~ REGISTER_PATTERN or
+        token =~ INSTRUCTION_PATTERN
+end
+
+def isIdentifier(token)
+    token =~ /\A[a-zA-Z]([a-zA-Z0-9_]*)\Z/ and not isKeyword(token)
+end
+
+def isLabel(token)
+    token =~ /\A_([a-zA-Z0-9_]*)\Z/
+end
+
+def isLocalLabel(token)
+    token =~ /\A\.([a-zA-Z0-9_]*)\Z/
+end
+
+def isVariable(token)
+    isIdentifier(token) or isRegister(token)
+end
+
+def isInteger(token)
+    token =~ /\A[0-9]/
+end
+
+#
+# The parser. Takes an array of tokens and returns an AST. Methods
+# other than parse(tokens) are not for public consumption.
+#
+
+class Parser
+    def initialize(data, fileName)
+        @tokens = lex(data, fileName)
+        @idx = 0
+    end
+    
+    def parseError(*comment)
+        if @tokens[@idx]
+            @tokens[@idx].parseError(*comment)
+        else
+            if comment.empty?
+                raise "Parse error at end of file"
+            else
+                raise "Parse error at end of file: #{comment[0]}"
+            end
+        end
+    end
+    
+    def consume(regexp)
+        if regexp
+            parseError unless @tokens[@idx] =~ regexp
+        else
+            parseError unless @idx == @tokens.length
+        end
+        @idx += 1
+    end
+    
+    def skipNewLine
+        while @tokens[@idx] == "\n"
+            @idx += 1
+        end
+    end
+    
+    def parsePredicateAtom
+        if @tokens[@idx] == "not"
+            @idx += 1
+            parsePredicateAtom
+        elsif @tokens[@idx] == "("
+            @idx += 1
+            skipNewLine
+            result = parsePredicate
+            parseError unless @tokens[@idx] == ")"
+            @idx += 1
+            result
+        elsif @tokens[@idx] == "true"
+            result = True.instance
+            @idx += 1
+            result
+        elsif @tokens[@idx] == "false"
+            result = False.instance
+            @idx += 1
+            result
+        elsif isIdentifier @tokens[@idx]
+            result = Setting.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
+            @idx += 1
+            result
+        else
+            parseError
+        end
+    end
+    
+    def parsePredicateAnd
+        result = parsePredicateAtom
+        while @tokens[@idx] == "and"
+            codeOrigin = @tokens[@idx].codeOrigin
+            @idx += 1
+            skipNewLine
+            right = parsePredicateAtom
+            result = And.new(codeOrigin, result, right)
+        end
+        result
+    end
+    
+    def parsePredicate
+        # some examples of precedence:
+        # not a and b -> (not a) and b
+        # a and b or c -> (a and b) or c
+        # a or b and c -> a or (b and c)
+        
+        result = parsePredicateAnd
+        while @tokens[@idx] == "or"
+            codeOrigin = @tokens[@idx].codeOrigin
+            @idx += 1
+            skipNewLine
+            right = parsePredicateAnd
+            result = Or.new(codeOrigin, result, right)
+        end
+        result
+    end
+    
+    def parseVariable
+        if isRegister(@tokens[@idx])
+            if @tokens[@idx] =~ FPR_PATTERN
+                result = FPRegisterID.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
+            else
+                result = RegisterID.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
+            end
+        elsif isIdentifier(@tokens[@idx])
+            result = Variable.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
+        else
+            parseError
+        end
+        @idx += 1
+        result
+    end
+    
+    def parseAddress(offset)
+        parseError unless @tokens[@idx] == "["
+        codeOrigin = @tokens[@idx].codeOrigin
+        
+        # Three possibilities:
+        # []       -> AbsoluteAddress
+        # [a]      -> Address
+        # [a,b]    -> BaseIndex with scale = 1
+        # [a,b,c]  -> BaseIndex
+        
+        @idx += 1
+        if @tokens[@idx] == "]"
+            @idx += 1
+            return AbsoluteAddress.new(codeOrigin, offset)
+        end
+        a = parseVariable
+        if @tokens[@idx] == "]"
+            result = Address.new(codeOrigin, a, offset)
+        else
+            parseError unless @tokens[@idx] == ","
+            @idx += 1
+            b = parseVariable
+            if @tokens[@idx] == "]"
+                result = BaseIndex.new(codeOrigin, a, b, 1, offset)
+            else
+                parseError unless @tokens[@idx] == ","
+                @idx += 1
+                parseError unless ["1", "2", "4", "8"].member? @tokens[@idx].string
+                c = @tokens[@idx].string.to_i
+                @idx += 1
+                parseError unless @tokens[@idx] == "]"
+                result = BaseIndex.new(codeOrigin, a, b, c, offset)
+            end
+        end
+        @idx += 1
+        result
+    end
+    
+    def parseColonColon
+        skipNewLine
+        codeOrigin = @tokens[@idx].codeOrigin
+        parseError unless isIdentifier @tokens[@idx]
+        names = [@tokens[@idx].string]
+        @idx += 1
+        while @tokens[@idx] == "::"
+            @idx += 1
+            parseError unless isIdentifier @tokens[@idx]
+            names << @tokens[@idx].string
+            @idx += 1
+        end
+        raise if names.empty?
+        [codeOrigin, names]
+    end
+    
+    def parseExpressionAtom
+        skipNewLine
+        if @tokens[@idx] == "-"
+            @idx += 1
+            NegImmediate.new(@tokens[@idx - 1].codeOrigin, parseExpressionAtom)
+        elsif @tokens[@idx] == "~"
+            @idx += 1
+            BitnotImmediate.new(@tokens[@idx - 1].codeOrigin, parseExpressionAtom)
+        elsif @tokens[@idx] == "("
+            @idx += 1
+            result = parseExpression
+            parseError unless @tokens[@idx] == ")"
+            @idx += 1
+            result
+        elsif isInteger @tokens[@idx]
+            result = Immediate.new(@tokens[@idx].codeOrigin, @tokens[@idx].string.to_i)
+            @idx += 1
+            result
+        elsif isIdentifier @tokens[@idx]
+            codeOrigin, names = parseColonColon
+            if names.size > 1
+                StructOffset.forField(codeOrigin, names[0..-2].join('::'), names[-1])
+            else
+                Variable.forName(codeOrigin, names[0])
+            end
+        elsif isRegister @tokens[@idx]
+            parseVariable
+        elsif @tokens[@idx] == "sizeof"
+            @idx += 1
+            codeOrigin, names = parseColonColon
+            Sizeof.forName(codeOrigin, names.join('::'))
+        else
+            parseError
+        end
+    end
+    
+    def parseExpressionMul
+        skipNewLine
+        result = parseExpressionAtom
+        while @tokens[@idx] == "*"
+            if @tokens[@idx] == "*"
+                @idx += 1
+                result = MulImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAtom)
+            else
+                raise
+            end
+        end
+        result
+    end
+    
+    def couldBeExpression
+        @tokens[@idx] == "-" or @tokens[@idx] == "~" or @tokens[@idx] == "sizeof" or isInteger(@tokens[@idx]) or isVariable(@tokens[@idx]) or @tokens[@idx] == "("
+    end
+    
+    def parseExpressionAdd
+        skipNewLine
+        result = parseExpressionMul
+        while @tokens[@idx] == "+" or @tokens[@idx] == "-"
+            if @tokens[@idx] == "+"
+                @idx += 1
+                result = AddImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionMul)
+            elsif @tokens[@idx] == "-"
+                @idx += 1
+                result = SubImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionMul)
+            else
+                raise
+            end
+        end
+        result
+    end
+    
+    def parseExpressionAnd
+        skipNewLine
+        result = parseExpressionAdd
+        while @tokens[@idx] == "&"
+            @idx += 1
+            result = AndImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAdd)
+        end
+        result
+    end
+    
+    def parseExpression
+        skipNewLine
+        result = parseExpressionAnd
+        while @tokens[@idx] == "|" or @tokens[@idx] == "^"
+            if @tokens[@idx] == "|"
+                @idx += 1
+                result = OrImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAnd)
+            elsif @tokens[@idx] == "^"
+                @idx += 1
+                result = XorImmediates.new(@tokens[@idx - 1].codeOrigin, result, parseExpressionAnd)
+            else
+                raise
+            end
+        end
+        result
+    end
+    
+    def parseOperand(comment)
+        skipNewLine
+        if couldBeExpression
+            expr = parseExpression
+            if @tokens[@idx] == "["
+                parseAddress(expr)
+            else
+                expr
+            end
+        elsif @tokens[@idx] == "["
+            parseAddress(Immediate.new(@tokens[@idx].codeOrigin, 0))
+        elsif isLabel @tokens[@idx]
+            result = LabelReference.new(@tokens[@idx].codeOrigin, Label.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string))
+            @idx += 1
+            result
+        elsif isLocalLabel @tokens[@idx]
+            result = LocalLabelReference.new(@tokens[@idx].codeOrigin, LocalLabel.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string))
+            @idx += 1
+            result
+        else
+            parseError(comment)
+        end
+    end
+    
+    def parseMacroVariables
+        skipNewLine
+        consume(/\A\(\Z/)
+        variables = []
+        loop {
+            skipNewLine
+            if @tokens[@idx] == ")"
+                @idx += 1
+                break
+            elsif isIdentifier(@tokens[@idx])
+                variables << Variable.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
+                @idx += 1
+                skipNewLine
+                if @tokens[@idx] == ")"
+                    @idx += 1
+                    break
+                elsif @tokens[@idx] == ","
+                    @idx += 1
+                else
+                    parseError
+                end
+            else
+                parseError
+            end
+        }
+        variables
+    end
+    
+    def parseSequence(final, comment)
+        firstCodeOrigin = @tokens[@idx].codeOrigin
+        list = []
+        loop {
+            if (@idx == @tokens.length and not final) or (final and @tokens[@idx] =~ final)
+                break
+            elsif @tokens[@idx] == "\n"
+                # ignore
+                @idx += 1
+            elsif @tokens[@idx] == "const"
+                @idx += 1
+                parseError unless isVariable @tokens[@idx]
+                variable = Variable.forName(@tokens[@idx].codeOrigin, @tokens[@idx].string)
+                @idx += 1
+                parseError unless @tokens[@idx] == "="
+                @idx += 1
+                value = parseOperand("while inside of const #{variable.name}")
+                list << ConstDecl.new(@tokens[@idx].codeOrigin, variable, value)
+            elsif @tokens[@idx] == "error"
+                list << Error.new(@tokens[@idx].codeOrigin)
+                @idx += 1
+            elsif @tokens[@idx] == "if"
+                codeOrigin = @tokens[@idx].codeOrigin
+                @idx += 1
+                skipNewLine
+                predicate = parsePredicate
+                consume(/\A((then)|(\n))\Z/)
+                skipNewLine
+                ifThenElse = IfThenElse.new(codeOrigin, predicate, parseSequence(/\A((else)|(end)|(elsif))\Z/, "while inside of \"if #{predicate.dump}\""))
+                list << ifThenElse
+                while @tokens[@idx] == "elsif"
+                    codeOrigin = @tokens[@idx].codeOrigin
+                    @idx += 1
+                    skipNewLine
+                    predicate = parsePredicate
+                    consume(/\A((then)|(\n))\Z/)
+                    skipNewLine
+                    elseCase = IfThenElse.new(codeOrigin, predicate, parseSequence(/\A((else)|(end)|(elsif))\Z/, "while inside of \"if #{predicate.dump}\""))
+                    ifThenElse.elseCase = elseCase
+                    ifThenElse = elseCase
+                end
+                if @tokens[@idx] == "else"
+                    @idx += 1
+                    ifThenElse.elseCase = parseSequence(/\Aend\Z/, "while inside of else case for \"if #{predicate.dump}\"")
+                    @idx += 1
+                else
+                    parseError unless @tokens[@idx] == "end"
+                    @idx += 1
+                end
+            elsif @tokens[@idx] == "macro"
+                codeOrigin = @tokens[@idx].codeOrigin
+                @idx += 1
+                skipNewLine
+                parseError unless isIdentifier(@tokens[@idx])
+                name = @tokens[@idx].string
+                @idx += 1
+                variables = parseMacroVariables
+                body = parseSequence(/\Aend\Z/, "while inside of macro #{name}")
+                @idx += 1
+                list << Macro.new(codeOrigin, name, variables, body)
+            elsif isInstruction @tokens[@idx]
+                codeOrigin = @tokens[@idx].codeOrigin
+                name = @tokens[@idx].string
+                @idx += 1
+                if (not final and @idx == @tokens.size) or (final and @tokens[@idx] =~ final)
+                    # Zero operand instruction, and it's the last one.
+                    list << Instruction.new(codeOrigin, name, [])
+                    break
+                elsif @tokens[@idx] == "\n"
+                    # Zero operand instruction.
+                    list << Instruction.new(codeOrigin, name, [])
+                    @idx += 1
+                else
+                    # It's definitely an instruction, and it has at least one operand.
+                    operands = []
+                    endOfSequence = false
+                    loop {
+                        operands << parseOperand("while inside of instruction #{name}")
+                        if (not final and @idx == @tokens.size) or (final and @tokens[@idx] =~ final)
+                            # The end of the instruction and of the sequence.
+                            endOfSequence = true
+                            break
+                        elsif @tokens[@idx] == ","
+                            # Has another operand.
+                            @idx += 1
+                        elsif @tokens[@idx] == "\n"
+                            # The end of the instruction.
+                            @idx += 1
+                            break
+                        else
+                            parseError("Expected a comma, newline, or #{final} after #{operands.last.dump}")
+                        end
+                    }
+                    list << Instruction.new(codeOrigin, name, operands)
+                    if endOfSequence
+                        break
+                    end
+                end
+            elsif isIdentifier @tokens[@idx]
+                codeOrigin = @tokens[@idx].codeOrigin
+                name = @tokens[@idx].string
+                @idx += 1
+                if @tokens[@idx] == "("
+                    # Macro invocation.
+                    @idx += 1
+                    operands = []
+                    skipNewLine
+                    if @tokens[@idx] == ")"
+                        @idx += 1
+                    else
+                        loop {
+                            skipNewLine
+                            if @tokens[@idx] == "macro"
+                                # It's a macro lambda!
+                                codeOriginInner = @tokens[@idx].codeOrigin
+                                @idx += 1
+                                variables = parseMacroVariables
+                                body = parseSequence(/\Aend\Z/, "while inside of anonymous macro passed as argument to #{name}")
+                                @idx += 1
+                                operands << Macro.new(codeOriginInner, nil, variables, body)
+                            else
+                                operands << parseOperand("while inside of macro call to #{name}")
+                            end
+                            skipNewLine
+                            if @tokens[@idx] == ")"
+                                @idx += 1
+                                break
+                            elsif @tokens[@idx] == ","
+                                @idx += 1
+                            else
+                                parseError "Unexpected #{@tokens[@idx].string.inspect} while parsing invocation of macro #{name}"
+                            end
+                        }
+                    end
+                    list << MacroCall.new(codeOrigin, name, operands)
+                else
+                    parseError "Expected \"(\" after #{name}"
+                end
+            elsif isLabel @tokens[@idx] or isLocalLabel @tokens[@idx]
+                codeOrigin = @tokens[@idx].codeOrigin
+                name = @tokens[@idx].string
+                @idx += 1
+                parseError unless @tokens[@idx] == ":"
+                # It's a label.
+                if isLabel name
+                    list << Label.forName(codeOrigin, name)
+                else
+                    list << LocalLabel.forName(codeOrigin, name)
+                end
+                @idx += 1
+            elsif @tokens[@idx] == "include"
+                @idx += 1
+                parseError unless isIdentifier(@tokens[@idx])
+                moduleName = @tokens[@idx].string
+                fileName = @tokens[@idx].codeOrigin.fileName.dirname + (moduleName + ".asm")
+                @idx += 1
+                $stderr.puts "offlineasm: Including file #{fileName}"
+                list << parse(fileName)
+            else
+                parseError "Expecting terminal #{final} #{comment}"
+            end
+        }
+        Sequence.new(firstCodeOrigin, list)
+    end
+end
+
+def parseData(data, fileName)
+    parser = Parser.new(data, fileName)
+    parser.parseSequence(nil, "")
+end
+
+def parse(fileName)
+    parseData(IO::read(fileName), fileName)
+end
+
+def parseHash(fileName)
+    dirHash(Pathname.new(fileName).dirname, /\.asm$/)
+end
+
diff --git a/offlineasm/registers.rb b/offlineasm/registers.rb
new file mode 100644 (file)
index 0000000..2c5a4eb
--- /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.
+
+GPRS =
+    [
+     "t0",
+     "t1",
+     "t2",
+     "t3",
+     "t4",
+     "cfr",
+     "a0",
+     "a1",
+     "r0",
+     "r1",
+     "sp",
+     "lr",
+     
+     # 64-bit only registers:
+     "t5",
+     "t6",  # r10
+     "csr1",  # r14, tag type number register
+     "csr2"   # r15, tag mask register
+    ]
+
+FPRS =
+    [
+     "ft0",
+     "ft1",
+     "ft2",
+     "ft3",
+     "ft4",
+     "ft5",
+     "fa0",
+     "fa1",
+     "fa2",
+     "fa3",
+     "fr"
+    ]
+
+REGISTERS = GPRS + FPRS
+
+GPR_PATTERN = Regexp.new('\\A((' + GPRS.join(')|(') + '))\\Z')
+FPR_PATTERN = Regexp.new('\\A((' + FPRS.join(')|(') + '))\\Z')
+
+REGISTER_PATTERN = Regexp.new('\\A((' + REGISTERS.join(')|(') + '))\\Z')
diff --git a/offlineasm/self_hash.rb b/offlineasm/self_hash.rb
new file mode 100644 (file)
index 0000000..2c300fc
--- /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. 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.
+
+require "digest/sha1"
+require "pathname"
+
+#
+# dirHash(directory, regexp) -> SHA1 hexdigest
+#
+# Returns a hash of all files in the given directory that fit the given
+# pattern.
+#
+
+def dirHash(directory, regexp)
+    directory = Pathname.new(directory)
+    contents = ""
+    Dir.foreach(directory) {
+        | entry |
+        if entry =~ regexp
+            contents += IO::read(directory + entry)
+        end
+    }
+    return Digest::SHA1.hexdigest(contents)
+end
+
+#
+# selfHash -> SHA1 hexdigest
+#
+# Returns a hash of the offlineasm source code. This allows dependency
+# tracking for not just changes in input, but also changes in the assembler
+# itself.
+#
+
+def selfHash
+    dirHash(Pathname.new(__FILE__).dirname, /\.rb$/)
+end
+
diff --git a/offlineasm/settings.rb b/offlineasm/settings.rb
new file mode 100644 (file)
index 0000000..b7daa74
--- /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.
+
+require "ast"
+require "backends"
+require "parser"
+require "transform"
+
+#
+# computeSettingsCombinations(ast) -> settingsCombiations
+#
+# Computes an array of settings maps, where a settings map constitutes
+# a configuration for the assembly code being generated. The map
+# contains key value pairs where keys are settings names (strings) and
+# the values are booleans (true for enabled, false for disabled).
+#
+
+def computeSettingsCombinations(ast)
+    settingsCombinations = []
+    
+    def settingsCombinator(settingsCombinations, mapSoFar, remaining)
+        if remaining.empty?
+            settingsCombinations << mapSoFar
+            return
+        end
+        
+        newMap = mapSoFar.dup
+        newMap[remaining[0]] = true
+        settingsCombinator(settingsCombinations, newMap, remaining[1..-1])
+        
+        newMap = mapSoFar.dup
+        newMap[remaining[0]] = false
+        settingsCombinator(settingsCombinations, newMap, remaining[1..-1])
+    end
+    
+    settingsCombinator(settingsCombinations, {}, (ast.filter(Setting).uniq.collect{|v| v.name} + BACKENDS).uniq)
+    
+    settingsCombinations
+end
+
+#
+# forSettings(concreteSettings, ast) {
+#     | concreteSettings, lowLevelAST, backend | ... }
+#
+# Determines if the settings combination is valid, and if so, calls
+# the block with the information you need to generate code.
+#
+
+def forSettings(concreteSettings, ast)
+    # Check which architectures this combinator claims to support.
+    numClaimedBackends = 0
+    selectedBackend = nil
+    BACKENDS.each {
+        | backend |
+        isSupported = concreteSettings[backend]
+        raise unless isSupported != nil
+        numClaimedBackends += if isSupported then 1 else 0 end
+        if isSupported
+            selectedBackend = backend
+        end
+    }
+    
+    return if numClaimedBackends > 1
+    
+    # Resolve the AST down to a low-level form (no macros or conditionals).
+    lowLevelAST = ast.resolveSettings(concreteSettings)
+    
+    yield concreteSettings, lowLevelAST, selectedBackend
+end
+
+#
+# forEachValidSettingsCombination(ast) {
+#     | concreteSettings, ast, backend, index | ... }
+#
+# forEachValidSettingsCombination(ast, settingsCombinations) {
+#     | concreteSettings, ast, backend, index | ... }
+#
+# Executes the given block for each valid settings combination in the
+# settings map. The ast passed into the block is resolved
+# (ast.resolve) against the settings.
+#
+# The first form will call computeSettingsCombinations(ast) for you.
+#
+
+def forEachValidSettingsCombination(ast, *optionalSettingsCombinations)
+    raise if optionalSettingsCombinations.size > 1
+    
+    if optionalSettingsCombinations.empty?
+        settingsCombinations = computeSettingsCombinations(ast)
+    else
+        settingsCombinations = optionalSettingsCombiations[0]
+    end
+    
+    settingsCombinations.each_with_index {
+        | concreteSettings, index |
+        forSettings(concreteSettings, ast) {
+            | concreteSettings_, lowLevelAST, backend |
+            yield concreteSettings, lowLevelAST, backend, index
+        }
+    }
+end
+
+#
+# cppSettingsTest(concreteSettings)
+#
+# Returns the C++ code used to test if we are in a configuration that
+# corresponds to the given concrete settings.
+#
+
+def cppSettingsTest(concreteSettings)
+    "#if " + concreteSettings.to_a.collect{
+        | pair |
+        (if pair[1]
+             ""
+         else
+             "!"
+         end) + "OFFLINE_ASM_" + pair[0]
+    }.join(" && ")
+end
+
+#
+# isASTErroneous(ast)
+#
+# Tests to see if the AST claims that there is an error - i.e. if the
+# user's code, after settings resolution, has Error nodes.
+#
+
+def isASTErroneous(ast)
+    not ast.filter(Error).empty?
+end
+
+#
+# assertConfiguration(concreteSettings)
+#
+# Emits a check that asserts that we're using the given configuration.
+#
+
+def assertConfiguration(concreteSettings)
+    $output.puts cppSettingsTest(concreteSettings)
+    $output.puts "#else"
+    $output.puts "#error \"Configuration mismatch.\""
+    $output.puts "#endif"
+end
+
+#
+# emitCodeInConfiguration(concreteSettings, ast, backend) {
+#     | concreteSettings, ast, backend | ... }
+#
+# Emits all relevant guards to see if the configuration holds and
+# calls the block if the configuration is not erroneous.
+#
+
+def emitCodeInConfiguration(concreteSettings, ast, backend)
+    $output.puts cppSettingsTest(concreteSettings)
+    
+    if isASTErroneous(ast)
+        $output.puts "#error \"Invalid configuration.\""
+    elsif not WORKING_BACKENDS.include? backend
+        $output.puts "#error \"This backend is not supported yet.\""
+    else
+        yield concreteSettings, ast, backend
+    end
+    
+    $output.puts "#endif"
+end
+
+#
+# emitCodeInAllConfigurations(ast) {
+#     | concreteSettings, ast, backend, index | ... }
+#
+# Emits guard codes for all valid configurations, and calls the block
+# for those configurations that are valid and not erroneous.
+#
+
+def emitCodeInAllConfigurations(ast)
+    forEachValidSettingsCombination(ast) {
+        | concreteSettings, lowLevelAST, backend, index |
+        $output.puts cppSettingsTest(concreteSettings)
+        yield concreteSettings, lowLevelAST, backend, index
+        $output.puts "#endif"
+    }
+end
+
+
+
diff --git a/offlineasm/transform.rb b/offlineasm/transform.rb
new file mode 100644 (file)
index 0000000..86c72be
--- /dev/null
@@ -0,0 +1,474 @@
+# 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.
+
+require "ast"
+
+#
+# node.resolveSettings(settings)
+#
+# Construct a new AST that does not have any IfThenElse nodes by
+# substituting concrete boolean values for each Setting.
+#
+
+class Node
+    def resolveSettings(settings)
+        mapChildren {
+            | child |
+            child.resolveSettings(settings)
+        }
+    end
+end
+
+class True
+    def resolveSettings(settings)
+        self
+    end
+end
+
+class False
+    def resolveSettings(settings)
+        self
+    end
+end
+
+class Setting
+    def resolveSettings(settings)
+        settings[@name].asNode
+    end
+end
+
+class And
+    def resolveSettings(settings)
+        (@left.resolveSettings(settings).value and @right.resolveSettings(settings).value).asNode
+    end
+end
+
+class Or
+    def resolveSettings(settings)
+        (@left.resolveSettings(settings).value or @right.resolveSettings(settings).value).asNode
+    end
+end
+
+class Not
+    def resolveSettings(settings)
+        (not @child.resolveSettings(settings).value).asNode
+    end
+end
+
+class IfThenElse
+    def resolveSettings(settings)
+        if @predicate.resolveSettings(settings).value
+            @thenCase.resolveSettings(settings)
+        else
+            @elseCase.resolveSettings(settings)
+        end
+    end
+end
+
+class Sequence
+    def resolveSettings(settings)
+        newList = []
+        @list.each {
+            | item |
+            item = item.resolveSettings(settings)
+            if item.is_a? Sequence
+                newList += item.list
+            else
+                newList << item
+            end
+        }
+        Sequence.new(codeOrigin, newList)
+    end
+end
+
+#
+# node.demacroify(macros)
+# node.substitute(mapping)
+#
+# demacroify() constructs a new AST that does not have any Macro
+# nodes, while substitute() replaces Variable nodes with the given
+# nodes in the mapping.
+#
+
+class Node
+    def demacroify(macros)
+        mapChildren {
+            | child |
+            child.demacroify(macros)
+        }
+    end
+    
+    def substitute(mapping)
+        mapChildren {
+            | child |
+            child.substitute(mapping)
+        }
+    end
+    
+    def substituteLabels(mapping)
+        mapChildren {
+            | child |
+            child.substituteLabels(mapping)
+        }
+    end
+end
+
+class Macro
+    def substitute(mapping)
+        myMapping = {}
+        mapping.each_pair {
+            | key, value |
+            unless @variables.include? key
+                myMapping[key] = value
+            end
+        }
+        mapChildren {
+            | child |
+            child.substitute(myMapping)
+        }
+    end
+end
+
+class Variable
+    def substitute(mapping)
+        if mapping[self]
+            mapping[self]
+        else
+            self
+        end
+    end
+end
+
+class LocalLabel
+    def substituteLabels(mapping)
+        if mapping[self]
+            mapping[self]
+        else
+            self
+        end
+    end
+end
+
+class Sequence
+    def substitute(constants)
+        newList = []
+        myConstants = constants.dup
+        @list.each {
+            | item |
+            if item.is_a? ConstDecl
+                myConstants[item.variable] = item.value.substitute(myConstants)
+            else
+                newList << item.substitute(myConstants)
+            end
+        }
+        Sequence.new(codeOrigin, newList)
+    end
+    
+    def renameLabels(comment)
+        mapping = {}
+        
+        @list.each {
+            | item |
+            if item.is_a? LocalLabel
+                mapping[item] = LocalLabel.unique(if comment then comment + "_" else "" end + item.cleanName)
+            end
+        }
+        
+        substituteLabels(mapping)
+    end
+    
+    def demacroify(macros)
+        myMacros = macros.dup
+        @list.each {
+            | item |
+            if item.is_a? Macro
+                myMacros[item.name] = item
+            end
+        }
+        newList = []
+        @list.each {
+            | item |
+            if item.is_a? Macro
+                # Ignore.
+            elsif item.is_a? MacroCall
+                mapping = {}
+                myMyMacros = myMacros.dup
+                raise "Could not find macro #{item.name} at #{item.codeOriginString}" unless myMacros[item.name]
+                raise "Argument count mismatch for call to #{item.name} at #{item.codeOriginString}" unless item.operands.size == myMacros[item.name].variables.size
+                item.operands.size.times {
+                    | idx |
+                    if item.operands[idx].is_a? Variable and myMacros[item.operands[idx].name]
+                        myMyMacros[myMacros[item.name].variables[idx].name] = myMacros[item.operands[idx].name]
+                        mapping[myMacros[item.name].variables[idx].name] = nil
+                    elsif item.operands[idx].is_a? Macro
+                        myMyMacros[myMacros[item.name].variables[idx].name] = item.operands[idx]
+                        mapping[myMacros[item.name].variables[idx].name] = nil
+                    else
+                        myMyMacros[myMacros[item.name].variables[idx]] = nil
+                        mapping[myMacros[item.name].variables[idx]] = item.operands[idx]
+                    end
+                }
+                newList += myMacros[item.name].body.substitute(mapping).demacroify(myMyMacros).renameLabels(item.name).list
+            else
+                newList << item.demacroify(myMacros)
+            end
+        }
+        Sequence.new(codeOrigin, newList).substitute({})
+    end
+end
+
+#
+# node.resolveOffsets(offsets, sizes)
+#
+# Construct a new AST that has offset values instead of symbolic
+# offsets.
+#
+
+class Node
+    def resolveOffsets(offsets, sizes)
+        mapChildren {
+            | child |
+            child.resolveOffsets(offsets, sizes)
+        }
+    end
+end
+
+class StructOffset
+    def resolveOffsets(offsets, sizes)
+        if offsets[self]
+            Immediate.new(codeOrigin, offsets[self])
+        else
+            self
+        end
+    end
+end
+
+class Sizeof
+    def resolveOffsets(offsets, sizes)
+        if sizes[self]
+            Immediate.new(codeOrigin, sizes[self])
+        else
+            puts "Could not find #{self.inspect} in #{sizes.keys.inspect}"
+            puts "sizes = #{sizes.inspect}"
+            self
+        end
+    end
+end
+
+#
+# node.fold
+#
+# Resolve constant references and compute arithmetic expressions.
+#
+
+class Node
+    def fold
+        mapChildren {
+            | child |
+            child.fold
+        }
+    end
+end
+
+class AddImmediates
+    def fold
+        @left = @left.fold
+        @right = @right.fold
+        return self unless @left.is_a? Immediate
+        return self unless @right.is_a? Immediate
+        Immediate.new(codeOrigin, @left.value + @right.value)
+    end
+end
+
+class SubImmediates
+    def fold
+        @left = @left.fold
+        @right = @right.fold
+        return self unless @left.is_a? Immediate
+        return self unless @right.is_a? Immediate
+        Immediate.new(codeOrigin, @left.value - @right.value)
+    end
+end
+
+class MulImmediates
+    def fold
+        @left = @left.fold
+        @right = @right.fold
+        return self unless @left.is_a? Immediate
+        return self unless @right.is_a? Immediate
+        Immediate.new(codeOrigin, @left.value * @right.value)
+    end
+end
+
+class NegImmediate
+    def fold
+        @child = @child.fold
+        return self unless @child.is_a? Immediate
+        Immediate.new(codeOrigin, -@child.value)
+    end
+end
+
+class OrImmediates
+    def fold
+        @left = @left.fold
+        @right = @right.fold
+        return self unless @left.is_a? Immediate
+        return self unless @right.is_a? Immediate
+        Immediate.new(codeOrigin, @left.value | @right.value)
+    end
+end
+
+class AndImmediates
+    def fold
+        @left = @left.fold
+        @right = @right.fold
+        return self unless @left.is_a? Immediate
+        return self unless @right.is_a? Immediate
+        Immediate.new(codeOrigin, @left.value & @right.value)
+    end
+end
+
+class XorImmediates
+    def fold
+        @left = @left.fold
+        @right = @right.fold
+        return self unless @left.is_a? Immediate
+        return self unless @right.is_a? Immediate
+        Immediate.new(codeOrigin, @left.value ^ @right.value)
+    end
+end
+
+class BitnotImmediate
+    def fold
+        @child = @child.fold
+        return self unless @child.is_a? Immediate
+        Immediate.new(codeOrigin, ~@child.value)
+    end
+end
+
+#
+# node.resolveAfterSettings(offsets, sizes)
+#
+# Compile assembly against a set of offsets.
+#
+
+class Node
+    def resolve(offsets, sizes)
+        demacroify({}).resolveOffsets(offsets, sizes).fold
+    end
+end
+
+#
+# node.validate
+#
+# Checks that the node is ready for backend compilation.
+#
+
+class Node
+    def validate
+        raise "Unresolved #{dump} at #{codeOriginString}"
+    end
+    
+    def validateChildren
+        children.each {
+            | node |
+            node.validate
+        }
+    end
+end
+
+class Sequence
+    def validate
+        validateChildren
+    end
+end
+
+class Immediate
+    def validate
+    end
+end
+
+class RegisterID
+    def validate
+    end
+end
+
+class FPRegisterID
+    def validate
+    end
+end
+
+class Address
+    def validate
+        validateChildren
+    end
+end
+
+class BaseIndex
+    def validate
+        validateChildren
+    end
+end
+
+class AbsoluteAddress
+    def validate
+        validateChildren
+    end
+end
+
+class Instruction
+    def validate
+        validateChildren
+    end
+end
+
+class Error
+    def validate
+    end
+end
+
+class Label
+    def validate
+    end
+end
+
+class LocalLabel
+    def validate
+    end
+end
+
+class LabelReference
+    def validate
+    end
+end
+
+class LocalLabelReference
+    def validate
+    end
+end
+
+class Skip
+    def validate
+    end
+end
+
diff --git a/offlineasm/x86.rb b/offlineasm/x86.rb
new file mode 100644 (file)
index 0000000..e6a5c92
--- /dev/null
@@ -0,0 +1,1023 @@
+# Copyright (C) 2012 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. 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.
+
+def isX64
+    case $activeBackend
+    when "X86"
+        false
+    when "X86_64"
+        true
+    else
+        raise "bad value for $activeBackend: #{$activeBackend}"
+    end
+end
+
+class SpecialRegister < NoChildren
+    def x86Operand(kind)
+        raise unless @name =~ /^r/
+        raise unless isX64
+        case kind
+        when :half
+            "%" + @name + "w"
+        when :int
+            "%" + @name + "d"
+        when :ptr
+            "%" + @name
+        else
+            raise
+        end
+    end
+    def x86CallOperand(kind)
+        "*#{x86Operand(kind)}"
+    end
+end
+
+X64_SCRATCH_REGISTER = SpecialRegister.new("r11")
+
+class RegisterID
+    def supports8BitOnX86
+        case name
+        when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3"
+            true
+        when "cfr", "ttnr", "tmr"
+            false
+        when "t4", "t5"
+            isX64
+        else
+            raise
+        end
+    end
+    
+    def x86Operand(kind)
+        case name
+        when "t0", "a0", "r0"
+            case kind
+            when :byte
+                "%al"
+            when :half
+                "%ax"
+            when :int
+                "%eax"
+            when :ptr
+                isX64 ? "%rax" : "%eax"
+            else
+                raise
+            end
+        when "t1", "a1", "r1"
+            case kind
+            when :byte
+                "%dl"
+            when :half
+                "%dx"
+            when :int
+                "%edx"
+            when :ptr
+                isX64 ? "%rdx" : "%edx"
+            else
+                raise
+            end
+        when "t2"
+            case kind
+            when :byte
+                "%cl"
+            when :half
+                "%cx"
+            when :int
+                "%ecx"
+            when :ptr
+                isX64 ? "%rcx" : "%ecx"
+            else
+                raise
+            end
+        when "t3"
+            case kind
+            when :byte
+                "%bl"
+            when :half
+                "%bx"
+            when :int
+                "%ebx"
+            when :ptr
+                isX64 ? "%rbx" : "%ebx"
+            else
+                raise
+            end
+        when "t4"
+            case kind
+            when :byte
+                "%sil"
+            when :half
+                "%si"
+            when :int
+                "%esi"
+            when :ptr
+                isX64 ? "%rsi" : "%esi"
+            else
+                raise
+            end
+        when "cfr"
+            if isX64
+                case kind
+                when :half
+                    "%r13w"
+                when :int
+                    "%r13d"
+                when :ptr
+                    "%r13"
+                else
+                    raise
+                end
+            else
+                case kind
+                when :byte
+                    "%dil"
+                when :half
+                    "%di"
+                when :int
+                    "%edi"
+                when :ptr
+                    "%edi"
+                else
+                    raise
+                end
+            end
+        when "sp"
+            case kind
+            when :byte
+                "%spl"
+            when :half
+                "%sp"
+            when :int
+                "%esp"
+            when :ptr
+                isX64 ? "%rsp" : "%esp"
+            else
+                raise
+            end
+        when "t5"
+            raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
+            case kind
+            when :byte
+                "%dil"
+            when :half
+                "%di"
+            when :int
+                "%edi"
+            when :ptr
+                "%rdi"
+            end
+        when "t6"
+            raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
+            case kind
+            when :half
+                "%r10w"
+            when :int
+                "%r10d"
+            when :ptr
+                "%r10"
+            end
+        when "csr1"
+            raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
+            case kind
+            when :half
+                "%r14w"
+            when :int
+                "%r14d"
+            when :ptr
+                "%r14"
+            end
+        when "csr2"
+            raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
+            case kind
+            when :half
+                "%r15w"
+            when :int
+                "%r15d"
+            when :ptr
+                "%r15"
+            end
+        else
+            raise "Bad register #{name} for X86 at #{codeOriginString}"
+        end
+    end
+    def x86CallOperand(kind)
+        "*#{x86Operand(kind)}"
+    end
+end
+
+class FPRegisterID
+    def x86Operand(kind)
+        raise unless kind == :double
+        case name
+        when "ft0", "fa0", "fr"
+            "%xmm0"
+        when "ft1", "fa1"
+            "%xmm1"
+        when "ft2", "fa2"
+            "%xmm2"
+        when "ft3", "fa3"
+            "%xmm3"
+        when "ft4"
+            "%xmm4"
+        when "ft5"
+            "%xmm5"
+        else
+            raise "Bad register #{name} for X86 at #{codeOriginString}"
+        end
+    end
+    def x86CallOperand(kind)
+        "*#{x86Operand(kind)}"
+    end
+end
+
+class Immediate
+    def validX86Immediate?
+        if isX64
+            value >= -0x80000000 and value <= 0x7fffffff
+        else
+            true
+        end
+    end
+    def x86Operand(kind)
+        "$#{value}"
+    end
+    def x86CallOperand(kind)
+        "#{value}"
+    end
+end
+
+class Address
+    def supports8BitOnX86
+        true
+    end
+    
+    def x86AddressOperand(addressKind)
+        "#{offset.value}(#{base.x86Operand(addressKind)})"
+    end
+    def x86Operand(kind)
+        x86AddressOperand(:ptr)
+    end
+    def x86CallOperand(kind)
+        "*#{x86Operand(kind)}"
+    end
+end
+
+class BaseIndex
+    def supports8BitOnX86
+        true
+    end
+    
+    def x86AddressOperand(addressKind)
+        "#{offset.value}(#{base.x86Operand(addressKind)}, #{index.x86Operand(addressKind)}, #{scale})"
+    end
+    
+    def x86Operand(kind)
+        x86AddressOperand(:ptr)
+    end
+
+    def x86CallOperand(kind)
+        "*#{x86Operand(kind)}"
+    end
+end
+
+class AbsoluteAddress
+    def supports8BitOnX86
+        true
+    end
+    
+    def x86AddressOperand(addressKind)
+        "#{address.value}"
+    end
+    
+    def x86Operand(kind)
+        "#{address.value}"
+    end
+
+    def x86CallOperand(kind)
+        "*#{address.value}"
+    end
+end
+
+class LabelReference
+    def x86CallOperand(kind)
+        asmLabel
+    end
+end
+
+class LocalLabelReference
+    def x86CallOperand(kind)
+        asmLabel
+    end
+end
+
+class Sequence
+    def getModifiedListX86_64
+        newList = []
+        
+        @list.each {
+            | node |
+            newNode = node
+            if node.is_a? Instruction
+                unless node.opcode == "move"
+                    usedScratch = false
+                    newOperands = node.operands.map {
+                        | operand |
+                        if operand.immediate? and not operand.validX86Immediate?
+                            if usedScratch
+                                raise "Attempt to use scratch register twice at #{operand.codeOriginString}"
+                            end
+                            newList << Instruction.new(operand.codeOrigin, "move", [operand, X64_SCRATCH_REGISTER])
+                            usedScratch = true
+                            X64_SCRATCH_REGISTER
+                        else
+                            operand
+                        end
+                    }
+                    newNode = Instruction.new(node.codeOrigin, node.opcode, newOperands)
+                end
+            else
+                unless node.is_a? Label or
+                        node.is_a? LocalLabel or
+                        node.is_a? Skip
+                    raise "Unexpected #{node.inspect} at #{node.codeOrigin}" 
+                end
+            end
+            if newNode
+                newList << newNode
+            end
+        }
+        
+        return newList
+    end
+end
+
+class Instruction
+    def x86Operands(*kinds)
+        raise unless kinds.size == operands.size
+        result = []
+        kinds.size.times {
+            | idx |
+            result << operands[idx].x86Operand(kinds[idx])
+        }
+        result.join(", ")
+    end
+
+    def x86Suffix(kind)
+        case kind
+        when :byte
+            "b"
+        when :half
+            "w"
+        when :int
+            "l"
+        when :ptr
+            isX64 ? "q" : "l"
+        when :double
+            "sd"
+        else
+            raise
+        end
+    end
+    
+    def x86Bytes(kind)
+        case kind
+        when :byte
+            1
+        when :half
+            2
+        when :int
+            4
+        when :ptr
+            isX64 ? 8 : 4
+        when :double
+            8
+        else
+            raise
+        end
+    end
+    
+    def handleX86OpWithNumOperands(opcode, kind, numOperands)
+        if numOperands == 3
+            if operands[0] == operands[2]
+                $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+            elsif operands[1] == operands[2]
+                $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+            else
+                $asm.puts "mov#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+                $asm.puts "#{opcode} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+            end
+        else
+            $asm.puts "#{opcode} #{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}"
+        end
+    end
+    
+    def handleX86Op(opcode, kind)
+        handleX86OpWithNumOperands(opcode, kind, operands.size)
+    end
+    
+    def handleX86Shift(opcode, kind)
+        if operands[0].is_a? Immediate or operands[0] == RegisterID.forName(nil, "t2")
+            $asm.puts "#{opcode} #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(kind)}"
+        else
+            cx = RegisterID.forName(nil, "t2")
+            $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
+            $asm.puts "#{opcode} %cl, #{operands[1].x86Operand(kind)}"
+            $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
+        end
+    end
+    
+    def handleX86DoubleBranch(branchOpcode, mode)
+        case mode
+        when :normal
+            $asm.puts "ucomisd #{operands[1].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
+        when :reverse
+            $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
+        else
+            raise mode.inspect
+        end
+        $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
+    end
+    
+    def handleX86IntCompare(opcodeSuffix, kind)
+        if operands[0].is_a? Immediate and operands[0].value == 0 and operands[1].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
+            $asm.puts "test#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}"
+        elsif operands[1].is_a? Immediate and operands[1].value == 0 and operands[0].is_a? RegisterID and (opcodeSuffix == "e" or opcodeSuffix == "ne")
+            $asm.puts "test#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}"
+        else
+            $asm.puts "cmp#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[0].x86Operand(kind)}"
+        end
+    end
+    
+    def handleX86IntBranch(branchOpcode, kind)
+        handleX86IntCompare(branchOpcode[1..-1], kind)
+        $asm.puts "#{branchOpcode} #{operands[2].asmLabel}"
+    end
+    
+    def handleX86Set(setOpcode, operand)
+        if operand.supports8BitOnX86
+            $asm.puts "#{setOpcode} #{operand.x86Operand(:byte)}"
+            $asm.puts "movzbl #{operand.x86Operand(:byte)}, #{operand.x86Operand(:int)}"
+        else
+            ax = RegisterID.new(nil, "t0")
+            $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
+            $asm.puts "#{setOpcode} %al"
+            $asm.puts "movzbl %al, %eax"
+            $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
+        end
+    end
+    
+    def handleX86IntCompareSet(setOpcode, kind)
+        handleX86IntCompare(setOpcode[3..-1], kind)
+        handleX86Set(setOpcode, operands[2])
+    end
+    
+    def handleX86Test(kind)
+        value = operands[0]
+        case operands.size
+        when 2
+            mask = Immediate.new(codeOrigin, -1)
+        when 3
+            mask = operands[1]
+        else
+            raise "Expected 2 or 3 operands, but got #{operands.size} at #{codeOriginString}"
+        end
+        
+        if mask.is_a? Immediate and mask.value == -1
+            if value.is_a? RegisterID
+                $asm.puts "test#{x86Suffix(kind)} #{value.x86Operand(kind)}, #{value.x86Operand(kind)}"
+            else
+                $asm.puts "cmp#{x86Suffix(kind)} $0, #{value.x86Operand(kind)}"
+            end
+        else
+            $asm.puts "test#{x86Suffix(kind)} #{mask.x86Operand(kind)}, #{value.x86Operand(kind)}"
+        end
+    end
+    
+    def handleX86BranchTest(branchOpcode, kind)
+        handleX86Test(kind)
+        $asm.puts "#{branchOpcode} #{operands.last.asmLabel}"
+    end
+    
+    def handleX86SetTest(setOpcode, kind)
+        handleX86Test(kind)
+        handleX86Set(setOpcode, operands.last)
+    end
+    
+    def handleX86OpBranch(opcode, branchOpcode, kind)
+        handleX86OpWithNumOperands(opcode, kind, operands.size - 1)
+        case operands.size
+        when 4
+            jumpTarget = operands[3]
+        when 3
+            jumpTarget = operands[2]
+        else
+            raise self.inspect
+        end
+        $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
+    end
+    
+    def handleX86SubBranch(branchOpcode, kind)
+        if operands.size == 4 and operands[1] == operands[2]
+            $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}"
+            $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+        else
+            handleX86OpWithNumOperands("sub#{x86Suffix(kind)}", kind, operands.size - 1)
+        end
+        case operands.size
+        when 4
+            jumpTarget = operands[3]
+        when 3
+            jumpTarget = operands[2]
+        else
+            raise self.inspect
+        end
+        $asm.puts "#{branchOpcode} #{jumpTarget.asmLabel}"
+    end
+    
+    def handleX86Add(kind)
+        if operands.size == 3 and operands[0].is_a? Immediate
+            raise unless operands[1].is_a? RegisterID
+            raise unless operands[2].is_a? RegisterID
+            if operands[0].value == 0
+                unless operands[1] == operands[2]
+                    $asm.puts "mov#{x86Suffix(kind)} #{operands[1].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+                end
+            else
+                $asm.puts "lea#{x86Suffix(kind)} #{operands[0].value}(#{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
+            end
+        elsif operands.size == 3 and operands[0].is_a? RegisterID
+            raise unless operands[1].is_a? RegisterID
+            raise unless operands[2].is_a? RegisterID
+            $asm.puts "lea#{x86Suffix(kind)} (#{operands[0].x86Operand(kind)}, #{operands[1].x86Operand(kind)}), #{operands[2].x86Operand(kind)}"
+        else
+            unless Immediate.new(nil, 0) == operands[0]
+                $asm.puts "add#{x86Suffix(kind)} #{x86Operands(kind, kind)}"
+            end
+        end
+    end
+    
+    def handleX86Sub(kind)
+        if operands.size == 3 and operands[1] == operands[2]
+            $asm.puts "neg#{x86Suffix(kind)} #{operands[2].x86Operand(kind)}"
+            $asm.puts "add#{x86Suffix(kind)} #{operands[0].x86Operand(kind)}, #{operands[2].x86Operand(kind)}"
+        else
+            handleX86Op("sub#{x86Suffix(kind)}", kind)
+        end
+    end
+    
+    def handleX86Mul(kind)
+        if operands.size == 3 and operands[0].is_a? Immediate
+            $asm.puts "imul#{x86Suffix(kind)} #{x86Operands(kind, kind, kind)}"
+        else
+            # FIXME: could do some peephole in case the left operand is immediate and it's
+            # a power of two.
+            handleX86Op("imul#{x86Suffix(kind)}", kind)
+        end
+    end
+    
+    def handleMove
+        if Immediate.new(nil, 0) == operands[0] and operands[1].is_a? RegisterID
+            $asm.puts "xor#{x86Suffix(:ptr)} #{operands[1].x86Operand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
+        elsif operands[0] != operands[1]
+            $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
+        end
+    end
+    
+    def lowerX86
+        raise unless $activeBackend == "X86"
+        lowerX86Common
+    end
+    
+    def lowerX86_64
+        raise unless $activeBackend == "X86_64"
+        lowerX86Common
+    end
+    
+    def lowerX86Common
+        $asm.comment codeOriginString
+        case opcode
+        when "addi"
+            handleX86Add(:int)
+        when "addp"
+            handleX86Add(:ptr)
+        when "andi"
+            handleX86Op("andl", :int)
+        when "andp"
+            handleX86Op("and#{x86Suffix(:ptr)}", :ptr)
+        when "lshifti"
+            handleX86Shift("sall", :int)
+        when "lshiftp"
+            handleX86Shift("sal#{x86Suffix(:ptr)}", :ptr)
+        when "muli"
+            handleX86Mul(:int)
+        when "mulp"
+            handleX86Mul(:ptr)
+        when "negi"
+            $asm.puts "negl #{x86Operands(:int)}"
+        when "negp"
+            $asm.puts "neg#{x86Suffix(:ptr)} #{x86Operands(:ptr)}"
+        when "noti"
+            $asm.puts "notl #{x86Operands(:int)}"
+        when "ori"
+            handleX86Op("orl", :int)
+        when "orp"
+            handleX86Op("or#{x86Suffix(:ptr)}", :ptr)
+        when "rshifti"
+            handleX86Shift("sarl", :int)
+        when "rshiftp"
+            handleX86Shift("sar#{x86Suffix(:ptr)}", :ptr)
+        when "urshifti"
+            handleX86Shift("shrl", :int)
+        when "urshiftp"
+            handleX86Shift("shr#{x86Suffix(:ptr)}", :ptr)
+        when "subi"
+            handleX86Sub(:int)
+        when "subp"
+            handleX86Sub(:ptr)
+        when "xori"
+            handleX86Op("xorl", :int)
+        when "xorp"
+            handleX86Op("xor#{x86Suffix(:ptr)}", :ptr)
+        when "loadi", "storei"
+            $asm.puts "movl #{x86Operands(:int, :int)}"
+        when "loadis"
+            if isX64
+                $asm.puts "movslq #{x86Operands(:int, :ptr)}"
+            else
+                $asm.puts "movl #{x86Operands(:int, :int)}"
+            end
+        when "loadp", "storep"
+            $asm.puts "mov#{x86Suffix(:ptr)} #{x86Operands(:ptr, :ptr)}"
+        when "loadb"
+            $asm.puts "movzbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
+        when "loadbs"
+            $asm.puts "movsbl #{operands[0].x86Operand(:byte)}, #{operands[1].x86Operand(:int)}"
+        when "loadh"
+            $asm.puts "movzwl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
+        when "loadhs"
+            $asm.puts "movswl #{operands[0].x86Operand(:half)}, #{operands[1].x86Operand(:int)}"
+        when "storeb"
+            $asm.puts "movb #{x86Operands(:byte, :byte)}"
+        when "loadd", "moved", "stored"
+            $asm.puts "movsd #{x86Operands(:double, :double)}"
+        when "addd"
+            $asm.puts "addsd #{x86Operands(:double, :double)}"
+        when "divd"
+            $asm.puts "divsd #{x86Operands(:double, :double)}"
+        when "subd"
+            $asm.puts "subsd #{x86Operands(:double, :double)}"
+        when "muld"
+            $asm.puts "mulsd #{x86Operands(:double, :double)}"
+        when "sqrtd"
+            $asm.puts "sqrtsd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
+        when "ci2d"
+            $asm.puts "cvtsi2sd #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:double)}"
+        when "bdeq"
+            isUnordered = LocalLabel.unique("bdeq")
+            $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
+            $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
+            $asm.puts "je #{LabelReference.new(codeOrigin, operands[2]).asmLabel}"
+            isUnordered.lower("X86")
+        when "bdneq"
+            handleX86DoubleBranch("jne", :normal)
+        when "bdgt"
+            handleX86DoubleBranch("ja", :normal)
+        when "bdgteq"
+            handleX86DoubleBranch("jae", :normal)
+        when "bdlt"
+            handleX86DoubleBranch("ja", :reverse)
+        when "bdlteq"
+            handleX86DoubleBranch("jae", :reverse)
+        when "bdequn"
+            handleX86DoubleBranch("je", :normal)
+        when "bdnequn"
+            isUnordered = LocalLabel.unique("bdnequn")
+            isEqual = LocalLabel.unique("bdnequn")
+            $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:double)}"
+            $asm.puts "jp #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
+            $asm.puts "je #{LabelReference.new(codeOrigin, isEqual).asmLabel}"
+            isUnordered.lower("X86")
+            $asm.puts "jmp #{operands[2].asmLabel}"
+            isEqual.lower("X86")
+        when "bdgtun"
+            handleX86DoubleBranch("jb", :reverse)
+        when "bdgtequn"
+            handleX86DoubleBranch("jbe", :reverse)
+        when "bdltun"
+            handleX86DoubleBranch("jb", :normal)
+        when "bdltequn"
+            handleX86DoubleBranch("jbe", :normal)
+        when "btd2i"
+            $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
+            $asm.puts "cmpl $0x80000000 #{operands[1].x86Operand(:int)}"
+            $asm.puts "je #{operands[2].asmLabel}"
+        when "td2i"
+            $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
+        when "bcd2i"
+            $asm.puts "cvttsd2si #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
+            $asm.puts "testl #{operands[1].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
+            $asm.puts "je #{operands[2].asmLabel}"
+            $asm.puts "cvtsi2sd #{operands[1].x86Operand(:int)}, %xmm7"
+            $asm.puts "ucomisd #{operands[0].x86Operand(:double)}, %xmm7"
+            $asm.puts "jp #{operands[2].asmLabel}"
+            $asm.puts "jne #{operands[2].asmLabel}"
+        when "movdz"
+            $asm.puts "xorpd #{operands[0].x86Operand(:double)}, #{operands[0].x86Operand(:double)}"
+        when "pop"
+            $asm.puts "pop #{operands[0].x86Operand(:ptr)}"
+        when "push"
+            $asm.puts "push #{operands[0].x86Operand(:ptr)}"
+        when "move"
+            handleMove
+        when "sxi2p"
+            if isX64
+                $asm.puts "movslq #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:ptr)}"
+            else
+                handleMove
+            end
+        when "zxi2p"
+            if isX64
+                $asm.puts "movl #{operands[0].x86Operand(:int)}, #{operands[1].x86Operand(:int)}"
+            else
+                handleMove
+            end
+        when "nop"
+            $asm.puts "nop"
+        when "bieq"
+            handleX86IntBranch("je", :int)
+        when "bpeq"
+            handleX86IntBranch("je", :ptr)
+        when "bineq"
+            handleX86IntBranch("jne", :int)
+        when "bpneq"
+            handleX86IntBranch("jne", :ptr)
+        when "bia"
+            handleX86IntBranch("ja", :int)
+        when "bpa"
+            handleX86IntBranch("ja", :ptr)
+        when "biaeq"
+            handleX86IntBranch("jae", :int)
+        when "bpaeq"
+            handleX86IntBranch("jae", :ptr)
+        when "bib"
+            handleX86IntBranch("jb", :int)
+        when "bpb"
+            handleX86IntBranch("jb", :ptr)
+        when "bibeq"
+            handleX86IntBranch("jbe", :int)
+        when "bpbeq"
+            handleX86IntBranch("jbe", :ptr)
+        when "bigt"
+            handleX86IntBranch("jg", :int)
+        when "bpgt"
+            handleX86IntBranch("jg", :ptr)
+        when "bigteq"
+            handleX86IntBranch("jge", :int)
+        when "bpgteq"
+            handleX86IntBranch("jge", :ptr)
+        when "bilt"
+            handleX86IntBranch("jl", :int)
+        when "bplt"
+            handleX86IntBranch("jl", :ptr)
+        when "bilteq"
+            handleX86IntBranch("jle", :int)
+        when "bplteq"
+            handleX86IntBranch("jle", :ptr)
+        when "bbeq"
+            handleX86IntBranch("je", :byte)
+        when "bbneq"
+            handleX86IntBranch("jne", :byte)
+        when "bba"
+            handleX86IntBranch("ja", :byte)
+        when "bbaeq"
+            handleX86IntBranch("jae", :byte)
+        when "bbb"
+            handleX86IntBranch("jb", :byte)
+        when "bbbeq"
+            handleX86IntBranch("jbe", :byte)
+        when "bbgt"
+            handleX86IntBranch("jg", :byte)
+        when "bbgteq"
+            handleX86IntBranch("jge", :byte)
+        when "bblt"
+            handleX86IntBranch("jl", :byte)
+        when "bblteq"
+            handleX86IntBranch("jlteq", :byte)
+        when "btio"
+            handleX86BranchTest("jo", :int)
+        when "btpo"
+            handleX86BranchTest("jo", :ptr)
+        when "btis"
+            handleX86BranchTest("js", :int)
+        when "btps"
+            handleX86BranchTest("js", :ptr)
+        when "btiz"
+            handleX86BranchTest("jz", :int)
+        when "btpz"
+            handleX86BranchTest("jz", :ptr)
+        when "btinz"
+            handleX86BranchTest("jnz", :int)
+        when "btpnz"
+            handleX86BranchTest("jnz", :ptr)
+        when "btbo"
+            handleX86BranchTest("jo", :byte)
+        when "btbs"
+            handleX86BranchTest("js", :byte)
+        when "btbz"
+            handleX86BranchTest("jz", :byte)
+        when "btbnz"
+            handleX86BranchTest("jnz", :byte)
+        when "jmp"
+            $asm.puts "jmp #{operands[0].x86CallOperand(:ptr)}"
+        when "baddio"
+            handleX86OpBranch("addl", "jo", :int)
+        when "baddpo"
+            handleX86OpBranch("add#{x86Suffix(:ptr)}", "jo", :ptr)
+        when "baddis"
+            handleX86OpBranch("addl", "js", :int)
+        when "baddps"
+            handleX86OpBranch("add#{x86Suffix(:ptr)}", "js", :ptr)
+        when "baddiz"
+            handleX86OpBranch("addl", "jz", :int)
+        when "baddpz"
+            handleX86OpBranch("add#{x86Suffix(:ptr)}", "jz", :ptr)
+        when "baddinz"
+            handleX86OpBranch("addl", "jnz", :int)
+        when "baddpnz"
+            handleX86OpBranch("add#{x86Suffix(:ptr)}", "jnz", :ptr)
+        when "bsubio"
+            handleX86SubBranch("jo", :int)
+        when "bsubis"
+            handleX86SubBranch("js", :int)
+        when "bsubiz"
+            handleX86SubBranch("jz", :int)
+        when "bsubinz"
+            handleX86SubBranch("jnz", :int)
+        when "bmulio"
+            handleX86OpBranch("imull", "jo", :int)
+        when "bmulis"
+            handleX86OpBranch("imull", "js", :int)
+        when "bmuliz"
+            handleX86OpBranch("imull", "jz", :int)
+        when "bmulinz"
+            handleX86OpBranch("imull", "jnz", :int)
+        when "borio"
+            handleX86OpBranch("orl", "jo", :int)
+        when "boris"
+            handleX86OpBranch("orl", "js", :int)
+        when "boriz"
+            handleX86OpBranch("orl", "jz", :int)
+        when "borinz"
+            handleX86OpBranch("orl", "jnz", :int)
+        when "break"
+            $asm.puts "int $3"
+        when "call"
+            $asm.puts "call #{operands[0].x86CallOperand(:ptr)}"
+        when "ret"
+            $asm.puts "ret"
+        when "cieq"
+            handleX86IntCompareSet("sete", :int)
+        when "cbeq"
+            handleX86IntCompareSet("sete", :byte)
+        when "cpeq"
+            handleX86IntCompareSet("sete", :ptr)
+        when "cineq"
+            handleX86IntCompareSet("setne", :int)
+        when "cbneq"
+            handleX86IntCompareSet("setne", :byte)
+        when "cpneq"
+            handleX86IntCompareSet("setne", :ptr)
+        when "cia"
+            handleX86IntCompareSet("seta", :int)
+        when "cba"
+            handleX86IntCompareSet("seta", :byte)
+        when "cpa"
+            handleX86IntCompareSet("seta", :ptr)
+        when "ciaeq"
+            handleX86IntCompareSet("setae", :int)
+        when "cbaeq"
+            handleX86IntCompareSet("setae", :byte)
+        when "cpaeq"
+            handleX86IntCompareSet("setae", :ptr)
+        when "cib"
+            handleX86IntCompareSet("setb", :int)
+        when "cbb"
+            handleX86IntCompareSet("setb", :byte)
+        when "cpb"
+            handleX86IntCompareSet("setb", :ptr)
+        when "cibeq"
+            handleX86IntCompareSet("setbe", :int)
+        when "cbbeq"
+            handleX86IntCompareSet("setbe", :byte)
+        when "cpbeq"
+            handleX86IntCompareSet("setbe", :ptr)
+        when "cigt"
+            handleX86IntCompareSet("setg", :int)
+        when "cbgt"
+            handleX86IntCompareSet("setg", :byte)
+        when "cpgt"
+            handleX86IntCompareSet("setg", :ptr)
+        when "cigteq"
+            handleX86IntCompareSet("setge", :int)
+        when "cbgteq"
+            handleX86IntCompareSet("setge", :byte)
+        when "cpgteq"
+            handleX86IntCompareSet("setge", :ptr)
+        when "cilt"
+            handleX86IntCompareSet("setl", :int)
+        when "cblt"
+            handleX86IntCompareSet("setl", :byte)
+        when "cplt"
+            handleX86IntCompareSet("setl", :ptr)
+        when "cilteq"
+            handleX86IntCompareSet("setle", :int)
+        when "cblteq"
+            handleX86IntCompareSet("setle", :byte)
+        when "cplteq"
+            handleX86IntCompareSet("setle", :ptr)
+        when "tio"
+            handleX86SetTest("seto", :int)
+        when "tis"
+            handleX86SetTest("sets", :int)
+        when "tiz"
+            handleX86SetTest("setz", :int)
+        when "tinz"
+            handleX86SetTest("setnz", :int)
+        when "tpo"
+            handleX86SetTest("seto", :ptr)
+        when "tps"
+            handleX86SetTest("sets", :ptr)
+        when "tpz"
+            handleX86SetTest("setz", :ptr)
+        when "tpnz"
+            handleX86SetTest("setnz", :ptr)
+        when "tbo"
+            handleX86SetTest("seto", :byte)
+        when "tbs"
+            handleX86SetTest("sets", :byte)
+        when "tbz"
+            handleX86SetTest("setz", :byte)
+        when "tbnz"
+            handleX86SetTest("setnz", :byte)
+        when "peek"
+            sp = RegisterID.new(nil, "sp")
+            $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)}), #{operands[1].x86Operand(:ptr)}"
+        when "poke"
+            sp = RegisterID.new(nil, "sp")
+            $asm.puts "mov#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{operands[1].value * x86Bytes(:ptr)}(#{sp.x86Operand(:ptr)})"
+        when "cdqi"
+            $asm.puts "cdq"
+        when "idivi"
+            $asm.puts "idivl #{operands[0].x86Operand(:int)}"
+        when "fii2d"
+            $asm.puts "movd #{operands[0].x86Operand(:int)}, #{operands[2].x86Operand(:double)}"
+            $asm.puts "movd #{operands[1].x86Operand(:int)}, %xmm7"
+            $asm.puts "psllq $32, %xmm7"
+            $asm.puts "por %xmm7, #{operands[2].x86Operand(:double)}"
+        when "fd2ii"
+            $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:int)}"
+            $asm.puts "movsd #{operands[0].x86Operand(:double)}, %xmm7"
+            $asm.puts "psrlq $32, %xmm7"
+            $asm.puts "movsd %xmm7, #{operands[2].x86Operand(:int)}"
+        when "fp2d"
+            $asm.puts "movd #{operands[0].x86Operand(:ptr)}, #{operands[1].x86Operand(:double)}"
+        when "fd2p"
+            $asm.puts "movd #{operands[0].x86Operand(:double)}, #{operands[1].x86Operand(:ptr)}"
+        when "bo"
+            $asm.puts "jo #{operands[0].asmLabel}"
+        when "bs"
+            $asm.puts "js #{operands[0].asmLabel}"
+        when "bz"
+            $asm.puts "jz #{operands[0].asmLabel}"
+        when "bnz"
+            $asm.puts "jnz #{operands[0].asmLabel}"
+        when "leai"
+            $asm.puts "leal #{operands[0].x86AddressOperand(:int)}, #{operands[1].x86Operand(:int)}"
+        when "leap"
+            $asm.puts "lea#{x86Suffix(:ptr)} #{operands[0].x86AddressOperand(:ptr)}, #{operands[1].x86Operand(:ptr)}"
+        else
+            raise "Bad opcode: #{opcode}"
+        end
+    end
+end
+
index 17800d0050412d21e1784d26bb15569505f8996f..d4ff3e6574321a79b8dcd096a5417c4925c923fc 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 #include "config.h"
  */
 
 #include "config.h"
-#include "Vector.h"
+#include <wtf/Vector.h>
 #include <winbase.h>
 #include <winnls.h>
 #include <wtf/UnusedParam.h>
 #include <winbase.h>
 #include <winnls.h>
 #include <wtf/UnusedParam.h>
index 0ed6718d8de1b307e75c29ec1ed3b665c074f005..af7390e9828c8a81f29d852e4aa02fe738abb44c 100644 (file)
 #error "This inttypes.h file should only be compiled with MSVC"
 #endif
 
 #error "This inttypes.h file should only be compiled with MSVC"
 #endif
 
+#ifdef WTF_COMPILER_MSVC7_OR_LOWER
+// https://bugs.webkit.org/show_bug.cgi?id=76210
+#error "Visual Studio 2005 or newer is required"
+#endif
+
 #if _MSC_VER > 1000
 #pragma once
 #endif
 #if _MSC_VER > 1000
 #pragma once
 #endif
 #define PRIdFAST16   "hd"
 #define PRIiFAST16   "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 PRId32       "d"
+#define PRIi32       "i"
+#define PRIdLEAST32  "d"
+#define PRIiLEAST32  "i"
+#define PRIdFAST32   "d"
+#define PRIiFAST32   "i"
 
 
-#define PRId64       "I64d"
-#define PRIi64       "I64i"
-#define PRIdLEAST64  "I64d"
-#define PRIiLEAST64  "I64i"
-#define PRIdFAST64   "I64d"
-#define PRIiFAST64   "I64i"
+#define PRId64       "lld"
+#define PRIi64       "lli"
+#define PRIdLEAST64  "lld"
+#define PRIiLEAST64  "lli"
+#define PRIdFAST64   "lld"
+#define PRIiFAST64   "lli"
 
 
-#define PRIdMAX     "I64d"
-#define PRIiMAX     "I64i"
+#define PRIdMAX     "lld"
+#define PRIiMAX     "lli"
 
 #define PRIdPTR     "Id"
 #define PRIiPTR     "Ii"
 
 #define PRIdPTR     "Id"
 #define PRIiPTR     "Ii"
 #define PRIxFAST16   "hx"
 #define PRIXFAST16   "hX"
 
 #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 PRIo32       "o"
+#define PRIu32       "u"
+#define PRIx32       "x"
+#define PRIX32       "X"
+#define PRIoLEAST32  "o"
+#define PRIuLEAST32  "u"
+#define PRIxLEAST32  "x"
+#define PRIXLEAST32  "X"
+#define PRIoFAST32   "o"
+#define PRIuFAST32   "u"
+#define PRIxFAST32   "x"
+#define PRIXFAST32   "X"
+
+#define PRIo64       "llo"
+#define PRIu64       "llu"
+#define PRIx64       "llx"
+#define PRIX64       "llX"
+#define PRIoLEAST64  "llo"
+#define PRIuLEAST64  "llu"
+#define PRIxLEAST64  "llx"
+#define PRIXLEAST64  "llX"
+#define PRIoFAST64   "llo"
+#define PRIuFAST64   "llu"
+#define PRIxFAST64   "llx"
+#define PRIXFAST64   "llX"
+
+#define PRIoMAX     "llo"
+#define PRIuMAX     "llu"
+#define PRIxMAX     "llx"
+#define PRIXMAX     "llX"
 
 #define PRIoPTR     "Io"
 #define PRIuPTR     "Iu"
 
 #define PRIoPTR     "Io"
 #define PRIuPTR     "Iu"
 #define SCNdFAST32   "ld"
 #define SCNiFAST32   "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 SCNd64       "lld"
+#define SCNi64       "lli"
+#define SCNdLEAST64  "lld"
+#define SCNiLEAST64  "lli"
+#define SCNdFAST64   "lld"
+#define SCNiFAST64   "lli"
 
 
-#define SCNdMAX     "I64d"
-#define SCNiMAX     "I64i"
+#define SCNdMAX     "lld"
+#define SCNiMAX     "lli"
 
 #ifdef _WIN64
 
 #ifdef _WIN64
-#  define SCNdPTR     "I64d"
-#  define SCNiPTR     "I64i"
+#  define SCNdPTR     "lld"
+#  define SCNiPTR     "lli"
 #else
 #  define SCNdPTR     "ld"
 #  define SCNiPTR     "li"
 #else
 #  define SCNdPTR     "ld"
 #  define SCNiPTR     "li"
 #define SCNxFAST32   "lx"
 #define SCNXFAST32   "lX"
 
 #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"
+#define SCNo64       "llo"
+#define SCNu64       "llu"
+#define SCNx64       "llx"
+#define SCNX64       "llX"
+#define SCNoLEAST64  "llo"
+#define SCNuLEAST64  "llu"
+#define SCNxLEAST64  "llx"
+#define SCNXLEAST64  "llX"
+#define SCNoFAST64   "llo"
+#define SCNuFAST64   "llu"
+#define SCNxFAST64   "llx"
+#define SCNXFAST64   "llX"
+
+#define SCNoMAX     "llo"
+#define SCNuMAX     "llu"
+#define SCNxMAX     "llx"
+#define SCNXMAX     "llX"
 
 #ifdef _WIN64
 
 #ifdef _WIN64
-#  define SCNoPTR     "I64o"
-#  define SCNuPTR     "I64u"
-#  define SCNxPTR     "I64x"
-#  define SCNXPTR     "I64X"
+#  define SCNoPTR     "llo"
+#  define SCNuPTR     "llu"
+#  define SCNxPTR     "llx"
+#  define SCNXPTR     "llX"
 #else
 #  define SCNoPTR     "lo"
 #  define SCNuPTR     "lu"
 #else
 #  define SCNoPTR     "lo"
 #  define SCNuPTR     "lu"
index 8025c13b445c839211688c30fe3ca19086175e97..0eb60cf8992ff0924991344328bf931a1bf736e7 100644 (file)
@@ -73,9 +73,9 @@ class ASTBuilder {
         Operator m_op;
     };
 public:
         Operator m_op;
     };
 public:
-    ASTBuilder(JSGlobalData* globalData, Lexer* lexer)
+    ASTBuilder(JSGlobalData* globalData, SourceCode* sourceCode)
         : m_globalData(globalData)
         : m_globalData(globalData)
-        , m_lexer(lexer)
+        , m_sourceCode(sourceCode)
         , m_scope(globalData)
         , m_evalCount(0)
     {
         , m_scope(globalData)
         , m_evalCount(0)
     {
@@ -112,10 +112,10 @@ public:
     static const int  DontBuildKeywords = 0;
     static const int  DontBuildStrings = 0;
 
     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);
+    ExpressionNode* makeBinaryNode(int lineNumber, int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>);
+    ExpressionNode* makeFunctionCallNode(int lineNumber, ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end);
 
 
-    JSC::SourceElements* createSourceElements() { return new (m_globalData) JSC::SourceElements(m_globalData); }
+    JSC::SourceElements* createSourceElements() { return new (m_globalData) JSC::SourceElements(); }
 
     ParserArenaData<DeclarationStacks::VarStack>* varDeclarations() { return m_scope.m_varDeclarations; }
     ParserArenaData<DeclarationStacks::FunctionStack>* funcDeclarations() { return m_scope.m_funcDeclarations; }
 
     ParserArenaData<DeclarationStacks::VarStack>* varDeclarations() { return m_scope.m_varDeclarations; }
     ParserArenaData<DeclarationStacks::FunctionStack>* funcDeclarations() { return m_scope.m_funcDeclarations; }
@@ -124,182 +124,194 @@ public:
 
     void appendToComma(CommaNode* commaNode, ExpressionNode* expr) { commaNode->append(expr); }
 
 
     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)
+    CommaNode* createCommaExpr(int lineNumber, ExpressionNode* lhs, ExpressionNode* rhs) { return new (m_globalData) CommaNode(lineNumber, lhs, rhs); }
+
+    ExpressionNode* makeAssignNode(int lineNumber, ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, int start, int divot, int end);
+    ExpressionNode* makePrefixNode(int lineNumber, ExpressionNode*, Operator, int start, int divot, int end);
+    ExpressionNode* makePostfixNode(int lineNumber, ExpressionNode*, Operator, int start, int divot, int end);
+    ExpressionNode* makeTypeOfNode(int lineNumber, ExpressionNode*);
+    ExpressionNode* makeDeleteNode(int lineNumber, ExpressionNode*, int start, int divot, int end);
+    ExpressionNode* makeNegateNode(int lineNumber, ExpressionNode*);
+    ExpressionNode* makeBitwiseNotNode(int lineNumber, ExpressionNode*);
+    ExpressionNode* makeMultNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeDivNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeModNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeAddNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeSubNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeBitXOrNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeBitAndNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeBitOrNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeLeftShiftNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeRightShiftNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeURightShiftNode(int lineNumber, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+
+    ExpressionNode* createLogicalNot(int lineNumber, ExpressionNode* expr) { return new (m_globalData) LogicalNotNode(lineNumber, expr); }
+    ExpressionNode* createUnaryPlus(int lineNumber, ExpressionNode* expr) { return new (m_globalData) UnaryPlusNode(lineNumber, expr); }
+    ExpressionNode* createVoid(int lineNumber, ExpressionNode* expr)
     {
         incConstants();
     {
         incConstants();
-        return new (m_globalData) VoidNode(m_globalData, expr);
+        return new (m_globalData) VoidNode(lineNumber, expr);
     }
     }
-    ExpressionNode* thisExpr()
+    ExpressionNode* thisExpr(int lineNumber)
     {
         usesThis();
     {
         usesThis();
-        return new (m_globalData) ThisNode(m_globalData);
+        return new (m_globalData) ThisNode(lineNumber);
     }
     }
-    ExpressionNode* createResolve(const Identifier* ident, int start)
+    ExpressionNode* createResolve(int lineNumber, const Identifier* ident, int start)
     {
         if (m_globalData->propertyNames->arguments == *ident)
             usesArguments();
     {
         if (m_globalData->propertyNames->arguments == *ident)
             usesArguments();
-        return new (m_globalData) ResolveNode(m_globalData, *ident, start);
+        return new (m_globalData) ResolveNode(lineNumber, *ident, start);
     }
     }
-    ExpressionNode* createObjectLiteral() { return new (m_globalData) ObjectLiteralNode(m_globalData); }
-    ExpressionNode* createObjectLiteral(PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(m_globalData, properties); }
+    ExpressionNode* createObjectLiteral(int lineNumber) { return new (m_globalData) ObjectLiteralNode(lineNumber); }
+    ExpressionNode* createObjectLiteral(int lineNumber, PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(lineNumber, properties); }
 
 
-    ExpressionNode* createArray(int elisions)
+    ExpressionNode* createArray(int lineNumber, int elisions)
     {
         if (elisions)
             incConstants();
     {
         if (elisions)
             incConstants();
-        return new (m_globalData) ArrayNode(m_globalData, elisions);
+        return new (m_globalData) ArrayNode(lineNumber, elisions);
     }
 
     }
 
-    ExpressionNode* createArray(ElementNode* elems) { return new (m_globalData) ArrayNode(m_globalData, elems); }
-    ExpressionNode* createArray(int elisions, ElementNode* elems)
+    ExpressionNode* createArray(int lineNumber, ElementNode* elems) { return new (m_globalData) ArrayNode(lineNumber, elems); }
+    ExpressionNode* createArray(int lineNumber, int elisions, ElementNode* elems)
     {
         if (elisions)
             incConstants();
     {
         if (elisions)
             incConstants();
-        return new (m_globalData) ArrayNode(m_globalData, elisions, elems);
+        return new (m_globalData) ArrayNode(lineNumber, elisions, elems);
     }
     }
-    ExpressionNode* createNumberExpr(double d)
+    ExpressionNode* createNumberExpr(int lineNumber, double d)
     {
         incConstants();
     {
         incConstants();
-        return new (m_globalData) NumberNode(m_globalData, d);
+        return new (m_globalData) NumberNode(lineNumber, d);
     }
 
     }
 
-    ExpressionNode* createString(const Identifier* string)
+    ExpressionNode* createString(int lineNumber, const Identifier* string)
     {
         incConstants();
     {
         incConstants();
-        return new (m_globalData) StringNode(m_globalData, *string);
+        return new (m_globalData) StringNode(lineNumber, *string);
     }
 
     }
 
-    ExpressionNode* createBoolean(bool b)
+    ExpressionNode* createBoolean(int lineNumber, bool b)
     {
         incConstants();
     {
         incConstants();
-        return new (m_globalData) BooleanNode(m_globalData, b);
+        return new (m_globalData) BooleanNode(lineNumber, b);
     }
 
     }
 
-    ExpressionNode* createNull()
+    ExpressionNode* createNull(int lineNumber)
     {
         incConstants();
     {
         incConstants();
-        return new (m_globalData) NullNode(m_globalData);
+        return new (m_globalData) NullNode(lineNumber);
     }
 
     }
 
-    ExpressionNode* createBracketAccess(ExpressionNode* base, ExpressionNode* property, bool propertyHasAssignments, int start, int divot, int end)
+    ExpressionNode* createBracketAccess(int lineNumber, ExpressionNode* base, ExpressionNode* property, bool propertyHasAssignments, int start, int divot, int end)
     {
     {
-        BracketAccessorNode* node = new (m_globalData) BracketAccessorNode(m_globalData, base, property, propertyHasAssignments);
+        BracketAccessorNode* node = new (m_globalData) BracketAccessorNode(lineNumber, base, property, propertyHasAssignments);
         setExceptionLocation(node, start, divot, end);
         return node;
     }
 
         setExceptionLocation(node, start, divot, end);
         return node;
     }
 
-    ExpressionNode* createDotAccess(ExpressionNode* base, const Identifier* property, int start, int divot, int end)
+    ExpressionNode* createDotAccess(int lineNumber, ExpressionNode* base, const Identifier* property, int start, int divot, int end)
     {
     {
-        DotAccessorNode* node = new (m_globalData) DotAccessorNode(m_globalData, base, *property);
+        DotAccessorNode* node = new (m_globalData) DotAccessorNode(lineNumber, base, *property);
         setExceptionLocation(node, start, divot, end);
         return node;
     }
 
         setExceptionLocation(node, start, divot, end);
         return node;
     }
 
-    ExpressionNode* createRegExp(const Identifier& pattern, const Identifier& flags, int start)
+    ExpressionNode* createRegExp(int lineNumber, const Identifier& pattern, const Identifier& flags, int start)
     {
         if (Yarr::checkSyntax(pattern.ustring()))
             return 0;
     {
         if (Yarr::checkSyntax(pattern.ustring()))
             return 0;
-        RegExpNode* node = new (m_globalData) RegExpNode(m_globalData, pattern, flags);
+        RegExpNode* node = new (m_globalData) RegExpNode(lineNumber, pattern, flags);
         int size = pattern.length() + 2; // + 2 for the two /'s
         setExceptionLocation(node, start, start + size, start + size);
         return node;
     }
 
         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)
+    ExpressionNode* createNewExpr(int lineNumber, ExpressionNode* expr, ArgumentsNode* arguments, int start, int divot, int end)
     {
     {
-        NewExprNode* node = new (m_globalData) NewExprNode(m_globalData, expr, arguments);
+        NewExprNode* node = new (m_globalData) NewExprNode(lineNumber, expr, arguments);
         setExceptionLocation(node, start, divot, end);
         return node;
     }
 
         setExceptionLocation(node, start, divot, end);
         return node;
     }
 
-    ExpressionNode* createNewExpr(ExpressionNode* expr, int start, int end)
+    ExpressionNode* createNewExpr(int lineNumber, ExpressionNode* expr, int start, int end)
     {
     {
-        NewExprNode* node = new (m_globalData) NewExprNode(m_globalData, expr);
+        NewExprNode* node = new (m_globalData) NewExprNode(lineNumber, expr);
         setExceptionLocation(node, start, end, end);
         return node;
     }
 
         setExceptionLocation(node, start, end, end);
         return node;
     }
 
-    ExpressionNode* createConditionalExpr(ExpressionNode* condition, ExpressionNode* lhs, ExpressionNode* rhs)
+    ExpressionNode* createConditionalExpr(int lineNumber, ExpressionNode* condition, ExpressionNode* lhs, ExpressionNode* rhs)
     {
     {
-        return new (m_globalData) ConditionalNode(m_globalData, condition, lhs, rhs);
+        return new (m_globalData) ConditionalNode(lineNumber, condition, lhs, rhs);
     }
 
     }
 
-    ExpressionNode* createAssignResolve(const Identifier& ident, ExpressionNode* rhs, bool rhsHasAssignment, int start, int divot, int end)
+    ExpressionNode* createAssignResolve(int lineNumber, const Identifier& ident, ExpressionNode* rhs, bool rhsHasAssignment, int start, int divot, int end)
     {
     {
-        AssignResolveNode* node = new (m_globalData) AssignResolveNode(m_globalData, ident, rhs, rhsHasAssignment);
+        if (rhs->isFuncExprNode())
+            static_cast<FuncExprNode*>(rhs)->body()->setInferredName(ident);
+        AssignResolveNode* node = new (m_globalData) AssignResolveNode(lineNumber, ident, rhs, rhsHasAssignment);
         setExceptionLocation(node, start, divot, end);
         return node;
     }
 
         setExceptionLocation(node, start, divot, end);
         return node;
     }
 
-    ExpressionNode* createFunctionExpr(const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+    ExpressionNode* createFunctionExpr(int lineNumber, 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);
+        FuncExprNode* result = new (m_globalData) FuncExprNode(lineNumber, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters);
         body->setLoc(bodyStartLine, bodyEndLine);
         return result;
     }
 
         body->setLoc(bodyStartLine, bodyEndLine);
         return result;
     }
 
-    FunctionBodyNode* createFunctionBody(bool inStrictContext)
+    FunctionBodyNode* createFunctionBody(int lineNumber, bool inStrictContext)
     {
     {
-        usesClosures();
-        return FunctionBodyNode::create(m_globalData, inStrictContext);
+        return FunctionBodyNode::create(m_globalData, lineNumber, inStrictContext);
     }
     
     }
     
-    template <bool> PropertyNode* createGetterOrSetterProperty(PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+    template <bool> PropertyNode* createGetterOrSetterProperty(int lineNumber, PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
     {
         ASSERT(name);
         body->setLoc(bodyStartLine, 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);
+        body->setInferredName(*name);
+        return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(lineNumber, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type);
     }
     
     }
     
+    template <bool> PropertyNode* createGetterOrSetterProperty(JSGlobalData*, int lineNumber, PropertyNode::Type type, double name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+    {
+        body->setLoc(bodyStartLine, bodyEndLine);
+        return new (m_globalData) PropertyNode(m_globalData, name, new (m_globalData) FuncExprNode(lineNumber, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(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); }
+    ArgumentsNode* createArguments() { return new (m_globalData) ArgumentsNode(); }
+    ArgumentsNode* createArguments(ArgumentListNode* args) { return new (m_globalData) ArgumentsNode(args); }
+    ArgumentListNode* createArgumentsList(int lineNumber, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(lineNumber, arg); }
+    ArgumentListNode* createArgumentsList(int lineNumber, ArgumentListNode* args, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(lineNumber, 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(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type)
+    {
+        if (node->isFuncExprNode())
+            static_cast<FuncExprNode*>(node)->body()->setInferredName(*propertyName);
+        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); }
     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); }
+    PropertyListNode* createPropertyList(int lineNumber, PropertyNode* property) { return new (m_globalData) PropertyListNode(lineNumber, property); }
+    PropertyListNode* createPropertyList(int lineNumber, PropertyNode* property, PropertyListNode* tail) { return new (m_globalData) PropertyListNode(lineNumber, 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); }
+    ElementNode* createElementList(int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(elisions, expr); }
+    ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(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); }
+    ParameterNode* createFormalParameterList(const Identifier& ident) { return new (m_globalData) ParameterNode(ident); }
+    ParameterNode* createFormalParameterList(ParameterNode* list, const Identifier& ident) { return new (m_globalData) ParameterNode(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); }
+    CaseClauseNode* createClause(ExpressionNode* expr, JSC::SourceElements* statements) { return new (m_globalData) CaseClauseNode(expr, statements); }
+    ClauseListNode* createClauseList(CaseClauseNode* clause) { return new (m_globalData) ClauseListNode(clause); }
+    ClauseListNode* createClauseList(ClauseListNode* tail, CaseClauseNode* clause) { return new (m_globalData) ClauseListNode(tail, clause); }
 
     void setUsesArguments(FunctionBodyNode* node) { node->setUsesArguments(); }
 
 
     void setUsesArguments(FunctionBodyNode* node) { node->setUsesArguments(); }
 
-    StatementNode* createFuncDeclStatement(const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+    StatementNode* createFuncDeclStatement(int lineNumber, 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);
+        FuncDeclNode* decl = new (m_globalData) FuncDeclNode(lineNumber, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters);
         if (*name == m_globalData->propertyNames->arguments)
             usesArguments();
         m_scope.m_funcDeclarations->data.append(decl->body());
         if (*name == m_globalData->propertyNames->arguments)
             usesArguments();
         m_scope.m_funcDeclarations->data.append(decl->body());
@@ -307,181 +319,181 @@ public:
         return decl;
     }
 
         return decl;
     }
 
-    StatementNode* createBlockStatement(JSC::SourceElements* elements, int startLine, int endLine)
+    StatementNode* createBlockStatement(int lineNumber, JSC::SourceElements* elements, int startLine, int endLine)
     {
     {
-        BlockNode* block = new (m_globalData) BlockNode(m_globalData, elements);
+        BlockNode* block = new (m_globalData) BlockNode(lineNumber, elements);
         block->setLoc(startLine, endLine);
         return block;
     }
 
         block->setLoc(startLine, endLine);
         return block;
     }
 
-    StatementNode* createExprStatement(ExpressionNode* expr, int start, int end)
+    StatementNode* createExprStatement(int lineNumber, ExpressionNode* expr, int start, int end)
     {
     {
-        ExprStatementNode* result = new (m_globalData) ExprStatementNode(m_globalData, expr);
+        ExprStatementNode* result = new (m_globalData) ExprStatementNode(lineNumber, expr);
         result->setLoc(start, end);
         return result;
     }
 
         result->setLoc(start, end);
         return result;
     }
 
-    StatementNode* createIfStatement(ExpressionNode* condition, StatementNode* trueBlock, int start, int end)
+    StatementNode* createIfStatement(int lineNumber, ExpressionNode* condition, StatementNode* trueBlock, int start, int end)
     {
     {
-        IfNode* result = new (m_globalData) IfNode(m_globalData, condition, trueBlock);
+        IfNode* result = new (m_globalData) IfNode(lineNumber, condition, trueBlock);
         result->setLoc(start, end);
         return result;
     }
 
         result->setLoc(start, end);
         return result;
     }
 
-    StatementNode* createIfStatement(ExpressionNode* condition, StatementNode* trueBlock, StatementNode* falseBlock, int start, int end)
+    StatementNode* createIfStatement(int lineNumber, ExpressionNode* condition, StatementNode* trueBlock, StatementNode* falseBlock, int start, int end)
     {
     {
-        IfNode* result = new (m_globalData) IfElseNode(m_globalData, condition, trueBlock, falseBlock);
+        IfNode* result = new (m_globalData) IfElseNode(lineNumber, condition, trueBlock, falseBlock);
         result->setLoc(start, end);
         return result;
     }
 
         result->setLoc(start, end);
         return result;
     }
 
-    StatementNode* createForLoop(ExpressionNode* initializer, ExpressionNode* condition, ExpressionNode* iter, StatementNode* statements, bool b, int start, int end)
+    StatementNode* createForLoop(int lineNumber, 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);
+        ForNode* result = new (m_globalData) ForNode(lineNumber, initializer, condition, iter, statements, b);
         result->setLoc(start, end);
         return result;
     }
 
         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)
+    StatementNode* createForInLoop(int lineNumber, 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);
+        ForInNode* result = new (m_globalData) ForInNode(m_globalData, lineNumber, *ident, initializer, iter, statements, initStart, initStart - start, initEnd - initStart);
         result->setLoc(startLine, endLine);
         setExceptionLocation(result, start, divot + 1, end);
         return result;
     }
 
         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)
+    StatementNode* createForInLoop(int lineNumber, 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);
+        ForInNode* result = new (m_globalData) ForInNode(m_globalData, lineNumber, lhs, iter, statements);
         result->setLoc(start, end);
         setExceptionLocation(result, eStart, eDivot, eEnd);
         return result;
     }
 
         result->setLoc(start, end);
         setExceptionLocation(result, eStart, eDivot, eEnd);
         return result;
     }
 
-    StatementNode* createEmptyStatement() { return new (m_globalData) EmptyStatementNode(m_globalData); }
+    StatementNode* createEmptyStatement(int lineNumber) { return new (m_globalData) EmptyStatementNode(lineNumber); }
 
 
-    StatementNode* createVarStatement(ExpressionNode* expr, int start, int end)
+    StatementNode* createVarStatement(int lineNumber, ExpressionNode* expr, int start, int end)
     {
         StatementNode* result;
         if (!expr)
     {
         StatementNode* result;
         if (!expr)
-            result = new (m_globalData) EmptyStatementNode(m_globalData);
+            result = new (m_globalData) EmptyStatementNode(lineNumber);
         else
         else
-            result = new (m_globalData) VarStatementNode(m_globalData, expr);
+            result = new (m_globalData) VarStatementNode(lineNumber, expr);
         result->setLoc(start, end);
         return result;
     }
 
         result->setLoc(start, end);
         return result;
     }
 
-    StatementNode* createReturnStatement(ExpressionNode* expression, int eStart, int eEnd, int startLine, int endLine)
+    StatementNode* createReturnStatement(int lineNumber, ExpressionNode* expression, int eStart, int eEnd, int startLine, int endLine)
     {
     {
-        ReturnNode* result = new (m_globalData) ReturnNode(m_globalData, expression);
+        ReturnNode* result = new (m_globalData) ReturnNode(lineNumber, expression);
         setExceptionLocation(result, eStart, eEnd, eEnd);
         result->setLoc(startLine, endLine);
         return result;
     }
 
         setExceptionLocation(result, eStart, eEnd, eEnd);
         result->setLoc(startLine, endLine);
         return result;
     }
 
-    StatementNode* createBreakStatement(int eStart, int eEnd, int startLine, int endLine)
+    StatementNode* createBreakStatement(int lineNumber, int eStart, int eEnd, int startLine, int endLine)
     {
     {
-        BreakNode* result = new (m_globalData) BreakNode(m_globalData);
+        BreakNode* result = new (m_globalData) BreakNode(m_globalData, lineNumber);
         setExceptionLocation(result, eStart, eEnd, eEnd);
         result->setLoc(startLine, endLine);
         return result;
     }
 
         setExceptionLocation(result, eStart, eEnd, eEnd);
         result->setLoc(startLine, endLine);
         return result;
     }
 
-    StatementNode* createBreakStatement(const Identifier* ident, int eStart, int eEnd, int startLine, int endLine)
+    StatementNode* createBreakStatement(int lineNumber, const Identifier* ident, int eStart, int eEnd, int startLine, int endLine)
     {
     {
-        BreakNode* result = new (m_globalData) BreakNode(m_globalData, *ident);
+        BreakNode* result = new (m_globalData) BreakNode(lineNumber, *ident);
         setExceptionLocation(result, eStart, eEnd, eEnd);
         result->setLoc(startLine, endLine);
         return result;
     }
 
         setExceptionLocation(result, eStart, eEnd, eEnd);
         result->setLoc(startLine, endLine);
         return result;
     }
 
-    StatementNode* createContinueStatement(int eStart, int eEnd, int startLine, int endLine)
+    StatementNode* createContinueStatement(int lineNumber, int eStart, int eEnd, int startLine, int endLine)
     {
     {
-        ContinueNode* result = new (m_globalData) ContinueNode(m_globalData);
+        ContinueNode* result = new (m_globalData) ContinueNode(m_globalData, lineNumber);
         setExceptionLocation(result, eStart, eEnd, eEnd);
         result->setLoc(startLine, endLine);
         return result;
     }
 
         setExceptionLocation(result, eStart, eEnd, eEnd);
         result->setLoc(startLine, endLine);
         return result;
     }
 
-    StatementNode* createContinueStatement(const Identifier* ident, int eStart, int eEnd, int startLine, int endLine)
+    StatementNode* createContinueStatement(int lineNumber, const Identifier* ident, int eStart, int eEnd, int startLine, int endLine)
     {
     {
-        ContinueNode* result = new (m_globalData) ContinueNode(m_globalData, *ident);
+        ContinueNode* result = new (m_globalData) ContinueNode(lineNumber, *ident);
         setExceptionLocation(result, eStart, eEnd, eEnd);
         result->setLoc(startLine, endLine);
         return result;
     }
 
         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)
+    StatementNode* createTryStatement(int lineNumber, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine)
     {
     {
-        TryNode* result = new (m_globalData) TryNode(m_globalData, tryBlock, *ident, catchHasEval, catchBlock, finallyBlock);
+        TryNode* result = new (m_globalData) TryNode(lineNumber, tryBlock, *ident, catchBlock, finallyBlock);
         if (catchBlock)
             usesCatch();
         result->setLoc(startLine, endLine);
         return result;
     }
 
         if (catchBlock)
             usesCatch();
         result->setLoc(startLine, endLine);
         return result;
     }
 
-    StatementNode* createSwitchStatement(ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine)
+    StatementNode* createSwitchStatement(int lineNumber, 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);
+        CaseBlockNode* cases = new (m_globalData) CaseBlockNode(firstClauses, defaultClause, secondClauses);
+        SwitchNode* result = new (m_globalData) SwitchNode(lineNumber, expr, cases);
         result->setLoc(startLine, endLine);
         return result;
     }
 
         result->setLoc(startLine, endLine);
         return result;
     }
 
-    StatementNode* createWhileStatement(ExpressionNode* expr, StatementNode* statement, int startLine, int endLine)
+    StatementNode* createWhileStatement(int lineNumber, ExpressionNode* expr, StatementNode* statement, int startLine, int endLine)
     {
     {
-        WhileNode* result = new (m_globalData) WhileNode(m_globalData, expr, statement);
+        WhileNode* result = new (m_globalData) WhileNode(lineNumber, expr, statement);
         result->setLoc(startLine, endLine);
         return result;
     }
 
         result->setLoc(startLine, endLine);
         return result;
     }
 
-    StatementNode* createDoWhileStatement(StatementNode* statement, ExpressionNode* expr, int startLine, int endLine)
+    StatementNode* createDoWhileStatement(int lineNumber, StatementNode* statement, ExpressionNode* expr, int startLine, int endLine)
     {
     {
-        DoWhileNode* result = new (m_globalData) DoWhileNode(m_globalData, statement, expr);
+        DoWhileNode* result = new (m_globalData) DoWhileNode(lineNumber, statement, expr);
         result->setLoc(startLine, endLine);
         return result;
     }
 
         result->setLoc(startLine, endLine);
         return result;
     }
 
-    StatementNode* createLabelStatement(const Identifier* ident, StatementNode* statement, int start, int end)
+    StatementNode* createLabelStatement(int lineNumber, const Identifier* ident, StatementNode* statement, int start, int end)
     {
     {
-        LabelNode* result = new (m_globalData) LabelNode(m_globalData, *ident, statement);
+        LabelNode* result = new (m_globalData) LabelNode(lineNumber, *ident, statement);
         setExceptionLocation(result, start, end, end);
         return result;
     }
 
         setExceptionLocation(result, start, end, end);
         return result;
     }
 
-    StatementNode* createWithStatement(ExpressionNode* expr, StatementNode* statement, int start, int end, int startLine, int endLine)
+    StatementNode* createWithStatement(int lineNumber, ExpressionNode* expr, StatementNode* statement, int start, int end, int startLine, int endLine)
     {
         usesWith();
     {
         usesWith();
-        WithNode* result = new (m_globalData) WithNode(m_globalData, expr, statement, end, end - start);
+        WithNode* result = new (m_globalData) WithNode(lineNumber, expr, statement, end, end - start);
         result->setLoc(startLine, endLine);
         return result;
     }    
     
         result->setLoc(startLine, endLine);
         return result;
     }    
     
-    StatementNode* createThrowStatement(ExpressionNode* expr, int start, int end, int startLine, int endLine)
+    StatementNode* createThrowStatement(int lineNumber, ExpressionNode* expr, int start, int end, int startLine, int endLine)
     {
     {
-        ThrowNode* result = new (m_globalData) ThrowNode(m_globalData, expr);
+        ThrowNode* result = new (m_globalData) ThrowNode(lineNumber, expr);
         result->setLoc(startLine, endLine);
         setExceptionLocation(result, start, end, end);
         return result;
     }
     
         result->setLoc(startLine, endLine);
         setExceptionLocation(result, start, end, end);
         return result;
     }
     
-    StatementNode* createDebugger(int startLine, int endLine)
+    StatementNode* createDebugger(int lineNumber, int startLine, int endLine)
     {
     {
-        DebuggerStatementNode* result = new (m_globalData) DebuggerStatementNode(m_globalData);
+        DebuggerStatementNode* result = new (m_globalData) DebuggerStatementNode(lineNumber);
         result->setLoc(startLine, endLine);
         return result;
     }
     
         result->setLoc(startLine, endLine);
         return result;
     }
     
-    StatementNode* createConstStatement(ConstDeclNode* decls, int startLine, int endLine)
+    StatementNode* createConstStatement(int lineNumber, ConstDeclNode* decls, int startLine, int endLine)
     {
     {
-        ConstStatementNode* result = new (m_globalData) ConstStatementNode(m_globalData, decls);
+        ConstStatementNode* result = new (m_globalData) ConstStatementNode(lineNumber, decls);
         result->setLoc(startLine, endLine);
         return result;
     }
 
         result->setLoc(startLine, endLine);
         return result;
     }
 
-    ConstDeclNode* appendConstDecl(ConstDeclNode* tail, const Identifier* name, ExpressionNode* initializer)
+    ConstDeclNode* appendConstDecl(int lineNumber, ConstDeclNode* tail, const Identifier* name, ExpressionNode* initializer)
     {
     {
-        ConstDeclNode* result = new (m_globalData) ConstDeclNode(m_globalData, *name, initializer);
+        ConstDeclNode* result = new (m_globalData) ConstDeclNode(lineNumber, *name, initializer);
         if (tail)
             tail->m_next = result;
         return result;
         if (tail)
             tail->m_next = result;
         return result;
@@ -499,7 +511,7 @@ public:
         m_scope.m_varDeclarations->data.append(std::make_pair(ident, attrs));
     }
 
         m_scope.m_varDeclarations->data.append(std::make_pair(ident, attrs));
     }
 
-    ExpressionNode* combineCommaNodes(ExpressionNode* list, ExpressionNode* init)
+    ExpressionNode* combineCommaNodes(int lineNumber, ExpressionNode* list, ExpressionNode* init)
     {
         if (!list)
             return init;
     {
         if (!list)
             return init;
@@ -507,7 +519,7 @@ public:
             static_cast<CommaNode*>(list)->append(init);
             return list;
         }
             static_cast<CommaNode*>(list)->append(init);
             return list;
         }
-        return new (m_globalData) CommaNode(m_globalData, list, init);
+        return new (m_globalData) CommaNode(lineNumber, list, init);
     }
 
     int evalCount() const { return m_evalCount; }
     }
 
     int evalCount() const { return m_evalCount; }
@@ -535,10 +547,10 @@ public:
         ASSERT(operandStackDepth >= 0);
         m_binaryOperandStack.resize(m_binaryOperandStack.size() - amount);
     }
         ASSERT(operandStackDepth >= 0);
         m_binaryOperandStack.resize(m_binaryOperandStack.size() - amount);
     }
-    void appendBinaryOperation(int& operandStackDepth, int&, const BinaryOperand& lhs, const BinaryOperand& rhs)
+    void appendBinaryOperation(int lineNumber, int& operandStackDepth, int&, const BinaryOperand& lhs, const BinaryOperand& rhs)
     {
         operandStackDepth++;
     {
         operandStackDepth++;
-        m_binaryOperandStack.append(std::make_pair(makeBinaryNode(m_binaryOperatorStack.last().first, lhs, rhs), BinaryOpInfo(lhs.second, rhs.second)));
+        m_binaryOperandStack.append(std::make_pair(makeBinaryNode(lineNumber, m_binaryOperatorStack.last().first, lhs, rhs), BinaryOpInfo(lhs.second, rhs.second)));
     }
     void operatorStackAppend(int& operatorStackDepth, int op, int precedence)
     {
     }
     void operatorStackAppend(int& operatorStackDepth, int op, int precedence)
     {
@@ -580,9 +592,9 @@ public:
         m_assignmentInfoStack.append(AssignmentInfo(node, start, divot, assignmentCount, op));
     }
 
         m_assignmentInfoStack.append(AssignmentInfo(node, start, divot, assignmentCount, op));
     }
 
-    ExpressionNode* createAssignment(int& assignmentStackDepth, ExpressionNode* rhs, int initialAssignmentCount, int currentAssignmentCount, int lastTokenEnd)
+    ExpressionNode* createAssignment(int lineNumber, 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);
+        ExpressionNode* result = makeAssignNode(lineNumber, 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;
         m_assignmentInfoStack.removeLast();
         assignmentStackDepth--;
         return result;
@@ -616,22 +628,20 @@ private:
     void incConstants() { m_scope.m_numConstants++; }
     void usesThis() { m_scope.m_features |= ThisFeature; }
     void usesCatch() { m_scope.m_features |= CatchFeature; }
     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 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;
     }
     void usesWith() { m_scope.m_features |= WithFeature; }
     void usesEval() 
     {
         m_evalCount++;
         m_scope.m_features |= EvalFeature;
     }
-    ExpressionNode* createNumber(double d)
+    ExpressionNode* createNumber(int lineNumber, double d)
     {
     {
-        return new (m_globalData) NumberNode(m_globalData, d);
+        return new (m_globalData) NumberNode(lineNumber, d);
     }
     
     JSGlobalData* m_globalData;
     }
     
     JSGlobalData* m_globalData;
-    Lexer* m_lexer;
+    SourceCode* m_sourceCode;
     Scope m_scope;
     Vector<BinaryOperand, 10> m_binaryOperandStack;
     Vector<AssignmentInfo, 10> m_assignmentInfoStack;
     Scope m_scope;
     Vector<BinaryOperand, 10> m_binaryOperandStack;
     Vector<AssignmentInfo, 10> m_assignmentInfoStack;
@@ -640,33 +650,33 @@ private:
     int m_evalCount;
 };
 
     int m_evalCount;
 };
 
-ExpressionNode* ASTBuilder::makeTypeOfNode(ExpressionNode* expr)
+ExpressionNode* ASTBuilder::makeTypeOfNode(int lineNumber, ExpressionNode* expr)
 {
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
 {
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (m_globalData) TypeOfResolveNode(m_globalData, resolve->identifier());
+        return new (m_globalData) TypeOfResolveNode(lineNumber, resolve->identifier());
     }
     }
-    return new (m_globalData) TypeOfValueNode(m_globalData, expr);
+    return new (m_globalData) TypeOfValueNode(lineNumber, expr);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeDeleteNode(ExpressionNode* expr, int start, int divot, int end)
+ExpressionNode* ASTBuilder::makeDeleteNode(int lineNumber, ExpressionNode* expr, int start, int divot, int end)
 {
     if (!expr->isLocation())
 {
     if (!expr->isLocation())
-        return new (m_globalData) DeleteValueNode(m_globalData, expr);
+        return new (m_globalData) DeleteValueNode(lineNumber, expr);
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (m_globalData) DeleteResolveNode(m_globalData, resolve->identifier(), divot, divot - start, end - divot);
+        return new (m_globalData) DeleteResolveNode(lineNumber, resolve->identifier(), divot, divot - start, end - divot);
     }
     if (expr->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
     }
     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);
+        return new (m_globalData) DeleteBracketNode(lineNumber, bracket->base(), bracket->subscript(), divot, divot - start, end - divot);
     }
     ASSERT(expr->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
     }
     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);
+    return new (m_globalData) DeleteDotNode(lineNumber, dot->base(), dot->identifier(), divot, divot - start, end - divot);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeNegateNode(ExpressionNode* n)
+ExpressionNode* ASTBuilder::makeNegateNode(int lineNumber, ExpressionNode* n)
 {
     if (n->isNumber()) {
         NumberNode* numberNode = static_cast<NumberNode*>(n);
 {
     if (n->isNumber()) {
         NumberNode* numberNode = static_cast<NumberNode*>(n);
@@ -674,128 +684,128 @@ ExpressionNode* ASTBuilder::makeNegateNode(ExpressionNode* n)
         return numberNode;
     }
 
         return numberNode;
     }
 
-    return new (m_globalData) NegateNode(m_globalData, n);
+    return new (m_globalData) NegateNode(lineNumber, n);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeBitwiseNotNode(ExpressionNode* expr)
+ExpressionNode* ASTBuilder::makeBitwiseNotNode(int lineNumber, ExpressionNode* expr)
 {
     if (expr->isNumber())
 {
     if (expr->isNumber())
-        return createNumber(~toInt32(static_cast<NumberNode*>(expr)->value()));
-    return new (m_globalData) BitwiseNotNode(m_globalData, expr);
+        return createNumber(lineNumber, ~toInt32(static_cast<NumberNode*>(expr)->value()));
+    return new (m_globalData) BitwiseNotNode(lineNumber, expr);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeMultNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ExpressionNode* ASTBuilder::makeMultNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     expr1 = expr1->stripUnaryPlus();
     expr2 = expr2->stripUnaryPlus();
 
     if (expr1->isNumber() && expr2->isNumber())
 {
     expr1 = expr1->stripUnaryPlus();
     expr2 = expr2->stripUnaryPlus();
 
     if (expr1->isNumber() && expr2->isNumber())
-        return createNumber(static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value());
+        return createNumber(lineNumber, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value());
 
     if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1)
 
     if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1)
-        return new (m_globalData) UnaryPlusNode(m_globalData, expr2);
+        return new (m_globalData) UnaryPlusNode(lineNumber, expr2);
 
     if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1)
 
     if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1)
-        return new (m_globalData) UnaryPlusNode(m_globalData, expr1);
+        return new (m_globalData) UnaryPlusNode(lineNumber, expr1);
 
 
-    return new (m_globalData) MultNode(m_globalData, expr1, expr2, rightHasAssignments);
+    return new (m_globalData) MultNode(lineNumber, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeDivNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ExpressionNode* ASTBuilder::makeDivNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     expr1 = expr1->stripUnaryPlus();
     expr2 = expr2->stripUnaryPlus();
 
     if (expr1->isNumber() && expr2->isNumber())
 {
     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);
+        return createNumber(lineNumber, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value());
+    return new (m_globalData) DivNode(lineNumber, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeModNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ExpressionNode* ASTBuilder::makeModNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     expr1 = expr1->stripUnaryPlus();
     expr2 = expr2->stripUnaryPlus();
     
     if (expr1->isNumber() && expr2->isNumber())
 {
     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);
+        return createNumber(lineNumber, fmod(static_cast<NumberNode*>(expr1)->value(), static_cast<NumberNode*>(expr2)->value()));
+    return new (m_globalData) ModNode(lineNumber, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeAddNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ExpressionNode* ASTBuilder::makeAddNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     if (expr1->isNumber() && expr2->isNumber())
 {
     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);
+        return createNumber(lineNumber, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value());
+    return new (m_globalData) AddNode(lineNumber, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeSubNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ExpressionNode* ASTBuilder::makeSubNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     expr1 = expr1->stripUnaryPlus();
     expr2 = expr2->stripUnaryPlus();
 
     if (expr1->isNumber() && expr2->isNumber())
 {
     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);
+        return createNumber(lineNumber, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value());
+    return new (m_globalData) SubNode(lineNumber, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeLeftShiftNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ExpressionNode* ASTBuilder::makeLeftShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     if (expr1->isNumber() && expr2->isNumber())
 {
     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);
+        return createNumber(lineNumber, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+    return new (m_globalData) LeftShiftNode(lineNumber, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeRightShiftNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ExpressionNode* ASTBuilder::makeRightShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     if (expr1->isNumber() && expr2->isNumber())
 {
     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);
+        return createNumber(lineNumber, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+    return new (m_globalData) RightShiftNode(lineNumber, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeURightShiftNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ExpressionNode* ASTBuilder::makeURightShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     if (expr1->isNumber() && expr2->isNumber())
 {
     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);
+        return createNumber(lineNumber, toUInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+    return new (m_globalData) UnsignedRightShiftNode(lineNumber, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeBitOrNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ExpressionNode* ASTBuilder::makeBitOrNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     if (expr1->isNumber() && expr2->isNumber())
 {
     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);
+        return createNumber(lineNumber, toInt32(static_cast<NumberNode*>(expr1)->value()) | toInt32(static_cast<NumberNode*>(expr2)->value()));
+    return new (m_globalData) BitOrNode(lineNumber, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeBitAndNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ExpressionNode* ASTBuilder::makeBitAndNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     if (expr1->isNumber() && expr2->isNumber())
 {
     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);
+        return createNumber(lineNumber, toInt32(static_cast<NumberNode*>(expr1)->value()) & toInt32(static_cast<NumberNode*>(expr2)->value()));
+    return new (m_globalData) BitAndNode(lineNumber, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeBitXOrNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+ExpressionNode* ASTBuilder::makeBitXOrNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
 {
     if (expr1->isNumber() && expr2->isNumber())
 {
     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);
+        return createNumber(lineNumber, toInt32(static_cast<NumberNode*>(expr1)->value()) ^ toInt32(static_cast<NumberNode*>(expr2)->value()));
+    return new (m_globalData) BitXOrNode(lineNumber, expr1, expr2, rightHasAssignments);
 }
 
 }
 
-ExpressionNode* ASTBuilder::makeFunctionCallNode(ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end)
+ExpressionNode* ASTBuilder::makeFunctionCallNode(int lineNumber, ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end)
 {
     if (!func->isLocation())
 {
     if (!func->isLocation())
-        return new (m_globalData) FunctionCallValueNode(m_globalData, func, args, divot, divot - start, end - divot);
+        return new (m_globalData) FunctionCallValueNode(lineNumber, 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();
     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) EvalFunctionCallNode(lineNumber, args, divot, divot - start, end - divot);
         }
         }
-        return new (m_globalData) FunctionCallResolveNode(m_globalData, identifier, args, divot, divot - start, end - divot);
+        return new (m_globalData) FunctionCallResolveNode(lineNumber, identifier, args, divot, divot - start, end - divot);
     }
     if (func->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func);
     }
     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);
+        FunctionCallBracketNode* node = new (m_globalData) FunctionCallBracketNode(lineNumber, bracket->base(), bracket->subscript(), args, divot, divot - start, end - divot);
         node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
         return node;
     }
         node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
         return node;
     }
@@ -803,173 +813,175 @@ ExpressionNode* ASTBuilder::makeFunctionCallNode(ExpressionNode* func, Arguments
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(func);
     FunctionCallDotNode* node;
     if (dot->identifier() == m_globalData->propertyNames->call)
     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);
+        node = new (m_globalData) CallFunctionCallDotNode(lineNumber, dot->base(), dot->identifier(), args, divot, divot - start, end - divot);
     else if (dot->identifier() == m_globalData->propertyNames->apply)
     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);
+        node = new (m_globalData) ApplyFunctionCallDotNode(lineNumber, dot->base(), dot->identifier(), args, divot, divot - start, end - divot);
     else
     else
-        node = new (m_globalData) FunctionCallDotNode(m_globalData, dot->base(), dot->identifier(), args, divot, divot - start, end - divot);
+        node = new (m_globalData) FunctionCallDotNode(lineNumber, dot->base(), dot->identifier(), args, divot, divot - start, end - divot);
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return node;
 }
 
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return node;
 }
 
-ExpressionNode* ASTBuilder::makeBinaryNode(int token, pair<ExpressionNode*, BinaryOpInfo> lhs, pair<ExpressionNode*, BinaryOpInfo> rhs)
+ExpressionNode* ASTBuilder::makeBinaryNode(int lineNumber, int token, pair<ExpressionNode*, BinaryOpInfo> lhs, pair<ExpressionNode*, BinaryOpInfo> rhs)
 {
     switch (token) {
     case OR:
 {
     switch (token) {
     case OR:
-        return new (m_globalData) LogicalOpNode(m_globalData, lhs.first, rhs.first, OpLogicalOr);
+        return new (m_globalData) LogicalOpNode(lineNumber, lhs.first, rhs.first, OpLogicalOr);
 
     case AND:
 
     case AND:
-        return new (m_globalData) LogicalOpNode(m_globalData, lhs.first, rhs.first, OpLogicalAnd);
+        return new (m_globalData) LogicalOpNode(lineNumber, lhs.first, rhs.first, OpLogicalAnd);
 
     case BITOR:
 
     case BITOR:
-        return makeBitOrNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+        return makeBitOrNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case BITXOR:
 
     case BITXOR:
-        return makeBitXOrNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+        return makeBitXOrNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case BITAND:
 
     case BITAND:
-        return makeBitAndNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+        return makeBitAndNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case EQEQ:
 
     case EQEQ:
-        return new (m_globalData) EqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+        return new (m_globalData) EqualNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case NE:
 
     case NE:
-        return new (m_globalData) NotEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+        return new (m_globalData) NotEqualNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case STREQ:
 
     case STREQ:
-        return new (m_globalData) StrictEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+        return new (m_globalData) StrictEqualNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case STRNEQ:
 
     case STRNEQ:
-        return new (m_globalData) NotStrictEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+        return new (m_globalData) NotStrictEqualNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case LT:
 
     case LT:
-        return new (m_globalData) LessNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+        return new (m_globalData) LessNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case GT:
 
     case GT:
-        return new (m_globalData) GreaterNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+        return new (m_globalData) GreaterNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case LE:
 
     case LE:
-        return new (m_globalData) LessEqNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+        return new (m_globalData) LessEqNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case GE:
 
     case GE:
-        return new (m_globalData) GreaterEqNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+        return new (m_globalData) GreaterEqNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case INSTANCEOF: {
 
     case INSTANCEOF: {
-        InstanceOfNode* node = new (m_globalData) InstanceOfNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+        InstanceOfNode* node = new (m_globalData) InstanceOfNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
         setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end);
         return node;
     }
 
     case INTOKEN: {
         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);
+        InNode* node = new (m_globalData) InNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
         setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end);
         return node;
     }
 
     case LSHIFT:
         setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end);
         return node;
     }
 
     case LSHIFT:
-        return makeLeftShiftNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+        return makeLeftShiftNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case RSHIFT:
 
     case RSHIFT:
-        return makeRightShiftNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+        return makeRightShiftNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case URSHIFT:
 
     case URSHIFT:
-        return makeURightShiftNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+        return makeURightShiftNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case PLUS:
 
     case PLUS:
-        return makeAddNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+        return makeAddNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case MINUS:
 
     case MINUS:
-        return makeSubNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+        return makeSubNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case TIMES:
 
     case TIMES:
-        return makeMultNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+        return makeMultNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case DIVIDE:
 
     case DIVIDE:
-        return makeDivNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+        return makeDivNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
 
     case MOD:
 
     case MOD:
-        return makeModNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+        return makeModNode(lineNumber, lhs.first, rhs.first, rhs.second.hasAssignment);
     }
     CRASH();
     return 0;
 }
 
     }
     CRASH();
     return 0;
 }
 
-ExpressionNode* ASTBuilder::makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end)
+ExpressionNode* ASTBuilder::makeAssignNode(int lineNumber, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end)
 {
 {
-    usesAssignment();
     if (!loc->isLocation())
     if (!loc->isLocation())
-        return new (m_globalData) AssignErrorNode(m_globalData, loc, op, expr, divot, divot - start, end - divot);
+        return new (m_globalData) AssignErrorNode(lineNumber, loc, op, expr, divot, divot - start, end - divot);
 
     if (loc->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(loc);
         if (op == OpEqual) {
 
     if (loc->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(loc);
         if (op == OpEqual) {
-            AssignResolveNode* node = new (m_globalData) AssignResolveNode(m_globalData, resolve->identifier(), expr, exprHasAssignments);
+            if (expr->isFuncExprNode())
+                static_cast<FuncExprNode*>(expr)->body()->setInferredName(resolve->identifier());
+            AssignResolveNode* node = new (m_globalData) AssignResolveNode(lineNumber, resolve->identifier(), expr, exprHasAssignments);
             setExceptionLocation(node, start, divot, end);
             return node;
         }
             setExceptionLocation(node, start, divot, end);
             return node;
         }
-        return new (m_globalData) ReadModifyResolveNode(m_globalData, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
+        return new (m_globalData) ReadModifyResolveNode(lineNumber, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
     }
     if (loc->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
         if (op == OpEqual)
     }
     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);
+            return new (m_globalData) AssignBracketNode(lineNumber, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot());
+        ReadModifyBracketNode* node = new (m_globalData) ReadModifyBracketNode(lineNumber, 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);
         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());
+    if (op == OpEqual) {
+        if (expr->isFuncExprNode())
+            static_cast<FuncExprNode*>(expr)->body()->setInferredName(dot->identifier());
+        return new (m_globalData) AssignDotNode(lineNumber, 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);
+    ReadModifyDotNode* node = new (m_globalData) ReadModifyDotNode(lineNumber, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return node;
 }
 
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return node;
 }
 
-ExpressionNode* ASTBuilder::makePrefixNode(ExpressionNode* expr, Operator op, int start, int divot, int end)
+ExpressionNode* ASTBuilder::makePrefixNode(int lineNumber, ExpressionNode* expr, Operator op, int start, int divot, int end)
 {
 {
-    usesAssignment();
     if (!expr->isLocation())
     if (!expr->isLocation())
-        return new (m_globalData) PrefixErrorNode(m_globalData, expr, op, divot, divot - start, end - divot);
+        return new (m_globalData) PrefixErrorNode(lineNumber, expr, op, divot, divot - start, end - divot);
 
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
 
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (m_globalData) PrefixResolveNode(m_globalData, resolve->identifier(), op, divot, divot - start, end - divot);
+        return new (m_globalData) PrefixResolveNode(lineNumber, resolve->identifier(), op, divot, divot - start, end - divot);
     }
     if (expr->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
     }
     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);
+        PrefixBracketNode* node = new (m_globalData) PrefixBracketNode(lineNumber, 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);
         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);
+    PrefixDotNode* node = new (m_globalData) PrefixDotNode(lineNumber, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
     node->setSubexpressionInfo(dot->divot(), dot->startOffset());
     return node;
 }
 
     node->setSubexpressionInfo(dot->divot(), dot->startOffset());
     return node;
 }
 
-ExpressionNode* ASTBuilder::makePostfixNode(ExpressionNode* expr, Operator op, int start, int divot, int end)
+ExpressionNode* ASTBuilder::makePostfixNode(int lineNumber, ExpressionNode* expr, Operator op, int start, int divot, int end)
 {
 {
-    usesAssignment();
     if (!expr->isLocation())
     if (!expr->isLocation())
-        return new (m_globalData) PostfixErrorNode(m_globalData, expr, op, divot, divot - start, end - divot);
+        return new (m_globalData) PostfixErrorNode(lineNumber, expr, op, divot, divot - start, end - divot);
 
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
 
     if (expr->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (m_globalData) PostfixResolveNode(m_globalData, resolve->identifier(), op, divot, divot - start, end - divot);
+        return new (m_globalData) PostfixResolveNode(lineNumber, resolve->identifier(), op, divot, divot - start, end - divot);
     }
     if (expr->isBracketAccessorNode()) {
         BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
     }
     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);
+        PostfixBracketNode* node = new (m_globalData) PostfixBracketNode(lineNumber, 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);
         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);
+    PostfixDotNode* node = new (m_globalData) PostfixDotNode(lineNumber, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return node;
 }
     node->setSubexpressionInfo(dot->divot(), dot->endOffset());
     return node;
 }
diff --git a/parser/JSParser.cpp b/parser/JSParser.cpp
deleted file mode 100644 (file)
index d56155b..0000000
+++ /dev/null
@@ -1,2186 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 8bb7dbb..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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 490c1cce0f9d99e751aa256706d9fb6bcb272949..527eada607b5aaf3d3d0a70eb08bf9e55054c903 100644 (file)
@@ -1,12 +1,12 @@
-# main keywords
-@begin mainTable 41
+# Main keywords.
+@begin mainTable 47
 
 
-# types
+# Types.
 null           NULLTOKEN
 true           TRUETOKEN
 false          FALSETOKEN
 
 null           NULLTOKEN
 true           TRUETOKEN
 false          FALSETOKEN
 
-# keywords
+# Keywords.
 break          BREAK
 case           CASE
 catch          CATCH
 break          BREAK
 case           CASE
 catch          CATCH
@@ -35,7 +35,7 @@ typeof                TYPEOF
 with           WITH
 debugger       DEBUGGER
 
 with           WITH
 debugger       DEBUGGER
 
-# reserved for future use
+# Reserved for future use.
 class           RESERVED
 enum            RESERVED
 export          RESERVED
 class           RESERVED
 enum            RESERVED
 export          RESERVED
@@ -43,30 +43,15 @@ extends         RESERVED
 import          RESERVED
 super           RESERVED
 
 import          RESERVED
 super           RESERVED
 
-# these words are reserved for future use in the ECMA spec, but not in WinIE
-# (see http://bugs.webkit.org/show_bug.cgi?id=6179)
-# abstract      RESERVED
-# boolean       RESERVED
-# byte          RESERVED
-# char          RESERVED
-# double        RESERVED
-# final         RESERVED
-# float         RESERVED
-# goto          RESERVED
-# implements    RESERVED
-# int           RESERVED
-# interface     RESERVED
-# long          RESERVED
-# native        RESERVED
-# package       RESERVED
-# private       RESERVED
-# protected     RESERVED
-# public        RESERVED
-# short         RESERVED
-# static        RESERVED
-# synchronized  RESERVED
-# throws        RESERVED
-# transient     RESERVED
-# volatile      RESERVED
-@end
+# Reserved for future use in strict code.
+implements      RESERVED_IF_STRICT
+interface       RESERVED_IF_STRICT
+let             RESERVED_IF_STRICT
+package         RESERVED_IF_STRICT
+private         RESERVED_IF_STRICT
+protected       RESERVED_IF_STRICT
+public          RESERVED_IF_STRICT
+static          RESERVED_IF_STRICT
+yield           RESERVED_IF_STRICT
 
 
+@end
index cae6bb99daeacfce8f75fa9783c6976936b22817..3b020f4f2b1b096a70a95a9b588827bd90b9859c 100644 (file)
@@ -1,8 +1,9 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All Rights Reserved.
+ *  Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All Rights Reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2010 Zoltan Herczeg (zherczeg@inf.u-szeged.hu)
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2010 Zoltan Herczeg (zherczeg@inf.u-szeged.hu)
+ *  Copyright (C) 2012 Mathias Bynens (mathias@qiwi.be)
  *
  *  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
@@ -30,7 +31,7 @@
 #include "Identifier.h"
 #include "NodeInfo.h"
 #include "Nodes.h"
 #include "Identifier.h"
 #include "NodeInfo.h"
 #include "Nodes.h"
-#include "dtoa.h"
+#include <wtf/dtoa.h>
 #include <ctype.h>
 #include <limits.h>
 #include <string.h>
 #include <ctype.h>
 #include <limits.h>
 #include <string.h>
 using namespace WTF;
 using namespace Unicode;
 
 using namespace WTF;
 using namespace Unicode;
 
-#include "JSParser.h"
 #include "KeywordLookup.h"
 #include "KeywordLookup.h"
-#include "Lookup.h"
 #include "Lexer.lut.h"
 #include "Lexer.lut.h"
+#include "Parser.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
+Keywords::Keywords(JSGlobalData* globalData)
+    : m_globalData(globalData)
+    , m_keywordTable(JSC::mainTable)
+{
+}
 
 enum CharacterType {
     // Types for the main switch
 
 enum CharacterType {
     // Types for the main switch
@@ -90,8 +95,8 @@ enum CharacterType {
     CharacterWhiteSpace,
 };
 
     CharacterWhiteSpace,
 };
 
-// 128 ASCII codes
-static const unsigned short typesOfASCIICharacters[128] = {
+// 256 Latin-1 codes
+static const unsigned short typesOfLatin1Characters[256] = {
 /*   0 - Null               */ CharacterInvalid,
 /*   1 - Start of Heading   */ CharacterInvalid,
 /*   2 - Start of Text      */ CharacterInvalid,
 /*   0 - Null               */ CharacterInvalid,
 /*   1 - Start of Heading   */ CharacterInvalid,
 /*   2 - Start of Text      */ CharacterInvalid,
@@ -220,91 +225,248 @@ static const unsigned short typesOfASCIICharacters[128] = {
 /* 125 - }                  */ CharacterCloseBrace,
 /* 126 - ~                  */ CharacterTilde,
 /* 127 - Delete             */ CharacterInvalid,
 /* 125 - }                  */ CharacterCloseBrace,
 /* 126 - ~                  */ CharacterTilde,
 /* 127 - Delete             */ CharacterInvalid,
+/* 128 - Cc category        */ CharacterInvalid,
+/* 129 - Cc category        */ CharacterInvalid,
+/* 130 - Cc category        */ CharacterInvalid,
+/* 131 - Cc category        */ CharacterInvalid,
+/* 132 - Cc category        */ CharacterInvalid,
+/* 133 - Cc category        */ CharacterInvalid,
+/* 134 - Cc category        */ CharacterInvalid,
+/* 135 - Cc category        */ CharacterInvalid,
+/* 136 - Cc category        */ CharacterInvalid,
+/* 137 - Cc category        */ CharacterInvalid,
+/* 138 - Cc category        */ CharacterInvalid,
+/* 139 - Cc category        */ CharacterInvalid,
+/* 140 - Cc category        */ CharacterInvalid,
+/* 141 - Cc category        */ CharacterInvalid,
+/* 142 - Cc category        */ CharacterInvalid,
+/* 143 - Cc category        */ CharacterInvalid,
+/* 144 - Cc category        */ CharacterInvalid,
+/* 145 - Cc category        */ CharacterInvalid,
+/* 146 - Cc category        */ CharacterInvalid,
+/* 147 - Cc category        */ CharacterInvalid,
+/* 148 - Cc category        */ CharacterInvalid,
+/* 149 - Cc category        */ CharacterInvalid,
+/* 150 - Cc category        */ CharacterInvalid,
+/* 151 - Cc category        */ CharacterInvalid,
+/* 152 - Cc category        */ CharacterInvalid,
+/* 153 - Cc category        */ CharacterInvalid,
+/* 154 - Cc category        */ CharacterInvalid,
+/* 155 - Cc category        */ CharacterInvalid,
+/* 156 - Cc category        */ CharacterInvalid,
+/* 157 - Cc category        */ CharacterInvalid,
+/* 158 - Cc category        */ CharacterInvalid,
+/* 159 - Cc category        */ CharacterInvalid,
+/* 160 - Zs category (nbsp) */ CharacterWhiteSpace,
+/* 161 - Po category        */ CharacterInvalid,
+/* 162 - Sc category        */ CharacterInvalid,
+/* 163 - Sc category        */ CharacterInvalid,
+/* 164 - Sc category        */ CharacterInvalid,
+/* 165 - Sc category        */ CharacterInvalid,
+/* 166 - So category        */ CharacterInvalid,
+/* 167 - So category        */ CharacterInvalid,
+/* 168 - Sk category        */ CharacterInvalid,
+/* 169 - So category        */ CharacterInvalid,
+/* 170 - Ll category        */ CharacterIdentifierStart,
+/* 171 - Pi category        */ CharacterInvalid,
+/* 172 - Sm category        */ CharacterInvalid,
+/* 173 - Cf category        */ CharacterInvalid,
+/* 174 - So category        */ CharacterInvalid,
+/* 175 - Sk category        */ CharacterInvalid,
+/* 176 - So category        */ CharacterInvalid,
+/* 177 - Sm category        */ CharacterInvalid,
+/* 178 - No category        */ CharacterInvalid,
+/* 179 - No category        */ CharacterInvalid,
+/* 180 - Sk category        */ CharacterInvalid,
+/* 181 - Ll category        */ CharacterIdentifierStart,
+/* 182 - So category        */ CharacterInvalid,
+/* 183 - Po category        */ CharacterInvalid,
+/* 184 - Sk category        */ CharacterInvalid,
+/* 185 - No category        */ CharacterInvalid,
+/* 186 - Ll category        */ CharacterIdentifierStart,
+/* 187 - Pf category        */ CharacterInvalid,
+/* 188 - No category        */ CharacterInvalid,
+/* 189 - No category        */ CharacterInvalid,
+/* 190 - No category        */ CharacterInvalid,
+/* 191 - Po category        */ CharacterInvalid,
+/* 192 - Lu category        */ CharacterIdentifierStart,
+/* 193 - Lu category        */ CharacterIdentifierStart,
+/* 194 - Lu category        */ CharacterIdentifierStart,
+/* 195 - Lu category        */ CharacterIdentifierStart,
+/* 196 - Lu category        */ CharacterIdentifierStart,
+/* 197 - Lu category        */ CharacterIdentifierStart,
+/* 198 - Lu category        */ CharacterIdentifierStart,
+/* 199 - Lu category        */ CharacterIdentifierStart,
+/* 200 - Lu category        */ CharacterIdentifierStart,
+/* 201 - Lu category        */ CharacterIdentifierStart,
+/* 202 - Lu category        */ CharacterIdentifierStart,
+/* 203 - Lu category        */ CharacterIdentifierStart,
+/* 204 - Lu category        */ CharacterIdentifierStart,
+/* 205 - Lu category        */ CharacterIdentifierStart,
+/* 206 - Lu category        */ CharacterIdentifierStart,
+/* 207 - Lu category        */ CharacterIdentifierStart,
+/* 208 - Lu category        */ CharacterIdentifierStart,
+/* 209 - Lu category        */ CharacterIdentifierStart,
+/* 210 - Lu category        */ CharacterIdentifierStart,
+/* 211 - Lu category        */ CharacterIdentifierStart,
+/* 212 - Lu category        */ CharacterIdentifierStart,
+/* 213 - Lu category        */ CharacterIdentifierStart,
+/* 214 - Lu category        */ CharacterIdentifierStart,
+/* 215 - Sm category        */ CharacterInvalid,
+/* 216 - Lu category        */ CharacterIdentifierStart,
+/* 217 - Lu category        */ CharacterIdentifierStart,
+/* 218 - Lu category        */ CharacterIdentifierStart,
+/* 219 - Lu category        */ CharacterIdentifierStart,
+/* 220 - Lu category        */ CharacterIdentifierStart,
+/* 221 - Lu category        */ CharacterIdentifierStart,
+/* 222 - Lu category        */ CharacterIdentifierStart,
+/* 223 - Ll category        */ CharacterIdentifierStart,
+/* 224 - Ll category        */ CharacterIdentifierStart,
+/* 225 - Ll category        */ CharacterIdentifierStart,
+/* 226 - Ll category        */ CharacterIdentifierStart,
+/* 227 - Ll category        */ CharacterIdentifierStart,
+/* 228 - Ll category        */ CharacterIdentifierStart,
+/* 229 - Ll category        */ CharacterIdentifierStart,
+/* 230 - Ll category        */ CharacterIdentifierStart,
+/* 231 - Ll category        */ CharacterIdentifierStart,
+/* 232 - Ll category        */ CharacterIdentifierStart,
+/* 233 - Ll category        */ CharacterIdentifierStart,
+/* 234 - Ll category        */ CharacterIdentifierStart,
+/* 235 - Ll category        */ CharacterIdentifierStart,
+/* 236 - Ll category        */ CharacterIdentifierStart,
+/* 237 - Ll category        */ CharacterIdentifierStart,
+/* 238 - Ll category        */ CharacterIdentifierStart,
+/* 239 - Ll category        */ CharacterIdentifierStart,
+/* 240 - Ll category        */ CharacterIdentifierStart,
+/* 241 - Ll category        */ CharacterIdentifierStart,
+/* 242 - Ll category        */ CharacterIdentifierStart,
+/* 243 - Ll category        */ CharacterIdentifierStart,
+/* 244 - Ll category        */ CharacterIdentifierStart,
+/* 245 - Ll category        */ CharacterIdentifierStart,
+/* 246 - Ll category        */ CharacterIdentifierStart,
+/* 247 - Sm category        */ CharacterInvalid,
+/* 248 - Ll category        */ CharacterIdentifierStart,
+/* 249 - Ll category        */ CharacterIdentifierStart,
+/* 250 - Ll category        */ CharacterIdentifierStart,
+/* 251 - Ll category        */ CharacterIdentifierStart,
+/* 252 - Ll category        */ CharacterIdentifierStart,
+/* 253 - Ll category        */ CharacterIdentifierStart,
+/* 254 - Ll category        */ CharacterIdentifierStart,
+/* 255 - Ll category        */ CharacterIdentifierStart
 };
 
 };
 
-Lexer::Lexer(JSGlobalData* globalData)
+template <typename T>
+Lexer<T>::Lexer(JSGlobalData* globalData)
     : m_isReparsing(false)
     , m_globalData(globalData)
     : m_isReparsing(false)
     , m_globalData(globalData)
-    , m_keywordTable(JSC::mainTable)
 {
 }
 
 {
 }
 
-Lexer::~Lexer()
+template <typename T>
+Lexer<T>::~Lexer()
 {
 {
-    m_keywordTable.deleteTable();
 }
 
 }
 
-ALWAYS_INLINE const UChar* Lexer::currentCharacter() const
+template <typename T>
+UString Lexer<T>::invalidCharacterMessage() const
 {
 {
-    ASSERT(m_code <= m_codeEnd);
-    return m_code;
+    switch (m_current) {
+    case 0:
+        return "Invalid character: '\\0'";
+    case 10:
+        return "Invalid character: '\\n'";
+    case 11:
+        return "Invalid character: '\\v'";
+    case 13:
+        return "Invalid character: '\\r'";
+    case 35:
+        return "Invalid character: '#'";
+    case 64:
+        return "Invalid character: '@'";
+    case 96:
+        return "Invalid character: '`'";
+    default:
+        return String::format("Invalid character '\\u%04u'", static_cast<unsigned>(m_current)).impl();
+    }
 }
 
 }
 
-ALWAYS_INLINE int Lexer::currentOffset() const
+template <typename T>
+ALWAYS_INLINE const T* Lexer<T>::currentCharacter() const
 {
 {
-    return currentCharacter() - m_codeStart;
+    ASSERT(m_code <= m_codeEnd);
+    return m_code;
 }
 
 }
 
-void Lexer::setCode(const SourceCode& source, ParserArena& arena)
+template <typename T>
+void Lexer<T>::setCode(const SourceCode& source, ParserArena* arena)
 {
 {
-    m_arena = &arena.identifierArena();
-
+    m_arena = &arena->identifierArena();
+    
     m_lineNumber = source.firstLine();
     m_lineNumber = source.firstLine();
-    m_delimited = false;
     m_lastToken = -1;
     m_lastToken = -1;
+    
+    const StringImpl* sourceString = source.provider()->data();
 
 
-    const UChar* data = source.provider()->data();
+    if (sourceString)
+        setCodeStart(sourceString);
+    else
+        m_codeStart = 0;
 
     m_source = &source;
 
     m_source = &source;
-    m_codeStart = data;
-    m_code = data + source.startOffset();
-    m_codeEnd = data + source.endOffset();
+    m_code = m_codeStart + source.startOffset();
+    m_codeEnd = m_codeStart + source.endOffset();
     m_error = false;
     m_atLineStart = true;
     m_error = false;
     m_atLineStart = true;
-
+    m_lexErrorMessage = UString();
+    
     m_buffer8.reserveInitialCapacity(initialReadBufferCapacity);
     m_buffer16.reserveInitialCapacity((m_codeEnd - m_code) / 2);
     m_buffer8.reserveInitialCapacity(initialReadBufferCapacity);
     m_buffer16.reserveInitialCapacity((m_codeEnd - m_code) / 2);
-
+    
     if (LIKELY(m_code < m_codeEnd))
         m_current = *m_code;
     else
     if (LIKELY(m_code < m_codeEnd))
         m_current = *m_code;
     else
-        m_current = -1;
+        m_current = 0;
     ASSERT(currentOffset() == source.startOffset());
 }
 
     ASSERT(currentOffset() == source.startOffset());
 }
 
-template <int shiftAmount, Lexer::ShiftType shouldBoundsCheck> ALWAYS_INLINE void Lexer::internalShift()
+template <typename T>
+template <int shiftAmount> ALWAYS_INLINE void Lexer<T>::internalShift()
 {
 {
-    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_code += shiftAmount;
+    m_current = *m_code;
+}
+
+template <typename T>
+ALWAYS_INLINE void Lexer<T>::shift()
+{
+    // At one point timing showed that setting m_current to 0 unconditionally was faster than an if-else sequence.
+    m_current = 0;
+    ++m_code;
+    if (LIKELY(m_code < m_codeEnd))
         m_current = *m_code;
         m_current = *m_code;
-    }
 }
 
 }
 
-ALWAYS_INLINE void Lexer::shift()
+template <typename T>
+ALWAYS_INLINE bool Lexer<T>::atEnd() const
 {
 {
-    internalShift<1, DoBoundsCheck>();
+    ASSERT(!m_current || m_code < m_codeEnd);
+    return UNLIKELY(UNLIKELY(!m_current) && m_code == m_codeEnd);
 }
 
 }
 
-ALWAYS_INLINE int Lexer::peek(int offset)
+template <typename T>
+ALWAYS_INLINE T Lexer<T>::peek(int offset) const
 {
 {
-    // Only use if necessary
     ASSERT(offset > 0 && offset < 5);
     ASSERT(offset > 0 && offset < 5);
-    const UChar* code = m_code + offset;
-    return (code < m_codeEnd) ? *code : -1;
+    const T* code = m_code + offset;
+    return (code < m_codeEnd) ? *code : 0;
 }
 
 }
 
-int Lexer::getUnicodeCharacter()
+template <typename T>
+int Lexer<T>::parseFourDigitUnicodeHex()
 {
 {
-    int char1 = peek(1);
-    int char2 = peek(2);
-    int char3 = peek(3);
+    T char1 = peek(1);
+    T char2 = peek(2);
+    T char3 = peek(3);
 
     if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(char1) || !isASCIIHexDigit(char2) || !isASCIIHexDigit(char3)))
         return -1;
 
     if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(char1) || !isASCIIHexDigit(char2) || !isASCIIHexDigit(char3)))
         return -1;
@@ -317,47 +479,69 @@ int Lexer::getUnicodeCharacter()
     return result;
 }
 
     return result;
 }
 
-void Lexer::shiftLineTerminator()
+template <typename T>
+void Lexer<T>::shiftLineTerminator()
 {
     ASSERT(isLineTerminator(m_current));
 
 {
     ASSERT(isLineTerminator(m_current));
 
-    int m_prev = m_current;
+    prev = m_current;
     shift();
 
     // Allow both CRLF and LFCR.
     shift();
 
     // Allow both CRLF and LFCR.
-    if (m_prev + m_current == '\n' + '\r')
+    if (prev + m_current == '\n' + '\r')
         shift();
 
     ++m_lineNumber;
 }
 
         shift();
 
     ++m_lineNumber;
 }
 
-ALWAYS_INLINE bool Lexer::lastTokenWasRestrKeyword() const
+template <typename T>
+ALWAYS_INLINE bool Lexer<T>::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;
 }
 
-static NEVER_INLINE bool isNonASCIIIdentStart(int c)
+static NEVER_INLINE bool isNonLatin1IdentStart(int c)
 {
     return category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other);
 }
 
 {
     return category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other);
 }
 
-static inline bool isIdentStart(int c)
+static ALWAYS_INLINE bool isLatin1(LChar)
 {
 {
-    return isASCII(c) ? typesOfASCIICharacters[c] == CharacterIdentifierStart : isNonASCIIIdentStart(c);
+    return true;
 }
 
 }
 
-static NEVER_INLINE bool isNonASCIIIdentPart(int c)
+static ALWAYS_INLINE bool isLatin1(UChar c)
 {
 {
-    return category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other
-        | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector);
+    return c < 256;
 }
 
 }
 
-static ALWAYS_INLINE bool isIdentPart(int c)
+static inline bool isIdentStart(LChar c)
+{
+    return typesOfLatin1Characters[c] == CharacterIdentifierStart;
+}
+
+static inline bool isIdentStart(UChar c)
+{
+    return isLatin1(c) ? isIdentStart(static_cast<LChar>(c)) : isNonLatin1IdentStart(c);
+}
+
+static NEVER_INLINE bool isNonLatin1IdentPart(int c)
+{
+    return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other
+        | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector)) || c == 0x200C || c == 0x200D;
+}
+
+static ALWAYS_INLINE bool isIdentPart(LChar 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.)
 {
     // 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);
+    return typesOfLatin1Characters[c] <= CharacterNumber;
+}
+
+static ALWAYS_INLINE bool isIdentPart(UChar c)
+{
+    return isLatin1(c) ? isIdentPart(static_cast<LChar>(c)) : isNonLatin1IdentPart(c);
 }
 
 static inline int singleEscape(int c)
 }
 
 static inline int singleEscape(int c)
@@ -386,36 +570,186 @@ static inline int singleEscape(int c)
     }
 }
 
     }
 }
 
-inline void Lexer::record8(int c)
+template <typename T>
+inline void Lexer<T>::record8(int c)
 {
     ASSERT(c >= 0);
     ASSERT(c <= 0xFF);
 {
     ASSERT(c >= 0);
     ASSERT(c <= 0xFF);
-    m_buffer8.append(static_cast<char>(c));
+    m_buffer8.append(static_cast<LChar>(c));
+}
+
+template <typename T>
+inline void assertCharIsIn8BitRange(T c)
+{
+    UNUSED_PARAM(c);
+    ASSERT(c >= 0);
+    ASSERT(c <= 0xFF);
+}
+
+template <>
+inline void assertCharIsIn8BitRange(UChar c)
+{
+    UNUSED_PARAM(c);
+    ASSERT(c <= 0xFF);
+}
+
+template <>
+inline void assertCharIsIn8BitRange(LChar)
+{
+}
+
+template <typename T>
+inline void Lexer<T>::append8(const T* p, size_t length)
+{
+    size_t currentSize = m_buffer8.size();
+    m_buffer8.grow(currentSize + length);
+    LChar* rawBuffer = m_buffer8.data() + currentSize;
+
+    for (size_t i = 0; i < length; i++) {
+        T c = p[i];
+        assertCharIsIn8BitRange(c);
+        rawBuffer[i] = c;
+    }
 }
 
 }
 
-inline void Lexer::record16(UChar c)
+template <typename T>
+inline void Lexer<T>::append16(const LChar* p, size_t length)
+{
+    size_t currentSize = m_buffer16.size();
+    m_buffer16.grow(currentSize + length);
+    UChar* rawBuffer = m_buffer16.data() + currentSize;
+
+    for (size_t i = 0; i < length; i++)
+        rawBuffer[i] = p[i];
+}
+
+template <typename T>
+inline void Lexer<T>::record16(T c)
 {
     m_buffer16.append(c);
 }
 
 {
     m_buffer16.append(c);
 }
 
-inline void Lexer::record16(int c)
+template <typename T>
+inline void Lexer<T>::record16(int c)
 {
     ASSERT(c >= 0);
 {
     ASSERT(c >= 0);
-    ASSERT(c <= USHRT_MAX);
-    record16(UChar(static_cast<unsigned short>(c)));
+    ASSERT(c <= static_cast<int>(USHRT_MAX));
+    m_buffer16.append(static_cast<UChar>(c));
 }
 
 }
 
-template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer::parseIdentifier(JSTokenData* tokenData, unsigned lexType)
+template <>
+template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<LChar>::parseIdentifier(JSTokenData* tokenData, unsigned lexerFlags, bool strictMode)
 {
     const ptrdiff_t remaining = m_codeEnd - m_code;
 {
     const ptrdiff_t remaining = m_codeEnd - m_code;
-    if ((remaining >= maxTokenLength) && !(lexType & IgnoreReservedWords)) {
+    if ((remaining >= maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords)) {
         JSTokenType keyword = parseKeyword<shouldCreateIdentifier>(tokenData);
         if (keyword != IDENT) {
             ASSERT((!shouldCreateIdentifier) || tokenData->ident);
         JSTokenType keyword = parseKeyword<shouldCreateIdentifier>(tokenData);
         if (keyword != IDENT) {
             ASSERT((!shouldCreateIdentifier) || tokenData->ident);
-            return keyword;
+            return keyword == RESERVED_IF_STRICT && !strictMode ? IDENT : keyword;
         }
     }
         }
     }
+
+    const LChar* identifierStart = currentCharacter();
+    
+    while (isIdentPart(m_current))
+        shift();
+    
+    if (UNLIKELY(m_current == '\\')) {
+        setOffsetFromCharOffset(identifierStart);
+        return parseIdentifierSlowCase<shouldCreateIdentifier>(tokenData, lexerFlags, strictMode);
+    }
+
+    const Identifier* ident = 0;
+    
+    if (shouldCreateIdentifier) {
+        int identifierLength = currentCharacter() - identifierStart;
+        ident = makeIdentifier(identifierStart, identifierLength);
+
+        tokenData->ident = ident;
+    } else
+        tokenData->ident = 0;
+
+    if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords))) {
+        ASSERT(shouldCreateIdentifier);
+        if (remaining < maxTokenLength) {
+            const HashEntry* entry = m_globalData->keywords->getKeyword(*ident);
+            ASSERT((remaining < maxTokenLength) || !entry);
+            if (!entry)
+                return IDENT;
+            JSTokenType token = static_cast<JSTokenType>(entry->lexerValue());
+            return (token != RESERVED_IF_STRICT) || strictMode ? token : IDENT;
+        }
+        return IDENT;
+    }
+
+    return IDENT;
+}
+
+template <>
+template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::parseIdentifier(JSTokenData* tokenData, unsigned lexerFlags, bool strictMode)
+{
+    const ptrdiff_t remaining = m_codeEnd - m_code;
+    if ((remaining >= maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords)) {
+        JSTokenType keyword = parseKeyword<shouldCreateIdentifier>(tokenData);
+        if (keyword != IDENT) {
+            ASSERT((!shouldCreateIdentifier) || tokenData->ident);
+            return keyword == RESERVED_IF_STRICT && !strictMode ? IDENT : keyword;
+        }
+    }
+
     const UChar* identifierStart = currentCharacter();
     const UChar* identifierStart = currentCharacter();
+
+    UChar orAllChars = 0;
+    
+    while (isIdentPart(m_current)) {
+        orAllChars |= m_current;
+        shift();
+    }
+    
+    if (UNLIKELY(m_current == '\\')) {
+        setOffsetFromCharOffset(identifierStart);
+        return parseIdentifierSlowCase<shouldCreateIdentifier>(tokenData, lexerFlags, strictMode);
+    }
+
+    bool isAll8Bit = false;
+
+    if (!(orAllChars & ~0xff))
+        isAll8Bit = true;
+
+    const Identifier* ident = 0;
+    
+    if (shouldCreateIdentifier) {
+        int identifierLength = currentCharacter() - identifierStart;
+        if (isAll8Bit)
+            ident = makeIdentifierLCharFromUChar(identifierStart, identifierLength);
+        else
+            ident = makeIdentifier(identifierStart, identifierLength);
+        
+        tokenData->ident = ident;
+    } else
+        tokenData->ident = 0;
+    
+    if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords))) {
+        ASSERT(shouldCreateIdentifier);
+        if (remaining < maxTokenLength) {
+            const HashEntry* entry = m_globalData->keywords->getKeyword(*ident);
+            ASSERT((remaining < maxTokenLength) || !entry);
+            if (!entry)
+                return IDENT;
+            JSTokenType token = static_cast<JSTokenType>(entry->lexerValue());
+            return (token != RESERVED_IF_STRICT) || strictMode ? token : IDENT;
+        }
+        return IDENT;
+    }
+
+    return IDENT;
+}
+
+template <typename T>
+template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlowCase(JSTokenData* tokenData, unsigned lexerFlags, bool strictMode)
+{
+    const ptrdiff_t remaining = m_codeEnd - m_code;
+    const T* identifierStart = currentCharacter();
     bool bufferRequired = false;
 
     while (true) {
     bool bufferRequired = false;
 
     while (true) {
@@ -434,42 +768,43 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer::parseIde
         if (UNLIKELY(m_current != 'u'))
             return ERRORTOK;
         shift();
         if (UNLIKELY(m_current != 'u'))
             return ERRORTOK;
         shift();
-        int character = getUnicodeCharacter();
+        int character = parseFourDigitUnicodeHex();
         if (UNLIKELY(character == -1))
             return ERRORTOK;
         if (UNLIKELY(character == -1))
             return ERRORTOK;
-        if (UNLIKELY(m_buffer16.size() ? !isIdentPart(character) : !isIdentStart(character)))
+        UChar ucharacter = static_cast<UChar>(character);
+        if (UNLIKELY(m_buffer16.size() ? !isIdentPart(ucharacter) : !isIdentStart(ucharacter)))
             return ERRORTOK;
             return ERRORTOK;
-        if  (shouldCreateIdentifier)
-            record16(character);
+        if (shouldCreateIdentifier)
+            record16(ucharacter);
         identifierStart = currentCharacter();
     }
         identifierStart = currentCharacter();
     }
-    
+
     int identifierLength;
     const Identifier* ident = 0;
     if (shouldCreateIdentifier) {
     int identifierLength;
     const Identifier* ident = 0;
     if (shouldCreateIdentifier) {
-        if (!bufferRequired)
+        if (!bufferRequired) {
             identifierLength = currentCharacter() - identifierStart;
             identifierLength = currentCharacter() - identifierStart;
-        else {
+            ident = makeIdentifier(identifierStart, identifierLength);
+        } else {
             if (identifierStart != currentCharacter())
                 m_buffer16.append(identifierStart, currentCharacter() - identifierStart);
             if (identifierStart != currentCharacter())
                 m_buffer16.append(identifierStart, currentCharacter() - identifierStart);
-            identifierStart = m_buffer16.data();
-            identifierLength = m_buffer16.size();
+            ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
         }
 
         }
 
-        ident = makeIdentifier(identifierStart, identifierLength);
         tokenData->ident = ident;
     } else
         tokenData->ident = 0;
 
         tokenData->ident = ident;
     } else
         tokenData->ident = 0;
 
-    m_delimited = false;
-
-    if (LIKELY(!bufferRequired && !(lexType & IgnoreReservedWords))) {
+    if (LIKELY(!bufferRequired && !(lexerFlags & LexerFlagsIgnoreReservedWords))) {
         ASSERT(shouldCreateIdentifier);
         // Keywords must not be recognized if there was an \uXXXX in the identifier.
         if (remaining < maxTokenLength) {
         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);
+            const HashEntry* entry = m_globalData->keywords->getKeyword(*ident);
             ASSERT((remaining < maxTokenLength) || !entry);
             ASSERT((remaining < maxTokenLength) || !entry);
-            return entry ? static_cast<JSTokenType>(entry->lexerValue()) : IDENT;
+            if (!entry)
+                return IDENT;
+            JSTokenType token = static_cast<JSTokenType>(entry->lexerValue());
+            return (token != RESERVED_IF_STRICT) || strictMode ? token : IDENT;
         }
         return IDENT;
     }
         }
         return IDENT;
     }
@@ -478,69 +813,147 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer::parseIde
     return IDENT;
 }
 
     return IDENT;
 }
 
-bool Lexer::isKeyword(const Identifier& ident)
+static ALWAYS_INLINE bool characterRequiresParseStringSlowCase(LChar character)
 {
 {
-    return m_keywordTable.entry(m_globalData, ident);
+    return character < 0xE;
 }
 
 }
 
-template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer::parseString(JSTokenData* tokenData, bool strictMode)
+static ALWAYS_INLINE bool characterRequiresParseStringSlowCase(UChar character)
 {
 {
-    int stringQuoteCharacter = m_current;
+    return character < 0xE || character > 0xFF;
+}
+
+template <typename T>
+template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer<T>::parseString(JSTokenData* tokenData, bool strictMode)
+{
+    int startingOffset = currentOffset();
+    int startingLineNumber = lineNumber();
+    T stringQuoteCharacter = m_current;
     shift();
 
     shift();
 
-    const UChar* stringStart = currentCharacter();
+    const T* stringStart = currentCharacter();
 
     while (m_current != stringQuoteCharacter) {
         if (UNLIKELY(m_current == '\\')) {
             if (stringStart != currentCharacter() && shouldBuildStrings)
 
     while (m_current != stringQuoteCharacter) {
         if (UNLIKELY(m_current == '\\')) {
             if (stringStart != currentCharacter() && shouldBuildStrings)
-                m_buffer16.append(stringStart, currentCharacter() - stringStart);
+                append8(stringStart, currentCharacter() - stringStart);
             shift();
 
             int escape = singleEscape(m_current);
 
             // Most common escape sequences first
             if (escape) {
             shift();
 
             int escape = singleEscape(m_current);
 
             // Most common escape sequences first
             if (escape) {
-                 if (shouldBuildStrings)
-                     record16(escape);
+                if (shouldBuildStrings)
+                    record8(escape);
                 shift();
             } else if (UNLIKELY(isLineTerminator(m_current)))
                 shiftLineTerminator();
             else if (m_current == 'x') {
                 shift();
                 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');
+                if (!isASCIIHexDigit(m_current) || !isASCIIHexDigit(peek(1))) {
+                    m_lexErrorMessage = "\\x can only be followed by a hex character sequence";
+                    return false;
+                }
+                T prev = m_current;
+                shift();
+                if (shouldBuildStrings)
+                    record8(convertHex(prev, m_current));
+                shift();
+            } else {
+                setOffset(startingOffset);
+                setLineNumber(startingLineNumber);
+                m_buffer8.resize(0);
+                return parseStringSlowCase<shouldBuildStrings>(tokenData, strictMode);
+            }
+            stringStart = currentCharacter();
+            continue;
+        }
+
+        if (UNLIKELY(characterRequiresParseStringSlowCase(m_current))) {
+            setOffset(startingOffset);
+            setLineNumber(startingLineNumber);
+            m_buffer8.resize(0);
+            return parseStringSlowCase<shouldBuildStrings>(tokenData, strictMode);
+        }
+
+        shift();
+    }
+
+    if (currentCharacter() != stringStart && shouldBuildStrings)
+        append8(stringStart, currentCharacter() - stringStart);
+    if (shouldBuildStrings) {
+        tokenData->ident = makeIdentifier(m_buffer8.data(), m_buffer8.size());
+        m_buffer8.resize(0);
+    } else
+        tokenData->ident = 0;
+
+    return true;
+}
+
+template <typename T>
+template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenData* tokenData, bool strictMode)
+{
+    T stringQuoteCharacter = m_current;
+    shift();
+
+    const T* stringStart = currentCharacter();
+
+    while (m_current != stringQuoteCharacter) {
+        if (UNLIKELY(m_current == '\\')) {
+            if (stringStart != currentCharacter() && shouldBuildStrings)
+                append16(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))) {
+                    m_lexErrorMessage = "\\x can only be followed by a hex character sequence";
+                    return false;
+                }
+                T prev = m_current;
+                shift();
+                if (shouldBuildStrings)
+                    record16(convertHex(prev, m_current));
+                shift();
             } else if (m_current == 'u') {
                 shift();
             } else if (m_current == 'u') {
                 shift();
-                int character = getUnicodeCharacter();
+                int character = parseFourDigitUnicodeHex();
                 if (character != -1) {
                     if (shouldBuildStrings)
                         record16(character);
                 } else if (m_current == stringQuoteCharacter) {
                     if (shouldBuildStrings)
                         record16('u');
                 if (character != -1) {
                     if (shouldBuildStrings)
                         record16(character);
                 } else if (m_current == stringQuoteCharacter) {
                     if (shouldBuildStrings)
                         record16('u');
-                } else // Only stringQuoteCharacter allowed after \u
+                } else {
+                    m_lexErrorMessage = "\\u can only be followed by a Unicode character sequence";
                     return false;
                     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();
             } 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))
+                if (character1 != '0' || isASCIIDigit(m_current)) {
+                    m_lexErrorMessage = "The only valid numeric escape in strict mode is '\\0'";
                     return false;
                     return false;
+                }
                 if (shouldBuildStrings)
                     record16(0);
             } else if (!strictMode && isASCIIOctalDigit(m_current)) {
                 // Octal character sequences
                 if (shouldBuildStrings)
                     record16(0);
             } else if (!strictMode && isASCIIOctalDigit(m_current)) {
                 // Octal character sequences
-                int character1 = m_current;
+                T character1 = m_current;
                 shift();
                 if (isASCIIOctalDigit(m_current)) {
                     // Two octal characters
                 shift();
                 if (isASCIIOctalDigit(m_current)) {
                     // Two octal characters
-                    int character2 = m_current;
+                    T character2 = m_current;
                     shift();
                     if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) {
                         if (shouldBuildStrings)
                     shift();
                     if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) {
                         if (shouldBuildStrings)
@@ -554,30 +967,34 @@ template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer::parseString(JSToken
                     if (shouldBuildStrings)
                         record16(character1 - '0');
                 }
                     if (shouldBuildStrings)
                         record16(character1 - '0');
                 }
-            } else if (m_current != -1) {
+            } else if (!atEnd()) {
                 if (shouldBuildStrings)
                     record16(m_current);
                 shift();
                 if (shouldBuildStrings)
                     record16(m_current);
                 shift();
-            } else
+            } else {
+                m_lexErrorMessage = "Unterminated string constant";
                 return false;
                 return false;
+            }
 
             stringStart = currentCharacter();
             continue;
         }
         // Fast check for characters that require special handling.
 
             stringStart = currentCharacter();
             continue;
         }
         // Fast check for characters that require special handling.
-        // Catches -1, \n, \r, 0x2028, and 0x2029 as efficiently
+        // Catches 0, \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
         // 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))
+            if (atEnd() || isLineTerminator(m_current)) {
+                m_lexErrorMessage = "Unexpected EOF";
                 return false;
                 return false;
+            }
             // Anything else is just a normal character
         }
         shift();
     }
 
     if (currentCharacter() != stringStart && shouldBuildStrings)
             // Anything else is just a normal character
         }
         shift();
     }
 
     if (currentCharacter() != stringStart && shouldBuildStrings)
-        m_buffer16.append(stringStart, currentCharacter() - stringStart);
+        append16(stringStart, currentCharacter() - stringStart);
     if (shouldBuildStrings)
         tokenData->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
     else
     if (shouldBuildStrings)
         tokenData->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
     else
@@ -587,7 +1004,8 @@ template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer::parseString(JSToken
     return true;
 }
 
     return true;
 }
 
-ALWAYS_INLINE void Lexer::parseHex(double& returnValue)
+template <typename T>
+ALWAYS_INLINE void Lexer<T>::parseHex(double& returnValue)
 {
     // Optimization: most hexadecimal values fit into 4 bytes.
     uint32_t hexValue = 0;
 {
     // Optimization: most hexadecimal values fit into 4 bytes.
     uint32_t hexValue = 0;
@@ -626,14 +1044,15 @@ ALWAYS_INLINE void Lexer::parseHex(double& returnValue)
     returnValue = parseIntOverflow(m_buffer8.data(), m_buffer8.size(), 16);
 }
 
     returnValue = parseIntOverflow(m_buffer8.data(), m_buffer8.size(), 16);
 }
 
-ALWAYS_INLINE bool Lexer::parseOctal(double& returnValue)
+template <typename T>
+ALWAYS_INLINE bool Lexer<T>::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.
 {
     // 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];
+    LChar digits[10];
 
     do {
         octalValue = octalValue * 8 + (m_current - '0');
 
     do {
         octalValue = octalValue * 8 + (m_current - '0');
@@ -662,7 +1081,8 @@ ALWAYS_INLINE bool Lexer::parseOctal(double& returnValue)
     return true;
 }
 
     return true;
 }
 
-ALWAYS_INLINE bool Lexer::parseDecimal(double& returnValue)
+template <typename T>
+ALWAYS_INLINE bool Lexer<T>::parseDecimal(double& returnValue)
 {
     // Optimization: most decimal values fit into 4 bytes.
     uint32_t decimalValue = 0;
 {
     // Optimization: most decimal values fit into 4 bytes.
     uint32_t decimalValue = 0;
@@ -673,7 +1093,7 @@ ALWAYS_INLINE bool Lexer::parseDecimal(double& returnValue)
         int maximumDigits = 9;
         // Temporary buffer for the digits. Makes easier
         // to reconstruct the input characters when needed.
         int maximumDigits = 9;
         // Temporary buffer for the digits. Makes easier
         // to reconstruct the input characters when needed.
-        char digits[10];
+        LChar digits[10];
 
         do {
             decimalValue = decimalValue * 10 + (m_current - '0');
 
         do {
             decimalValue = decimalValue * 10 + (m_current - '0');
@@ -699,7 +1119,8 @@ ALWAYS_INLINE bool Lexer::parseDecimal(double& returnValue)
     return false;
 }
 
     return false;
 }
 
-ALWAYS_INLINE void Lexer::parseNumberAfterDecimalPoint()
+template <typename T>
+ALWAYS_INLINE void Lexer<T>::parseNumberAfterDecimalPoint()
 {
     record8('.');
     while (isASCIIDigit(m_current)) {
 {
     record8('.');
     while (isASCIIDigit(m_current)) {
@@ -708,7 +1129,8 @@ ALWAYS_INLINE void Lexer::parseNumberAfterDecimalPoint()
     }
 }
 
     }
 }
 
-ALWAYS_INLINE bool Lexer::parseNumberAfterExponentIndicator()
+template <typename T>
+ALWAYS_INLINE bool Lexer<T>::parseNumberAfterExponentIndicator()
 {
     record8('e');
     shift();
 {
     record8('e');
     shift();
@@ -727,7 +1149,8 @@ ALWAYS_INLINE bool Lexer::parseNumberAfterExponentIndicator()
     return true;
 }
 
     return true;
 }
 
-ALWAYS_INLINE bool Lexer::parseMultilineComment()
+template <typename T>
+ALWAYS_INLINE bool Lexer<T>::parseMultilineComment()
 {
     while (true) {
         while (UNLIKELY(m_current == '*')) {
 {
     while (true) {
         while (UNLIKELY(m_current == '*')) {
@@ -738,26 +1161,29 @@ ALWAYS_INLINE bool Lexer::parseMultilineComment()
             }
         }
 
             }
         }
 
-        if (UNLIKELY(m_current == -1))
+        if (atEnd())
             return false;
 
             return false;
 
-        if (isLineTerminator(m_current))
+        if (isLineTerminator(m_current)) {
             shiftLineTerminator();
             shiftLineTerminator();
-        else
+            m_terminator = true;
+        } else
             shift();
     }
 }
 
             shift();
     }
 }
 
-bool Lexer::nextTokenIsColon()
+template <typename T>
+bool Lexer<T>::nextTokenIsColon()
 {
 {
-    const UChar* code = m_code;
+    const T* code = m_code;
     while (code < m_codeEnd && (isWhiteSpace(*code) || isLineTerminator(*code)))
         code++;
     while (code < m_codeEnd && (isWhiteSpace(*code) || isLineTerminator(*code)))
         code++;
-        
+    
     return code < m_codeEnd && *code == ':';
 }
 
     return code < m_codeEnd && *code == ':';
 }
 
-JSTokenType Lexer::lex(JSTokenData* tokenData, JSTokenInfo* tokenInfo, unsigned lexType, bool strictMode)
+template <typename T>
+JSTokenType Lexer<T>::lex(JSTokenData* tokenData, JSTokenInfo* tokenInfo, unsigned lexerFlags, bool strictMode)
 {
     ASSERT(!m_error);
     ASSERT(m_buffer8.isEmpty());
 {
     ASSERT(!m_error);
     ASSERT(m_buffer8.isEmpty());
@@ -770,17 +1196,15 @@ start:
     while (isWhiteSpace(m_current))
         shift();
 
     while (isWhiteSpace(m_current))
         shift();
 
-    int startOffset = currentOffset();
-
-    if (UNLIKELY(m_current == -1))
+    if (atEnd())
         return EOFTOK;
         return EOFTOK;
-
-    m_delimited = false;
+    
+    tokenInfo->startOffset = currentOffset();
 
     CharacterType type;
 
     CharacterType type;
-    if (LIKELY(isASCII(m_current)))
-        type = static_cast<CharacterType>(typesOfASCIICharacters[m_current]);
-    else if (isNonASCIIIdentStart(m_current))
+    if (LIKELY(isLatin1(m_current)))
+        type = static_cast<CharacterType>(typesOfLatin1Characters[m_current]);
+    else if (isNonLatin1IdentStart(m_current))
         type = CharacterIdentifierStart;
     else if (isLineTerminator(m_current))
         type = CharacterLineTerminator;
         type = CharacterIdentifierStart;
     else if (isLineTerminator(m_current))
         type = CharacterLineTerminator;
@@ -919,6 +1343,7 @@ start:
             shift();
             if (parseMultilineComment())
                 goto start;
             shift();
             if (parseMultilineComment())
                 goto start;
+            m_lexErrorMessage = "Multiline comment was not closed properly";
             goto returnError;
         }
         if (m_current == '=') {
             goto returnError;
         }
         if (m_current == '=') {
@@ -1007,7 +1432,6 @@ start:
         shift();
         break;
     case CharacterSemicolon:
         shift();
         break;
     case CharacterSemicolon:
-        m_delimited = true;
         shift();
         token = SEMICOLON;
         break;
         shift();
         token = SEMICOLON;
         break;
@@ -1018,7 +1442,6 @@ start:
         break;
     case CharacterCloseBrace:
         tokenData->intValue = currentOffset();
         break;
     case CharacterCloseBrace:
         tokenData->intValue = currentOffset();
-        m_delimited = true;
         shift();
         token = CLOSEBRACE;
         break;
         shift();
         token = CLOSEBRACE;
         break;
@@ -1038,8 +1461,10 @@ start:
             record8('0');
             if (isASCIIOctalDigit(m_current)) {
                 if (parseOctal(tokenData->doubleValue)) {
             record8('0');
             if (isASCIIOctalDigit(m_current)) {
                 if (parseOctal(tokenData->doubleValue)) {
-                    if (strictMode)
+                    if (strictMode) {
+                        m_lexErrorMessage = "Octal escapes are forbidden in strict mode";
                         goto returnError;
                         goto returnError;
+                    }
                     token = NUMBER;
                 }
             }
                     token = NUMBER;
                 }
             }
@@ -1053,24 +1478,27 @@ start:
 inNumberAfterDecimalPoint:
                     parseNumberAfterDecimalPoint();
                 }
 inNumberAfterDecimalPoint:
                     parseNumberAfterDecimalPoint();
                 }
-                if ((m_current | 0x20) == 'e')
-                    if (!parseNumberAfterExponentIndicator())
+                if ((m_current | 0x20) == 'e') {
+                    if (!parseNumberAfterExponentIndicator()) {
+                        m_lexErrorMessage = "Non-number found after exponent indicator";
                         goto returnError;
                         goto returnError;
-                // Null-terminate string for strtod.
-                m_buffer8.append('\0');
-                tokenData->doubleValue = WTF::strtod(m_buffer8.data(), 0);
+                    }
+                }
+                size_t parsedLength;
+                tokenData->doubleValue = parseDouble(m_buffer8.data(), m_buffer8.size(), parsedLength);
             }
             token = NUMBER;
         }
 
         // No identifiers allowed directly after numeric literal, e.g. "3in" is bad.
             }
             token = NUMBER;
         }
 
         // No identifiers allowed directly after numeric literal, e.g. "3in" is bad.
-        if (UNLIKELY(isIdentStart(m_current)))
+        if (UNLIKELY(isIdentStart(m_current))) {
+            m_lexErrorMessage = "At least one digit must occur after a decimal point";
             goto returnError;
             goto returnError;
+        }
         m_buffer8.resize(0);
         m_buffer8.resize(0);
-        m_delimited = false;
         break;
     case CharacterQuote:
         break;
     case CharacterQuote:
-        if (lexType & DontBuildStrings) {
+        if (lexerFlags & LexerFlagsDontBuildStrings) {
             if (UNLIKELY(!parseString<false>(tokenData, strictMode)))
                 goto returnError;
         } else {
             if (UNLIKELY(!parseString<false>(tokenData, strictMode)))
                 goto returnError;
         } else {
@@ -1078,17 +1506,16 @@ inNumberAfterDecimalPoint:
                 goto returnError;
         }
         shift();
                 goto returnError;
         }
         shift();
-        m_delimited = false;
         token = STRING;
         break;
     case CharacterIdentifierStart:
         ASSERT(isIdentStart(m_current));
         // Fall through into CharacterBackSlash.
     case CharacterBackSlash:
         token = STRING;
         break;
     case CharacterIdentifierStart:
         ASSERT(isIdentStart(m_current));
         // Fall through into CharacterBackSlash.
     case CharacterBackSlash:
-        if (lexType & DontBuildKeywords)
-            token = parseIdentifier<false>(tokenData, lexType);
+        if (lexerFlags & LexexFlagsDontBuildKeywords)
+            token = parseIdentifier<false>(tokenData, lexerFlags, strictMode);
         else
         else
-            token = parseIdentifier<true>(tokenData, lexType);
+            token = parseIdentifier<true>(tokenData, lexerFlags, strictMode);
         break;
     case CharacterLineTerminator:
         ASSERT(isLineTerminator(m_current));
         break;
     case CharacterLineTerminator:
         ASSERT(isLineTerminator(m_current));
@@ -1097,9 +1524,11 @@ inNumberAfterDecimalPoint:
         m_terminator = true;
         goto start;
     case CharacterInvalid:
         m_terminator = true;
         goto start;
     case CharacterInvalid:
+        m_lexErrorMessage = invalidCharacterMessage();
         goto returnError;
     default:
         ASSERT_NOT_REACHED();
         goto returnError;
     default:
         ASSERT_NOT_REACHED();
+        m_lexErrorMessage = "Internal Error";
         goto returnError;
     }
 
         goto returnError;
     }
 
@@ -1108,7 +1537,7 @@ inNumberAfterDecimalPoint:
 
 inSingleLineComment:
     while (!isLineTerminator(m_current)) {
 
 inSingleLineComment:
     while (!isLineTerminator(m_current)) {
-        if (UNLIKELY(m_current == -1))
+        if (atEnd())
             return EOFTOK;
         shift();
     }
             return EOFTOK;
         shift();
     }
@@ -1119,22 +1548,23 @@ inSingleLineComment:
         goto start;
 
     token = SEMICOLON;
         goto start;
 
     token = SEMICOLON;
-    m_delimited = true;
     // Fall through into returnToken.
 
 returnToken:
     tokenInfo->line = m_lineNumber;
     // Fall through into returnToken.
 
 returnToken:
     tokenInfo->line = m_lineNumber;
-    tokenInfo->startOffset = startOffset;
     tokenInfo->endOffset = currentOffset();
     m_lastToken = token;
     return token;
 
 returnError:
     m_error = true;
     tokenInfo->endOffset = currentOffset();
     m_lastToken = token;
     return token;
 
 returnError:
     m_error = true;
+    tokenInfo->line = m_lineNumber;
+    tokenInfo->endOffset = currentOffset();
     return ERRORTOK;
 }
 
     return ERRORTOK;
 }
 
-bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix)
+template <typename T>
+bool Lexer<T>::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix)
 {
     ASSERT(m_buffer16.isEmpty());
 
 {
     ASSERT(m_buffer16.isEmpty());
 
@@ -1149,26 +1579,26 @@ bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UCh
     }
 
     while (true) {
     }
 
     while (true) {
-        int current = m_current;
-
-        if (isLineTerminator(current) || current == -1) {
+        if (isLineTerminator(m_current) || atEnd()) {
             m_buffer16.resize(0);
             return false;
         }
 
             m_buffer16.resize(0);
             return false;
         }
 
+        T prev = m_current;
+        
         shift();
 
         shift();
 
-        if (current == '/' && !lastWasEscape && !inBrackets)
+        if (prev == '/' && !lastWasEscape && !inBrackets)
             break;
 
             break;
 
-        record16(current);
+        record16(prev);
 
         if (lastWasEscape) {
             lastWasEscape = false;
             continue;
         }
 
 
         if (lastWasEscape) {
             lastWasEscape = false;
             continue;
         }
 
-        switch (current) {
+        switch (prev) {
         case '[':
             inBrackets = true;
             break;
         case '[':
             inBrackets = true;
             break;
@@ -1195,20 +1625,21 @@ bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UCh
     return true;
 }
 
     return true;
 }
 
-bool Lexer::skipRegExp()
+template <typename T>
+bool Lexer<T>::skipRegExp()
 {
     bool lastWasEscape = false;
     bool inBrackets = false;
 
     while (true) {
 {
     bool lastWasEscape = false;
     bool inBrackets = false;
 
     while (true) {
-        int current = m_current;
-
-        if (isLineTerminator(current) || current == -1)
+        if (isLineTerminator(m_current) || atEnd())
             return false;
 
             return false;
 
+        T prev = m_current;
+        
         shift();
 
         shift();
 
-        if (current == '/' && !lastWasEscape && !inBrackets)
+        if (prev == '/' && !lastWasEscape && !inBrackets)
             break;
 
         if (lastWasEscape) {
             break;
 
         if (lastWasEscape) {
@@ -1216,7 +1647,7 @@ bool Lexer::skipRegExp()
             continue;
         }
 
             continue;
         }
 
-        switch (current) {
+        switch (prev) {
         case '[':
             inBrackets = true;
             break;
         case '[':
             inBrackets = true;
             break;
@@ -1235,11 +1666,12 @@ bool Lexer::skipRegExp()
     return true;
 }
 
     return true;
 }
 
-void Lexer::clear()
+template <typename T>
+void Lexer<T>::clear()
 {
     m_arena = 0;
 
 {
     m_arena = 0;
 
-    Vector<char> newBuffer8;
+    Vector<LChar> newBuffer8;
     m_buffer8.swap(newBuffer8);
 
     Vector<UChar> newBuffer16;
     m_buffer8.swap(newBuffer8);
 
     Vector<UChar> newBuffer16;
@@ -1248,11 +1680,16 @@ void Lexer::clear()
     m_isReparsing = false;
 }
 
     m_isReparsing = false;
 }
 
-SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine)
+template <typename T>
+SourceCode Lexer<T>::sourceCode(int openBrace, int closeBrace, int firstLine)
 {
 {
-    ASSERT(m_source->provider()->data()[openBrace] == '{');
-    ASSERT(m_source->provider()->data()[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);
 }
 
+// Instantiate the two flavors of Lexer we need instead of putting most of this file in Lexer.h
+template class Lexer<LChar>;
+template class Lexer<UChar>;
+
 } // namespace JSC
 } // namespace JSC
index 46501aa882be672ffe34b680ec4cd19fb25973ed..41f1f8553e1eb25f544bee1935a2af4bbd069e64 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) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 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
  *  Copyright (C) 2010 Zoltan Herczeg (zherczeg@inf.u-szeged.hu)
  *
  *  This library is free software; you can redistribute it and/or
@@ -23,9 +23,9 @@
 #ifndef Lexer_h
 #define Lexer_h
 
 #ifndef Lexer_h
 #define Lexer_h
 
-#include "JSParser.h"
 #include "Lookup.h"
 #include "ParserArena.h"
 #include "Lookup.h"
 #include "ParserArena.h"
+#include "ParserTokens.h"
 #include "SourceCode.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/AlwaysInline.h>
 #include "SourceCode.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/AlwaysInline.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class RegExp;
-
-    class Lexer {
-        WTF_MAKE_NONCOPYABLE(Lexer); WTF_MAKE_FAST_ALLOCATED;
-    public:
-        // Character manipulation functions.
-        static bool isWhiteSpace(int character);
-        static bool isLineTerminator(int character);
-        static unsigned char convertHex(int c1, int c2);
-        static UChar convertUnicode(int c1, int c2, int c3, int c4);
-
-        // 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.
-        enum LexType {
-            IgnoreReservedWords = 1, 
-            DontBuildStrings = 2,
-            DontBuildKeywords = 4
-        };
-        JSTokenType lex(JSTokenData*, JSTokenInfo*, unsigned, bool strictMode);
-        bool nextTokenIsColon();
-        int lineNumber() const { return m_lineNumber; }
-        void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; }
-        int lastLineNumber() const { return m_lastLineNumber; }
-        bool prevTerminator() const { return m_terminator; }
-        SourceCode sourceCode(int openBrace, int closeBrace, int firstLine);
-        bool scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix = 0);
-        bool skipRegExp();
-
-        // 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;
-
-        Lexer(JSGlobalData*);
-        ~Lexer();
-
-        void record8(int);
-        void record16(int);
-        void record16(UChar);
-
-        void copyCodeWithoutBOMs();
-
-        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);
-
-        ALWAYS_INLINE bool lastTokenWasRestrKeyword() const;
-
-        enum ShiftType { DoBoundsCheck, DoNotBoundsCheck };
-        template <int shiftAmount, ShiftType shouldBoundsCheck> void internalShift();
-        template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType parseKeyword(JSTokenData*);
-        template <bool shouldBuildIdentifiers> ALWAYS_INLINE JSTokenType parseIdentifier(JSTokenData*, unsigned);
-        template <bool shouldBuildStrings> ALWAYS_INLINE bool parseString(JSTokenData*, bool strictMode);
-        ALWAYS_INLINE void parseHex(double& returnValue);
-        ALWAYS_INLINE bool parseOctal(double& returnValue);
-        ALWAYS_INLINE bool parseDecimal(double& returnValue);
-        ALWAYS_INLINE void parseNumberAfterDecimalPoint();
-        ALWAYS_INLINE bool parseNumberAfterExponentIndicator();
-        ALWAYS_INLINE bool parseMultilineComment();
-
-        static const size_t initialReadBufferCapacity = 32;
-
-        int m_lineNumber;
-        int m_lastLineNumber;
-
-        Vector<char> m_buffer8;
-        Vector<UChar> m_buffer16;
-        bool m_terminator;
-        bool m_delimited; // encountered delimiter like "'" and "}" on last run
-        int m_lastToken;
-
-        const SourceCode* m_source;
-        const UChar* m_code;
-        const UChar* m_codeStart;
-        const UChar* m_codeEnd;
-        bool m_isReparsing;
-        bool m_atLineStart;
-        bool m_error;
-
-        // current and following unicode characters (int to allow for -1 for end-of-file marker)
-        int m_current;
-
-        IdentifierArena* m_arena;
-
-        JSGlobalData* m_globalData;
-
-        const HashTable m_keywordTable;
-    };
-
-    ALWAYS_INLINE bool Lexer::isWhiteSpace(int ch)
+class Keywords {
+public:
+    bool isKeyword(const Identifier& ident) const
     {
     {
-        return isASCII(ch) ? (ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC) : (WTF::Unicode::isSeparatorSpace(ch) || ch == 0xFEFF);
+        return m_keywordTable.entry(m_globalData, ident);
     }
     }
-
-    ALWAYS_INLINE bool Lexer::isLineTerminator(int ch)
+    
+    const HashEntry* getKeyword(const Identifier& ident) const
     {
     {
-        return ch == '\r' || ch == '\n' || (ch & ~1) == 0x2028;
+        return m_keywordTable.entry(m_globalData, ident);
     }
     }
-
-    inline unsigned char Lexer::convertHex(int c1, int c2)
+    
+    ~Keywords()
     {
     {
-        return (toASCIIHexValue(c1) << 4) | toASCIIHexValue(c2);
+        m_keywordTable.deleteTable();
     }
     }
-
-    inline UChar Lexer::convertUnicode(int c1, int c2, int c3, int c4)
+    
+private:
+    friend class JSGlobalData;
+    
+    Keywords(JSGlobalData*);
+    
+    JSGlobalData* m_globalData;
+    const HashTable m_keywordTable;
+};
+
+enum LexerFlags {
+    LexerFlagsIgnoreReservedWords = 1, 
+    LexerFlagsDontBuildStrings = 2,
+    LexexFlagsDontBuildKeywords = 4
+};
+
+template <typename T>
+class Lexer {
+    WTF_MAKE_NONCOPYABLE(Lexer);
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    Lexer(JSGlobalData*);
+    ~Lexer();
+
+    // Character manipulation functions.
+    static bool isWhiteSpace(T character);
+    static bool isLineTerminator(T character);
+    static unsigned char convertHex(int c1, int c2);
+    static UChar convertUnicode(int c1, int c2, int c3, int c4);
+
+    // Functions to set up parsing.
+    void setCode(const SourceCode&, ParserArena*);
+    void setIsReparsing() { m_isReparsing = true; }
+    bool isReparsing() const { return m_isReparsing; }
+
+    JSTokenType lex(JSTokenData*, JSTokenInfo*, unsigned, bool strictMode);
+    bool nextTokenIsColon();
+    int lineNumber() const { return m_lineNumber; }
+    void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; }
+    int lastLineNumber() const { return m_lastLineNumber; }
+    bool prevTerminator() const { return m_terminator; }
+    SourceCode sourceCode(int openBrace, int closeBrace, int firstLine);
+    bool scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix = 0);
+    bool skipRegExp();
+
+    // Functions for use after parsing.
+    bool sawError() const { return m_error; }
+    UString getErrorMessage() const { return m_lexErrorMessage; }
+    void clear();
+    void setOffset(int offset)
     {
     {
-        return (convertHex(c1, c2) << 8) | convertHex(c3, c4);
+        m_error = 0;
+        m_lexErrorMessage = UString();
+        m_code = m_codeStart + offset;
+        m_buffer8.resize(0);
+        m_buffer16.resize(0);
+        if (LIKELY(m_code < m_codeEnd))
+            m_current = *m_code;
+        else
+            m_current = 0;
     }
     }
-    
-    ALWAYS_INLINE const Identifier* Lexer::makeIdentifier(const UChar* characters, size_t length)
+    void setLineNumber(int line)
     {
     {
-        return &m_arena->makeIdentifier(m_globalData, characters, length);
+        m_lineNumber = line;
     }
 
     }
 
-    ALWAYS_INLINE JSTokenType Lexer::lexExpectIdentifier(JSTokenData* tokenData, JSTokenInfo* tokenInfo, unsigned lexType, bool strictMode)
-    {
-        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;
+    SourceProvider* sourceProvider() const { return m_source->provider(); }
+
+    JSTokenType lexExpectIdentifier(JSTokenData*, JSTokenInfo*, unsigned, bool strictMode);
+
+private:
+    void record8(int);
+    void append8(const T*, size_t);
+    void record16(int);
+    void record16(T);
+    void append16(const LChar*, size_t);
+    void append16(const UChar* characters, size_t length) { m_buffer16.append(characters, length); }
+
+    ALWAYS_INLINE void shift();
+    ALWAYS_INLINE bool atEnd() const;
+    ALWAYS_INLINE T peek(int offset) const;
+    int parseFourDigitUnicodeHex();
+    void shiftLineTerminator();
+
+    UString invalidCharacterMessage() const;
+    ALWAYS_INLINE const T* currentCharacter() const;
+    ALWAYS_INLINE int currentOffset() const { return m_code - m_codeStart; }
+    ALWAYS_INLINE void setOffsetFromCharOffset(const T* charOffset) { setOffset(charOffset - m_codeStart); }
+
+    ALWAYS_INLINE void setCodeStart(const StringImpl*);
+
+    ALWAYS_INLINE const Identifier* makeIdentifier(const LChar* characters, size_t length);
+    ALWAYS_INLINE const Identifier* makeIdentifier(const UChar* characters, size_t length);
+    ALWAYS_INLINE const Identifier* makeIdentifierLCharFromUChar(const UChar* characters, size_t length);
+
+    ALWAYS_INLINE bool lastTokenWasRestrKeyword() const;
+
+    template <int shiftAmount> void internalShift();
+    template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType parseKeyword(JSTokenData*);
+    template <bool shouldBuildIdentifiers> ALWAYS_INLINE JSTokenType parseIdentifier(JSTokenData*, unsigned lexerFlags, bool strictMode);
+    template <bool shouldBuildIdentifiers> NEVER_INLINE JSTokenType parseIdentifierSlowCase(JSTokenData*, unsigned lexerFlags, bool strictMode);
+    template <bool shouldBuildStrings> ALWAYS_INLINE bool parseString(JSTokenData*, bool strictMode);
+    template <bool shouldBuildStrings> NEVER_INLINE bool parseStringSlowCase(JSTokenData*, bool strictMode);
+    ALWAYS_INLINE void parseHex(double& returnValue);
+    ALWAYS_INLINE bool parseOctal(double& returnValue);
+    ALWAYS_INLINE bool parseDecimal(double& returnValue);
+    ALWAYS_INLINE void parseNumberAfterDecimalPoint();
+    ALWAYS_INLINE bool parseNumberAfterExponentIndicator();
+    ALWAYS_INLINE bool parseMultilineComment();
+
+    static const size_t initialReadBufferCapacity = 32;
+
+    int m_lineNumber;
+    int m_lastLineNumber;
+
+    Vector<LChar> m_buffer8;
+    Vector<UChar> m_buffer16;
+    bool m_terminator;
+    int m_lastToken;
+
+    const SourceCode* m_source;
+    const T* m_code;
+    const T* m_codeStart;
+    const T* m_codeEnd;
+    bool m_isReparsing;
+    bool m_atLineStart;
+    bool m_error;
+    UString m_lexErrorMessage;
+
+    T m_current;
+
+    IdentifierArena* m_arena;
+
+    JSGlobalData* m_globalData;
+};
+
+template <>
+ALWAYS_INLINE bool Lexer<LChar>::isWhiteSpace(LChar ch)
+{
+    return ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC || ch == 0xA0;
+}
+
+template <>
+ALWAYS_INLINE bool Lexer<UChar>::isWhiteSpace(UChar ch)
+{
+    return (ch < 256) ? Lexer<LChar>::isWhiteSpace(static_cast<LChar>(ch)) : (WTF::Unicode::isSeparatorSpace(ch) || ch == 0xFEFF);
+}
+
+template <>
+ALWAYS_INLINE bool Lexer<LChar>::isLineTerminator(LChar ch)
+{
+    return ch == '\r' || ch == '\n';
+}
+
+template <>
+ALWAYS_INLINE bool Lexer<UChar>::isLineTerminator(UChar ch)
+{
+    return ch == '\r' || ch == '\n' || (ch & ~1) == 0x2028;
+}
+
+template <typename T>
+inline unsigned char Lexer<T>::convertHex(int c1, int c2)
+{
+    return (toASCIIHexValue(c1) << 4) | toASCIIHexValue(c2);
+}
+
+template <typename T>
+inline UChar Lexer<T>::convertUnicode(int c1, int c2, int c3, int c4)
+{
+    return (convertHex(c1, c2) << 8) | convertHex(c3, c4);
+}
+
+template <typename T>
+ALWAYS_INLINE const Identifier* Lexer<T>::makeIdentifier(const LChar* characters, size_t length)
+{
+    return &m_arena->makeIdentifier(m_globalData, characters, length);
+}
+
+template <typename T>
+ALWAYS_INLINE const Identifier* Lexer<T>::makeIdentifier(const UChar* characters, size_t length)
+{
+    return &m_arena->makeIdentifier(m_globalData, characters, length);
+}
+
+template <>
+ALWAYS_INLINE void Lexer<LChar>::setCodeStart(const StringImpl* sourceString)
+{
+    ASSERT(sourceString->is8Bit());
+    m_codeStart = sourceString->characters8();
+}
+
+template <>
+ALWAYS_INLINE void Lexer<UChar>::setCodeStart(const StringImpl* sourceString)
+{
+    ASSERT(!sourceString->is8Bit());
+    m_codeStart = sourceString->characters16();
+}
+
+template <typename T>
+ALWAYS_INLINE const Identifier* Lexer<T>::makeIdentifierLCharFromUChar(const UChar* characters, size_t length)
+{
+    return &m_arena->makeIdentifierLCharFromUChar(m_globalData, characters, length);
+}
+
+template <typename T>
+ALWAYS_INLINE JSTokenType Lexer<T>::lexExpectIdentifier(JSTokenData* tokenData, JSTokenInfo* tokenInfo, unsigned lexerFlags, bool strictMode)
+{
+    ASSERT((lexerFlags & LexerFlagsIgnoreReservedWords));
+    const T* start = m_code;
+    const T* ptr = start;
+    const T* 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;
         ++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);
     }
 
     }
 
+    // Here's the shift
+    if (ptr < end) {
+        if ((!WTF::isASCII(*ptr)) || (*ptr == '\\') || (*ptr == '_') || (*ptr == '$'))
+            goto slowCase;
+        m_current = *ptr;
+    } else
+        m_current = 0;
+
+    m_code = ptr;
+
+    // Create the identifier if needed
+    if (lexerFlags & LexexFlagsDontBuildKeywords)
+        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, lexerFlags, strictMode);
+}
+
 } // namespace JSC
 
 #endif // Lexer_h
 } // namespace JSC
 
 #endif // Lexer_h
index 4e094b6e9b99693e8b49d1b29953d40c8a037d83..e496d2342b3401fa4ae74e246394eb97c33bca1f 100644 (file)
@@ -29,86 +29,86 @@ namespace JSC {
 
     inline void* ParserArenaFreeable::operator new(size_t size, JSGlobalData* globalData)
     {
 
     inline void* ParserArenaFreeable::operator new(size_t size, JSGlobalData* globalData)
     {
-        return globalData->parser->arena().allocateFreeable(size);
+        return globalData->parserArena->allocateFreeable(size);
     }
 
     inline void* ParserArenaDeletable::operator new(size_t size, JSGlobalData* globalData)
     {
     }
 
     inline void* ParserArenaDeletable::operator new(size_t size, JSGlobalData* globalData)
     {
-        return globalData->parser->arena().allocateDeletable(size);
+        return globalData->parserArena->allocateDeletable(size);
     }
 
     inline ParserArenaRefCounted::ParserArenaRefCounted(JSGlobalData* globalData)
     {
     }
 
     inline ParserArenaRefCounted::ParserArenaRefCounted(JSGlobalData* globalData)
     {
-        globalData->parser->arena().derefWithArena(adoptRef(this));
+        globalData->parserArena->derefWithArena(adoptRef(this));
     }
 
     }
 
-    inline Node::Node(JSGlobalData* globalData)
-        : m_line(globalData->lexer->lastLineNumber())
+    inline Node::Node(int lineNumber)
+        : m_lineNumber(lineNumber)
     {
     }
 
     {
     }
 
-    inline ExpressionNode::ExpressionNode(JSGlobalData* globalData, ResultType resultType)
-        : Node(globalData)
+    inline ExpressionNode::ExpressionNode(int lineNumber, ResultType resultType)
+        : Node(lineNumber)
         , m_resultType(resultType)
     {
     }
 
         , m_resultType(resultType)
     {
     }
 
-    inline StatementNode::StatementNode(JSGlobalData* globalData)
-        : Node(globalData)
+    inline StatementNode::StatementNode(int lineNumber)
+        : Node(lineNumber)
         , m_lastLine(-1)
     {
     }
 
         , m_lastLine(-1)
     {
     }
 
-    inline NullNode::NullNode(JSGlobalData* globalData)
-        : ExpressionNode(globalData, ResultType::nullType())
+    inline NullNode::NullNode(int lineNumber)
+        : ExpressionNode(lineNumber, ResultType::nullType())
     {
     }
 
     {
     }
 
-    inline BooleanNode::BooleanNode(JSGlobalData* globalData, bool value)
-        : ExpressionNode(globalData, ResultType::booleanType())
+    inline BooleanNode::BooleanNode(int lineNumber, bool value)
+        : ExpressionNode(lineNumber, ResultType::booleanType())
         , m_value(value)
     {
     }
 
         , m_value(value)
     {
     }
 
-    inline NumberNode::NumberNode(JSGlobalData* globalData, double value)
-        : ExpressionNode(globalData, ResultType::numberType())
+    inline NumberNode::NumberNode(int lineNumber, double value)
+        : ExpressionNode(lineNumber, ResultType::numberType())
         , m_value(value)
     {
     }
 
         , m_value(value)
     {
     }
 
-    inline StringNode::StringNode(JSGlobalData* globalData, const Identifier& value)
-        : ExpressionNode(globalData, ResultType::stringType())
+    inline StringNode::StringNode(int lineNumber, const Identifier& value)
+        : ExpressionNode(lineNumber, ResultType::stringType())
         , m_value(value)
     {
     }
 
         , m_value(value)
     {
     }
 
-    inline RegExpNode::RegExpNode(JSGlobalData* globalData, const Identifier& pattern, const Identifier& flags)
-        : ExpressionNode(globalData)
+    inline RegExpNode::RegExpNode(int lineNumber, const Identifier& pattern, const Identifier& flags)
+        : ExpressionNode(lineNumber)
         , m_pattern(pattern)
         , m_flags(flags)
     {
     }
 
         , m_pattern(pattern)
         , m_flags(flags)
     {
     }
 
-    inline ThisNode::ThisNode(JSGlobalData* globalData)
-        : ExpressionNode(globalData)
+    inline ThisNode::ThisNode(int lineNumber)
+        : ExpressionNode(lineNumber)
     {
     }
 
     {
     }
 
-    inline ResolveNode::ResolveNode(JSGlobalData* globalData, const Identifier& ident, int startOffset)
-        : ExpressionNode(globalData)
+    inline ResolveNode::ResolveNode(int lineNumber, const Identifier& ident, int startOffset)
+        : ExpressionNode(lineNumber)
         , m_ident(ident)
         , m_startOffset(startOffset)
     {
     }
 
         , m_ident(ident)
         , m_startOffset(startOffset)
     {
     }
 
-    inline ElementNode::ElementNode(JSGlobalData*, int elision, ExpressionNode* node)
+    inline ElementNode::ElementNode(int elision, ExpressionNode* node)
         : m_next(0)
         , m_elision(elision)
         , m_node(node)
     {
     }
 
         : m_next(0)
         , m_elision(elision)
         , m_node(node)
     {
     }
 
-    inline ElementNode::ElementNode(JSGlobalData*, ElementNode* l, int elision, ExpressionNode* node)
+    inline ElementNode::ElementNode(ElementNode* l, int elision, ExpressionNode* node)
         : m_next(0)
         , m_elision(elision)
         , m_node(node)
         : m_next(0)
         , m_elision(elision)
         , m_node(node)
@@ -116,24 +116,24 @@ namespace JSC {
         l->m_next = this;
     }
 
         l->m_next = this;
     }
 
-    inline ArrayNode::ArrayNode(JSGlobalData* globalData, int elision)
-        : ExpressionNode(globalData)
+    inline ArrayNode::ArrayNode(int lineNumber, int elision)
+        : ExpressionNode(lineNumber)
         , m_element(0)
         , m_elision(elision)
         , m_optional(true)
     {
     }
 
         , m_element(0)
         , m_elision(elision)
         , m_optional(true)
     {
     }
 
-    inline ArrayNode::ArrayNode(JSGlobalData* globalData, ElementNode* element)
-        : ExpressionNode(globalData)
+    inline ArrayNode::ArrayNode(int lineNumber, ElementNode* element)
+        : ExpressionNode(lineNumber)
         , m_element(element)
         , m_elision(0)
         , m_optional(false)
     {
     }
 
         , m_element(element)
         , m_elision(0)
         , m_optional(false)
     {
     }
 
-    inline ArrayNode::ArrayNode(JSGlobalData* globalData, int elision, ElementNode* element)
-        : ExpressionNode(globalData)
+    inline ArrayNode::ArrayNode(int lineNumber, int elision, ElementNode* element)
+        : ExpressionNode(lineNumber)
         , m_element(element)
         , m_elision(elision)
         , m_optional(true)
         , m_element(element)
         , m_elision(elision)
         , m_optional(true)
@@ -148,118 +148,118 @@ namespace JSC {
     }
 
     inline PropertyNode::PropertyNode(JSGlobalData* globalData, double name, ExpressionNode* assign, Type type)
     }
 
     inline PropertyNode::PropertyNode(JSGlobalData* globalData, double name, ExpressionNode* assign, Type type)
-        : m_name(globalData->parser->arena().identifierArena().makeNumericIdentifier(globalData, name))
+        : m_name(globalData->parserArena->identifierArena().makeNumericIdentifier(globalData, name))
         , m_assign(assign)
         , m_type(type)
     {
     }
 
         , m_assign(assign)
         , m_type(type)
     {
     }
 
-    inline PropertyListNode::PropertyListNode(JSGlobalData* globalData, PropertyNode* node)
-        : Node(globalData)
+    inline PropertyListNode::PropertyListNode(int lineNumber, PropertyNode* node)
+        : Node(lineNumber)
         , m_node(node)
         , m_next(0)
     {
     }
 
         , m_node(node)
         , m_next(0)
     {
     }
 
-    inline PropertyListNode::PropertyListNode(JSGlobalData* globalData, PropertyNode* node, PropertyListNode* list)
-        : Node(globalData)
+    inline PropertyListNode::PropertyListNode(int lineNumber, PropertyNode* node, PropertyListNode* list)
+        : Node(lineNumber)
         , m_node(node)
         , m_next(0)
     {
         list->m_next = this;
     }
 
         , m_node(node)
         , m_next(0)
     {
         list->m_next = this;
     }
 
-    inline ObjectLiteralNode::ObjectLiteralNode(JSGlobalData* globalData)
-        : ExpressionNode(globalData)
+    inline ObjectLiteralNode::ObjectLiteralNode(int lineNumber)
+        : ExpressionNode(lineNumber)
         , m_list(0)
     {
     }
 
         , m_list(0)
     {
     }
 
-    inline ObjectLiteralNode::ObjectLiteralNode(JSGlobalData* globalData, PropertyListNode* list)
-        : ExpressionNode(globalData)
+    inline ObjectLiteralNode::ObjectLiteralNode(int lineNumber, PropertyListNode* list)
+        : ExpressionNode(lineNumber)
         , m_list(list)
     {
     }
 
         , m_list(list)
     {
     }
 
-    inline BracketAccessorNode::BracketAccessorNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments)
-        : ExpressionNode(globalData)
+    inline BracketAccessorNode::BracketAccessorNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments)
+        : ExpressionNode(lineNumber)
         , m_base(base)
         , m_subscript(subscript)
         , m_subscriptHasAssignments(subscriptHasAssignments)
     {
     }
 
         , m_base(base)
         , m_subscript(subscript)
         , m_subscriptHasAssignments(subscriptHasAssignments)
     {
     }
 
-    inline DotAccessorNode::DotAccessorNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident)
-        : ExpressionNode(globalData)
+    inline DotAccessorNode::DotAccessorNode(int lineNumber, ExpressionNode* base, const Identifier& ident)
+        : ExpressionNode(lineNumber)
         , m_base(base)
         , m_ident(ident)
     {
     }
 
         , m_base(base)
         , m_ident(ident)
     {
     }
 
-    inline ArgumentListNode::ArgumentListNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : Node(globalData)
+    inline ArgumentListNode::ArgumentListNode(int lineNumber, ExpressionNode* expr)
+        : Node(lineNumber)
         , m_next(0)
         , m_expr(expr)
     {
     }
 
         , m_next(0)
         , m_expr(expr)
     {
     }
 
-    inline ArgumentListNode::ArgumentListNode(JSGlobalData* globalData, ArgumentListNode* listNode, ExpressionNode* expr)
-        : Node(globalData)
+    inline ArgumentListNode::ArgumentListNode(int lineNumber, ArgumentListNode* listNode, ExpressionNode* expr)
+        : Node(lineNumber)
         , m_next(0)
         , m_expr(expr)
     {
         listNode->m_next = this;
     }
 
         , m_next(0)
         , m_expr(expr)
     {
         listNode->m_next = this;
     }
 
-    inline ArgumentsNode::ArgumentsNode(JSGlobalData*)
+    inline ArgumentsNode::ArgumentsNode()
         : m_listNode(0)
     {
     }
 
         : m_listNode(0)
     {
     }
 
-    inline ArgumentsNode::ArgumentsNode(JSGlobalData*, ArgumentListNode* listNode)
+    inline ArgumentsNode::ArgumentsNode(ArgumentListNode* listNode)
         : m_listNode(listNode)
     {
     }
 
         : m_listNode(listNode)
     {
     }
 
-    inline NewExprNode::NewExprNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : ExpressionNode(globalData)
+    inline NewExprNode::NewExprNode(int lineNumber, ExpressionNode* expr)
+        : ExpressionNode(lineNumber)
         , m_expr(expr)
         , m_args(0)
     {
     }
 
         , m_expr(expr)
         , m_args(0)
     {
     }
 
-    inline NewExprNode::NewExprNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args)
-        : ExpressionNode(globalData)
+    inline NewExprNode::NewExprNode(int lineNumber, ExpressionNode* expr, ArgumentsNode* args)
+        : ExpressionNode(lineNumber)
         , m_expr(expr)
         , m_args(args)
     {
     }
 
         , m_expr(expr)
         , m_args(args)
     {
     }
 
-    inline EvalFunctionCallNode::EvalFunctionCallNode(JSGlobalData* globalData, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline EvalFunctionCallNode::EvalFunctionCallNode(int lineNumber, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_args(args)
     {
     }
 
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_args(args)
     {
     }
 
-    inline FunctionCallValueNode::FunctionCallValueNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline FunctionCallValueNode::FunctionCallValueNode(int lineNumber, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_expr(expr)
         , m_args(args)
     {
     }
 
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_expr(expr)
         , m_args(args)
     {
     }
 
-    inline FunctionCallResolveNode::FunctionCallResolveNode(JSGlobalData* globalData, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline FunctionCallResolveNode::FunctionCallResolveNode(int lineNumber, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_ident(ident)
         , m_args(args)
     {
     }
 
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_ident(ident)
         , m_args(args)
     {
     }
 
-    inline FunctionCallBracketNode::FunctionCallBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline FunctionCallBracketNode::FunctionCallBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
@@ -267,8 +267,8 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline FunctionCallDotNode::FunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline FunctionCallDotNode::FunctionCallDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
@@ -276,31 +276,31 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline CallFunctionCallDotNode::CallFunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : FunctionCallDotNode(globalData, base, ident, args, divot, startOffset, endOffset)
+    inline CallFunctionCallDotNode::CallFunctionCallDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : FunctionCallDotNode(lineNumber, base, ident, args, divot, startOffset, endOffset)
     {
     }
 
     {
     }
 
-    inline ApplyFunctionCallDotNode::ApplyFunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : FunctionCallDotNode(globalData, base, ident, args, divot, startOffset, endOffset)
+    inline ApplyFunctionCallDotNode::ApplyFunctionCallDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : FunctionCallDotNode(lineNumber, base, ident, args, divot, startOffset, endOffset)
     {
     }
 
     {
     }
 
-    inline PrePostResolveNode::PrePostResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData, ResultType::numberType()) // could be reusable for pre?
+    inline PrePostResolveNode::PrePostResolveNode(int lineNumber, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber, ResultType::numberType()) // could be reusable for pre?
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_ident(ident)
     {
     }
 
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_ident(ident)
     {
     }
 
-    inline PostfixResolveNode::PostfixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset)
+    inline PostfixResolveNode::PostfixResolveNode(int lineNumber, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : PrePostResolveNode(lineNumber, ident, divot, startOffset, endOffset)
         , m_operator(oper)
     {
     }
 
         , m_operator(oper)
     {
     }
 
-    inline PostfixBracketNode::PostfixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline PostfixBracketNode::PostfixBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
@@ -308,8 +308,8 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline PostfixDotNode::PostfixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline PostfixDotNode::PostfixDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
@@ -317,69 +317,69 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline PostfixErrorNode::PostfixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline PostfixErrorNode::PostfixErrorNode(int lineNumber, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_expr(expr)
         , m_operator(oper)
     {
     }
 
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_expr(expr)
         , m_operator(oper)
     {
     }
 
-    inline DeleteResolveNode::DeleteResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline DeleteResolveNode::DeleteResolveNode(int lineNumber, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_ident(ident)
     {
     }
 
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_ident(ident)
     {
     }
 
-    inline DeleteBracketNode::DeleteBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline DeleteBracketNode::DeleteBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
     {
     }
 
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
     {
     }
 
-    inline DeleteDotNode::DeleteDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline DeleteDotNode::DeleteDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
     {
     }
 
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
     {
     }
 
-    inline DeleteValueNode::DeleteValueNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : ExpressionNode(globalData)
+    inline DeleteValueNode::DeleteValueNode(int lineNumber, ExpressionNode* expr)
+        : ExpressionNode(lineNumber)
         , m_expr(expr)
     {
     }
 
         , m_expr(expr)
     {
     }
 
-    inline VoidNode::VoidNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : ExpressionNode(globalData)
+    inline VoidNode::VoidNode(int lineNumber, ExpressionNode* expr)
+        : ExpressionNode(lineNumber)
         , m_expr(expr)
     {
     }
 
         , m_expr(expr)
     {
     }
 
-    inline TypeOfResolveNode::TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident)
-        : ExpressionNode(globalData, ResultType::stringType())
+    inline TypeOfResolveNode::TypeOfResolveNode(int lineNumber, const Identifier& ident)
+        : ExpressionNode(lineNumber, ResultType::stringType())
         , m_ident(ident)
     {
     }
 
         , m_ident(ident)
     {
     }
 
-    inline TypeOfValueNode::TypeOfValueNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : ExpressionNode(globalData, ResultType::stringType())
+    inline TypeOfValueNode::TypeOfValueNode(int lineNumber, ExpressionNode* expr)
+        : ExpressionNode(lineNumber, ResultType::stringType())
         , m_expr(expr)
     {
     }
 
         , m_expr(expr)
     {
     }
 
-    inline PrefixResolveNode::PrefixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset)
+    inline PrefixResolveNode::PrefixResolveNode(int lineNumber, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : PrePostResolveNode(lineNumber, ident, divot, startOffset, endOffset)
         , m_operator(oper)
     {
     }
 
         , m_operator(oper)
     {
     }
 
-    inline PrefixBracketNode::PrefixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline PrefixBracketNode::PrefixBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
         , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
@@ -387,8 +387,8 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline PrefixDotNode::PrefixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline PrefixDotNode::PrefixDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
         , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
@@ -396,43 +396,44 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline PrefixErrorNode::PrefixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline PrefixErrorNode::PrefixErrorNode(int lineNumber, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_expr(expr)
         , m_operator(oper)
     {
     }
 
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_expr(expr)
         , m_operator(oper)
     {
     }
 
-    inline UnaryOpNode::UnaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr, OpcodeID opcodeID)
-        : ExpressionNode(globalData, type)
+    inline UnaryOpNode::UnaryOpNode(int lineNumber, ResultType type, ExpressionNode* expr, OpcodeID opcodeID)
+        : ExpressionNode(lineNumber, type)
         , m_expr(expr)
         , m_opcodeID(opcodeID)
     {
     }
 
         , m_expr(expr)
         , m_opcodeID(opcodeID)
     {
     }
 
-    inline UnaryPlusNode::UnaryPlusNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : UnaryOpNode(globalData, ResultType::numberType(), expr, op_to_jsnumber)
+    inline UnaryPlusNode::UnaryPlusNode(int lineNumber, ExpressionNode* expr)
+        : UnaryOpNode(lineNumber, ResultType::numberType(), expr, op_to_jsnumber)
     {
     }
 
     {
     }
 
-    inline NegateNode::NegateNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : UnaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr, op_negate)
+    inline NegateNode::NegateNode(int lineNumber, ExpressionNode* expr)
+        : UnaryOpNode(lineNumber, ResultType::numberType(), expr, op_negate)
     {
     }
 
     {
     }
 
-    inline BitwiseNotNode::BitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : UnaryOpNode(globalData, ResultType::forBitOp(), expr, op_bitnot)
+    inline BitwiseNotNode::BitwiseNotNode(int lineNumber, ExpressionNode* expr)
+        : ExpressionNode(lineNumber, ResultType::forBitOp())
+        , m_expr(expr)
     {
     }
 
     {
     }
 
-    inline LogicalNotNode::LogicalNotNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : UnaryOpNode(globalData, ResultType::booleanType(), expr, op_not)
+    inline LogicalNotNode::LogicalNotNode(int lineNumber, ExpressionNode* expr)
+        : UnaryOpNode(lineNumber, ResultType::booleanType(), expr, op_not)
     {
     }
 
     {
     }
 
-    inline BinaryOpNode::BinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
-        : ExpressionNode(globalData)
+    inline BinaryOpNode::BinaryOpNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
+        : ExpressionNode(lineNumber)
         , m_expr1(expr1)
         , m_expr2(expr2)
         , m_opcodeID(opcodeID)
         , m_expr1(expr1)
         , m_expr2(expr2)
         , m_opcodeID(opcodeID)
@@ -440,8 +441,8 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline BinaryOpNode::BinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
-        : ExpressionNode(globalData, type)
+    inline BinaryOpNode::BinaryOpNode(int lineNumber, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
+        : ExpressionNode(lineNumber, type)
         , m_expr1(expr1)
         , m_expr2(expr2)
         , m_opcodeID(opcodeID)
         , m_expr1(expr1)
         , m_expr2(expr2)
         , m_opcodeID(opcodeID)
@@ -449,150 +450,140 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline ReverseBinaryOpNode::ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
-        : BinaryOpNode(globalData, expr1, expr2, opcodeID, rightHasAssignments)
-    {
-    }
-
-    inline ReverseBinaryOpNode::ReverseBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
-        : BinaryOpNode(globalData, type, expr1, expr2, opcodeID, rightHasAssignments)
-    {
-    }
-
-    inline MultNode::MultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_mul, rightHasAssignments)
+    inline MultNode::MultNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_mul, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline DivNode::DivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_div, rightHasAssignments)
+    inline DivNode::DivNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_div, rightHasAssignments)
     {
     }
 
 
     {
     }
 
 
-    inline ModNode::ModNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_mod, rightHasAssignments)
+    inline ModNode::ModNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_mod, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline AddNode::AddNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, op_add, rightHasAssignments)
+    inline AddNode::AddNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, op_add, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline SubNode::SubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_sub, rightHasAssignments)
+    inline SubNode::SubNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_sub, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline LeftShiftNode::LeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_lshift, rightHasAssignments)
+    inline LeftShiftNode::LeftShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::forBitOp(), expr1, expr2, op_lshift, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline RightShiftNode::RightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_rshift, rightHasAssignments)
+    inline RightShiftNode::RightShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::forBitOp(), expr1, expr2, op_rshift, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline UnsignedRightShiftNode::UnsignedRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_urshift, rightHasAssignments)
+    inline UnsignedRightShiftNode::UnsignedRightShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_urshift, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline LessNode::LessNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_less, rightHasAssignments)
+    inline LessNode::LessNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_less, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline GreaterNode::GreaterNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_less, rightHasAssignments)
+    inline GreaterNode::GreaterNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_greater, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline LessEqNode::LessEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_lesseq, rightHasAssignments)
+    inline LessEqNode::LessEqNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_lesseq, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline GreaterEqNode::GreaterEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_lesseq, rightHasAssignments)
+    inline GreaterEqNode::GreaterEqNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_greatereq, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
-        : BinaryOpNode(globalData, type, expr1, expr2, opcodeID, rightHasAssignments)
+    inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(int lineNumber, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, type, expr1, expr2, opcodeID, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
-        : BinaryOpNode(globalData, expr1, expr2, opcodeID, rightHasAssignments)
+    inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, expr1, expr2, opcodeID, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline InstanceOfNode::InstanceOfNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : ThrowableBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_instanceof, rightHasAssignments)
+    inline InstanceOfNode::InstanceOfNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : ThrowableBinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_instanceof, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline InNode::InNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : ThrowableBinaryOpNode(globalData, expr1, expr2, op_in, rightHasAssignments)
+    inline InNode::InNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : ThrowableBinaryOpNode(lineNumber, expr1, expr2, op_in, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline EqualNode::EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_eq, rightHasAssignments)
+    inline EqualNode::EqualNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_eq, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline NotEqualNode::NotEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_neq, rightHasAssignments)
+    inline NotEqualNode::NotEqualNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_neq, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline StrictEqualNode::StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_stricteq, rightHasAssignments)
+    inline StrictEqualNode::StrictEqualNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_stricteq, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline NotStrictEqualNode::NotStrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_nstricteq, rightHasAssignments)
+    inline NotStrictEqualNode::NotStrictEqualNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::booleanType(), expr1, expr2, op_nstricteq, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline BitAndNode::BitAndNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_bitand, rightHasAssignments)
+    inline BitAndNode::BitAndNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::forBitOp(), expr1, expr2, op_bitand, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline BitOrNode::BitOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_bitor, rightHasAssignments)
+    inline BitOrNode::BitOrNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::forBitOp(), expr1, expr2, op_bitor, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline BitXOrNode::BitXOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-        : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_bitxor, rightHasAssignments)
+    inline BitXOrNode::BitXOrNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+        : BinaryOpNode(lineNumber, ResultType::forBitOp(), expr1, expr2, op_bitxor, rightHasAssignments)
     {
     }
 
     {
     }
 
-    inline LogicalOpNode::LogicalOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper)
-        : ExpressionNode(globalData, ResultType::booleanType())
+    inline LogicalOpNode::LogicalOpNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper)
+        : ExpressionNode(lineNumber, ResultType::booleanType())
         , m_expr1(expr1)
         , m_expr2(expr2)
         , m_operator(oper)
     {
     }
 
         , m_expr1(expr1)
         , m_expr2(expr2)
         , m_operator(oper)
     {
     }
 
-    inline ConditionalNode::ConditionalNode(JSGlobalData* globalData, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2)
-        : ExpressionNode(globalData)
+    inline ConditionalNode::ConditionalNode(int lineNumber, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2)
+        : ExpressionNode(lineNumber)
         , m_logical(logical)
         , m_expr1(expr1)
         , m_expr2(expr2)
     {
     }
 
         , m_logical(logical)
         , m_expr1(expr1)
         , m_expr2(expr2)
     {
     }
 
-    inline ReadModifyResolveNode::ReadModifyResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, ExpressionNode*  right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline ReadModifyResolveNode::ReadModifyResolveNode(int lineNumber, const Identifier& ident, Operator oper, ExpressionNode*  right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_ident(ident)
         , m_right(right)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_ident(ident)
         , m_right(right)
@@ -601,16 +592,16 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline AssignResolveNode::AssignResolveNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments)
-        : ExpressionNode(globalData)
+    inline AssignResolveNode::AssignResolveNode(int lineNumber, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments)
+        : ExpressionNode(lineNumber)
         , m_ident(ident)
         , m_right(right)
         , m_rightHasAssignments(rightHasAssignments)
     {
     }
 
         , m_ident(ident)
         , m_right(right)
         , m_rightHasAssignments(rightHasAssignments)
     {
     }
 
-    inline ReadModifyBracketNode::ReadModifyBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline ReadModifyBracketNode::ReadModifyBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
@@ -621,8 +612,8 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline AssignBracketNode::AssignBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline AssignBracketNode::AssignBracketNode(int lineNumber, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_subscript(subscript)
@@ -632,8 +623,8 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline AssignDotNode::AssignDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline AssignDotNode::AssignDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
@@ -642,8 +633,8 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline ReadModifyDotNode::ReadModifyDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline ReadModifyDotNode::ReadModifyDotNode(int lineNumber, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
         , ThrowableSubExpressionData(divot, startOffset, endOffset)
         , m_base(base)
         , m_ident(ident)
@@ -653,8 +644,8 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline AssignErrorNode::AssignErrorNode(JSGlobalData* globalData, ExpressionNode* left, Operator oper, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset)
-        : ExpressionNode(globalData)
+    inline AssignErrorNode::AssignErrorNode(int lineNumber, ExpressionNode* left, Operator oper, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset)
+        : ExpressionNode(lineNumber)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_left(left)
         , m_operator(oper)
         , ThrowableExpressionData(divot, startOffset, endOffset)
         , m_left(left)
         , m_operator(oper)
@@ -662,74 +653,74 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline CommaNode::CommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2)
-        : ExpressionNode(globalData)
+    inline CommaNode::CommaNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2)
+        : ExpressionNode(lineNumber)
     {
         m_expressions.append(expr1);
         m_expressions.append(expr2);
     }
 
     {
         m_expressions.append(expr1);
         m_expressions.append(expr2);
     }
 
-    inline ConstStatementNode::ConstStatementNode(JSGlobalData* globalData, ConstDeclNode* next)
-        : StatementNode(globalData)
+    inline ConstStatementNode::ConstStatementNode(int lineNumber, ConstDeclNode* next)
+        : StatementNode(lineNumber)
         , m_next(next)
     {
     }
 
         , m_next(next)
     {
     }
 
-    inline SourceElements::SourceElements(JSGlobalData*)
+    inline SourceElements::SourceElements()
     {
     }
 
     {
     }
 
-    inline EmptyStatementNode::EmptyStatementNode(JSGlobalData* globalData)
-        : StatementNode(globalData)
+    inline EmptyStatementNode::EmptyStatementNode(int lineNumber)
+        : StatementNode(lineNumber)
     {
     }
 
     {
     }
 
-    inline DebuggerStatementNode::DebuggerStatementNode(JSGlobalData* globalData)
-        : StatementNode(globalData)
+    inline DebuggerStatementNode::DebuggerStatementNode(int lineNumber)
+        : StatementNode(lineNumber)
     {
     }
     
     {
     }
     
-    inline ExprStatementNode::ExprStatementNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : StatementNode(globalData)
+    inline ExprStatementNode::ExprStatementNode(int lineNumber, ExpressionNode* expr)
+        : StatementNode(lineNumber)
         , m_expr(expr)
     {
     }
 
         , m_expr(expr)
     {
     }
 
-    inline VarStatementNode::VarStatementNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : StatementNode(globalData)
+    inline VarStatementNode::VarStatementNode(int lineNumber, ExpressionNode* expr)
+        : StatementNode(lineNumber)
         , m_expr(expr)
     {
     }
     
         , m_expr(expr)
     {
     }
     
-    inline IfNode::IfNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock)
-        : StatementNode(globalData)
+    inline IfNode::IfNode(int lineNumber, ExpressionNode* condition, StatementNode* ifBlock)
+        : StatementNode(lineNumber)
         , m_condition(condition)
         , m_ifBlock(ifBlock)
     {
     }
 
         , m_condition(condition)
         , m_ifBlock(ifBlock)
     {
     }
 
-    inline IfElseNode::IfElseNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock)
-        : IfNode(globalData, condition, ifBlock)
+    inline IfElseNode::IfElseNode(int lineNumber, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock)
+        : IfNode(lineNumber, condition, ifBlock)
         , m_elseBlock(elseBlock)
     {
     }
 
         , m_elseBlock(elseBlock)
     {
     }
 
-    inline DoWhileNode::DoWhileNode(JSGlobalData* globalData, StatementNode* statement, ExpressionNode* expr)
-        : StatementNode(globalData)
+    inline DoWhileNode::DoWhileNode(int lineNumber, StatementNode* statement, ExpressionNode* expr)
+        : StatementNode(lineNumber)
         , m_statement(statement)
         , m_expr(expr)
     {
     }
 
         , m_statement(statement)
         , m_expr(expr)
     {
     }
 
-    inline WhileNode::WhileNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement)
-        : StatementNode(globalData)
+    inline WhileNode::WhileNode(int lineNumber, ExpressionNode* expr, StatementNode* statement)
+        : StatementNode(lineNumber)
         , m_expr(expr)
         , m_statement(statement)
     {
     }
 
         , m_expr(expr)
         , m_statement(statement)
     {
     }
 
-    inline ForNode::ForNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl)
-        : StatementNode(globalData)
+    inline ForNode::ForNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl)
+        : StatementNode(lineNumber)
         , m_expr1(expr1)
         , m_expr2(expr2)
         , m_expr3(expr3)
         , m_expr1(expr1)
         , m_expr2(expr2)
         , m_expr3(expr3)
@@ -739,38 +730,38 @@ namespace JSC {
         ASSERT(statement);
     }
 
         ASSERT(statement);
     }
 
-    inline ContinueNode::ContinueNode(JSGlobalData* globalData)
-        : StatementNode(globalData)
+    inline ContinueNode::ContinueNode(JSGlobalData* globalData, int lineNumber)
+        : StatementNode(lineNumber)
         , m_ident(globalData->propertyNames->nullIdentifier)
     {
     }
 
         , m_ident(globalData->propertyNames->nullIdentifier)
     {
     }
 
-    inline ContinueNode::ContinueNode(JSGlobalData* globalData, const Identifier& ident)
-        : StatementNode(globalData)
+    inline ContinueNode::ContinueNode(int lineNumber, const Identifier& ident)
+        : StatementNode(lineNumber)
         , m_ident(ident)
     {
     }
     
         , m_ident(ident)
     {
     }
     
-    inline BreakNode::BreakNode(JSGlobalData* globalData)
-        : StatementNode(globalData)
+    inline BreakNode::BreakNode(JSGlobalData* globalData, int lineNumber)
+        : StatementNode(lineNumber)
         , m_ident(globalData->propertyNames->nullIdentifier)
     {
     }
 
         , m_ident(globalData->propertyNames->nullIdentifier)
     {
     }
 
-    inline BreakNode::BreakNode(JSGlobalData* globalData, const Identifier& ident)
-        : StatementNode(globalData)
+    inline BreakNode::BreakNode(int lineNumber, const Identifier& ident)
+        : StatementNode(lineNumber)
         , m_ident(ident)
     {
     }
     
         , m_ident(ident)
     {
     }
     
-    inline ReturnNode::ReturnNode(JSGlobalData* globalData, ExpressionNode* value)
-        : StatementNode(globalData)
+    inline ReturnNode::ReturnNode(int lineNumber, ExpressionNode* value)
+        : StatementNode(lineNumber)
         , m_value(value)
     {
     }
 
         , m_value(value)
     {
     }
 
-    inline WithNode::WithNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength)
-        : StatementNode(globalData)
+    inline WithNode::WithNode(int lineNumber, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength)
+        : StatementNode(lineNumber)
         , m_expr(expr)
         , m_statement(statement)
         , m_divot(divot)
         , m_expr(expr)
         , m_statement(statement)
         , m_divot(divot)
@@ -778,105 +769,104 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline LabelNode::LabelNode(JSGlobalData* globalData, const Identifier& name, StatementNode* statement)
-        : StatementNode(globalData)
+    inline LabelNode::LabelNode(int lineNumber, const Identifier& name, StatementNode* statement)
+        : StatementNode(lineNumber)
         , m_name(name)
         , m_statement(statement)
     {
     }
 
         , m_name(name)
         , m_statement(statement)
     {
     }
 
-    inline ThrowNode::ThrowNode(JSGlobalData* globalData, ExpressionNode* expr)
-        : StatementNode(globalData)
+    inline ThrowNode::ThrowNode(int lineNumber, ExpressionNode* expr)
+        : StatementNode(lineNumber)
         , m_expr(expr)
     {
     }
 
         , m_expr(expr)
     {
     }
 
-    inline TryNode::TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock)
-        : StatementNode(globalData)
+    inline TryNode::TryNode(int lineNumber, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock)
+        : StatementNode(lineNumber)
         , m_tryBlock(tryBlock)
         , m_exceptionIdent(exceptionIdent)
         , m_catchBlock(catchBlock)
         , m_finallyBlock(finallyBlock)
         , m_tryBlock(tryBlock)
         , m_exceptionIdent(exceptionIdent)
         , m_catchBlock(catchBlock)
         , m_finallyBlock(finallyBlock)
-        , m_catchHasEval(catchHasEval)
     {
     }
 
     {
     }
 
-    inline ParameterNode::ParameterNode(JSGlobalData*, const Identifier& ident)
+    inline ParameterNode::ParameterNode(const Identifier& ident)
         : m_ident(ident)
         , m_next(0)
     {
     }
 
         : m_ident(ident)
         , m_next(0)
     {
     }
 
-    inline ParameterNode::ParameterNode(JSGlobalData*, ParameterNode* l, const Identifier& ident)
+    inline ParameterNode::ParameterNode(ParameterNode* l, const Identifier& ident)
         : m_ident(ident)
         , m_next(0)
     {
         l->m_next = this;
     }
 
         : m_ident(ident)
         , m_next(0)
     {
         l->m_next = this;
     }
 
-    inline FuncExprNode::FuncExprNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter)
-        : ExpressionNode(globalData)
+    inline FuncExprNode::FuncExprNode(int lineNumber, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter)
+        : ExpressionNode(lineNumber)
         , m_body(body)
     {
         m_body->finishParsing(source, parameter, ident);
     }
 
         , m_body(body)
     {
         m_body->finishParsing(source, parameter, ident);
     }
 
-    inline FuncDeclNode::FuncDeclNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter)
-        : StatementNode(globalData)
+    inline FuncDeclNode::FuncDeclNode(int lineNumber, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter)
+        : StatementNode(lineNumber)
         , m_body(body)
     {
         m_body->finishParsing(source, parameter, ident);
     }
 
         , m_body(body)
     {
         m_body->finishParsing(source, parameter, ident);
     }
 
-    inline CaseClauseNode::CaseClauseNode(JSGlobalData*, ExpressionNode* expr, SourceElements* statements)
+    inline CaseClauseNode::CaseClauseNode(ExpressionNode* expr, SourceElements* statements)
         : m_expr(expr)
         , m_statements(statements)
     {
     }
 
         : m_expr(expr)
         , m_statements(statements)
     {
     }
 
-    inline ClauseListNode::ClauseListNode(JSGlobalData*, CaseClauseNode* clause)
+    inline ClauseListNode::ClauseListNode(CaseClauseNode* clause)
         : m_clause(clause)
         , m_next(0)
     {
     }
 
         : m_clause(clause)
         , m_next(0)
     {
     }
 
-    inline ClauseListNode::ClauseListNode(JSGlobalData*, ClauseListNode* clauseList, CaseClauseNode* clause)
+    inline ClauseListNode::ClauseListNode(ClauseListNode* clauseList, CaseClauseNode* clause)
         : m_clause(clause)
         , m_next(0)
     {
         clauseList->m_next = this;
     }
 
         : m_clause(clause)
         , m_next(0)
     {
         clauseList->m_next = this;
     }
 
-    inline CaseBlockNode::CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2)
+    inline CaseBlockNode::CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2)
         : m_list1(list1)
         , m_defaultClause(defaultClause)
         , m_list2(list2)
     {
     }
 
         : m_list1(list1)
         , m_defaultClause(defaultClause)
         , m_list2(list2)
     {
     }
 
-    inline SwitchNode::SwitchNode(JSGlobalData* globalData, ExpressionNode* expr, CaseBlockNode* block)
-        : StatementNode(globalData)
+    inline SwitchNode::SwitchNode(int lineNumber, ExpressionNode* expr, CaseBlockNode* block)
+        : StatementNode(lineNumber)
         , m_expr(expr)
         , m_block(block)
     {
     }
 
         , m_expr(expr)
         , m_block(block)
     {
     }
 
-    inline ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init)
-        : ExpressionNode(globalData)
+    inline ConstDeclNode::ConstDeclNode(int lineNumber, const Identifier& ident, ExpressionNode* init)
+        : ExpressionNode(lineNumber)
         , m_ident(ident)
         , m_next(0)
         , m_init(init)
     {
     }
 
         , m_ident(ident)
         , m_next(0)
         , m_init(init)
     {
     }
 
-    inline BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* statements)
-        : StatementNode(globalData)
+    inline BlockNode::BlockNode(int lineNumber, SourceElements* statements)
+        : StatementNode(lineNumber)
         , m_statements(statements)
     {
     }
 
         , m_statements(statements)
     {
     }
 
-    inline ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
-        : StatementNode(globalData)
+    inline ForInNode::ForInNode(JSGlobalData* globalData, int lineNumber, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
+        : StatementNode(lineNumber)
         , m_ident(globalData->propertyNames->nullIdentifier)
         , m_init(0)
         , m_lexpr(l)
         , m_ident(globalData->propertyNames->nullIdentifier)
         , m_init(0)
         , m_lexpr(l)
@@ -886,17 +876,17 @@ namespace JSC {
     {
     }
 
     {
     }
 
-    inline ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset)
-        : StatementNode(globalData)
+    inline ForInNode::ForInNode(JSGlobalData* globalData, int lineNumber, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset)
+        : StatementNode(lineNumber)
         , m_ident(ident)
         , m_init(0)
         , m_ident(ident)
         , m_init(0)
-        , m_lexpr(new (globalData) ResolveNode(globalData, ident, divot - startOffset))
+        , m_lexpr(new (globalData) ResolveNode(lineNumber, ident, divot - startOffset))
         , m_expr(expr)
         , m_statement(statement)
         , m_identIsVarDecl(true)
     {
         if (in) {
         , m_expr(expr)
         , m_statement(statement)
         , m_identIsVarDecl(true)
     {
         if (in) {
-            AssignResolveNode* node = new (globalData) AssignResolveNode(globalData, ident, in, true);
+            AssignResolveNode* node = new (globalData) AssignResolveNode(lineNumber, ident, in, true);
             node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot);
             m_init = node;
         }
             node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot);
             m_init = node;
         }
index 7f4deffac9018c2a248138884b89190bca5c5e22..4853aec42895a4135f65f4fdf0439a70906e8d04 100644 (file)
@@ -21,7 +21,6 @@
 #define NodeInfo_h
 
 #include "Nodes.h"
 #define NodeInfo_h
 
 #include "Nodes.h"
-#include "Parser.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
index 34aa6746dc0174a39621416cf0a95f88b6768c2c..c32e4c73a24ebeb233cd5e01fffd63a48685c886 100644 (file)
@@ -54,7 +54,7 @@ namespace JSC {
 
 void StatementNode::setLoc(int firstLine, int lastLine)
 {
 
 void StatementNode::setLoc(int firstLine, int lastLine)
 {
-    m_line = firstLine;
+    m_lineNumber = firstLine;
     m_lastLine = lastLine;
 }
 
     m_lastLine = lastLine;
 }
 
@@ -73,75 +73,70 @@ StatementNode* SourceElements::singleStatement() const
     return size == 1 ? m_statements[0] : 0;
 }
 
     return size == 1 ? m_statements[0] : 0;
 }
 
-// -----------------------------ScopeNodeData ---------------------------
-
-ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, int numConstants)
-    : m_numConstants(numConstants)
-    , m_statements(statements)
-{
-    m_arena.swap(arena);
-    if (varStack)
-        m_varStack.swap(*varStack);
-    if (funcStack)
-        m_functionStack.swap(*funcStack);
-    m_capturedVariables.swap(capturedVariables);
-}
-
 // ------------------------------ ScopeNode -----------------------------
 
 // ------------------------------ ScopeNode -----------------------------
 
-ScopeNode::ScopeNode(JSGlobalData* globalData, bool inStrictContext)
-    : StatementNode(globalData)
+ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext)
+    : StatementNode(lineNumber)
     , ParserArenaRefCounted(globalData)
     , m_features(inStrictContext ? StrictModeFeature : NoFeatures)
     , ParserArenaRefCounted(globalData)
     , m_features(inStrictContext ? StrictModeFeature : NoFeatures)
+    , m_numConstants(0)
+    , m_statements(0)
 {
 }
 
 {
 }
 
-ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants)
-    : StatementNode(globalData)
+ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants)
+    : StatementNode(lineNumber)
     , ParserArenaRefCounted(globalData)
     , ParserArenaRefCounted(globalData)
-    , 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)
+    , m_numConstants(numConstants)
+    , m_statements(children)
 {
 {
+    m_arena.swap(*globalData->parserArena);
+    if (varStack)
+        m_varStack.swap(*varStack);
+    if (funcStack)
+        m_functionStack.swap(*funcStack);
+    m_capturedVariables.swap(capturedVariables);
 }
 
 StatementNode* ScopeNode::singleStatement() const
 {
 }
 
 StatementNode* ScopeNode::singleStatement() const
 {
-    return m_data->m_statements ? m_data->m_statements->singleStatement() : 0;
+    return m_statements ? m_statements->singleStatement() : 0;
 }
 
 // ------------------------------ ProgramNode -----------------------------
 
 }
 
 // ------------------------------ ProgramNode -----------------------------
 
-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)
+inline ProgramNode::ProgramNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+    : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, features, numConstants)
 {
 }
 
 {
 }
 
-PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
 {
 {
-    RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, capturedVariables, source, features, numConstants);
+    RefPtr<ProgramNode> node = new ProgramNode(globalData, lineNumber, children, varStack, funcStack,  capturedVariables, source, features, numConstants);
 
 
-    ASSERT(node->data()->m_arena.last() == node);
-    node->data()->m_arena.removeLast();
-    ASSERT(!node->data()->m_arena.contains(node.get()));
+    ASSERT(node->m_arena.last() == node);
+    node->m_arena.removeLast();
+    ASSERT(!node->m_arena.contains(node.get()));
 
     return node.release();
 }
 
 // ------------------------------ EvalNode -----------------------------
 
 
     return node.release();
 }
 
 // ------------------------------ EvalNode -----------------------------
 
-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)
+inline EvalNode::EvalNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+    : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, features, numConstants)
 {
 }
 
 {
 }
 
-PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
 {
 {
-    RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, capturedVariables, source, features, numConstants);
+    RefPtr<EvalNode> node = new EvalNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, features, numConstants);
 
 
-    ASSERT(node->data()->m_arena.last() == node);
-    node->data()->m_arena.removeLast();
-    ASSERT(!node->data()->m_arena.contains(node.get()));
+    ASSERT(node->m_arena.last() == node);
+    node->m_arena.removeLast();
+    ASSERT(!node->m_arena.contains(node.get()));
 
     return node.release();
 }
 
     return node.release();
 }
@@ -154,13 +149,13 @@ FunctionParameters::FunctionParameters(ParameterNode* firstParameter)
         append(parameter->ident());
 }
 
         append(parameter->ident());
 }
 
-inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, bool inStrictContext)
-    : ScopeNode(globalData, inStrictContext)
+inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext)
+    : ScopeNode(globalData, lineNumber, inStrictContext)
 {
 }
 
 {
 }
 
-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)
+inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
+    : ScopeNode(globalData, lineNumber, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants)
 {
 }
 
 {
 }
 
@@ -177,18 +172,18 @@ void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters,
     m_ident = ident;
 }
 
     m_ident = ident;
 }
 
-FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, bool inStrictContext)
+FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, bool inStrictContext)
 {
 {
-    return new FunctionBodyNode(globalData, inStrictContext);
+    return new FunctionBodyNode(globalData, lineNumber, inStrictContext);
 }
 
 }
 
-PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
+PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
 {
 {
-    RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants);
+    RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants);
 
 
-    ASSERT(node->data()->m_arena.last() == node);
-    node->data()->m_arena.removeLast();
-    ASSERT(!node->data()->m_arena.contains(node.get()));
+    ASSERT(node->m_arena.last() == node);
+    node->m_arena.removeLast();
+    ASSERT(!node->m_arena.contains(node.get()));
 
     return node.release();
 }
 
     return node.release();
 }
index 6e73c00ccce939286826b3beb5a67d2537d82d4b..5c90bb9fe66360e92a997adb64b3ee7963732266 100644 (file)
@@ -51,17 +51,14 @@ namespace JSC {
 
     const CodeFeatures NoFeatures = 0;
     const CodeFeatures EvalFeature = 1 << 0;
 
     const CodeFeatures NoFeatures = 0;
     const CodeFeatures EvalFeature = 1 << 0;
-    const CodeFeatures ClosureFeature = 1 << 1;
-    const CodeFeatures AssignFeature = 1 << 2;
-    const CodeFeatures ArgumentsFeature = 1 << 3;
-    const CodeFeatures WithFeature = 1 << 4;
-    const CodeFeatures CatchFeature = 1 << 5;
-    const CodeFeatures ThisFeature = 1 << 6;
-    const CodeFeatures StrictModeFeature = 1 << 7;
-    const CodeFeatures ShadowsArgumentsFeature = 1 << 8;
+    const CodeFeatures ArgumentsFeature = 1 << 1;
+    const CodeFeatures WithFeature = 1 << 2;
+    const CodeFeatures CatchFeature = 1 << 3;
+    const CodeFeatures ThisFeature = 1 << 4;
+    const CodeFeatures StrictModeFeature = 1 << 5;
+    const CodeFeatures ShadowsArgumentsFeature = 1 << 6;
     
     
-    
-    const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature;
+    const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature;
 
     enum Operator {
         OpEqual,
 
     enum Operator {
         OpEqual,
@@ -115,6 +112,11 @@ namespace JSC {
         void* operator new(size_t, JSGlobalData*);
     };
 
         void* operator new(size_t, JSGlobalData*);
     };
 
+    template <typename T>
+    struct ParserArenaData : ParserArenaDeletable {
+        T data;
+    };
+
     class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> {
     protected:
         ParserArenaRefCounted(JSGlobalData*);
     class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> {
     protected:
         ParserArenaRefCounted(JSGlobalData*);
@@ -128,22 +130,22 @@ namespace JSC {
 
     class Node : public ParserArenaFreeable {
     protected:
 
     class Node : public ParserArenaFreeable {
     protected:
-        Node(JSGlobalData*);
+        Node(int);
 
     public:
         virtual ~Node() { }
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0;
 
 
     public:
         virtual ~Node() { }
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0;
 
-        int lineNo() const { return m_line; }
+        int lineNo() const { return m_lineNumber; }
 
     protected:
 
     protected:
-        int m_line;
+        int m_lineNumber;
     };
 
     class ExpressionNode : public Node {
     protected:
     };
 
     class ExpressionNode : public Node {
     protected:
-        ExpressionNode(JSGlobalData*, ResultType = ResultType::unknownType());
+        ExpressionNode(int, ResultType = ResultType::unknownType());
 
     public:
         virtual bool isNumber() const { return false; }
 
     public:
         virtual bool isNumber() const { return false; }
@@ -173,10 +175,10 @@ namespace JSC {
 
     class StatementNode : public Node {
     protected:
 
     class StatementNode : public Node {
     protected:
-        StatementNode(JSGlobalData*);
+        StatementNode(int);
 
     public:
 
     public:
-        void setLoc(int firstLine, int lastLine);
+        JS_EXPORT_PRIVATE void setLoc(int firstLine, int lastLine);
         int firstLine() const { return lineNo(); }
         int lastLine() const { return m_lastLine; }
 
         int firstLine() const { return lineNo(); }
         int lastLine() const { return m_lastLine; }
 
@@ -192,7 +194,7 @@ namespace JSC {
 
     class NullNode : public ExpressionNode {
     public:
 
     class NullNode : public ExpressionNode {
     public:
-        NullNode(JSGlobalData*);
+        NullNode(int);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -202,7 +204,7 @@ namespace JSC {
 
     class BooleanNode : public ExpressionNode {
     public:
 
     class BooleanNode : public ExpressionNode {
     public:
-        BooleanNode(JSGlobalData*, bool value);
+        BooleanNode(int, bool value);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -214,7 +216,7 @@ namespace JSC {
 
     class NumberNode : public ExpressionNode {
     public:
 
     class NumberNode : public ExpressionNode {
     public:
-        NumberNode(JSGlobalData*, double value);
+        NumberNode(int, double value);
 
         double value() const { return m_value; }
         void setValue(double value) { m_value = value; }
 
         double value() const { return m_value; }
         void setValue(double value) { m_value = value; }
@@ -230,7 +232,7 @@ namespace JSC {
 
     class StringNode : public ExpressionNode {
     public:
 
     class StringNode : public ExpressionNode {
     public:
-        StringNode(JSGlobalData*, const Identifier&);
+        StringNode(int, const Identifier&);
 
         const Identifier& value() { return m_value; }
 
 
         const Identifier& value() { return m_value; }
 
@@ -340,7 +342,7 @@ namespace JSC {
 
     class RegExpNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class RegExpNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        RegExpNode(JSGlobalData*, const Identifier& pattern, const Identifier& flags);
+        RegExpNode(int, const Identifier& pattern, const Identifier& flags);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -351,7 +353,7 @@ namespace JSC {
 
     class ThisNode : public ExpressionNode {
     public:
 
     class ThisNode : public ExpressionNode {
     public:
-        ThisNode(JSGlobalData*);
+        ThisNode(int);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -359,7 +361,7 @@ namespace JSC {
 
     class ResolveNode : public ExpressionNode {
     public:
 
     class ResolveNode : public ExpressionNode {
     public:
-        ResolveNode(JSGlobalData*, const Identifier&, int startOffset);
+        ResolveNode(int, const Identifier&, int startOffset);
 
         const Identifier& identifier() const { return m_ident; }
 
 
         const Identifier& identifier() const { return m_ident; }
 
@@ -376,8 +378,8 @@ namespace JSC {
 
     class ElementNode : public ParserArenaFreeable {
     public:
 
     class ElementNode : public ParserArenaFreeable {
     public:
-        ElementNode(JSGlobalData*, int elision, ExpressionNode*);
-        ElementNode(JSGlobalData*, ElementNode*, int elision, ExpressionNode*);
+        ElementNode(int elision, ExpressionNode*);
+        ElementNode(ElementNode*, int elision, ExpressionNode*);
 
         int elision() const { return m_elision; }
         ExpressionNode* value() { return m_node; }
 
         int elision() const { return m_elision; }
         ExpressionNode* value() { return m_node; }
@@ -391,11 +393,11 @@ namespace JSC {
 
     class ArrayNode : public ExpressionNode {
     public:
 
     class ArrayNode : public ExpressionNode {
     public:
-        ArrayNode(JSGlobalData*, int elision);
-        ArrayNode(JSGlobalData*, ElementNode*);
-        ArrayNode(JSGlobalData*, int elision, ElementNode*);
+        ArrayNode(int, int elision);
+        ArrayNode(int, ElementNode*);
+        ArrayNode(int, int elision, ElementNode*);
 
 
-        ArgumentListNode* toArgumentList(JSGlobalData*) const;
+        ArgumentListNode* toArgumentList(JSGlobalData*, int) const;
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -411,8 +413,8 @@ namespace JSC {
     public:
         enum Type { Constant = 1, Getter = 2, Setter = 4 };
 
     public:
         enum Type { Constant = 1, Getter = 2, Setter = 4 };
 
-        PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type);
-        PropertyNode(JSGlobalData*, double name, ExpressionNode* value, Type);
+        PropertyNode(JSGlobalData*, const Identifier&, ExpressionNode*, Type);
+        PropertyNode(JSGlobalData*, double, ExpressionNode*, Type);
 
         const Identifier& name() const { return m_name; }
         Type type() const { return m_type; }
 
         const Identifier& name() const { return m_name; }
         Type type() const { return m_type; }
@@ -426,8 +428,8 @@ namespace JSC {
 
     class PropertyListNode : public Node {
     public:
 
     class PropertyListNode : public Node {
     public:
-        PropertyListNode(JSGlobalData*, PropertyNode*);
-        PropertyListNode(JSGlobalData*, PropertyNode*, PropertyListNode*);
+        PropertyListNode(int, PropertyNode*);
+        PropertyListNode(int, PropertyNode*, PropertyListNode*);
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
@@ -438,8 +440,8 @@ namespace JSC {
 
     class ObjectLiteralNode : public ExpressionNode {
     public:
 
     class ObjectLiteralNode : public ExpressionNode {
     public:
-        ObjectLiteralNode(JSGlobalData*);
-        ObjectLiteralNode(JSGlobalData*, PropertyListNode*);
+        ObjectLiteralNode(int);
+        ObjectLiteralNode(int, PropertyListNode*);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -449,7 +451,7 @@ namespace JSC {
     
     class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData {
     public:
     
     class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        BracketAccessorNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments);
+        BracketAccessorNode(int, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments);
 
         ExpressionNode* base() const { return m_base; }
         ExpressionNode* subscript() const { return m_subscript; }
 
         ExpressionNode* base() const { return m_base; }
         ExpressionNode* subscript() const { return m_subscript; }
@@ -467,7 +469,7 @@ namespace JSC {
 
     class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        DotAccessorNode(JSGlobalData*, ExpressionNode* base, const Identifier&);
+        DotAccessorNode(int, ExpressionNode* base, const Identifier&);
 
         ExpressionNode* base() const { return m_base; }
         const Identifier& identifier() const { return m_ident; }
 
         ExpressionNode* base() const { return m_base; }
         const Identifier& identifier() const { return m_ident; }
@@ -484,8 +486,8 @@ namespace JSC {
 
     class ArgumentListNode : public Node {
     public:
 
     class ArgumentListNode : public Node {
     public:
-        ArgumentListNode(JSGlobalData*, ExpressionNode*);
-        ArgumentListNode(JSGlobalData*, ArgumentListNode*, ExpressionNode*);
+        ArgumentListNode(int, ExpressionNode*);
+        ArgumentListNode(int, ArgumentListNode*, ExpressionNode*);
 
         ArgumentListNode* m_next;
         ExpressionNode* m_expr;
 
         ArgumentListNode* m_next;
         ExpressionNode* m_expr;
@@ -496,16 +498,16 @@ namespace JSC {
 
     class ArgumentsNode : public ParserArenaFreeable {
     public:
 
     class ArgumentsNode : public ParserArenaFreeable {
     public:
-        ArgumentsNode(JSGlobalData*);
-        ArgumentsNode(JSGlobalData*, ArgumentListNode*);
+        ArgumentsNode();
+        ArgumentsNode(ArgumentListNode*);
 
         ArgumentListNode* m_listNode;
     };
 
     class NewExprNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
         ArgumentListNode* m_listNode;
     };
 
     class NewExprNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        NewExprNode(JSGlobalData*, ExpressionNode*);
-        NewExprNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*);
+        NewExprNode(int, ExpressionNode*);
+        NewExprNode(int, ExpressionNode*, ArgumentsNode*);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -516,7 +518,7 @@ namespace JSC {
 
     class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        EvalFunctionCallNode(JSGlobalData*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+        EvalFunctionCallNode(int, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -526,7 +528,7 @@ namespace JSC {
 
     class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        FunctionCallValueNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+        FunctionCallValueNode(int, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -537,7 +539,7 @@ namespace JSC {
 
     class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        FunctionCallResolveNode(JSGlobalData*, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+        FunctionCallResolveNode(int, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -550,7 +552,7 @@ namespace JSC {
     
     class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
     
     class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
-        FunctionCallBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+        FunctionCallBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -562,7 +564,7 @@ namespace JSC {
 
     class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
 
     class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
-        FunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+        FunctionCallDotNode(int, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -575,7 +577,7 @@ namespace JSC {
 
     class CallFunctionCallDotNode : public FunctionCallDotNode {
     public:
 
     class CallFunctionCallDotNode : public FunctionCallDotNode {
     public:
-        CallFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+        CallFunctionCallDotNode(int, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -583,7 +585,7 @@ namespace JSC {
     
     class ApplyFunctionCallDotNode : public FunctionCallDotNode {
     public:
     
     class ApplyFunctionCallDotNode : public FunctionCallDotNode {
     public:
-        ApplyFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+        ApplyFunctionCallDotNode(int, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -591,7 +593,7 @@ namespace JSC {
 
     class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        PrePostResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
+        PrePostResolveNode(int, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     protected:
         const Identifier& m_ident;
 
     protected:
         const Identifier& m_ident;
@@ -599,7 +601,7 @@ namespace JSC {
 
     class PostfixResolveNode : public PrePostResolveNode {
     public:
 
     class PostfixResolveNode : public PrePostResolveNode {
     public:
-        PostfixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+        PostfixResolveNode(int, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -609,7 +611,7 @@ namespace JSC {
 
     class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
 
     class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
-        PostfixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+        PostfixBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -621,7 +623,7 @@ namespace JSC {
 
     class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
 
     class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
-        PostfixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+        PostfixDotNode(int, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -633,7 +635,7 @@ namespace JSC {
 
     class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
 
     class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
-        PostfixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+        PostfixErrorNode(int, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -644,7 +646,7 @@ namespace JSC {
 
     class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        DeleteResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
+        DeleteResolveNode(int, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -654,7 +656,7 @@ namespace JSC {
 
     class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        DeleteBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset);
+        DeleteBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -665,7 +667,7 @@ namespace JSC {
 
     class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        DeleteDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
+        DeleteDotNode(int, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -676,7 +678,7 @@ namespace JSC {
 
     class DeleteValueNode : public ExpressionNode {
     public:
 
     class DeleteValueNode : public ExpressionNode {
     public:
-        DeleteValueNode(JSGlobalData*, ExpressionNode*);
+        DeleteValueNode(int, ExpressionNode*);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -686,7 +688,7 @@ namespace JSC {
 
     class VoidNode : public ExpressionNode {
     public:
 
     class VoidNode : public ExpressionNode {
     public:
-        VoidNode(JSGlobalData*, ExpressionNode*);
+        VoidNode(int, ExpressionNode*);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -696,7 +698,7 @@ namespace JSC {
 
     class TypeOfResolveNode : public ExpressionNode {
     public:
 
     class TypeOfResolveNode : public ExpressionNode {
     public:
-        TypeOfResolveNode(JSGlobalData*, const Identifier&);
+        TypeOfResolveNode(int, const Identifier&);
 
         const Identifier& identifier() const { return m_ident; }
 
 
         const Identifier& identifier() const { return m_ident; }
 
@@ -708,7 +710,7 @@ namespace JSC {
 
     class TypeOfValueNode : public ExpressionNode {
     public:
 
     class TypeOfValueNode : public ExpressionNode {
     public:
-        TypeOfValueNode(JSGlobalData*, ExpressionNode*);
+        TypeOfValueNode(int, ExpressionNode*);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -718,7 +720,7 @@ namespace JSC {
 
     class PrefixResolveNode : public PrePostResolveNode {
     public:
 
     class PrefixResolveNode : public PrePostResolveNode {
     public:
-        PrefixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+        PrefixResolveNode(int, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -728,7 +730,7 @@ namespace JSC {
 
     class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
     public:
 
     class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
     public:
-        PrefixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+        PrefixBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -740,7 +742,7 @@ namespace JSC {
 
     class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
     public:
 
     class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData {
     public:
-        PrefixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+        PrefixDotNode(int, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -752,7 +754,7 @@ namespace JSC {
 
     class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        PrefixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
+        PrefixErrorNode(int, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -763,7 +765,7 @@ namespace JSC {
 
     class UnaryOpNode : public ExpressionNode {
     public:
 
     class UnaryOpNode : public ExpressionNode {
     public:
-        UnaryOpNode(JSGlobalData*, ResultType, ExpressionNode*, OpcodeID);
+        UnaryOpNode(int, ResultType, ExpressionNode*, OpcodeID);
 
     protected:
         ExpressionNode* expr() { return m_expr; }
 
     protected:
         ExpressionNode* expr() { return m_expr; }
@@ -780,7 +782,7 @@ namespace JSC {
 
     class UnaryPlusNode : public UnaryOpNode {
     public:
 
     class UnaryPlusNode : public UnaryOpNode {
     public:
-        UnaryPlusNode(JSGlobalData*, ExpressionNode*);
+        UnaryPlusNode(int, ExpressionNode*);
 
     private:
         virtual ExpressionNode* stripUnaryPlus() { return expr(); }
 
     private:
         virtual ExpressionNode* stripUnaryPlus() { return expr(); }
@@ -788,17 +790,26 @@ namespace JSC {
 
     class NegateNode : public UnaryOpNode {
     public:
 
     class NegateNode : public UnaryOpNode {
     public:
-        NegateNode(JSGlobalData*, ExpressionNode*);
+        NegateNode(int, ExpressionNode*);
     };
 
     };
 
-    class BitwiseNotNode : public UnaryOpNode {
+    class BitwiseNotNode : public ExpressionNode {
     public:
     public:
-        BitwiseNotNode(JSGlobalData*, ExpressionNode*);
-    };
+        BitwiseNotNode(int, ExpressionNode*);
+
+    protected:
+        ExpressionNode* expr() { return m_expr; }
+        const ExpressionNode* expr() const { return m_expr; }
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
 
+        ExpressionNode* m_expr;
+    };
     class LogicalNotNode : public UnaryOpNode {
     public:
     class LogicalNotNode : public UnaryOpNode {
     public:
-        LogicalNotNode(JSGlobalData*, ExpressionNode*);
+        LogicalNotNode(int, ExpressionNode*);
     private:
         void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
         virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); }
     private:
         void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
         virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); }
@@ -806,8 +817,8 @@ namespace JSC {
 
     class BinaryOpNode : public ExpressionNode {
     public:
 
     class BinaryOpNode : public ExpressionNode {
     public:
-        BinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
-        BinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+        BinaryOpNode(int, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+        BinaryOpNode(int, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
 
         RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
 
 
         RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
 
@@ -829,82 +840,74 @@ namespace JSC {
         bool m_rightHasAssignments;
     };
 
         bool m_rightHasAssignments;
     };
 
-    class ReverseBinaryOpNode : public BinaryOpNode {
-    public:
-        ReverseBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
-        ReverseBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
-
-        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
-    };
-
     class MultNode : public BinaryOpNode {
     public:
     class MultNode : public BinaryOpNode {
     public:
-        MultNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        MultNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class DivNode : public BinaryOpNode {
     public:
     };
 
     class DivNode : public BinaryOpNode {
     public:
-        DivNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        DivNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class ModNode : public BinaryOpNode {
     public:
     };
 
     class ModNode : public BinaryOpNode {
     public:
-        ModNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        ModNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class AddNode : public BinaryOpNode {
     public:
     };
 
     class AddNode : public BinaryOpNode {
     public:
-        AddNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        AddNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
 
         virtual bool isAdd() const { return true; }
     };
 
     class SubNode : public BinaryOpNode {
     public:
 
         virtual bool isAdd() const { return true; }
     };
 
     class SubNode : public BinaryOpNode {
     public:
-        SubNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        SubNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
 
         virtual bool isSubtract() const { return true; }
     };
 
     class LeftShiftNode : public BinaryOpNode {
     public:
 
         virtual bool isSubtract() const { return true; }
     };
 
     class LeftShiftNode : public BinaryOpNode {
     public:
-        LeftShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        LeftShiftNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class RightShiftNode : public BinaryOpNode {
     public:
     };
 
     class RightShiftNode : public BinaryOpNode {
     public:
-        RightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        RightShiftNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class UnsignedRightShiftNode : public BinaryOpNode {
     public:
     };
 
     class UnsignedRightShiftNode : public BinaryOpNode {
     public:
-        UnsignedRightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        UnsignedRightShiftNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class LessNode : public BinaryOpNode {
     public:
     };
 
     class LessNode : public BinaryOpNode {
     public:
-        LessNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        LessNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     };
 
-    class GreaterNode : public ReverseBinaryOpNode {
+    class GreaterNode : public BinaryOpNode {
     public:
     public:
-        GreaterNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        GreaterNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class LessEqNode : public BinaryOpNode {
     public:
     };
 
     class LessEqNode : public BinaryOpNode {
     public:
-        LessEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        LessEqNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     };
 
-    class GreaterEqNode : public ReverseBinaryOpNode {
+    class GreaterEqNode : public BinaryOpNode {
     public:
     public:
-        GreaterEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        GreaterEqNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData {
     public:
     };
 
     class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData {
     public:
-        ThrowableBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
-        ThrowableBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+        ThrowableBinaryOpNode(int, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
+        ThrowableBinaryOpNode(int, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -912,7 +915,7 @@ namespace JSC {
     
     class InstanceOfNode : public ThrowableBinaryOpNode {
     public:
     
     class InstanceOfNode : public ThrowableBinaryOpNode {
     public:
-        InstanceOfNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        InstanceOfNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -920,12 +923,12 @@ namespace JSC {
 
     class InNode : public ThrowableBinaryOpNode {
     public:
 
     class InNode : public ThrowableBinaryOpNode {
     public:
-        InNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        InNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class EqualNode : public BinaryOpNode {
     public:
     };
 
     class EqualNode : public BinaryOpNode {
     public:
-        EqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        EqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -933,12 +936,12 @@ namespace JSC {
 
     class NotEqualNode : public BinaryOpNode {
     public:
 
     class NotEqualNode : public BinaryOpNode {
     public:
-        NotEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        NotEqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class StrictEqualNode : public BinaryOpNode {
     public:
     };
 
     class StrictEqualNode : public BinaryOpNode {
     public:
-        StrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        StrictEqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -946,28 +949,28 @@ namespace JSC {
 
     class NotStrictEqualNode : public BinaryOpNode {
     public:
 
     class NotStrictEqualNode : public BinaryOpNode {
     public:
-        NotStrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        NotStrictEqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class BitAndNode : public BinaryOpNode {
     public:
     };
 
     class BitAndNode : public BinaryOpNode {
     public:
-        BitAndNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        BitAndNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class BitOrNode : public BinaryOpNode {
     public:
     };
 
     class BitOrNode : public BinaryOpNode {
     public:
-        BitOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        BitOrNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     class BitXOrNode : public BinaryOpNode {
     public:
     };
 
     class BitXOrNode : public BinaryOpNode {
     public:
-        BitXOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+        BitXOrNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
     };
 
     // m_expr1 && m_expr2, m_expr1 || m_expr2
     class LogicalOpNode : public ExpressionNode {
     public:
     };
 
     // m_expr1 && m_expr2, m_expr1 || m_expr2
     class LogicalOpNode : public ExpressionNode {
     public:
-        LogicalOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator);
+        LogicalOpNode(int, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -982,7 +985,7 @@ namespace JSC {
     // The ternary operator, "m_logical ? m_expr1 : m_expr2"
     class ConditionalNode : public ExpressionNode {
     public:
     // The ternary operator, "m_logical ? m_expr1 : m_expr2"
     class ConditionalNode : public ExpressionNode {
     public:
-        ConditionalNode(JSGlobalData*, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2);
+        ConditionalNode(int, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -994,7 +997,7 @@ namespace JSC {
 
     class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        ReadModifyResolveNode(JSGlobalData*, const Identifier&, Operator, ExpressionNode*  right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
+        ReadModifyResolveNode(int, const Identifier&, Operator, ExpressionNode*  right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1008,7 +1011,7 @@ namespace JSC {
 
     class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        AssignResolveNode(JSGlobalData*, const Identifier&, ExpressionNode* right, bool rightHasAssignments);
+        AssignResolveNode(int, const Identifier&, ExpressionNode* right, bool rightHasAssignments);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1021,7 +1024,7 @@ namespace JSC {
 
     class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
 
     class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
-        ReadModifyBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
+        ReadModifyBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1036,7 +1039,7 @@ namespace JSC {
 
     class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        AssignBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
+        AssignBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1050,7 +1053,7 @@ namespace JSC {
 
     class AssignDotNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class AssignDotNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        AssignDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
+        AssignDotNode(int, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1063,7 +1066,7 @@ namespace JSC {
 
     class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
 
     class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData {
     public:
-        ReadModifyDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
+        ReadModifyDotNode(int, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1077,7 +1080,7 @@ namespace JSC {
 
     class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData {
     public:
 
     class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData {
     public:
-        AssignErrorNode(JSGlobalData*, ExpressionNode* left, Operator, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset);
+        AssignErrorNode(int, ExpressionNode* left, Operator, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1091,7 +1094,7 @@ namespace JSC {
 
     class CommaNode : public ExpressionNode, public ParserArenaDeletable {
     public:
 
     class CommaNode : public ExpressionNode, public ParserArenaDeletable {
     public:
-        CommaNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2);
+        CommaNode(int, ExpressionNode* expr1, ExpressionNode* expr2);
 
         using ParserArenaDeletable::operator new;
 
 
         using ParserArenaDeletable::operator new;
 
@@ -1106,7 +1109,7 @@ namespace JSC {
     
     class ConstDeclNode : public ExpressionNode {
     public:
     
     class ConstDeclNode : public ExpressionNode {
     public:
-        ConstDeclNode(JSGlobalData*, const Identifier&, ExpressionNode*);
+        ConstDeclNode(int, const Identifier&, ExpressionNode*);
 
         bool hasInitializer() const { return m_init; }
         const Identifier& ident() { return m_ident; }
 
         bool hasInitializer() const { return m_init; }
         const Identifier& ident() { return m_ident; }
@@ -1126,7 +1129,7 @@ namespace JSC {
 
     class ConstStatementNode : public StatementNode {
     public:
 
     class ConstStatementNode : public StatementNode {
     public:
-        ConstStatementNode(JSGlobalData*, ConstDeclNode* next);
+        ConstStatementNode(int, ConstDeclNode* next);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1136,7 +1139,7 @@ namespace JSC {
 
     class SourceElements : public ParserArenaDeletable {
     public:
 
     class SourceElements : public ParserArenaDeletable {
     public:
-        SourceElements(JSGlobalData*);
+        SourceElements();
 
         void append(StatementNode*);
 
 
         void append(StatementNode*);
 
@@ -1151,7 +1154,7 @@ namespace JSC {
 
     class BlockNode : public StatementNode {
     public:
 
     class BlockNode : public StatementNode {
     public:
-        BlockNode(JSGlobalData*, SourceElements* = 0);
+        BlockNode(int, SourceElements* = 0);
 
         StatementNode* singleStatement() const;
         StatementNode* lastStatement() const;
 
         StatementNode* singleStatement() const;
         StatementNode* lastStatement() const;
@@ -1166,7 +1169,7 @@ namespace JSC {
 
     class EmptyStatementNode : public StatementNode {
     public:
 
     class EmptyStatementNode : public StatementNode {
     public:
-        EmptyStatementNode(JSGlobalData*);
+        EmptyStatementNode(int);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1176,7 +1179,7 @@ namespace JSC {
     
     class DebuggerStatementNode : public StatementNode {
     public:
     
     class DebuggerStatementNode : public StatementNode {
     public:
-        DebuggerStatementNode(JSGlobalData*);
+        DebuggerStatementNode(int);
         
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
         
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1184,7 +1187,7 @@ namespace JSC {
 
     class ExprStatementNode : public StatementNode {
     public:
 
     class ExprStatementNode : public StatementNode {
     public:
-        ExprStatementNode(JSGlobalData*, ExpressionNode*);
+        ExprStatementNode(int, ExpressionNode*);
 
         ExpressionNode* expr() const { return m_expr; }
 
 
         ExpressionNode* expr() const { return m_expr; }
 
@@ -1198,7 +1201,7 @@ namespace JSC {
 
     class VarStatementNode : public StatementNode {
     public:
 
     class VarStatementNode : public StatementNode {
     public:
-        VarStatementNode(JSGlobalData*, ExpressionNode*);        
+        VarStatementNode(int, ExpressionNode*);        
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1208,7 +1211,7 @@ namespace JSC {
 
     class IfNode : public StatementNode {
     public:
 
     class IfNode : public StatementNode {
     public:
-        IfNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock);
+        IfNode(int, ExpressionNode* condition, StatementNode* ifBlock);
 
     protected:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     protected:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1219,7 +1222,7 @@ namespace JSC {
 
     class IfElseNode : public IfNode {
     public:
 
     class IfElseNode : public IfNode {
     public:
-        IfElseNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock);
+        IfElseNode(int, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1229,7 +1232,7 @@ namespace JSC {
 
     class DoWhileNode : public StatementNode {
     public:
 
     class DoWhileNode : public StatementNode {
     public:
-        DoWhileNode(JSGlobalData*, StatementNode* statement, ExpressionNode*);
+        DoWhileNode(int, StatementNode*, ExpressionNode*);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1240,7 +1243,7 @@ namespace JSC {
 
     class WhileNode : public StatementNode {
     public:
 
     class WhileNode : public StatementNode {
     public:
-        WhileNode(JSGlobalData*, ExpressionNode*, StatementNode* statement);
+        WhileNode(int, ExpressionNode*, StatementNode*);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1251,7 +1254,7 @@ namespace JSC {
 
     class ForNode : public StatementNode {
     public:
 
     class ForNode : public StatementNode {
     public:
-        ForNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl);
+        ForNode(int, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*, bool expr1WasVarDecl);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1265,8 +1268,8 @@ namespace JSC {
 
     class ForInNode : public StatementNode, public ThrowableExpressionData {
     public:
 
     class ForInNode : public StatementNode, public ThrowableExpressionData {
     public:
-        ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*);
-        ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset);
+        ForInNode(JSGlobalData*, int, ExpressionNode*, ExpressionNode*, StatementNode*);
+        ForInNode(JSGlobalData*, int, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1281,8 +1284,8 @@ namespace JSC {
 
     class ContinueNode : public StatementNode, public ThrowableExpressionData {
     public:
 
     class ContinueNode : public StatementNode, public ThrowableExpressionData {
     public:
-        ContinueNode(JSGlobalData*);
-        ContinueNode(JSGlobalData*, const Identifier&);
+        ContinueNode(JSGlobalData*, int);
+        ContinueNode(int, const Identifier&);
         
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
         
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1292,8 +1295,8 @@ namespace JSC {
 
     class BreakNode : public StatementNode, public ThrowableExpressionData {
     public:
 
     class BreakNode : public StatementNode, public ThrowableExpressionData {
     public:
-        BreakNode(JSGlobalData*);
-        BreakNode(JSGlobalData*, const Identifier&);
+        BreakNode(JSGlobalData*, int);
+        BreakNode(int, const Identifier&);
         
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
         
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1303,7 +1306,7 @@ namespace JSC {
 
     class ReturnNode : public StatementNode, public ThrowableExpressionData {
     public:
 
     class ReturnNode : public StatementNode, public ThrowableExpressionData {
     public:
-        ReturnNode(JSGlobalData*, ExpressionNode* value);
+        ReturnNode(int, ExpressionNode* value);
 
         ExpressionNode* value() { return m_value; }
 
 
         ExpressionNode* value() { return m_value; }
 
@@ -1317,7 +1320,7 @@ namespace JSC {
 
     class WithNode : public StatementNode {
     public:
 
     class WithNode : public StatementNode {
     public:
-        WithNode(JSGlobalData*, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength);
+        WithNode(int, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1330,7 +1333,7 @@ namespace JSC {
 
     class LabelNode : public StatementNode, public ThrowableExpressionData {
     public:
 
     class LabelNode : public StatementNode, public ThrowableExpressionData {
     public:
-        LabelNode(JSGlobalData*, const Identifier& name, StatementNode*);
+        LabelNode(int, const Identifier& name, StatementNode*);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1341,7 +1344,7 @@ namespace JSC {
 
     class ThrowNode : public StatementNode, public ThrowableExpressionData {
     public:
 
     class ThrowNode : public StatementNode, public ThrowableExpressionData {
     public:
-        ThrowNode(JSGlobalData*, ExpressionNode*);
+        ThrowNode(int, ExpressionNode*);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1351,7 +1354,7 @@ namespace JSC {
 
     class TryNode : public StatementNode {
     public:
 
     class TryNode : public StatementNode {
     public:
-        TryNode(JSGlobalData*, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock);
+        TryNode(int, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -1360,13 +1363,12 @@ namespace JSC {
         const Identifier& m_exceptionIdent;
         StatementNode* m_catchBlock;
         StatementNode* m_finallyBlock;
         const Identifier& m_exceptionIdent;
         StatementNode* m_catchBlock;
         StatementNode* m_finallyBlock;
-        bool m_catchHasEval;
     };
 
     class ParameterNode : public ParserArenaFreeable {
     public:
     };
 
     class ParameterNode : public ParserArenaFreeable {
     public:
-        ParameterNode(JSGlobalData*, const Identifier&);
-        ParameterNode(JSGlobalData*, ParameterNode*, const Identifier&);
+        ParameterNode(const Identifier&);
+        ParameterNode(ParameterNode*, const Identifier&);
 
         const Identifier& ident() const { return m_ident; }
         ParameterNode* nextParam() const { return m_next; }
 
         const Identifier& ident() const { return m_ident; }
         ParameterNode* nextParam() const { return m_next; }
@@ -1376,38 +1378,28 @@ namespace JSC {
         ParameterNode* m_next;
     };
 
         ParameterNode* m_next;
     };
 
-    struct ScopeNodeData {
-        WTF_MAKE_FAST_ALLOCATED;
-    public:
-        typedef DeclarationStacks::VarStack VarStack;
-        typedef DeclarationStacks::FunctionStack FunctionStack;
-
-        ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, int numConstants);
-
-        ParserArena m_arena;
-        VarStack m_varStack;
-        FunctionStack m_functionStack;
-        int m_numConstants;
-        SourceElements* m_statements;
-        IdentifierSet m_capturedVariables;
-    };
-
     class ScopeNode : public StatementNode, public ParserArenaRefCounted {
     public:
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
     class ScopeNode : public StatementNode, public ParserArenaRefCounted {
     public:
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
-        ScopeNode(JSGlobalData*, bool inStrictContext);
-        ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants);
+        ScopeNode(JSGlobalData*, int, bool inStrictContext);
+        ScopeNode(JSGlobalData*, int, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants);
 
         using ParserArenaRefCounted::operator new;
 
 
         using ParserArenaRefCounted::operator new;
 
-        ScopeNodeData* data() const { return m_data.get(); }
-        void destroyData() { m_data.clear(); }
+        void destroyData()
+        {
+            m_arena.reset();
+            m_varStack.clear();
+            m_functionStack.clear();
+            m_statements = 0;
+            m_capturedVariables.clear();
+        }
 
         const SourceCode& source() const { return m_source; }
         const UString& sourceURL() const { return m_source.provider()->url(); }
 
         const SourceCode& source() const { return m_source; }
         const UString& sourceURL() const { return m_source.provider()->url(); }
-        intptr_t sourceID() const { return m_source.provider()->asID(); }
+        intptr_t sourceID() const { return m_source.providerID(); }
 
         void setFeatures(CodeFeatures features) { m_features = features; }
         CodeFeatures features() { return m_features; }
 
         void setFeatures(CodeFeatures features) { m_features = features; }
         CodeFeatures features() { return m_features; }
@@ -1417,21 +1409,20 @@ namespace JSC {
         bool isStrictMode() const { return m_features & StrictModeFeature; }
         void setUsesArguments() { m_features |= ArgumentsFeature; }
         bool usesThis() const { return m_features & ThisFeature; }
         bool isStrictMode() const { return m_features & StrictModeFeature; }
         void setUsesArguments() { m_features |= ArgumentsFeature; }
         bool usesThis() const { return m_features & ThisFeature; }
-        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()); }
+        bool needsActivationForMoreThanVariables() const { return m_features & (EvalFeature | WithFeature | CatchFeature); }
+        bool needsActivation() const { return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); }
+        bool hasCapturedVariables() const { return !!m_capturedVariables.size(); }
+        size_t capturedVariableCount() const { return m_capturedVariables.size(); }
+        bool captures(const Identifier& ident) { return 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() { return m_varStack; }
+        FunctionStack& functionStack() { return m_functionStack; }
 
         int neededConstants()
         {
 
         int neededConstants()
         {
-            ASSERT(m_data);
             // We may need 2 more constants than the count given by the parser,
             // because of the various uses of jsUndefined() and jsNull().
             // We may need 2 more constants than the count given by the parser,
             // because of the various uses of jsUndefined() and jsNull().
-            return m_data->m_numConstants + 2;
+            return m_numConstants + 2;
         }
 
         StatementNode* singleStatement() const;
         }
 
         StatementNode* singleStatement() const;
@@ -1440,22 +1431,27 @@ namespace JSC {
 
     protected:
         void setSource(const SourceCode& source) { m_source = source; }
 
     protected:
         void setSource(const SourceCode& source) { m_source = source; }
+        ParserArena m_arena;
 
     private:
 
     private:
-        OwnPtr<ScopeNodeData> m_data;
         CodeFeatures m_features;
         SourceCode m_source;
         CodeFeatures m_features;
         SourceCode m_source;
+        VarStack m_varStack;
+        FunctionStack m_functionStack;
+        int m_numConstants;
+        SourceElements* m_statements;
+        IdentifierSet m_capturedVariables;
     };
 
     class ProgramNode : public ScopeNode {
     public:
         static const bool isFunctionNode = false;
     };
 
     class ProgramNode : public ScopeNode {
     public:
         static const bool isFunctionNode = false;
-        static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        static PassRefPtr<ProgramNode> create(JSGlobalData*, int, 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*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        ProgramNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
     };
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
     };
@@ -1463,12 +1459,12 @@ namespace JSC {
     class EvalNode : public ScopeNode {
     public:
         static const bool isFunctionNode = false;
     class EvalNode : public ScopeNode {
     public:
         static const bool isFunctionNode = false;
-        static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        static PassRefPtr<EvalNode> create(JSGlobalData*, int, 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*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        EvalNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
     };
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
     };
@@ -1485,8 +1481,8 @@ namespace JSC {
     class FunctionBodyNode : public ScopeNode {
     public:
         static const bool isFunctionNode = true;
     class FunctionBodyNode : public ScopeNode {
     public:
         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);
+        static FunctionBodyNode* create(JSGlobalData*, int, bool isStrictMode);
+        static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, int, 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(); }
@@ -1497,20 +1493,23 @@ namespace JSC {
         void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&);
         
         const Identifier& ident() { return m_ident; }
         void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&);
         
         const Identifier& ident() { return m_ident; }
+        void setInferredName(const Identifier& inferredName) { ASSERT(!inferredName.isNull()); m_inferredName = inferredName; }
+        const Identifier& inferredName() { return m_inferredName.isEmpty() ? m_ident : m_inferredName; }
 
         static const bool scopeIsFunction = true;
 
     private:
 
         static const bool scopeIsFunction = true;
 
     private:
-        FunctionBodyNode(JSGlobalData*, bool inStrictContext);
-        FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
+        FunctionBodyNode(JSGlobalData*, int, bool inStrictContext);
+        FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         Identifier m_ident;
 
         Identifier m_ident;
+        Identifier m_inferredName;
         RefPtr<FunctionParameters> m_parameters;
     };
 
     class FuncExprNode : public ExpressionNode {
     public:
         RefPtr<FunctionParameters> m_parameters;
     };
 
     class FuncExprNode : public ExpressionNode {
     public:
-        FuncExprNode(JSGlobalData*, const Identifier&, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0);
+        FuncExprNode(int, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0);
 
         FunctionBodyNode* body() { return m_body; }
 
 
         FunctionBodyNode* body() { return m_body; }
 
@@ -1524,7 +1523,7 @@ namespace JSC {
 
     class FuncDeclNode : public StatementNode {
     public:
 
     class FuncDeclNode : public StatementNode {
     public:
-        FuncDeclNode(JSGlobalData*, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0);
+        FuncDeclNode(int, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0);
 
         FunctionBodyNode* body() { return m_body; }
 
 
         FunctionBodyNode* body() { return m_body; }
 
@@ -1536,7 +1535,7 @@ namespace JSC {
 
     class CaseClauseNode : public ParserArenaFreeable {
     public:
 
     class CaseClauseNode : public ParserArenaFreeable {
     public:
-        CaseClauseNode(JSGlobalData*, ExpressionNode*, SourceElements* = 0);
+        CaseClauseNode(ExpressionNode*, SourceElements* = 0);
 
         ExpressionNode* expr() const { return m_expr; }
 
 
         ExpressionNode* expr() const { return m_expr; }
 
@@ -1549,8 +1548,8 @@ namespace JSC {
 
     class ClauseListNode : public ParserArenaFreeable {
     public:
 
     class ClauseListNode : public ParserArenaFreeable {
     public:
-        ClauseListNode(JSGlobalData*, CaseClauseNode*);
-        ClauseListNode(JSGlobalData*, ClauseListNode*, CaseClauseNode*);
+        ClauseListNode(CaseClauseNode*);
+        ClauseListNode(ClauseListNode*, CaseClauseNode*);
 
         CaseClauseNode* getClause() const { return m_clause; }
         ClauseListNode* getNext() const { return m_next; }
 
         CaseClauseNode* getClause() const { return m_clause; }
         ClauseListNode* getNext() const { return m_next; }
@@ -1562,7 +1561,7 @@ namespace JSC {
 
     class CaseBlockNode : public ParserArenaFreeable {
     public:
 
     class CaseBlockNode : public ParserArenaFreeable {
     public:
-        CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2);
+        CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2);
 
         RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination);
 
 
         RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination);
 
@@ -1575,7 +1574,7 @@ namespace JSC {
 
     class SwitchNode : public StatementNode {
     public:
 
     class SwitchNode : public StatementNode {
     public:
-        SwitchNode(JSGlobalData*, ExpressionNode*, CaseBlockNode*);
+        SwitchNode(int, ExpressionNode*, CaseBlockNode*);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
index fc1e986683ee6dce40932af61bbf93633b8e978b..d88a9a8b76bede8a092ae7fb2c5fbdc5ad58fa39 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, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 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
 #include "config.h"
 #include "Parser.h"
 
 #include "config.h"
 #include "Parser.h"
 
+#include "ASTBuilder.h"
+#include "CodeBlock.h"
 #include "Debugger.h"
 #include "Debugger.h"
-#include "JSParser.h"
+#include "JSGlobalData.h"
 #include "Lexer.h"
 #include "Lexer.h"
+#include "NodeInfo.h"
+#include "SourceProvider.h"
+#include <utility>
+#include <wtf/HashFunctions.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/WTFThreadData.h>
+
+using namespace std;
 
 namespace JSC {
 
 
 namespace JSC {
 
-void Parser::parse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg)
+template <typename LexerType>
+Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode)
+    : m_globalData(globalData)
+    , m_source(&source)
+    , m_stack(wtfThreadData().stack())
+    , m_error(false)
+    , m_errorMessage("Parse error")
+    , m_allowsIn(true)
+    , m_lastLine(0)
+    , m_lastTokenEnd(0)
+    , m_assignmentCount(0)
+    , m_nonLHSCount(0)
+    , m_syntaxAlreadyValidated(source.provider()->isValid())
+    , m_statementDepth(0)
+    , m_nonTrivialExpressionCount(0)
+    , m_lastIdentifier(0)
+    , m_sourceElements(0)
 {
 {
-    ASSERT(globalData);
-    m_sourceElements = 0;
+    m_lexer = adoptPtr(new LexerType(globalData));
+    m_arena = m_globalData->parserArena.get();
+    m_lexer->setCode(source, m_arena);
 
 
-    int defaultErrLine;
-    UString defaultErrMsg;
+    m_functionCache = source.provider()->cache();
+    ScopeRef scope = pushScope();
+    if (parserMode == JSParseFunctionCode)
+        scope->setIsFunction();
+    if (strictness == JSParseStrict)
+        scope->setStrictMode();
+    if (parameters) {
+        for (unsigned i = 0; i < parameters->size(); i++)
+            scope->declareParameter(&parameters->at(i));
+    }
+    next();
+    m_lexer->setLastLineNumber(tokenLine());
+}
 
 
-    if (!errLine)
-        errLine = &defaultErrLine;
-    if (!errMsg)
-        errMsg = &defaultErrMsg;
+template <typename LexerType>
+Parser<LexerType>::~Parser()
+{
+}
 
 
-    *errLine = -1;
-    *errMsg = UString();
+template <typename LexerType>
+UString Parser<LexerType>::parseInner()
+{
+    UString parseError = UString();
+    
+    unsigned oldFunctionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0;
+    ASTBuilder context(const_cast<JSGlobalData*>(m_globalData), const_cast<SourceCode*>(m_source));
+    if (m_lexer->isReparsing())
+        m_statementDepth--;
+    ScopeRef scope = currentScope();
+    SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context);
+    if (!sourceElements || !consume(EOFTOK))
+        parseError = m_errorMessage;
 
 
-    Lexer& lexer = *globalData->lexer;
-    lexer.setCode(*m_source, m_arena);
+    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);
 
 
-    const char* parseError = jsParse(globalData, parameters, strictness, mode, m_source);
-    int lineNumber = lexer.lineNumber();
-    bool lexError = lexer.sawError();
-    lexer.clear();
+    didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
+                     m_lastLine, context.numConstants(), capturedVariables);
 
 
-    if (parseError || lexError) {
-        *errLine = lineNumber;
-        *errMsg = parseError ? parseError : "Parse error";
-        m_sourceElements = 0;
-    }
+    return parseError;
 }
 
 }
 
-void Parser::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, 
+template <typename LexerType>
+void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, 
                               ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants, IdentifierSet& capturedVars)
 {
     m_sourceElements = sourceElements;
                               ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants, IdentifierSet& capturedVars)
 {
     m_sourceElements = sourceElements;
@@ -72,4 +124,1569 @@ void Parser::didFinishParsing(SourceElements* sourceElements, ParserArenaData<De
     m_numConstants = numConstants;
 }
 
     m_numConstants = numConstants;
 }
 
+template <typename LexerType>
+bool Parser<LexerType>::allowAutomaticSemicolon()
+{
+    return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
+}
+
+template <typename LexerType>
+template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context)
+{
+    const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
+    TreeSourceElements sourceElements = context.createSourceElements();
+    bool seenNonDirective = false;
+    const Identifier* directive = 0;
+    unsigned directiveLiteralLength = 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, &directiveLiteralLength)) {
+        if (mode == CheckForStrictMode && !seenNonDirective) {
+            if (directive) {
+                // "use strict" must be the exact literal without escape sequences or line continuation.
+                if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && 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 <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::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(m_lexer->lastLineNumber(), varDecls, start, end);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclaration(TreeBuilder& context)
+{
+    ASSERT(match(CONSTTOKEN));
+    int start = tokenLine();
+    int end = 0;
+    TreeConstDeclList constDecls = parseConstDeclarationList(context);
+    failIfTrue(m_error);
+    failIfFalse(autoSemiColon());
+    
+    return context.createConstStatement(m_lexer->lastLineNumber(), constDecls, start, end);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::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(m_lexer->lastLineNumber(), statement, expr, startLine, endLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::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(m_lexer->lastLineNumber(), expr, statement, startLine, endLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::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);
+        failIfFalseIfStrictWithNameAndMessage(declareVariable(name), "Cannot declare a variable named", name->impl(), "in strict mode.");
+        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(m_lexer->lastLineNumber(), *name, initializer, initialAssignments != m_assignmentCount, varStart, varDivot, lastTokenEnd());
+            if (!varDecls)
+                varDecls = node;
+            else
+                varDecls = context.combineCommaNodes(m_lexer->lastLineNumber(), varDecls, node);
+        }
+    } while (match(COMMA));
+    return varDecls;
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::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(m_lexer->lastLineNumber(), tail, name, initializer);
+        if (!constDecls)
+            constDecls = tail;
+    } while (match(COMMA));
+    return constDecls;
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::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();
+        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(m_lexer->lastLineNumber(), 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(m_lexer->lastLineNumber(), 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(m_lexer->lastLineNumber(), decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
+{
+    ASSERT(match(BREAK));
+    int startCol = tokenStart();
+    int endCol = tokenEnd();
+    int startLine = tokenLine();
+    int endLine = tokenLine();
+    next();
+    
+    if (autoSemiColon()) {
+        failIfFalseWithMessage(breakIsValid(), "'break' is only valid inside a switch or loop statement");
+        return context.createBreakStatement(m_lexer->lastLineNumber(), startCol, endCol, startLine, endLine);
+    }
+    matchOrFail(IDENT);
+    const Identifier* ident = m_token.m_data.ident;
+    failIfFalseWithNameAndMessage(getLabel(ident), "Label", ident->impl(), "is not defined");
+    endCol = tokenEnd();
+    endLine = tokenLine();
+    next();
+    failIfFalse(autoSemiColon());
+    return context.createBreakStatement(m_lexer->lastLineNumber(), ident, startCol, endCol, startLine, endLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
+{
+    ASSERT(match(CONTINUE));
+    int startCol = tokenStart();
+    int endCol = tokenEnd();
+    int startLine = tokenLine();
+    int endLine = tokenLine();
+    next();
+    
+    if (autoSemiColon()) {
+        failIfFalseWithMessage(continueIsValid(), "'continue' is only valid inside a loop statement");
+        return context.createContinueStatement(m_lexer->lastLineNumber(), startCol, endCol, startLine, endLine);
+    }
+    matchOrFail(IDENT);
+    const Identifier* ident = m_token.m_data.ident;
+    ScopeLabelInfo* label = getLabel(ident);
+    failIfFalseWithNameAndMessage(label, "Label", ident->impl(), "is not defined");
+    failIfFalseWithMessage(label->m_isLoop, "'continue' is only valid inside a loop statement");
+    endCol = tokenEnd();
+    endLine = tokenLine();
+    next();
+    failIfFalse(autoSemiColon());
+    return context.createContinueStatement(m_lexer->lastLineNumber(), ident, startCol, endCol, startLine, endLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::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(m_lexer->lastLineNumber(), 0, start, end, startLine, endLine);
+    TreeExpression expr = parseExpression(context);
+    failIfFalse(expr);
+    end = lastTokenEnd();
+    if (match(SEMICOLON))
+        endLine  = tokenLine();
+    failIfFalse(autoSemiColon());
+    return context.createReturnStatement(m_lexer->lastLineNumber(), expr, start, end, startLine, endLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::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(m_lexer->lastLineNumber(), expr, eStart, eEnd, startLine, endLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
+{
+    ASSERT(match(WITH));
+    failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode");
+    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(m_lexer->lastLineNumber(), expr, statement, start, end, startLine, endLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::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(m_lexer->lastLineNumber(), expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
+    
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeClauseList Parser<LexerType>::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 <typename LexerType>
+template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
+{
+    if (!match(DEFAULT))
+        return 0;
+    next();
+    consumeOrFail(COLON);
+    TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
+    failIfFalse(statements);
+    return context.createClause(0, statements);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
+{
+    ASSERT(match(TRY));
+    TreeStatement tryBlock = 0;
+    const Identifier* ident = &m_globalData->propertyNames->nullIdentifier;
+    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());
+        failIfFalseIfStrictWithNameAndMessage(declareVariable(ident), "Cannot declare a variable named", ident->impl(), "in strict mode");
+        catchScope->preventNewDecls();
+        consumeOrFail(CLOSEPAREN);
+        matchOrFail(OPENBRACE);
+        catchBlock = parseBlockStatement(context);
+        failIfFalseWithMessage(catchBlock, "'try' must have a catch or finally block");
+        failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo));
+    }
+    
+    if (match(FINALLY)) {
+        next();
+        matchOrFail(OPENBRACE);
+        finallyBlock = parseBlockStatement(context);
+        failIfFalse(finallyBlock);
+    }
+    failIfFalse(catchBlock || finallyBlock);
+    return context.createTryStatement(m_lexer->lastLineNumber(), tryBlock, ident, catchBlock, finallyBlock, firstLine, lastLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
+{
+    ASSERT(match(DEBUGGER));
+    int startLine = tokenLine();
+    int endLine = startLine;
+    next();
+    if (match(SEMICOLON))
+        startLine = tokenLine();
+    failIfFalse(autoSemiColon());
+    return context.createDebugger(m_lexer->lastLineNumber(), startLine, endLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
+{
+    ASSERT(match(OPENBRACE));
+    int start = tokenLine();
+    next();
+    if (match(CLOSEBRACE)) {
+        next();
+        return context.createBlockStatement(m_lexer->lastLineNumber(), 0, start, m_lastLine);
+    }
+    TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context);
+    failIfFalse(subtree);
+    matchOrFail(CLOSEBRACE);
+    next();
+    return context.createBlockStatement(m_lexer->lastLineNumber(), subtree, start, m_lastLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
+{
+    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:
+        failIfFalseIfStrictWithMessage(m_statementDepth == 1, "Functions cannot be declared in a nested block in strict mode");
+        return parseFunctionDeclaration(context);
+    case SEMICOLON:
+        next();
+        return context.createEmptyStatement(m_lexer->lastLineNumber());
+    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;
+        if (directiveLiteralLength)
+            *directiveLiteralLength = m_token.m_info.endOffset - m_token.m_info.startOffset;
+        nonTrivialExpressionCount = m_nonTrivialExpressionCount;
+    default:
+        TreeStatement exprStatement = parseExpressionStatement(context);
+        if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
+            directive = 0;
+        return exprStatement;
+    }
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFormalParameters(TreeBuilder& context)
+{
+    matchOrFail(IDENT);
+    failIfFalseIfStrictWithNameAndMessage(declareParameter(m_token.m_data.ident), "Cannot declare a parameter named", m_token.m_data.ident->impl(), " in strict mode");
+    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;
+        failIfFalseIfStrictWithNameAndMessage(declareParameter(ident), "Cannot declare a parameter named", ident->impl(), "in strict mode");
+        next();
+        tail = context.createFormalParameterList(tail, *ident);
+    }
+    return list;
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context)
+{
+    if (match(CLOSEBRACE))
+        return context.createFunctionBody(m_lexer->lastLineNumber(), strictMode());
+    DepthManager statementDepth(&m_statementDepth);
+    m_statementDepth = 0;
+    typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<JSGlobalData*>(m_globalData), m_lexer.get());
+    failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder));
+    return context.createFunctionBody(m_lexer->lastLineNumber(), strictMode());
+}
+
+template <typename LexerType>
+template <FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool Parser<LexerType>::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;
+        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 we know about this function already, we can use the cached info and skip the parser to the end of the function.
+    if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBracePos) : 0) {
+        // If we're in a strict context, the cached function info must say it was strict too.
+        ASSERT(!strictMode() || cachedInfo->strictMode);
+        body = context.createFunctionBody(m_lexer->lastLineNumber(), cachedInfo->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) {
+        failIfTrueWithNameAndMessage(m_globalData->propertyNames->arguments == *name, "Function name", name->impl(), "is not valid in strict mode");
+        failIfTrueWithNameAndMessage(m_globalData->propertyNames->eval == *name, "Function name", name->impl(), "is not valid in strict mode");
+    }
+    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 <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::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(m_lexer->lastLineNumber(), 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 <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::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(m_lexer->lastLineNumber(), 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(m_lexer->lastLineNumber(), info.m_ident, statement, info.m_start, info.m_end);
+    }
+    return statement;
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
+{
+    int startLine = tokenLine();
+    TreeExpression expression = parseExpression(context);
+    failIfFalse(expression);
+    failIfFalse(autoSemiColon());
+    return context.createExprStatement(m_lexer->lastLineNumber(), expression, startLine, m_lastLine);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::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(m_lexer->lastLineNumber(), 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(m_lexer->lastLineNumber(), 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(m_lexer->lastLineNumber(), condition, trueBlock, falseBlock, pos.first, pos.second));
+    }
+    
+    return context.createIfStatement(m_lexer->lastLineNumber(), condition, trueBlock, statementStack.last(), start, end);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::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(m_lexer->lastLineNumber(), node, right);
+    while (match(COMMA)) {
+        next(TreeBuilder::DontBuildStrings);
+        right = parseAssignmentExpression(context);
+        failIfFalse(right);
+        context.appendToComma(commaNode, right);
+    }
+    return commaNode;
+}
+
+template <typename LexerType>
+template <typename TreeBuilder> TreeExpression Parser<LexerType>::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)) {
+            failIfTrueIfStrictWithMessage(m_globalData->propertyNames->eval == *m_lastIdentifier, "'eval' cannot be modified in strict mode");
+            failIfTrueIfStrictWithMessage(m_globalData->propertyNames->arguments == *m_lastIdentifier, "'arguments' cannot be modified in strict mode");
+            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(m_lexer->lastLineNumber(), assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEnd());
+    
+    return lhs;
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::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(m_lexer->lastLineNumber(), cond, lhs, rhs);
+}
+
+ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
+{
+    return token & UnaryOpTokenFlag;
+}
+
+template <typename LexerType>
+int Parser<LexerType>::isBinaryOperator(JSTokenType token)
+{
+    if (m_allowsIn)
+        return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
+    return token & BinaryOpTokenPrecedenceMask;
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::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(m_lexer->lastLineNumber(), 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(m_lexer->lastLineNumber(), operandStackDepth, operatorStackDepth, lhs, rhs);
+        context.operatorStackPop(operatorStackDepth);
+    }
+    return context.popOperandStack(operandStackDepth);
+}
+
+template <typename LexerType>
+template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::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(LexerFlagsIgnoreReservedWords);
+        else
+            nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
+        
+        if (match(COLON)) {
+            next();
+            TreeExpression node = parseAssignmentExpression(context);
+            failIfFalse(node);
+            return context.template createProperty<complete>(ident, node, PropertyNode::Constant);
+        }
+        failIfFalse(wasIdent);
+        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();
+        const Identifier* stringPropertyName = 0;
+        double numericPropertyName = 0;
+        if (m_token.m_type == IDENT || m_token.m_type == STRING)
+            stringPropertyName = m_token.m_data.ident;
+        else if (m_token.m_type == NUMBER)
+            numericPropertyName = m_token.m_data.doubleValue;
+        else
+            fail();
+        next();
+        failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
+        if (stringPropertyName)
+            return context.template createGetterOrSetterProperty<complete>(m_lexer->lastLineNumber(), type, stringPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
+        return context.template createGetterOrSetterProperty<complete>(const_cast<JSGlobalData*>(m_globalData), m_lexer->lastLineNumber(), type, numericPropertyName, 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>(const_cast<JSGlobalData*>(m_globalData), propertyName, node, PropertyNode::Constant);
+    }
+    default:
+        failIfFalse(m_token.m_type & KeywordTokenFlag);
+        goto namedProperty;
+    }
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
+{
+    int startOffset = m_token.m_data.intValue;
+    unsigned oldLastLineNumber = m_lexer->lastLineNumber();
+    unsigned oldLineNumber = m_lexer->lineNumber();
+    consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings);
+    
+    int oldNonLHSCount = m_nonLHSCount;
+    
+    if (match(CLOSEBRACE)) {
+        next();
+        return context.createObjectLiteral(m_lexer->lastLineNumber());
+    }
+    
+    TreeProperty property = parseProperty<false>(context);
+    failIfFalse(property);
+    if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
+        m_lexer->setOffset(startOffset);
+        next();
+        m_lexer->setLastLineNumber(oldLastLineNumber);
+        m_lexer->setLineNumber(oldLineNumber);
+        return parseStrictObjectLiteral(context);
+    }
+    TreePropertyList propertyList = context.createPropertyList(m_lexer->lastLineNumber(), 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();
+            m_lexer->setLastLineNumber(oldLastLineNumber);
+            m_lexer->setLineNumber(oldLineNumber);
+            return parseStrictObjectLiteral(context);
+        }
+        tail = context.createPropertyList(m_lexer->lastLineNumber(), property, tail);
+    }
+    
+    consumeOrFail(CLOSEBRACE);
+    
+    m_nonLHSCount = oldNonLHSCount;
+    
+    return context.createObjectLiteral(m_lexer->lastLineNumber(), propertyList);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
+{
+    consumeOrFail(OPENBRACE);
+    
+    int oldNonLHSCount = m_nonLHSCount;
+
+    if (match(CLOSEBRACE)) {
+        next();
+        return context.createObjectLiteral(m_lexer->lastLineNumber());
+    }
+    
+    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(m_lexer->lastLineNumber(), 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) {
+            ObjectValidationMap::AddResult propertyEntry = objectValidator.add(context.getName(property).impl(), context.getType(property));
+            if (!propertyEntry.isNewEntry) {
+                failIfTrue(propertyEntry.iterator->second == PropertyNode::Constant);
+                failIfTrue(context.getType(property) == PropertyNode::Constant);
+                failIfTrue(context.getType(property) & propertyEntry.iterator->second);
+                propertyEntry.iterator->second |= context.getType(property);
+            }
+        }
+        tail = context.createPropertyList(m_lexer->lastLineNumber(), property, tail);
+    }
+    
+    consumeOrFail(CLOSEBRACE);
+
+    m_nonLHSCount = oldNonLHSCount;
+
+    return context.createObjectLiteral(m_lexer->lastLineNumber(), propertyList);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
+{
+    consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings);
+    
+    int oldNonLHSCount = m_nonLHSCount;
+    
+    int elisions = 0;
+    while (match(COMMA)) {
+        next(TreeBuilder::DontBuildStrings);
+        elisions++;
+    }
+    if (match(CLOSEBRACKET)) {
+        next(TreeBuilder::DontBuildStrings);
+        return context.createArray(m_lexer->lastLineNumber(), 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(m_lexer->lastLineNumber(), elisions, elementList);
+        }
+        TreeExpression elem = parseAssignmentExpression(context);
+        failIfFalse(elem);
+        tail = context.createElementList(tail, elisions, elem);
+    }
+    
+    consumeOrFail(CLOSEBRACKET);
+    
+    m_nonLHSCount = oldNonLHSCount;
+    
+    return context.createArray(m_lexer->lastLineNumber(), elementList);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
+{
+    failIfStackOverflow();
+    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(m_lexer->lastLineNumber());
+    }
+    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(m_lexer->lastLineNumber(), ident, start);
+    }
+    case STRING: {
+        const Identifier* ident = m_token.m_data.ident;
+        next();
+        return context.createString(m_lexer->lastLineNumber(), ident);
+    }
+    case NUMBER: {
+        double d = m_token.m_data.doubleValue;
+        next();
+        return context.createNumberExpr(m_lexer->lastLineNumber(), d);
+    }
+    case NULLTOKEN: {
+        next();
+        return context.createNull(m_lexer->lastLineNumber());
+    }
+    case TRUETOKEN: {
+        next();
+        return context.createBoolean(m_lexer->lastLineNumber(), true);
+    }
+    case FALSETOKEN: {
+        next();
+        return context.createBoolean(m_lexer->lastLineNumber(), 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(m_lexer->lastLineNumber(), *pattern, *flags, start);
+        if (!re) {
+            const char* yarrErrorMsg = Yarr::checkSyntax(pattern->ustring());
+            ASSERT(!m_errorMessage.isNull());
+            failWithMessage(yarrErrorMsg);
+        }
+        return re;
+    }
+    default:
+        fail();
+    }
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeArguments Parser<LexerType>::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(m_lexer->lastLineNumber(), firstArg);
+    TreeArgumentsList tail = argList;
+    while (match(COMMA)) {
+        next(TreeBuilder::DontBuildStrings);
+        TreeExpression arg = parseAssignmentExpression(context);
+        failIfFalse(arg);
+        tail = context.createArgumentsList(m_lexer->lastLineNumber(), tail, arg);
+    }
+    consumeOrFail(CLOSEPAREN);
+    return context.createArguments(argList);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::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(m_lexer->lastLineNumber(), 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(m_lexer->lastLineNumber(), base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd());
+            consumeOrFail(CLOSEBRACKET);
+            m_nonLHSCount = nonLHSCount;
+            break;
+        }
+        case OPENPAREN: {
+            m_nonTrivialExpressionCount++;
+            int nonLHSCount = m_nonLHSCount;
+            if (newCount) {
+                newCount--;
+                int exprEnd = lastTokenEnd();
+                TreeArguments arguments = parseArguments(context);
+                failIfFalse(arguments);
+                base = context.createNewExpr(m_lexer->lastLineNumber(), base, arguments, start, exprEnd, lastTokenEnd());           
+            } else {
+                int expressionEnd = lastTokenEnd();
+                TreeArguments arguments = parseArguments(context);
+                failIfFalse(arguments);
+                base = context.makeFunctionCallNode(m_lexer->lastLineNumber(), base, arguments, expressionStart, expressionEnd, lastTokenEnd());
+            }
+            m_nonLHSCount = nonLHSCount;
+            break;
+        }
+        case DOT: {
+            m_nonTrivialExpressionCount++;
+            int expressionEnd = lastTokenEnd();
+            nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
+            matchOrFail(IDENT);
+            base = context.createDotAccess(m_lexer->lastLineNumber(), base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd());
+            next();
+            break;
+        }
+        default:
+            goto endMemberExpression;
+        }
+    }
+endMemberExpression:
+    while (newCount--)
+        base = context.createNewExpr(m_lexer->lastLineNumber(), base, start, lastTokenEnd());
+    return base;
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeExpression Parser<LexerType>::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;
+    }
+    failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments && modifiesExpr, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
+    switch (m_token.m_type) {
+    case PLUSPLUS:
+        m_nonTrivialExpressionCount++;
+        m_nonLHSCount++;
+        expr = context.makePostfixNode(m_lexer->lastLineNumber(), expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd());
+        m_assignmentCount++;
+        failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
+        failIfTrueIfStrict(requiresLExpr);
+        next();
+        break;
+    case MINUSMINUS:
+        m_nonTrivialExpressionCount++;
+        m_nonLHSCount++;
+        expr = context.makePostfixNode(m_lexer->lastLineNumber(), expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd());
+        m_assignmentCount++;
+        failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode");
+        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(m_lexer->lastLineNumber(), expr);
+            break;
+        case TILDE:
+            expr = context.makeBitwiseNotNode(m_lexer->lastLineNumber(), expr);
+            break;
+        case MINUS:
+            expr = context.makeNegateNode(m_lexer->lastLineNumber(), expr);
+            break;
+        case PLUS:
+            expr = context.createUnaryPlus(m_lexer->lastLineNumber(), expr);
+            break;
+        case PLUSPLUS:
+        case AUTOPLUSPLUS:
+            expr = context.makePrefixNode(m_lexer->lastLineNumber(), expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
+            m_assignmentCount++;
+            break;
+        case MINUSMINUS:
+        case AUTOMINUSMINUS:
+            expr = context.makePrefixNode(m_lexer->lastLineNumber(), expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
+            m_assignmentCount++;
+            break;
+        case TYPEOF:
+            expr = context.makeTypeOfNode(m_lexer->lastLineNumber(), expr);
+            break;
+        case VOIDTOKEN:
+            expr = context.createVoid(m_lexer->lastLineNumber(), expr);
+            break;
+        case DELETETOKEN:
+            failIfTrueIfStrictWithNameAndMessage(context.isResolve(expr), "Cannot delete unqualified property", m_lastIdentifier->impl(), "in strict mode");
+            expr = context.makeDeleteNode(m_lexer->lastLineNumber(), 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;
+}
+
+// Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
+template class Parser< Lexer<LChar> >;
+template class Parser< Lexer<UChar> >;
+
 } // namespace JSC
 } // namespace JSC
index 58398d1d3335f164b5225c0cce7c59dffe6e1982..c2a11d665b7913ec5f6431c0636c1a8a6dd6a016 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, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 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
 #include "Lexer.h"
 #include "Nodes.h"
 #include "ParserArena.h"
 #include "Lexer.h"
 #include "Nodes.h"
 #include "ParserArena.h"
+#include "ParserTokens.h"
 #include "SourceProvider.h"
 #include "SourceProvider.h"
+#include "SourceProviderCacheItem.h"
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/RefPtr.h>
+namespace JSC {
+struct Scope;
+}
+
+namespace WTF {
+template <> struct VectorTraits<JSC::Scope> : SimpleClassVectorTraits {
+    static const bool canInitializeWithMemset = false; // Not all Scope data members initialize to 0.
+};
+}
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class FunctionBodyNode;
-    
-    class ProgramNode;
-    class UString;
+class ExecState;
+class FunctionBodyNode;
+class FunctionParameters;
+class Identifier;
+class JSGlobalData;
+class ProgramNode;
+class SourceCode;
+class UString;
+
+#define fail() do { if (!m_error) updateErrorMessage(); return 0; } while (0)
+#define failWithToken(tok) do { if (!m_error) updateErrorMessage(tok); return 0; } while (0)
+#define failWithMessage(msg) do { if (!m_error) updateErrorMessage(msg); return 0; } while (0)
+#define failWithNameAndMessage(before, name, after) do { if (!m_error) updateErrorWithNameAndMessage(before, name, after); return 0; } while (0)
+#define failIfFalse(cond) do { if (!(cond)) fail(); } while (0)
+#define failIfFalseWithMessage(cond, msg) do { if (!(cond)) failWithMessage(msg); } while (0)
+#define failIfFalseWithNameAndMessage(cond, before, name, msg) do { if (!(cond)) failWithNameAndMessage(before, name, msg); } while (0)
+#define failIfTrue(cond) do { if ((cond)) fail(); } while (0)
+#define failIfTrueWithMessage(cond, msg) do { if ((cond)) failWithMessage(msg); } while (0)
+#define failIfTrueWithNameAndMessage(cond, before, name, msg) do { if ((cond)) failWithNameAndMessage(before, name, msg); } while (0)
+#define failIfTrueIfStrict(cond) do { if ((cond) && strictMode()) fail(); } while (0)
+#define failIfTrueIfStrictWithMessage(cond, msg) do { if ((cond) && strictMode()) failWithMessage(msg); } while (0)
+#define failIfTrueIfStrictWithNameAndMessage(cond, before, name, after) do { if ((cond) && strictMode()) failWithNameAndMessage(before, name, after); } while (0)
+#define failIfFalseIfStrict(cond) do { if ((!(cond)) && strictMode()) fail(); } while (0)
+#define failIfFalseIfStrictWithMessage(cond, msg) do { if ((!(cond)) && strictMode()) failWithMessage(msg); } while (0)
+#define failIfFalseIfStrictWithNameAndMessage(cond, before, name, after) do { if ((!(cond)) && strictMode()) failWithNameAndMessage(before, name, after); } while (0)
+#define consumeOrFail(tokenType) do { if (!consume(tokenType)) failWithToken(tokenType); } while (0)
+#define consumeOrFailWithFlags(tokenType, flags) do { if (!consume(tokenType, flags)) failWithToken(tokenType); } while (0)
+#define matchOrFail(tokenType) do { if (!match(tokenType)) failWithToken(tokenType); } while (0)
+#define failIfStackOverflow() do { failIfFalseWithMessage(canRecurse(), "Code nested too deeply."); } 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);
+
+enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
+enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
+
+template <typename T> inline bool isEvalNode() { return false; }
+template <> inline bool isEvalNode<EvalNode>() { return true; }
+
+struct DepthManager {
+    DepthManager(int* depth)
+        : m_originalDepth(*depth)
+        , m_depth(depth)
+    {
+    }
+
+    ~DepthManager()
+    {
+        *m_depth = m_originalDepth;
+    }
+
+private:
+    int m_originalDepth;
+    int* m_depth;
+};
+
+struct ScopeLabelInfo {
+    ScopeLabelInfo(StringImpl* ident, bool isLoop)
+        : m_ident(ident)
+        , m_isLoop(isLoop)
+    {
+    }
+
+    StringImpl* m_ident;
+    bool m_isLoop;
+};
+
+struct Scope {
+    Scope(const 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()).isNewEntry && 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());
+    }
 
 
-    template <typename T> struct ParserArenaData : ParserArenaDeletable { T data; };
+    void setNeedsFullActivation() { m_needsFullActivation = true; }
 
 
-    class Parser {
-        WTF_MAKE_NONCOPYABLE(Parser); WTF_MAKE_FAST_ALLOCATED;
-    public:
-        Parser() { }
-        template <class ParsedNode>
-        PassRefPtr<ParsedNode> parse(JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, const SourceCode& source, FunctionParameters*, JSParserStrictness strictness, JSObject** exception);
+    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;
+        info->strictMode = m_strictMode;
+        info->needsFullActivation = m_needsFullActivation;
+        copyCapturedVariablesToVector(m_writtenVariables, info->writtenVariables);
+        copyCapturedVariablesToVector(m_usedVariables, info->usedVariables);
+    }
+
+    void restoreFunctionInfo(const SourceProviderCacheItem* info)
+    {
+        ASSERT(m_isFunction);
+        m_usesEval = info->usesEval;
+        m_strictMode = info->strictMode;
+        m_needsFullActivation = info->needsFullActivation;
+        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:
+    const 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;
 
 
-        void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, 
-                              ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features,
-                              int lastLine, int numConstants, IdentifierSet&);
+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;
+};
 
 
-        ParserArena& arena() { return m_arena; }
+template <typename LexerType>
+class Parser {
+    WTF_MAKE_NONCOPYABLE(Parser);
+    WTF_MAKE_FAST_ALLOCATED;
 
 
+public:
+    Parser(JSGlobalData*, const SourceCode&, FunctionParameters*, JSParserStrictness, JSParserMode);
+    ~Parser();
+
+    template <class ParsedNode>
+    PassRefPtr<ParsedNode> parse(JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, JSObject**);
+
+private:
+    struct AllowInOverride {
+        AllowInOverride(Parser* parser)
+            : m_parser(parser)
+            , m_oldAllowsIn(parser->m_allowsIn)
+        {
+            parser->m_allowsIn = true;
+        }
+        ~AllowInOverride()
+        {
+            m_parser->m_allowsIn = m_oldAllowsIn;
+        }
+        Parser* m_parser;
+        bool m_oldAllowsIn;
+    };
+
+    struct AutoPopScopeRef : public ScopeRef {
+        AutoPopScopeRef(Parser* parser, ScopeRef scope)
+        : ScopeRef(scope)
+        , m_parser(parser)
+        {
+        }
+        
+        ~AutoPopScopeRef()
+        {
+            if (m_parser)
+                m_parser->popScope(*this, false);
+        }
+        
+        void setPopped()
+        {
+            m_parser = 0;
+        }
+        
     private:
     private:
-        void parse(JSGlobalData*, FunctionParameters*, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg);
-
-        // Used to determine type of error to report.
-        bool isFunctionBodyNode(ScopeNode*) { return false; }
-        bool isFunctionBodyNode(FunctionBodyNode*) { return true; }
-
-        ParserArena m_arena;
-        const SourceCode* m_source;
-        SourceElements* m_sourceElements;
-        ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
-        ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
-        IdentifierSet m_capturedVariables;
-        CodeFeatures m_features;
-        int m_lastLine;
-        int m_numConstants;
+        Parser* m_parser;
     };
 
     };
 
-    template <class ParsedNode>
-    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)
-            lexicalGlobalObject->globalData().lexer->setIsReparsing();
-        parse(&lexicalGlobalObject->globalData(), parameters, strictness, ParsedNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, &errLine, &errMsg);
-
-        RefPtr<ParsedNode> result;
-        if (m_sourceElements) {
-            result = ParsedNode::create(&lexicalGlobalObject->globalData(),
-                m_sourceElements,
-                m_varDeclarations ? &m_varDeclarations->data : 0,
-                m_funcDeclarations ? &m_funcDeclarations->data : 0,
-                m_capturedVariables,
-                source,
-                m_features,
-                m_numConstants);
-            result->setLoc(m_source->firstLine(), m_lastLine);
-        } else if (lexicalGlobalObject) {
-            // We can never see a syntax error when reparsing a function, since we should have
-            // reported the error when parsing the containing program or eval code. So if we're
-            // parsing a function body node, we assume that what actually happened here is that
-            // we ran out of stack while parsing. If we see an error while parsing eval or program
-            // code we assume that it was a syntax error since running out of stack is much less
-            // likely, and we are currently unable to distinguish between the two cases.
-            if (isFunctionBodyNode(static_cast<ParsedNode*>(0)))
-                *exception = createStackOverflowError(lexicalGlobalObject);
+    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;
+    }
+
+    Parser();
+    UString parseInner();
+
+    void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, 
+                          ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures,
+                          int, int, IdentifierSet&);
+
+    // Used to determine type of error to report.
+    bool isFunctionBodyNode(ScopeNode*) { return false; }
+    bool isFunctionBodyNode(FunctionBodyNode*) { return true; }
+
+
+    ALWAYS_INLINE void next(unsigned lexerFlags = 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, lexerFlags, strictMode());
+    }
+
+    ALWAYS_INLINE void nextExpectIdentifier(unsigned lexerFlags = 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, lexerFlags, 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;
+        if (result)
+            next(flags);
+        return result;
+    }
+    
+    ALWAYS_INLINE UString getToken() {
+        SourceProvider* sourceProvider = m_source->provider();
+        return UString(sourceProvider->getRange(tokenStart(), tokenEnd()).impl());
+    }
+    
+    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;
+    }
+    
+    const char* getTokenName(JSTokenType tok) 
+    {
+        switch (tok) {
+        case NULLTOKEN: 
+            return "null";
+        case TRUETOKEN:
+            return "true";
+        case FALSETOKEN: 
+            return "false";
+        case BREAK: 
+            return "break";
+        case CASE: 
+            return "case";
+        case DEFAULT: 
+            return "default";
+        case FOR: 
+            return "for";
+        case NEW: 
+            return "new";
+        case VAR: 
+            return "var";
+        case CONSTTOKEN: 
+            return "const";
+        case CONTINUE: 
+            return "continue";
+        case FUNCTION: 
+            return "function";
+        case IF: 
+            return "if";
+        case THISTOKEN: 
+            return "this";
+        case DO: 
+            return "do";
+        case WHILE: 
+            return "while";
+        case SWITCH: 
+            return "switch";
+        case WITH: 
+            return "with";
+        case THROW: 
+            return "throw";
+        case TRY: 
+            return "try";
+        case CATCH: 
+            return "catch";
+        case FINALLY: 
+            return "finally";
+        case DEBUGGER: 
+            return "debugger";
+        case ELSE: 
+            return "else";
+        case OPENBRACE: 
+            return "{";
+        case CLOSEBRACE: 
+            return "}";
+        case OPENPAREN: 
+            return "(";
+        case CLOSEPAREN: 
+            return ")";
+        case OPENBRACKET: 
+            return "[";
+        case CLOSEBRACKET: 
+            return "]";
+        case COMMA: 
+            return ",";
+        case QUESTION: 
+            return "?";
+        case SEMICOLON: 
+            return ";";
+        case COLON: 
+            return ":";
+        case DOT: 
+            return ".";
+        case EQUAL: 
+            return "=";
+        case PLUSEQUAL: 
+            return "+=";
+        case MINUSEQUAL: 
+            return "-=";
+        case MULTEQUAL: 
+            return "*=";
+        case DIVEQUAL: 
+            return "/=";
+        case LSHIFTEQUAL: 
+            return "<<=";
+        case RSHIFTEQUAL: 
+            return ">>=";
+        case URSHIFTEQUAL: 
+            return ">>>=";
+        case ANDEQUAL: 
+            return "&=";
+        case MODEQUAL: 
+            return "%=";
+        case XOREQUAL: 
+            return "^=";
+        case OREQUAL: 
+            return "|=";
+        case AUTOPLUSPLUS: 
+        case PLUSPLUS: 
+            return "++";
+        case AUTOMINUSMINUS: 
+        case MINUSMINUS: 
+            return "--";
+        case EXCLAMATION: 
+            return "!";
+        case TILDE: 
+            return "~";
+        case TYPEOF: 
+            return "typeof";
+        case VOIDTOKEN: 
+            return "void";
+        case DELETETOKEN: 
+            return "delete";
+        case OR: 
+            return "||";
+        case AND: 
+            return "&&";
+        case BITOR: 
+            return "|";
+        case BITXOR: 
+            return "^";
+        case BITAND: 
+            return "&";
+        case EQEQ: 
+            return "==";
+        case NE: 
+            return "!=";
+        case STREQ: 
+            return "===";
+        case STRNEQ: 
+            return "!==";
+        case LT: 
+            return "<";
+        case GT: 
+            return ">";
+        case LE: 
+            return "<=";
+        case GE: 
+            return ">=";
+        case INSTANCEOF: 
+            return "instanceof";
+        case INTOKEN: 
+            return "in";
+        case LSHIFT: 
+            return "<<";
+        case RSHIFT: 
+            return ">>";
+        case URSHIFT: 
+            return ">>>";
+        case PLUS: 
+            return "+";
+        case MINUS: 
+            return "-";
+        case TIMES: 
+            return "*";
+        case DIVIDE: 
+            return "/";
+        case MOD: 
+            return "%";
+        case RETURN: 
+        case RESERVED_IF_STRICT:
+        case RESERVED: 
+        case NUMBER:
+        case IDENT: 
+        case STRING: 
+        case ERRORTOK:
+        case EOFTOK: 
+            return 0;
+        case LastUntaggedToken: 
+            break;
+        }
+        ASSERT_NOT_REACHED();
+        return "internal error";
+    }
+    
+    ALWAYS_INLINE void updateErrorMessageSpecialCase(JSTokenType expectedToken) 
+    {
+        String errorMessage;
+        switch (expectedToken) {
+        case RESERVED_IF_STRICT:
+            errorMessage = "Use of reserved word '";
+            errorMessage += getToken().impl();
+            errorMessage += "' in strict mode";
+            m_errorMessage = errorMessage.impl();
+            return;
+        case RESERVED:
+            errorMessage = "Use of reserved word '";
+            errorMessage += getToken().impl();
+            errorMessage += "'";
+            m_errorMessage = errorMessage.impl();
+            return;
+        case NUMBER: 
+            errorMessage = "Unexpected number '";
+            errorMessage += getToken().impl();
+            errorMessage += "'";
+            m_errorMessage = errorMessage.impl();
+            return;
+        case IDENT: 
+            errorMessage = "Expected an identifier but found '";
+            errorMessage += getToken().impl();
+            errorMessage += "' instead";
+            m_errorMessage = errorMessage.impl();
+            return;
+        case STRING: 
+            errorMessage = "Unexpected string ";
+            errorMessage += getToken().impl();
+            m_errorMessage = errorMessage.impl();
+            return;
+        case ERRORTOK: 
+            errorMessage = "Unrecognized token '";
+            errorMessage += getToken().impl();
+            errorMessage += "'";
+            m_errorMessage = errorMessage.impl();
+            return;
+        case EOFTOK:  
+            m_errorMessage = "Unexpected EOF";
+            return;
+        case RETURN:
+            m_errorMessage = "Return statements are only valid inside functions";
+            return;
+        default:
+            ASSERT_NOT_REACHED();
+            m_errorMessage = "internal error";
+            return;
+        }
+    }
+    
+    NEVER_INLINE void updateErrorMessage() 
+    {
+        m_error = true;
+        const char* name = getTokenName(m_token.m_type);
+        if (!name) 
+            updateErrorMessageSpecialCase(m_token.m_type);
+        else 
+            m_errorMessage = UString(String::format("Unexpected token '%s'", name).impl());
+    }
+    
+    NEVER_INLINE void updateErrorMessage(JSTokenType expectedToken) 
+    {
+        m_error = true;
+        const char* name = getTokenName(expectedToken);
+        if (name)
+            m_errorMessage = UString(String::format("Expected token '%s'", name).impl());
+        else {
+            if (!getTokenName(m_token.m_type))
+                updateErrorMessageSpecialCase(m_token.m_type);
             else
             else
-                *exception = addErrorInfo(&lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, source);
+                updateErrorMessageSpecialCase(expectedToken);
+        } 
+    }
+    
+    NEVER_INLINE void updateErrorWithNameAndMessage(const char* beforeMsg, UString name, const char* afterMsg) 
+    {
+        m_error = true;
+        String prefix(beforeMsg);
+        String postfix(afterMsg);
+        prefix += " '";
+        prefix += name.impl();
+        prefix += "' ";
+        prefix += postfix;
+        m_errorMessage = prefix.impl();
+    }
+    
+    NEVER_INLINE void updateErrorMessage(const char* msg) 
+    {   
+        m_error = true;
+        m_errorMessage = UString(msg);
+    }
+    
+    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;
+    }
+    
+    template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
+    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);
+    template <FunctionRequirements, bool nameIsInContainingScope, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine);
+    ALWAYS_INLINE int isBinaryOperator(JSTokenType);
+    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;
+    }
+
+    mutable const JSGlobalData* m_globalData;
+    const SourceCode* m_source;
+    ParserArena* m_arena;
+    OwnPtr<LexerType> m_lexer;
+    
+    StackBounds m_stack;
+    bool m_error;
+    UString m_errorMessage;
+    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;
+    SourceProviderCache* m_functionCache;
+    SourceElements* m_sourceElements;
+    ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
+    ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
+    IdentifierSet m_capturedVariables;
+    CodeFeatures m_features;
+    int m_numConstants;
+    
+    struct DepthManager {
+        DepthManager(int* depth)
+        : m_originalDepth(*depth)
+        , m_depth(depth)
+        {
+        }
+        
+        ~DepthManager()
+        {
+            *m_depth = m_originalDepth;
+        }
+        
+    private:
+        int m_originalDepth;
+        int* m_depth;
+    };
+};
+
+template <typename LexerType>
+template <class ParsedNode>
+PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObject, Debugger* debugger, ExecState* debuggerExecState, JSObject** exception)
+{
+    ASSERT(lexicalGlobalObject);
+    ASSERT(exception && !*exception);
+    int errLine;
+    UString errMsg;
+
+    if (ParsedNode::scopeIsFunction)
+        m_lexer->setIsReparsing();
+
+    m_sourceElements = 0;
 
 
-        m_arena.reset();
+    errLine = -1;
+    errMsg = UString();
 
 
-        m_source = 0;
+    UString parseError = parseInner();
+
+    int lineNumber = m_lexer->lineNumber();
+    bool lexError = m_lexer->sawError();
+    UString lexErrorMessage = lexError ? m_lexer->getErrorMessage() : UString();
+    ASSERT(lexErrorMessage.isNull() != lexError);
+    m_lexer->clear();
+
+    if (!parseError.isNull() || lexError) {
+        errLine = lineNumber;
+        errMsg = !lexErrorMessage.isNull() ? lexErrorMessage : parseError;
         m_sourceElements = 0;
         m_sourceElements = 0;
-        m_varDeclarations = 0;
-        m_funcDeclarations = 0;
+    }
 
 
-        if (debugger && !ParsedNode::scopeIsFunction)
-            debugger->sourceParsed(debuggerExecState, source.provider(), errLine, errMsg);
-        return result.release();
+    RefPtr<ParsedNode> result;
+    if (m_sourceElements) {
+        result = ParsedNode::create(&lexicalGlobalObject->globalData(),
+                                    m_lexer->lastLineNumber(),
+                                    m_sourceElements,
+                                    m_varDeclarations ? &m_varDeclarations->data : 0,
+                                    m_funcDeclarations ? &m_funcDeclarations->data : 0,
+                                    m_capturedVariables,
+                                    *m_source,
+                                    m_features,
+                                    m_numConstants);
+        result->setLoc(m_source->firstLine(), m_lastLine);
+    } else if (lexicalGlobalObject) {
+        // We can never see a syntax error when reparsing a function, since we should have
+        // reported the error when parsing the containing program or eval code. So if we're
+        // parsing a function body node, we assume that what actually happened here is that
+        // we ran out of stack while parsing. If we see an error while parsing eval or program
+        // code we assume that it was a syntax error since running out of stack is much less
+        // likely, and we are currently unable to distinguish between the two cases.
+        if (isFunctionBodyNode(static_cast<ParsedNode*>(0)))
+            *exception = createStackOverflowError(lexicalGlobalObject);
+        else if (isEvalNode<ParsedNode>())
+            *exception = createSyntaxError(lexicalGlobalObject, errMsg);
+        else
+            *exception = addErrorInfo(lexicalGlobalObject->globalExec(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, *m_source);
     }
 
     }
 
-} // namespace JSC
+    if (debugger && !ParsedNode::scopeIsFunction)
+        debugger->sourceParsed(debuggerExecState, m_source->provider(), errLine, errMsg);
+
+    m_arena->reset();
+
+    return result.release();
+}
+
+template <class ParsedNode>
+PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, Debugger* debugger, ExecState* execState, JSObject** exception)
+{
+    SamplingRegion samplingRegion("Parsing");
+
+    ASSERT(source.provider()->data());
+
+    if (source.provider()->data()->is8Bit()) {
+        Parser< Lexer<LChar> > parser(globalData, source, parameters, strictness, parserMode);
+        return parser.parse<ParsedNode>(lexicalGlobalObject, debugger, execState, exception);
+    }
+    Parser< Lexer<UChar> > parser(globalData, source, parameters, strictness, parserMode);
+    return parser.parse<ParsedNode>(lexicalGlobalObject, debugger, execState, exception);
+}
 
 
-#endif // Parser_h
+} // namespace 
+#endif
index 9c96de7625b00aa89e4036fcd7b8a766826216d5..c53f30753f2f712bf9b751c0684cd6dee5a240a1 100644 (file)
@@ -34,7 +34,6 @@ namespace JSC {
 ParserArena::ParserArena()
     : m_freeableMemory(0)
     , m_freeablePoolEnd(0)
 ParserArena::ParserArena()
     : m_freeableMemory(0)
     , m_freeablePoolEnd(0)
-    , m_identifierArena(adoptPtr(new IdentifierArena))
 {
 }
 
 {
 }
 
@@ -46,19 +45,16 @@ inline void* ParserArena::freeablePool()
 
 inline void ParserArena::deallocateObjects()
 {
 
 inline void ParserArena::deallocateObjects()
 {
+    size_t size = m_deletableObjects.size();
+    for (size_t i = 0; i < size; ++i)
+        m_deletableObjects[i]->~ParserArenaDeletable();
+
     if (m_freeablePoolEnd)
         fastFree(freeablePool());
 
     if (m_freeablePoolEnd)
         fastFree(freeablePool());
 
-    size_t size = m_freeablePools.size();
+    size = m_freeablePools.size();
     for (size_t i = 0; i < size; ++i)
         fastFree(m_freeablePools[i]);
     for (size_t i = 0; i < size; ++i)
         fastFree(m_freeablePools[i]);
-
-    size = m_deletableObjects.size();
-    for (size_t i = 0; i < size; ++i) {
-        ParserArenaDeletable* object = m_deletableObjects[i];
-        object->~ParserArenaDeletable();
-        fastFree(object);
-    }
 }
 
 ParserArena::~ParserArena()
 }
 
 ParserArena::~ParserArena()
@@ -91,7 +87,8 @@ void ParserArena::reset()
 
     m_freeableMemory = 0;
     m_freeablePoolEnd = 0;
 
     m_freeableMemory = 0;
     m_freeablePoolEnd = 0;
-    m_identifierArena->clear();
+    if (m_identifierArena)
+        m_identifierArena->clear();
     m_freeablePools.clear();
     m_deletableObjects.clear();
     m_refCountedObjects.clear();
     m_freeablePools.clear();
     m_deletableObjects.clear();
     m_refCountedObjects.clear();
@@ -111,7 +108,7 @@ void ParserArena::allocateFreeablePool()
 bool ParserArena::isEmpty() const
 {
     return !m_freeablePoolEnd
 bool ParserArena::isEmpty() const
 {
     return !m_freeablePoolEnd
-        && m_identifierArena->isEmpty()
+        && (!m_identifierArena || m_identifierArena->isEmpty())
         && m_freeablePools.isEmpty()
         && m_deletableObjects.isEmpty()
         && m_refCountedObjects.isEmpty();
         && m_freeablePools.isEmpty()
         && m_deletableObjects.isEmpty()
         && m_refCountedObjects.isEmpty();
index 1563e498f416cef00c3cb9fff3b6a52426ba3794..067b83a262f120eaaeada9f1de2ada35779009cc 100644 (file)
@@ -42,37 +42,75 @@ namespace JSC {
             clear();
         }
 
             clear();
         }
 
-        ALWAYS_INLINE const Identifier& makeIdentifier(JSGlobalData*, const UChar* characters, size_t length);
+        template <typename T>
+        ALWAYS_INLINE const Identifier& makeIdentifier(JSGlobalData*, const T* characters, size_t length);
+        ALWAYS_INLINE const Identifier& makeIdentifierLCharFromUChar(JSGlobalData*, const UChar* characters, size_t length);
+
         const Identifier& makeNumericIdentifier(JSGlobalData*, double number);
 
         const Identifier& makeNumericIdentifier(JSGlobalData*, double number);
 
+        bool isEmpty() const { return m_identifiers.isEmpty(); }
+
+    public:
+        static const int MaximumCachableCharacter = 128;
+        typedef SegmentedVector<Identifier, 64> IdentifierVector;
         void clear()
         {
             m_identifiers.clear();
         void clear()
         {
             m_identifiers.clear();
-            for (unsigned  i = 0; i < 128; i++)
+            for (int i = 0; i < MaximumCachableCharacter; i++)
                 m_shortIdentifiers[i] = 0;
                 m_shortIdentifiers[i] = 0;
+            for (int i = 0; i < MaximumCachableCharacter; i++)
+                m_recentIdentifiers[i] = 0;
         }
         }
-        bool isEmpty() const { return m_identifiers.isEmpty(); }
 
     private:
 
     private:
-        static const int MaximumCachableCharacter = 128;
-        typedef SegmentedVector<Identifier, 64> IdentifierVector;
         IdentifierVector m_identifiers;
         FixedArray<Identifier*, MaximumCachableCharacter> m_shortIdentifiers;
         IdentifierVector m_identifiers;
         FixedArray<Identifier*, MaximumCachableCharacter> m_shortIdentifiers;
+        FixedArray<Identifier*, MaximumCachableCharacter> m_recentIdentifiers;
     };
 
     };
 
-    ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(JSGlobalData* globalData, const UChar* characters, size_t length)
+    template <typename T>
+    ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(JSGlobalData* globalData, const T* characters, size_t length)
     {
     {
-        if (length == 1 && characters[0] < MaximumCachableCharacter) {
+        if (characters[0] >= MaximumCachableCharacter) {
+            m_identifiers.append(Identifier(globalData, characters, length));
+            return m_identifiers.last();
+        }
+        if (length == 1) {
             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();
         }
             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();
         }
+        Identifier* ident = m_recentIdentifiers[characters[0]];
+        if (ident && Identifier::equal(ident->impl(), characters, length))
+            return *ident;
         m_identifiers.append(Identifier(globalData, characters, length));
         m_identifiers.append(Identifier(globalData, characters, length));
+        m_recentIdentifiers[characters[0]] = &m_identifiers.last();
         return m_identifiers.last();
     }
 
         return m_identifiers.last();
     }
 
+    ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifierLCharFromUChar(JSGlobalData* globalData, const UChar* characters, size_t length)
+    {
+        if (characters[0] >= MaximumCachableCharacter) {
+            m_identifiers.append(Identifier::createLCharFromUChar(globalData, characters, length));
+            return m_identifiers.last();
+        }
+        if (length == 1) {
+            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();
+        }
+        Identifier* ident = m_recentIdentifiers[characters[0]];
+        if (ident && Identifier::equal(ident->impl(), characters, length))
+            return *ident;
+        m_identifiers.append(Identifier::createLCharFromUChar(globalData, characters, length));
+        m_recentIdentifiers[characters[0]] = &m_identifiers.last();
+        return m_identifiers.last();
+    }
+    
     inline const Identifier& IdentifierArena::makeNumericIdentifier(JSGlobalData* globalData, double number)
     {
         m_identifiers.append(Identifier(globalData, UString::number(number)));
     inline const Identifier& IdentifierArena::makeNumericIdentifier(JSGlobalData* globalData, double number)
     {
         m_identifiers.append(Identifier(globalData, UString::number(number)));
@@ -110,7 +148,7 @@ namespace JSC {
 
         void* allocateDeletable(size_t size)
         {
 
         void* allocateDeletable(size_t size)
         {
-            ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(fastMalloc(size));
+            ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(allocateFreeable(size));
             m_deletableObjects.append(deletable);
             return deletable;
         }
             m_deletableObjects.append(deletable);
             return deletable;
         }
@@ -121,9 +159,14 @@ namespace JSC {
         void removeLast();
 
         bool isEmpty() const;
         void removeLast();
 
         bool isEmpty() const;
-        void reset();
+        JS_EXPORT_PRIVATE void reset();
 
 
-        IdentifierArena& identifierArena() { return *m_identifierArena; }
+        IdentifierArena& identifierArena()
+        {
+            if (UNLIKELY (!m_identifierArena))
+                m_identifierArena = adoptPtr(new IdentifierArena);
+            return *m_identifierArena;
+        }
 
     private:
         static const size_t freeablePoolSize = 8000;
 
     private:
         static const size_t freeablePoolSize = 8000;
diff --git a/parser/ParserTokens.h b/parser/ParserTokens.h
new file mode 100644 (file)
index 0000000..a1ea751
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * 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 ParserTokens_h
+#define ParserTokens_h
+
+namespace JSC {
+
+class Identifier;
+
+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,
+    RESERVED_IF_STRICT,
+    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 };
+    
+}
+
+
+#endif // ParserTokens_h
index 27b8112a0e7a7da3f2ed8163bb91289b472428ee..8f30e5b6482b235c8de092f29a93f2f0dafd5d2f 100644 (file)
@@ -32,8 +32,7 @@ namespace JSC {
         friend struct OperandTypes;
 
         typedef char Type;
         friend struct OperandTypes;
 
         typedef char Type;
-        static const Type TypeReusable = 1;
-        static const Type TypeInt32    = 2;
+        static const Type TypeInt32 = 1;
         
         static const Type TypeMaybeNumber = 0x04;
         static const Type TypeMaybeString = 0x08;
         
         static const Type TypeMaybeNumber = 0x04;
         static const Type TypeMaybeString = 0x08;
@@ -48,11 +47,6 @@ namespace JSC {
         {
         }
         
         {
         }
         
-        bool isReusable()
-        {
-            return m_type & TypeReusable;
-        }
-
         bool isInt32()
         {
             return m_type & TypeInt32;
         bool isInt32()
         {
             return m_type & TypeInt32;
@@ -93,19 +87,14 @@ namespace JSC {
             return ResultType(TypeMaybeNumber);
         }
         
             return ResultType(TypeMaybeNumber);
         }
         
-        static ResultType numberTypeCanReuse()
-        {
-            return ResultType(TypeReusable | TypeMaybeNumber);
-        }
-        
-        static ResultType numberTypeCanReuseIsInt32()
+        static ResultType numberTypeIsInt32()
         {
         {
-            return ResultType(TypeReusable | TypeInt32 | TypeMaybeNumber);
+            return ResultType(TypeInt32 | TypeMaybeNumber);
         }
         
         }
         
-        static ResultType stringOrNumberTypeCanReuse()
+        static ResultType stringOrNumberType()
         {
         {
-            return ResultType(TypeReusable | TypeMaybeNumber | TypeMaybeString);
+            return ResultType(TypeMaybeNumber | TypeMaybeString);
         }
         
         static ResultType stringType()
         }
         
         static ResultType stringType()
@@ -121,15 +110,15 @@ namespace JSC {
         static ResultType forAdd(ResultType op1, ResultType op2)
         {
             if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
         static ResultType forAdd(ResultType op1, ResultType op2)
         {
             if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
-                return numberTypeCanReuse();
+                return numberType();
             if (op1.definitelyIsString() || op2.definitelyIsString())
                 return stringType();
             if (op1.definitelyIsString() || op2.definitelyIsString())
                 return stringType();
-            return stringOrNumberTypeCanReuse();
+            return stringOrNumberType();
         }
         
         static ResultType forBitOp()
         {
         }
         
         static ResultType forBitOp()
         {
-            return numberTypeCanReuseIsInt32();
+            return numberTypeIsInt32();
         }
 
     private:
         }
 
     private:
index 9ba4da3d80678f48de6d1bfa269330fa448842ba..11a00337da853cb09bdd5d61e5ed2392345f448f 100644 (file)
@@ -67,13 +67,21 @@ namespace JSC {
             return m_provider->getRange(m_startChar, m_endChar);
         }
         
             return m_provider->getRange(m_startChar, m_endChar);
         }
         
+        intptr_t providerID() const
+        {
+            if (!m_provider)
+                return SourceProvider::nullID;
+            return m_provider->asID();
+        }
+        
         bool isNull() const { return !m_provider; }
         SourceProvider* provider() const { return m_provider.get(); }
         int firstLine() const { return m_firstLine; }
         int startOffset() const { return m_startChar; }
         int endOffset() const { return m_endChar; }
         bool isNull() const { return !m_provider; }
         SourceProvider* provider() const { return m_provider.get(); }
         int firstLine() const { return m_firstLine; }
         int startOffset() const { return m_startChar; }
         int endOffset() const { return m_endChar; }
-        const UChar* data() const { return m_provider->data() + m_startChar; }
         int length() const { return m_endChar - m_startChar; }
         int length() const { return m_endChar - m_startChar; }
+        
+        SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine);
 
     private:
         RefPtr<SourceProvider> m_provider;
 
     private:
         RefPtr<SourceProvider> m_provider;
@@ -82,9 +90,16 @@ namespace JSC {
         int m_firstLine;
     };
 
         int m_firstLine;
     };
 
-    inline SourceCode makeSource(const UString& source, const UString& url = UString(), int firstLine = 1)
+    inline SourceCode makeSource(const UString& source, const UString& url = UString(), const TextPosition& startPosition = TextPosition::minimumPosition())
+    {
+        return SourceCode(UStringSourceProvider::create(source, url, startPosition), startPosition.m_line.oneBasedInt());
+    }
+
+    inline SourceCode SourceCode::subExpression(unsigned openBrace, unsigned closeBrace, int firstLine)
     {
     {
-        return SourceCode(UStringSourceProvider::create(source, url), firstLine);
+        ASSERT((*provider()->data())[openBrace] == '{');
+        ASSERT((*provider()->data())[closeBrace] == '}');
+        return SourceCode(provider(), openBrace, closeBrace + 1, firstLine);
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
index e9b6b5614ed967e19d0f7f14d7307504ea43a2cd..946792b2c2ebf56128bcca9eecb0c20706bfc703 100644 (file)
@@ -40,12 +40,16 @@ namespace JSC {
 
     class SourceProvider : public RefCounted<SourceProvider> {
     public:
 
     class SourceProvider : public RefCounted<SourceProvider> {
     public:
-        SourceProvider(const UString& url, SourceProviderCache* cache = 0)
+        static const intptr_t nullID = 1;
+        
+        SourceProvider(const UString& url, const TextPosition& startPosition, SourceProviderCache* cache = 0)
             : m_url(url)
             : m_url(url)
+            , m_startPosition(startPosition)
             , m_validated(false)
             , m_cache(cache ? cache : new SourceProviderCache)
             , m_cacheOwned(!cache)
         {
             , m_validated(false)
             , m_cache(cache ? cache : new SourceProviderCache)
             , m_cacheOwned(!cache)
         {
+            turnOffVerifier();
         }
         virtual ~SourceProvider()
         {
         }
         virtual ~SourceProvider()
         {
@@ -54,12 +58,18 @@ namespace JSC {
         }
 
         virtual UString getRange(int start, int end) const = 0;
         }
 
         virtual UString getRange(int start, int end) const = 0;
-        virtual const UChar* data() const = 0;
+        virtual const StringImpl* data() const = 0;
         virtual int length() const = 0;
         
         const UString& url() { return m_url; }
         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); }
+        TextPosition startPosition() const { return m_startPosition; }
+        intptr_t asID()
+        {
+            ASSERT(this);
+            if (!this) // Be defensive in release mode.
+                return nullID;
+            return reinterpret_cast<intptr_t>(this);
+        }
 
         bool isValid() const { return m_validated; }
         void setValid() { m_validated = true; }
 
         bool isValid() const { return m_validated; }
         void setValid() { m_validated = true; }
@@ -71,6 +81,7 @@ namespace JSC {
         virtual void cacheSizeChanged(int delta) { UNUSED_PARAM(delta); }
 
         UString m_url;
         virtual void cacheSizeChanged(int delta) { UNUSED_PARAM(delta); }
 
         UString m_url;
+        TextPosition m_startPosition;
         bool m_validated;
         SourceProviderCache* m_cache;
         bool m_cacheOwned;
         bool m_validated;
         SourceProviderCache* m_cache;
         bool m_cacheOwned;
@@ -78,21 +89,21 @@ namespace JSC {
 
     class UStringSourceProvider : public SourceProvider {
     public:
 
     class UStringSourceProvider : public SourceProvider {
     public:
-        static PassRefPtr<UStringSourceProvider> create(const UString& source, const UString& url)
+        static PassRefPtr<UStringSourceProvider> create(const UString& source, const UString& url, const TextPosition& startPosition = TextPosition::minimumPosition())
         {
         {
-            return adoptRef(new UStringSourceProvider(source, url));
+            return adoptRef(new UStringSourceProvider(source, url, startPosition));
         }
 
         }
 
-        UString getRange(int start, int end) const
+        virtual UString getRange(int start, int end) const OVERRIDE
         {
             return m_source.substringSharingImpl(start, end - start);
         }
         {
             return m_source.substringSharingImpl(start, end - start);
         }
-        const UChar* data() const { return m_source.characters(); }
+        const StringImpl* data() const { return m_source.impl(); }
         int length() const { return m_source.length(); }
 
     private:
         int length() const { return m_source.length(); }
 
     private:
-        UStringSourceProvider(const UString& source, const UString& url)
-            : SourceProvider(url)
+        UStringSourceProvider(const UString& source, const UString& url, const TextPosition& startPosition)
+            : SourceProvider(url, startPosition)
             , m_source(source)
         {
         }
             , m_source(source)
         {
         }
index afeec52830f516381d952d03e732c864ab5d975f..ad1cbe02e7641049d61932a51751b2c16cb2c4d8 100644 (file)
@@ -26,8 +26,6 @@
 #include "config.h"
 #include "SourceProviderCache.h"
 
 #include "config.h"
 #include "SourceProviderCache.h"
 
-#include "SourceProviderCacheItem.h"
-
 namespace JSC {
 
 SourceProviderCache::~SourceProviderCache()
 namespace JSC {
 
 SourceProviderCache::~SourceProviderCache()
@@ -37,7 +35,6 @@ SourceProviderCache::~SourceProviderCache()
 
 void SourceProviderCache::clear()
 {
 
 void SourceProviderCache::clear()
 {
-    deleteAllValues(m_map);
     m_map.clear();
     m_contentByteSize = 0;
 }
     m_map.clear();
     m_contentByteSize = 0;
 }
@@ -49,7 +46,7 @@ unsigned SourceProviderCache::byteSize() const
 
 void SourceProviderCache::add(int sourcePosition, PassOwnPtr<SourceProviderCacheItem> item, unsigned size)
 {
 
 void SourceProviderCache::add(int sourcePosition, PassOwnPtr<SourceProviderCacheItem> item, unsigned size)
 {
-    m_map.add(sourcePosition, item.leakPtr());
+    m_map.add(sourcePosition, item);
     m_contentByteSize += size;
 }
 
     m_contentByteSize += size;
 }
 
index 4df46f72ac61af7819faeb16cdffbc77e4296fe1..e94230d101dd49ce92094e9402b1a39b3a1ee1ea 100644 (file)
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifndef SourceProviderCache_h
+#define SourceProviderCache_h
+
+#include "SourceProviderCacheItem.h"
 #include <wtf/HashMap.h>
 #include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
 #include <wtf/PassOwnPtr.h>
 
 namespace JSC {
 
 #include <wtf/PassOwnPtr.h>
 
 namespace JSC {
 
-class SourceProviderCacheItem;
-
 class SourceProviderCache {
 public:
     SourceProviderCache() : m_contentByteSize(0) {}
 class SourceProviderCache {
 public:
     SourceProviderCache() : m_contentByteSize(0) {}
-    ~SourceProviderCache();
+    JS_EXPORT_PRIVATE ~SourceProviderCache();
 
 
-    void clear();
-    unsigned byteSize() const;
+    JS_EXPORT_PRIVATE void clear();
+    JS_EXPORT_PRIVATE unsigned byteSize() const;
     void add(int sourcePosition, PassOwnPtr<SourceProviderCacheItem>, unsigned size);
     const SourceProviderCacheItem* get(int sourcePosition) const { return m_map.get(sourcePosition); }
 
 private:
     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;
+    HashMap<int, OwnPtr<SourceProviderCacheItem> > m_map;
     unsigned m_contentByteSize;
 };
 
 }
     unsigned m_contentByteSize;
 };
 
 }
+
+#endif // SourceProviderCache_h
index b9ab225ea95e6abf346fd2181df0617f0985c457..3662367a01b709d9cd4ec3d47d2f3db93e5e24a7 100644 (file)
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "JSParser.h"
+#ifndef SourceProviderCacheItem_h
+#define SourceProviderCacheItem_h
+
+#include "ParserTokens.h"
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
 
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
 
@@ -59,8 +62,12 @@ public:
     int closeBraceLine;
     int closeBracePos;
     bool usesEval;
     int closeBraceLine;
     int closeBracePos;
     bool usesEval;
+    bool strictMode;
+    bool needsFullActivation;
     Vector<RefPtr<StringImpl> > usedVariables;
     Vector<RefPtr<StringImpl> > writtenVariables;
 };
 
 }
     Vector<RefPtr<StringImpl> > usedVariables;
     Vector<RefPtr<StringImpl> > writtenVariables;
 };
 
 }
+
+#endif // SourceProviderCacheItem_h
index 2392244b9438cdc2347f7226b05e5da1e6b88dae..c2c93756de03abca295de13ac8ee1381c7d40c48 100644 (file)
@@ -30,6 +30,7 @@
 #include <yarr/YarrSyntaxChecker.h>
 
 namespace JSC {
 #include <yarr/YarrSyntaxChecker.h>
 
 namespace JSC {
+    
 class SyntaxChecker {
 public:
     struct BinaryExprContext {
 class SyntaxChecker {
 public:
     struct BinaryExprContext {
@@ -63,7 +64,7 @@ public:
         SyntaxChecker* m_context;
     };
     
         SyntaxChecker* m_context;
     };
     
-    SyntaxChecker(JSGlobalData* , Lexer*)
+    SyntaxChecker(JSGlobalData* , void*)
     {
     }
 
     {
     }
 
@@ -114,46 +115,46 @@ public:
     static const bool CreatesAST = false;
     static const bool NeedsFreeVariableInfo = false;
     static const bool CanUseFunctionCache = true;
     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;
+    static const unsigned DontBuildKeywords = LexexFlagsDontBuildKeywords;
+    static const unsigned DontBuildStrings = LexerFlagsDontBuildStrings;
 
     int createSourceElements() { return 1; }
 
     int createSourceElements() { return 1; }
-    ExpressionType makeFunctionCallNode(int, int, int, int, int) { return CallExpr; }
+    ExpressionType makeFunctionCallNode(int, int, int, int, int, int) { return CallExpr; }
     void appendToComma(ExpressionType& base, ExpressionType right) { base = right; }
     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 createCommaExpr(int, ExpressionType, ExpressionType right) { return right; }
+    ExpressionType makeAssignNode(int, ExpressionType, Operator, ExpressionType, bool, bool, int, int, int) { return AssignmentExpr; }
+    ExpressionType makePrefixNode(int, ExpressionType, Operator, int, int, int) { return PreExpr; }
+    ExpressionType makePostfixNode(int, ExpressionType, Operator, int, int, int) { return PostExpr; }
+    ExpressionType makeTypeOfNode(int, ExpressionType) { return TypeofExpr; }
+    ExpressionType makeDeleteNode(int, ExpressionType, int, int, int) { return DeleteExpr; }
+    ExpressionType makeNegateNode(int, ExpressionType) { return UnaryExpr; }
+    ExpressionType makeBitwiseNotNode(int, ExpressionType) { return UnaryExpr; }
+    ExpressionType createLogicalNot(int, ExpressionType) { return UnaryExpr; }
+    ExpressionType createUnaryPlus(int, ExpressionType) { return UnaryExpr; }
+    ExpressionType createVoid(int, ExpressionType) { return UnaryExpr; }
+    ExpressionType thisExpr(int) { return ThisExpr; }
+    ExpressionType createResolve(int, const Identifier*, int) { return ResolveExpr; }
     ExpressionType createObjectLiteral(int) { return ObjectLiteralExpr; }
     ExpressionType createObjectLiteral(int) { return ObjectLiteralExpr; }
-    ExpressionType createArray(int) { return ArrayLiteralExpr; }
+    ExpressionType createObjectLiteral(int, int) { return ObjectLiteralExpr; }
     ExpressionType createArray(int, 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; }
+    ExpressionType createArray(int, int, int) { return ArrayLiteralExpr; }
+    ExpressionType createNumberExpr(int, double) { return NumberExpr; }
+    ExpressionType createString(int, const Identifier*) { return StringExpr; }
+    ExpressionType createBoolean(int, bool) { return BoolExpr; }
+    ExpressionType createNull(int) { return NullExpr; }
+    ExpressionType createBracketAccess(int, ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; }
+    ExpressionType createDotAccess(int, ExpressionType, const Identifier*, int, int, int) { return DotExpr; }
+    ExpressionType createRegExp(int, const Identifier& pattern, const Identifier&, int) { return Yarr::checkSyntax(pattern.ustring()) ? 0 : RegExpExpr; }
+    ExpressionType createNewExpr(int, ExpressionType, int, int, int, int) { return NewExpr; }
+    ExpressionType createNewExpr(int, ExpressionType, int, int) { return NewExpr; }
+    ExpressionType createConditionalExpr(int, ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; }
+    ExpressionType createAssignResolve(int, const Identifier&, ExpressionType, bool, int, int, int) { return AssignmentExpr; }
+    ExpressionType createFunctionExpr(int, const Identifier*, int, int, int, int, int, int) { return FunctionExpr; }
+    int createFunctionBody(int, bool) { return 1; }
     int createArguments() { return 1; }
     int createArguments(int) { return 1; }
     int createArguments() { return 1; }
     int createArguments(int) { return 1; }
-    int createArgumentsList(int) { return 1; }
     int createArgumentsList(int, int) { return 1; }
     int createArgumentsList(int, int) { return 1; }
+    int createArgumentsList(int, int, int) { return 1; }
     template <bool complete> Property createProperty(const Identifier* name, int, PropertyNode::Type type)
     {
         if (!complete)
     template <bool complete> Property createProperty(const Identifier* name, int, PropertyNode::Type type)
     {
         if (!complete)
@@ -165,10 +166,10 @@ public:
     {
         if (!complete)
             return Property(type);
     {
         if (!complete)
             return Property(type);
-        return Property(&globalData->parser->arena().identifierArena().makeNumericIdentifier(globalData, name), type);
+        return Property(&globalData->parserArena->identifierArena().makeNumericIdentifier(globalData, name), type);
     }
     }
-    int createPropertyList(Property) { return 1; }
-    int createPropertyList(Property, int) { return 1; }
+    int createPropertyList(int, Property) { return 1; }
+    int createPropertyList(int, Property, int) { return 1; }
     int createElementList(int, int) { return 1; }
     int createElementList(int, int, int) { return 1; }
     int createFormalParameterList(const Identifier&) { return 1; }
     int createElementList(int, int) { return 1; }
     int createElementList(int, int, int) { return 1; }
     int createFormalParameterList(const Identifier&) { return 1; }
@@ -177,42 +178,48 @@ public:
     int createClauseList(int) { return 1; }
     int createClauseList(int, int) { return 1; }
     void setUsesArguments(int) { }
     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 createFuncDeclStatement(int, const Identifier*, int, int, int, int, int, int) { return 1; }
+    int createBlockStatement(int, int, int, int) { return 1; }
+    int createExprStatement(int, int, int, int) { return 1; }
     int createIfStatement(int, 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)
+    int createIfStatement(int, int, int, int, int, int) { return 1; }
+    int createForLoop(int, int, int, int, int, bool, int, int) { return 1; }
+    int createForInLoop(int, const Identifier*, int, int, int, int, int, int, int, int, int, int) { return 1; }
+    int createForInLoop(int, int, int, int, int, int, int, int, int) { return 1; }
+    int createEmptyStatement(int) { return 1; }
+    int createVarStatement(int, int, int, int) { return 1; }
+    int createReturnStatement(int, int, int, int, int, int) { return 1; }
+    int createBreakStatement(int, int, int, int, int) { return 1; }
+    int createBreakStatement(int, const Identifier*, int, int, int, int) { return 1; }
+    int createContinueStatement(int, int, int, int, int) { return 1; }
+    int createContinueStatement(int, const Identifier*, int, int, int, int) { return 1; }
+    int createTryStatement(int, int, const Identifier*, int, int, int, int) { return 1; }
+    int createSwitchStatement(int, int, int, int, int, int, int) { return 1; }
+    int createWhileStatement(int, int, int, int, int) { return 1; }
+    int createWithStatement(int, int, int, int, int, int, int) { return 1; }
+    int createDoWhileStatement(int, int, int, int, int) { return 1; }
+    int createLabelStatement(int, const Identifier*, int, int, int) { return 1; }
+    int createThrowStatement(int, int, int, int, int, int) { return 1; }
+    int createDebugger(int, int, int) { return 1; }
+    int createConstStatement(int, int, int, int) { return 1; }
+    int appendConstDecl(int, int, const Identifier*, int) { return 1; }
+    template <bool strict> Property createGetterOrSetterProperty(int, PropertyNode::Type type, const Identifier* name, int, int, int, int, int, int)
     {
         ASSERT(name);
         if (!strict)
             return Property(type);
         return Property(name, type);
     }
     {
         ASSERT(name);
         if (!strict)
             return Property(type);
         return Property(name, type);
     }
+    template <bool strict> Property createGetterOrSetterProperty(JSGlobalData* globalData, int, PropertyNode::Type type, double name, int, int, int, int, int, int)
+    {
+        if (!strict)
+            return Property(type);
+        return Property(&globalData->parserArena->identifierArena().makeNumericIdentifier(globalData, name), type);
+    }
 
     void appendStatement(int, int) { }
     void addVar(const Identifier*, bool) { }
 
     void appendStatement(int, int) { }
     void addVar(const Identifier*, bool) { }
-    int combineCommaNodes(int, int) { return 1; }
+    int combineCommaNodes(int, int, int) { return 1; }
     int evalCount() const { return 0; }
     void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool)
     {
     int evalCount() const { return 0; }
     void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool)
     {
@@ -228,7 +235,7 @@ public:
     bool operatorStackHasHigherPrecedence(int&, int) { return true; }
     BinaryOperand getFromOperandStack(int) { return m_topBinaryExpr; }
     void shrinkOperandStackBy(int& operandStackDepth, int amount) { operandStackDepth -= amount; }
     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 appendBinaryOperation(int, 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 operatorStackAppend(int& operatorStackDepth, int, int) { operatorStackDepth++; }
     int popOperandStack(int&) { int res = m_topBinaryExpr; m_topBinaryExpr = 0; return res; }
     
@@ -238,7 +245,7 @@ public:
     void unaryTokenStackRemoveLast(int& stackDepth) { stackDepth = 0; }
     
     void assignmentStackAppend(int, int, int, int, int, Operator) { }
     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; }
+    int createAssignment(int, 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; }
     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; }
index 1ba5ec604376f9797c523bee1798da065f75806d..2da8a2ff104f9893f5f87d907f321c0d2cadbfed 100644 (file)
@@ -87,7 +87,7 @@ namespace WTF {
     template<> struct HashTraits<JSC::CallIdentifier> : GenericHashTraits<JSC::CallIdentifier> {
         static void constructDeletedValue(JSC::CallIdentifier& slot)
         {
     template<> struct HashTraits<JSC::CallIdentifier> : GenericHashTraits<JSC::CallIdentifier> {
         static void constructDeletedValue(JSC::CallIdentifier& slot)
         {
-            new (&slot) JSC::CallIdentifier(JSC::UString(), JSC::UString(), std::numeric_limits<unsigned>::max());
+            new (NotNull, &slot) JSC::CallIdentifier(JSC::UString(), JSC::UString(), std::numeric_limits<unsigned>::max());
         }
         static bool isDeletedValue(const JSC::CallIdentifier& value)
         {
         }
         static bool isDeletedValue(const JSC::CallIdentifier& value)
         {
index 1a84518c1bbb9538c7ffd8d7e5474119eb95b3b3..49d6de97a98ab0c53feea65b38969fd301133997 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "ProfileNode.h"
 #include <stdio.h>
 
 #include "ProfileNode.h"
 #include <stdio.h>
+#include <wtf/DataLog.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -102,7 +103,7 @@ void Profile::restoreAll()
 #ifndef NDEBUG
 void Profile::debugPrintData() const
 {
 #ifndef NDEBUG
 void Profile::debugPrintData() const
 {
-    printf("Call graph:\n");
+    dataLog("Call graph:\n");
     m_head->debugPrintData(0);
 }
 
     m_head->debugPrintData(0);
 }
 
@@ -118,18 +119,18 @@ void Profile::debugPrintDataSampleStyle() const
     typedef Vector<NameCountPair> NameCountPairVector;
 
     FunctionCallHashCount countedFunctions;
     typedef Vector<NameCountPair> NameCountPairVector;
 
     FunctionCallHashCount countedFunctions;
-    printf("Call graph:\n");
+    dataLog("Call graph:\n");
     m_head->debugPrintDataSampleStyle(0, countedFunctions);
 
     m_head->debugPrintDataSampleStyle(0, countedFunctions);
 
-    printf("\nTotal number in stack:\n");
+    dataLog("\nTotal number in stack:\n");
     NameCountPairVector sortedFunctions(countedFunctions.size());
     copyToVector(countedFunctions, sortedFunctions);
 
     std::sort(sortedFunctions.begin(), sortedFunctions.end(), functionNameCountPairComparator);
     for (NameCountPairVector::iterator it = sortedFunctions.begin(); it != sortedFunctions.end(); ++it)
     NameCountPairVector sortedFunctions(countedFunctions.size());
     copyToVector(countedFunctions, sortedFunctions);
 
     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).utf8().data());
+        dataLog("        %-12d%s\n", (*it).second, UString((*it).first).utf8().data());
 
 
-    printf("\nSort by top of stack, same collapsed (when >= 5):\n");
+    dataLog("\nSort by top of stack, same collapsed (when >= 5):\n");
 }
 #endif
 
 }
 #endif
 
index 6bf29f7a6f88b9ae4eee3ed67976020f1eb27f0f..9455e3595032f2c3d9c52a08095d54ac9986ea0e 100644 (file)
@@ -44,11 +44,11 @@ namespace JSC {
         double totalTime() const { return m_head->totalTime(); }
         unsigned int uid() const { return m_uid; }
 
         double totalTime() const { return m_head->totalTime(); }
         unsigned int uid() const { return m_uid; }
 
-        void forEach(void (ProfileNode::*)());
+        JS_EXPORT_PRIVATE void forEach(void (ProfileNode::*)());
 
 
-        void focus(const ProfileNode*);
-        void exclude(const ProfileNode*);
-        void restoreAll();
+        JS_EXPORT_PRIVATE void focus(const ProfileNode*);
+        JS_EXPORT_PRIVATE void exclude(const ProfileNode*);
+        JS_EXPORT_PRIVATE void restoreAll();
 
 #ifndef NDEBUG
         void debugPrintData() const;
 
 #ifndef NDEBUG
         void debugPrintData() const;
index 8f20bbeff8a60b512c506fd4bf9e240e17fa062b..ab43d1511eee4880f2066e8cf492d05481df761d 100644 (file)
@@ -32,6 +32,7 @@
 #include "Profiler.h"
 #include <stdio.h>
 #include <wtf/DateMath.h>
 #include "Profiler.h"
 #include <stdio.h>
 #include <wtf/DateMath.h>
+#include <wtf/DataLog.h>
 #include <wtf/text/StringHash.h>
 
 #if OS(WINDOWS)
 #include <wtf/text/StringHash.h>
 
 #if OS(WINDOWS)
@@ -293,9 +294,9 @@ void ProfileNode::debugPrintData(int indentLevel) const
 {
     // Print function names
     for (int i = 0; i < indentLevel; ++i)
 {
     // Print function names
     for (int i = 0; i < indentLevel; ++i)
-        printf("  ");
+        dataLog("  ");
 
 
-    printf("Function Name %s %d SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% VSelf %.3fms VTotal %.3fms Visible %s Next Sibling %s\n",
+    dataLog("Function Name %s %d SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% VSelf %.3fms VTotal %.3fms Visible %s Next Sibling %s\n",
         functionName().utf8().data(), 
         m_numberOfCalls, m_actualSelfTime, selfPercent(), m_actualTotalTime, totalPercent(),
         m_visibleSelfTime, m_visibleTotalTime, 
         functionName().utf8().data(), 
         m_numberOfCalls, m_actualSelfTime, selfPercent(), m_actualTotalTime, totalPercent(),
         m_visibleSelfTime, m_visibleTotalTime, 
@@ -312,20 +313,20 @@ void ProfileNode::debugPrintData(int indentLevel) const
 // print the profiled data in a format that matches the tool sample's output.
 double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount& countedFunctions) const
 {
 // print the profiled data in a format that matches the tool sample's output.
 double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount& countedFunctions) const
 {
-    printf("    ");
+    dataLog("    ");
 
     // Print function names
     const char* name = functionName().utf8().data();
     double sampleCount = m_actualTotalTime * 1000;
     if (indentLevel) {
         for (int i = 0; i < indentLevel; ++i)
 
     // Print function names
     const char* name = functionName().utf8().data();
     double sampleCount = m_actualTotalTime * 1000;
     if (indentLevel) {
         for (int i = 0; i < indentLevel; ++i)
-            printf("  ");
+            dataLog("  ");
 
          countedFunctions.add(functionName().impl());
 
 
          countedFunctions.add(functionName().impl());
 
-        printf("%.0f %s\n", sampleCount ? sampleCount : 1, name);
+        dataLog("%.0f %s\n", sampleCount ? sampleCount : 1, name);
     } else
     } else
-        printf("%s\n", name);
+        dataLog("%s\n", name);
 
     ++indentLevel;
 
 
     ++indentLevel;
 
@@ -337,11 +338,11 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC
     sumOfChildrensCount *= 1000;    //
     // Print remainder of samples to match sample's output
     if (sumOfChildrensCount < sampleCount) {
     sumOfChildrensCount *= 1000;    //
     // Print remainder of samples to match sample's output
     if (sumOfChildrensCount < sampleCount) {
-        printf("    ");
+        dataLog("    ");
         while (indentLevel--)
         while (indentLevel--)
-            printf("  ");
+            dataLog("  ");
 
 
-        printf("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
+        dataLog("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
     }
 
     return m_actualTotalTime;
     }
 
     return m_actualTotalTime;
index bcaaaacbf217b08425f4327ca8bd37bf23a14a26..0ecd5b2c98553700125468485c86ae849e2ee41b 100644 (file)
@@ -48,7 +48,7 @@ static const char* GlobalCodeExecution = "(program)";
 static const char* AnonymousFunction = "(anonymous function)";
 static unsigned ProfilesUID = 0;
 
 static const char* AnonymousFunction = "(anonymous function)";
 static unsigned ProfilesUID = 0;
 
-static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSFunction*);
+static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSObject*, const UString& defaultSourceURL, int defaultLineNumber);
 
 Profiler* Profiler::s_sharedProfiler = 0;
 Profiler* Profiler::s_sharedEnabledProfilerReference = 0;
 
 Profiler* Profiler::s_sharedProfiler = 0;
 Profiler* Profiler::s_sharedEnabledProfilerReference = 0;
@@ -163,23 +163,18 @@ 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::s_info)) {
-        JSFunction* function = asFunction(functionValue);
-        if (!function->executable()->isHostFunction())
-            return createCallIdentifierFromFunctionImp(exec, function);
-    }
-    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(makeUString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber);
+    if (asObject(functionValue)->inherits(&JSFunction::s_info) || asObject(functionValue)->inherits(&InternalFunction::s_info))
+        return createCallIdentifierFromFunctionImp(exec, asObject(functionValue), defaultSourceURL, defaultLineNumber);
+    return CallIdentifier(makeUString("(", asObject(functionValue)->methodTable()->className(asObject(functionValue)), " object)"), defaultSourceURL, defaultLineNumber);
 }
 
 }
 
-CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSFunction* function)
+CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSObject* function, const UString& defaultSourceURL, int defaultLineNumber)
 {
 {
-    ASSERT(!function->isHostFunction());
-    const UString& name = function->calculatedDisplayName(exec);
-    return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->jsExecutable()->sourceURL(), function->jsExecutable()->lineNo());
+    const UString& name = getCalculatedDisplayName(exec, function);
+    JSFunction* jsFunction = jsDynamicCast<JSFunction*>(function);
+    if (jsFunction && !jsFunction->isHostFunction())
+        return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, jsFunction->jsExecutable()->sourceURL(), jsFunction->jsExecutable()->lineNo());
+    return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, defaultSourceURL, defaultLineNumber);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 86366c1c4f9198d3df116229e55c0c9935fdea1d..45f91af4465065534ba05795e379bd51645a031f 100644 (file)
@@ -53,11 +53,11 @@ namespace JSC {
             return &s_sharedEnabledProfilerReference;
         }
 
             return &s_sharedEnabledProfilerReference;
         }
 
-        static Profiler* profiler(); 
+        JS_EXPORT_PRIVATE static Profiler* profiler(); 
         static CallIdentifier createCallIdentifier(ExecState* exec, JSValue, const UString& sourceURL, int lineNumber);
 
         static CallIdentifier createCallIdentifier(ExecState* exec, JSValue, const UString& sourceURL, int lineNumber);
 
-        void startProfiling(ExecState*, const UString& title);
-        PassRefPtr<Profile> stopProfiling(ExecState*, const UString& title);
+        JS_EXPORT_PRIVATE void startProfiling(ExecState*, const UString& title);
+        JS_EXPORT_PRIVATE PassRefPtr<Profile> stopProfiling(ExecState*, const UString& title);
         void stopProfiling(JSGlobalObject*);
 
         void willExecute(ExecState* callerCallFrame, JSValue function);
         void stopProfiling(JSGlobalObject*);
 
         void willExecute(ExecState* callerCallFrame, JSValue function);
diff --git a/profiler/ProfilerServer.h b/profiler/ProfilerServer.h
deleted file mode 100644 (file)
index 5b7cc46..0000000
+++ /dev/null
@@ -1,35 +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.
- */
-
-#ifndef ProfileServer_h
-#define ProfileServer_h
-
-namespace JSC {
-
-void startProfilerServerIfNeeded();
-
-} // namespace JSC
-
-#endif // ProfileServer_h
diff --git a/profiler/ProfilerServer.mm b/profiler/ProfilerServer.mm
deleted file mode 100644 (file)
index a2c5d9e..0000000
+++ /dev/null
@@ -1,115 +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.
- */
-
-#import "config.h"
-#import "ProfilerServer.h"
-
-#import "JSProfilerPrivate.h"
-#import "JSRetainPtr.h"
-#import <Foundation/Foundation.h>
-
-#if PLATFORM(IOS_SIMULATOR)
-#import <Foundation/NSDistributedNotificationCenter.h>
-#endif
-
-@interface ProfilerServer : NSObject {
-@private
-    NSString *_serverName;
-    unsigned _listenerCount;
-}
-+ (ProfilerServer *)sharedProfileServer;
-- (void)startProfiling;
-- (void)stopProfiling;
-@end
-
-@implementation ProfilerServer
-
-+ (ProfilerServer *)sharedProfileServer
-{
-    static ProfilerServer *sharedServer;
-    if (!sharedServer)
-        sharedServer = [[ProfilerServer alloc] init];
-    return sharedServer;
-}
-
-- (id)init
-{
-    if (!(self = [super init]))
-        return nil;
-
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
-    if ([defaults boolForKey:@"EnableJSProfiling"])
-        [self startProfiling];
-
-#if PLATFORM(IOS_SIMULATOR)
-    // FIXME: <rdar://problem/6546135>
-    // The catch-all notifications
-    [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(startProfiling) name:@"ProfilerServerStartNotification" object:nil];
-    [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(stopProfiling) name:@"ProfilerServerStopNotification" object:nil];
-#endif
-
-    // The specific notifications
-    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
-    _serverName = [[NSString alloc] initWithFormat:@"ProfilerServer-%d", [processInfo processIdentifier]];
-
-#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];
-#endif
-
-    [pool drain];
-
-    return self;
-}
-
-- (void)startProfiling
-{
-    if (++_listenerCount > 1)
-        return;
-    JSRetainPtr<JSStringRef> profileName(Adopt, JSStringCreateWithUTF8CString([_serverName UTF8String]));
-    JSStartProfiling(0, profileName.get());
-}
-
-- (void)stopProfiling
-{
-    if (!_listenerCount || --_listenerCount > 0)
-        return;
-    JSRetainPtr<JSStringRef> profileName(Adopt, JSStringCreateWithUTF8CString([_serverName UTF8String]));
-    JSEndProfiling(0, profileName.get());
-}
-
-@end
-
-namespace JSC {
-
-void startProfilerServerIfNeeded()
-{
-    [ProfilerServer sharedProfileServer];
-}
-
-} // namespace JSC
diff --git a/qt/ChangeLog b/qt/ChangeLog
deleted file mode 100644 (file)
index 22484b7..0000000
+++ /dev/null
@@ -1,467 +0,0 @@
-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):
-
diff --git a/qt/api/QtScript.pro b/qt/api/QtScript.pro
deleted file mode 100644 (file)
index 22e8b0c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-TARGET     = QtScript
-TEMPLATE   = lib
-QT         = core
-
-INCLUDEPATH += $$PWD
-
-CONFIG += building-libs
-
-isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = ../../generated
-
-isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../..
-include($$PWD/../../../WebKit.pri)
-
-include($$PWD/../../JavaScriptCore.pri)
-prependJavaScriptCoreLib(../..)
-
-INCLUDEPATH += $$PWD/../../API
-
-SOURCES +=  $$PWD/qscriptengine.cpp \
-            $$PWD/qscriptengine_p.cpp \
-            $$PWD/qscriptvalue.cpp \
-            $$PWD/qscriptvalueiterator.cpp \
-            $$PWD/qscriptstring.cpp \
-            $$PWD/qscriptprogram.cpp \
-            $$PWD/qscriptsyntaxcheckresult.cpp \
-            $$PWD/qscriptfunction.cpp
-
-HEADERS +=  $$PWD/qtscriptglobal.h \
-            $$PWD/qscriptengine.h \
-            $$PWD/qscriptengine_p.h \
-            $$PWD/qscriptvalue.h \
-            $$PWD/qscriptvalue_p.h \
-            $$PWD/qscriptvalueiterator.h \
-            $$PWD/qscriptvalueiterator_p.h \
-            $$PWD/qscriptconverter_p.h \
-            $$PWD/qscriptstring.h \
-            $$PWD/qscriptstring_p.h \
-            $$PWD/qscriptprogram.h \
-            $$PWD/qscriptprogram_p.h \
-            $$PWD/qscriptsyntaxcheckresult.h \
-            $$PWD/qscriptoriginalglobalobject_p.h \
-            $$PWD/qscriptfunction_p.h
-
-!static: DEFINES += QT_MAKEDLL
-
-DESTDIR = $$OUTPUT_DIR/lib
diff --git a/qt/api/qscriptconverter_p.h b/qt/api/qscriptconverter_p.h
deleted file mode 100644 (file)
index 0c57d95..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
-    Copyright (C) 2008 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 qscriptconverter_p_h
-#define qscriptconverter_p_h
-
-#include "qscriptvalue.h"
-#include <JavaScriptCore/JavaScript.h>
-#include <QtCore/qglobal.h>
-#include <QtCore/qnumeric.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qvarlengtharray.h>
-
-extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **digits_str);
-
-/*
-  \internal
-  \class QScriptConverter
-  QScriptValue and QScriptEngine helper class. This class's responsibility is to convert values
-  between JS values and Qt/C++ values.
-
-  This is a nice way to inline these functions in both QScriptValue and QScriptEngine.
-*/
-class QScriptConverter {
-public:
-    static quint32 toArrayIndex(const JSStringRef jsstring)
-    {
-        // FIXME this function should be exported by JSC C API.
-        QString qstring = toString(jsstring);
-
-        bool ok;
-        quint32 idx = qstring.toUInt(&ok);
-        if (!ok || toString(idx) != qstring)
-            idx = 0xffffffff;
-
-        return idx;
-    }
-
-    static QString toString(const JSStringRef str)
-    {
-        return QString(reinterpret_cast<const QChar*>(JSStringGetCharactersPtr(str)), JSStringGetLength(str));
-    }
-    static JSStringRef toString(const QString& str)
-    {
-        return JSStringCreateWithUTF8CString(str.toUtf8().constData());
-    }
-    static JSStringRef toString(const char* str)
-    {
-        return JSStringCreateWithUTF8CString(str);
-    }
-    static QString toString(double value)
-    {
-        // FIXME this should be easier. The ideal fix is to create
-        // a new function in JSC C API which could cover the functionality.
-
-        if (qIsNaN(value))
-            return QString::fromLatin1("NaN");
-        if (qIsInf(value))
-            return QString::fromLatin1(value < 0 ? "-Infinity" : "Infinity");
-        if (!value)
-            return QString::fromLatin1("0");
-
-        QVarLengthArray<char, 25> buf;
-        int decpt;
-        int sign;
-        char* result = 0;
-        char* endresult;
-        (void)qdtoa(value, 0, 0, &decpt, &sign, &endresult, &result);
-
-        if (!result)
-            return QString();
-
-        int resultLen = endresult - result;
-        if (decpt <= 0 && decpt > -6) {
-            buf.resize(-decpt + 2 + sign);
-            qMemSet(buf.data(), '0', -decpt + 2 + sign);
-            if (sign) // fix the sign.
-                buf[0] = '-';
-            buf[sign + 1] = '.';
-            buf.append(result, resultLen);
-        } else {
-            if (sign)
-                buf.append('-');
-            int length = buf.size() - sign + resultLen;
-            if (decpt <= 21 && decpt > 0) {
-                if (length <= decpt) {
-                    const char* zeros = "0000000000000000000000000";
-                    buf.append(result, resultLen);
-                    buf.append(zeros, decpt - length);
-                } else {
-                    buf.append(result, decpt);
-                    buf.append('.');
-                    buf.append(result + decpt, resultLen - decpt);
-                }
-            } else if (result[0] >= '0' && result[0] <= '9') {
-                if (length > 1) {
-                    buf.append(result, 1);
-                    buf.append('.');
-                    buf.append(result + 1, resultLen - 1);
-                } else
-                    buf.append(result, resultLen);
-                buf.append('e');
-                buf.append(decpt >= 0 ? '+' : '-');
-                int e = qAbs(decpt - 1);
-                if (e >= 100)
-                    buf.append('0' + e / 100);
-                if (e >= 10)
-                    buf.append('0' + (e % 100) / 10);
-                buf.append('0' + e % 10);
-            }
-        }
-        free(result);
-        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
diff --git a/qt/api/qscriptengine.cpp b/qt/api/qscriptengine.cpp
deleted file mode 100644 (file)
index 607b0b9..0000000
+++ /dev/null
@@ -1,426 +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 "qscriptengine.h"
-
-#include "qscriptengine_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.
-
-    The globalObject() is initialized to have properties as described in ECMA-262, Section 15.1.
-*/
-QScriptEngine::QScriptEngine()
-    : d_ptr(new QScriptEnginePrivate(this))
-{
-}
-
-/*!
-    Destroys this QScriptEngine.
-*/
-QScriptEngine::~QScriptEngine()
-{
-}
-
-/*!
-  Checks the syntax of the given \a program. Returns a
-  QScriptSyntaxCheckResult object that contains the result of the check.
-*/
-QScriptSyntaxCheckResult QScriptEngine::checkSyntax(const QString &program)
-{
-    // FIXME This is not optimal.
-    // The JSC C API needs a context to perform a syntax check, it means that a QScriptEnginePrivate
-    // had to be created. This function is static so we have to create QScriptEnginePrivate for each
-    // call. We can't remove the "static" for compatibility reason, at least up to Qt5.
-    // QScriptSyntaxCheckResultPrivate takes ownership of newly created engine. The engine will be
-    // kept as long as it is needed for lazy evaluation of properties of
-    // the QScriptSyntaxCheckResultPrivate.
-    QScriptEnginePrivate* engine = new QScriptEnginePrivate(/* q_ptr */ 0);
-    return QScriptSyntaxCheckResultPrivate::get(engine->checkSyntax(program));
-}
-
-/*!
-    Evaluates \a program, using \a lineNumber as the base line number,
-    and returns the result of the evaluation.
-
-    The script code will be evaluated in the current context.
-
-    The evaluation of \a program can cause an exception in the
-    engine; in this case the return value will be the exception
-    that was thrown (typically an \c{Error} object). You can call
-    hasUncaughtException() to determine if an exception occurred in
-    the last call to evaluate().
-
-    \a lineNumber is used to specify a starting line number for \a
-    program; line number information reported by the engine that pertain
-    to this evaluation (e.g. uncaughtExceptionLineNumber()) will be
-    based on this argument. For example, if \a program consists of two
-    lines of code, and the statement on the second line causes a script
-    exception, uncaughtExceptionLineNumber() would return the given \a
-    lineNumber plus one. When no starting line number is specified, line
-    numbers will be 1-based.
-
-    \a fileName is used for error reporting. For example in error objects
-    the file name is accessible through the "fileName" property if it's
-    provided with this function.
-*/
-QScriptValue QScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber)
-{
-    return QScriptValuePrivate::get(d_ptr->evaluate(program, fileName, lineNumber));
-}
-
-QScriptValue QScriptEngine::evaluate(const QScriptProgram& program)
-{
-    return QScriptValuePrivate::get(d_ptr->evaluate(QScriptProgramPrivate::get(program)));
-}
-
-/*!
-    Returns true if the last script evaluation resulted in an uncaught
-    exception; otherwise returns false.
-
-    The exception state is cleared when evaluate() is called.
-
-    \sa uncaughtException(), uncaughtExceptionLineNumber(),
-      uncaughtExceptionBacktrace()
-*/
-bool QScriptEngine::hasUncaughtException() const
-{
-    return d_ptr->hasUncaughtException();
-}
-
-/*!
-    Returns the current uncaught exception, or an invalid QScriptValue
-    if there is no uncaught exception.
-
-    The exception value is typically an \c{Error} object; in that case,
-    you can call toString() on the return value to obtain an error
-    message.
-
-    \sa hasUncaughtException(), uncaughtExceptionLineNumber(),
-      uncaughtExceptionBacktrace()
-*/
-QScriptValue QScriptEngine::uncaughtException() const
-{
-    return QScriptValuePrivate::get(d_ptr->uncaughtException());
-}
-
-/*!
-    Clears any uncaught exceptions in this engine.
-
-    \sa hasUncaughtException()
-*/
-void QScriptEngine::clearExceptions()
-{
-    d_ptr->clearExceptions();
-}
-
-/*!
-    Returns the line number where the last uncaught exception occurred.
-
-    Line numbers are 1-based, unless a different base was specified as
-    the second argument to evaluate().
-
-    \sa hasUncaughtException(), uncaughtExceptionBacktrace()
-*/
-int QScriptEngine::uncaughtExceptionLineNumber() const
-{
-    return d_ptr->uncaughtExceptionLineNumber();
-}
-
-/*!
-    Returns a human-readable backtrace of the last uncaught exception.
-
-    Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}.
-
-    \sa uncaughtException()
-*/
-QStringList QScriptEngine::uncaughtExceptionBacktrace() const
-{
-    return d_ptr->uncaughtExceptionBacktrace();
-}
-
-/*!
-    Runs the garbage collector.
-
-    The garbage collector will attempt to reclaim memory by locating and disposing of objects that are
-    no longer reachable in the script environment.
-
-    Normally you don't need to call this function; the garbage collector will automatically be invoked
-    when the QScriptEngine decides that it's wise to do so (i.e. when a certain number of new objects
-    have been created). However, you can call this function to explicitly request that garbage
-    collection should be performed as soon as possible.
-
-    \sa reportAdditionalMemoryCost()
-*/
-void QScriptEngine::collectGarbage()
-{
-    d_ptr->collectGarbage();
-}
-
-/*!
-  Reports an additional memory cost of the given \a size, measured in
-  bytes, to the garbage collector.
-
-  This function can be called to indicate that a JavaScript object has
-  memory associated with it that isn't managed by Qt Script itself.
-  Reporting the additional cost makes it more likely that the garbage
-  collector will be triggered.
-
-  Note that if the additional memory is shared with objects outside
-  the scripting environment, the cost should not be reported, since
-  collecting the JavaScript object would not cause the memory to be
-  freed anyway.
-
-  Negative \a size values are ignored, i.e. this function can't be
-  used to report that the additional memory has been deallocated.
-
-  \sa collectGarbage()
-*/
-void QScriptEngine::reportAdditionalMemoryCost(int cost)
-{
-    d_ptr->reportAdditionalMemoryCost(cost);
-}
-
-/*!
-  Returns a handle that represents the given string, \a str.
-
-  QScriptString can be used to quickly look up properties, and
-  compare property names, of script objects.
-
-  \sa QScriptValue::property()
-*/
-QScriptString QScriptEngine::toStringHandle(const QString& str)
-{
-    return QScriptStringPrivate::get(d_ptr->toStringHandle(str));
-}
-
-/*!
-  Converts the given \a value to an object, if such a conversion is
-  possible; otherwise returns an invalid QScriptValue. The conversion
-  is performed according to the following table:
-
-    \table
-    \header \o Input Type \o Result
-    \row    \o Undefined  \o An invalid QScriptValue.
-    \row    \o Null       \o An invalid QScriptValue.
-    \row    \o Boolean    \o A new Boolean object whose internal value is set to the value of the boolean.
-    \row    \o Number     \o A new Number object whose internal value is set to the value of the number.
-    \row    \o String     \o A new String object whose internal value is set to the value of the string.
-    \row    \o Object     \o The result is the object itself (no conversion).
-    \endtable
-
-    \sa newObject()
-*/
-QScriptValue QScriptEngine::toObject(const QScriptValue& value)
-{
-    return QScriptValuePrivate::get(QScriptValuePrivate::get(value)->toObject(d_ptr.data()));
-}
-
-/*!
-  Returns a QScriptValue of the primitive type Null.
-
-  \sa undefinedValue()
-*/
-QScriptValue QScriptEngine::nullValue()
-{
-    return QScriptValue(this, QScriptValue::NullValue);
-}
-
-/*!
-  Returns a QScriptValue of the primitive type Undefined.
-
-  \sa nullValue()
-*/
-QScriptValue QScriptEngine::undefinedValue()
-{
-    return QScriptValue(this, QScriptValue::UndefinedValue);
-}
-
-/*!
-    Creates a QScriptValue that wraps a native (C++) function. \a fun
-    must be a C++ function with signature QScriptEngine::FunctionSignature.
-    \a length is the number of arguments that \a fun expects; this becomes
-    the \c{length} property of the created QScriptValue.
-
-    Note that \a length only gives an indication of the number of
-    arguments that the function expects; an actual invocation of a
-    function can include any number of arguments. You can check the
-    \l{QScriptContext::argumentCount()}{argumentCount()} of the
-    QScriptContext associated with the invocation to determine the
-    actual number of arguments passed.
-
-    A \c{prototype} property is automatically created for the resulting
-    function object, to provide for the possibility that the function
-    will be used as a constructor.
-
-    By combining newFunction() and the property flags
-    QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you
-    can create script object properties that behave like normal
-    properties in script code, but are in fact accessed through
-    functions (analogous to how properties work in \l{Qt's Property
-    System}). Example:
-
-    \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11
-
-    When the property \c{foo} of the script object is subsequently
-    accessed in script code, \c{getSetFoo()} will be invoked to handle
-    the access.  In this particular case, we chose to store the "real"
-    value of \c{foo} as a property of the accessor function itself; you
-    are of course free to do whatever you like in this function.
-
-    In the above example, a single native function was used to handle
-    both reads and writes to the property; the argument count is used to
-    determine if we are handling a read or write. You can also use two
-    separate functions; just specify the relevant flag
-    (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when
-    setting the property, e.g.:
-
-    \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12
-
-    \sa QScriptValue::call()
-*/
-QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length)
-{
-    return QScriptValuePrivate::get(d_ptr->newFunction(fun, 0, length));
-}
-
-/*!
-    Creates a constructor function from \a fun, with the given \a length.
-    The \c{prototype} property of the resulting function is set to be the
-    given \a prototype. The \c{constructor} property of \a prototype is
-    set to be the resulting function.
-
-    When a function is called as a constructor (e.g. \c{new Foo()}), the
-    `this' object associated with the function call is the new object
-    that the function is expected to initialize; the prototype of this
-    default constructed object will be the function's public
-    \c{prototype} property. If you always want the function to behave as
-    a constructor (e.g. \c{Foo()} should also create a new object), or
-    if you need to create your own object rather than using the default
-    `this' object, you should make sure that the prototype of your
-    object is set correctly; either by setting it manually, or, when
-    wrapping a custom type, by having registered the defaultPrototype()
-    of that type. Example:
-
-    \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9
-
-    To wrap a custom type and provide a constructor for it, you'd typically
-    do something like this:
-
-    \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10
-*/
-QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, const QScriptValue& prototype, int length)
-{
-    return QScriptValuePrivate::get(d_ptr->newFunction(fun, QScriptValuePrivate::get(prototype), length));
-}
-
-/*!
-    \internal
-    \since 4.4
-*/
-QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void* arg)
-{
-    return QScriptValuePrivate::get(d_ptr->newFunction(fun, arg));
-}
-
-/*!
-  Creates a QtScript object of class Object.
-
-  The prototype of the created object will be the Object
-  prototype object.
-
-  \sa newArray(), QScriptValue::setProperty()
-*/
-QScriptValue QScriptEngine::newObject()
-{
-    return QScriptValuePrivate::get(d_ptr->newObject());
-}
-
-/*!
-  Creates a QtScript object of class Array with the given \a length.
-
-  \sa newObject()
-*/
-QScriptValue QScriptEngine::newArray(uint length)
-{
-    return QScriptValuePrivate::get(d_ptr->newArray(length));
-}
-
-/*!
-    Creates a QtScript object of class Date with the given \a value
-    (the number of milliseconds since 01 January 1970, UTC).
-*/
-QScriptValue QScriptEngine::newDate(qsreal value)
-{
-    return QScriptValuePrivate::get(d_ptr->newDate(value));
-}
-
-/*!
-    Creates a QtScript object of class Date from the given \a value.
-
-    \sa QScriptValue::toDateTime()
-*/
-QScriptValue QScriptEngine::newDate(const QDateTime& value)
-{
-    if (value.isValid())
-        return QScriptValuePrivate::get(d_ptr->newDate(qsreal(value.toMSecsSinceEpoch())));
-    return QScriptValuePrivate::get(d_ptr->newDate(qSNaN()));
-}
-
-/*!
-  Returns this engine's Global Object.
-
-  By default, the Global Object contains the built-in objects that are
-  part of \l{ECMA-262}, such as Math, Date and String. Additionally,
-  you can set properties of the Global Object to make your own
-  extensions available to all script code. Non-local variables in
-  script code will be created as properties of the Global Object, as
-  well as local variables in global code.
-*/
-QScriptValue QScriptEngine::globalObject() const
-{
-    return QScriptValuePrivate::get(d_ptr->globalObject());
-}
-
-/*!
-    \typedef QScriptEngine::FunctionSignature
-    \relates QScriptEngine
-
-    The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *)}.
-
-    A function with such a signature can be passed to
-    QScriptEngine::newFunction() to wrap the function.
-*/
-
-/*!
-    \typedef QScriptEngine::FunctionWithArgSignature
-    \relates QScriptEngine
-
-    The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *, void *)}.
-
-    A function with such a signature can be passed to
-    QScriptEngine::newFunction() to wrap the function.
-*/
diff --git a/qt/api/qscriptengine.h b/qt/api/qscriptengine.h
deleted file mode 100644 (file)
index 281707f..0000000
+++ /dev/null
@@ -1,82 +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.
-*/
-
-#ifndef qscriptengine_h
-#define qscriptengine_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>
-
-class QDateTime;
-class QScriptEnginePrivate;
-
-// FIXME: Remove this once QScriptContext is properly defined.
-typedef void QScriptContext;
-
-// Internal typedef
-typedef QExplicitlySharedDataPointer<QScriptEnginePrivate> QScriptEnginePtr;
-
-class QScriptEngine : public QObject {
-public:
-    QScriptEngine();
-    ~QScriptEngine();
-
-    static QScriptSyntaxCheckResult checkSyntax(const QString& 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);
-    QScriptValue toObject(const QScriptValue& value);
-
-    QScriptValue nullValue();
-    QScriptValue undefinedValue();
-
-    typedef QScriptValue (*FunctionSignature)(QScriptContext *, QScriptEngine *);
-    typedef QScriptValue (*FunctionWithArgSignature)(QScriptContext *, QScriptEngine *, void *);
-
-    QScriptValue newFunction(FunctionSignature fun, int length = 0);
-    QScriptValue newFunction(FunctionSignature fun, const QScriptValue& prototype, int length = 0);
-    QScriptValue newFunction(FunctionWithArgSignature fun, void* arg);
-
-    QScriptValue newObject();
-    QScriptValue newArray(uint length = 0);
-    QScriptValue newDate(qsreal value);
-    QScriptValue newDate(const QDateTime& value);
-    QScriptValue globalObject() const;
-private:
-    friend class QScriptEnginePrivate;
-
-    QScriptEnginePtr d_ptr;
-};
-
-#endif
diff --git a/qt/api/qscriptengine_p.cpp b/qt/api/qscriptengine_p.cpp
deleted file mode 100644 (file)
index 89054c0..0000000
+++ /dev/null
@@ -1,167 +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 "qscriptengine_p.h"
-
-#include "qscriptfunction_p.h"
-#include "qscriptprogram_p.h"
-#include "qscriptvalue_p.h"
-
-/*!
-    Constructs a default QScriptEnginePrivate object, a new global context will be created.
-    \internal
-*/
-QScriptEnginePrivate::QScriptEnginePrivate(const QScriptEngine* engine)
-    : q_ptr(const_cast<QScriptEngine*>(engine))
-    , m_context(JSGlobalContextCreate(0))
-    , m_exception(0)
-    , m_originalGlobalObject(m_context)
-    , m_nativeFunctionClass(JSClassCreate(&qt_NativeFunctionClass))
-    , m_nativeFunctionWithArgClass(JSClassCreate(&qt_NativeFunctionWithArgClass))
-{
-}
-
-QScriptEnginePrivate::~QScriptEnginePrivate()
-{
-    JSClassRelease(m_nativeFunctionClass);
-    JSClassRelease(m_nativeFunctionWithArgClass);
-    if (m_exception)
-        JSValueUnprotect(m_context, m_exception);
-    JSGlobalContextRelease(m_context);
-}
-
-QScriptSyntaxCheckResultPrivate* QScriptEnginePrivate::checkSyntax(const QString& program)
-{
-    JSValueRef exception;
-    JSStringRef source = QScriptConverter::toString(program);
-    bool syntaxIsCorrect = JSCheckScriptSyntax(m_context, source, /* url */ 0, /* starting line */ 1, &exception);
-    JSStringRelease(source);
-    if (syntaxIsCorrect) {
-        return new QScriptSyntaxCheckResultPrivate(this);
-    }
-    JSValueProtect(m_context, exception);
-    return new QScriptSyntaxCheckResultPrivate(this, const_cast<JSObjectRef>(exception));
-}
-
-/*!
-    Evaluates program and returns the result of the evaluation.
-    \internal
-*/
-QScriptValuePrivate* QScriptEnginePrivate::evaluate(const QString& program, const QString& fileName, int lineNumber)
-{
-    JSStringRef script = QScriptConverter::toString(program);
-    JSStringRef file = QScriptConverter::toString(fileName);
-    QScriptValuePrivate* result = new QScriptValuePrivate(this, evaluate(script, file, lineNumber));
-    JSStringRelease(script);
-    JSStringRelease(file);
-    return result;
-}
-
-/*!
-    Evaluates program and returns the result of the evaluation.
-    \internal
-*/
-QScriptValuePrivate* QScriptEnginePrivate::evaluate(const QScriptProgramPrivate* program)
-{
-    if (program->isNull())
-        return new QScriptValuePrivate;
-    return new QScriptValuePrivate(this, evaluate(*program, program->file(), program->line()));
-}
-
-QScriptValuePrivate* QScriptEnginePrivate::uncaughtException() const
-{
-    return m_exception ? new QScriptValuePrivate(this, m_exception) : new QScriptValuePrivate();
-}
-
-QScriptValuePrivate* QScriptEnginePrivate::newFunction(QScriptEngine::FunctionSignature fun, QScriptValuePrivate* prototype, int length)
-{
-    // Note that this private data will be deleted in the object finalize function.
-    QNativeFunctionData* data = new QNativeFunctionData(this, fun);
-    JSObjectRef funJS = JSObjectMake(m_context, m_nativeFunctionClass, reinterpret_cast<void*>(data));
-    QScriptValuePrivate* proto = prototype ? prototype : newObject();
-    return newFunction(funJS, proto);
-}
-
-QScriptValuePrivate* QScriptEnginePrivate::newFunction(QScriptEngine::FunctionWithArgSignature fun, void* arg)
-{
-    // Note that this private data will be deleted in the object finalize function.
-    QNativeFunctionWithArgData* data = new QNativeFunctionWithArgData(this, fun, arg);
-    JSObjectRef funJS = JSObjectMake(m_context, m_nativeFunctionWithArgClass, reinterpret_cast<void*>(data));
-    QScriptValuePrivate* proto = newObject();
-    return newFunction(funJS, proto);
-}
-
-QScriptValuePrivate* QScriptEnginePrivate::newFunction(JSObjectRef funJS, QScriptValuePrivate* prototype)
-{
-    JSObjectSetPrototype(m_context, funJS, m_originalGlobalObject.functionPrototype());
-
-    QScriptValuePrivate* result = new QScriptValuePrivate(this, funJS);
-    static JSStringRef protoName = QScriptConverter::toString("prototype");
-    static JSStringRef constructorName = QScriptConverter::toString("constructor");
-    result->setProperty(protoName, prototype, QScriptValue::Undeletable);
-    prototype->setProperty(constructorName, result, QScriptValue::PropertyFlags(QScriptValue::Undeletable | QScriptValue::SkipInEnumeration));
-
-    return result;
-}
-
-QScriptValuePrivate* QScriptEnginePrivate::newObject() const
-{
-    return new QScriptValuePrivate(this, JSObjectMake(m_context, /* jsClass */ 0, /* userData */ 0));
-}
-
-QScriptValuePrivate* QScriptEnginePrivate::newArray(uint length)
-{
-    JSValueRef exception = 0;
-    JSObjectRef array = JSObjectMakeArray(m_context, /* argumentCount */ 0, /* arguments */ 0, &exception);
-
-    if (!exception) {
-        if (length > 0) {
-            JSRetainPtr<JSStringRef> lengthRef(Adopt, JSStringCreateWithUTF8CString("length"));
-            // array is an Array instance, so an exception should not occure here.
-            JSObjectSetProperty(m_context, array, lengthRef.get(), JSValueMakeNumber(m_context, length), kJSPropertyAttributeNone, /* exception */ 0);
-        }
-    } else {
-        setException(exception, NotNullException);
-        return new QScriptValuePrivate();
-    }
-
-    return new QScriptValuePrivate(this, array);
-}
-
-QScriptValuePrivate* QScriptEnginePrivate::newDate(qsreal value)
-{
-    JSValueRef exception = 0;
-    JSValueRef argument = JSValueMakeNumber(m_context, value);
-    JSObjectRef result = JSObjectMakeDate(m_context, /* argumentCount */ 1, &argument, &exception);
-
-    if (exception) {
-        setException(exception, NotNullException);
-        return new QScriptValuePrivate();
-    }
-
-    return new QScriptValuePrivate(this, result);
-}
-
-QScriptValuePrivate* QScriptEnginePrivate::globalObject() const
-{
-    JSObjectRef globalObject = JSContextGetGlobalObject(m_context);
-    return new QScriptValuePrivate(this, globalObject);
-}
diff --git a/qt/api/qscriptengine_p.h b/qt/api/qscriptengine_p.h
deleted file mode 100644 (file)
index 4603b91..0000000
+++ /dev/null
@@ -1,259 +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.
-*/
-
-#ifndef qscriptengine_p_h
-#define qscriptengine_p_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 <JavaScriptCore/JSRetainPtr.h>
-#include <JSBasePrivate.h>
-#include <QtCore/qshareddata.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qstringlist.h>
-
-class QScriptEngine;
-class QScriptSyntaxCheckResultPrivate;
-
-class QScriptEnginePrivate : public QSharedData {
-public:
-    static QScriptEnginePrivate* get(const QScriptEngine* q) { Q_ASSERT(q); return q->d_ptr.data(); }
-    static QScriptEngine* get(const QScriptEnginePrivate* d) { Q_ASSERT(d); return d->q_ptr; }
-
-    QScriptEnginePrivate(const QScriptEngine*);
-    ~QScriptEnginePrivate();
-
-    enum SetExceptionFlag {
-        IgnoreNullException = 0x01,
-        NotNullException = 0x02,
-    };
-
-    QScriptSyntaxCheckResultPrivate* checkSyntax(const QString& program);
-    QScriptValuePrivate* evaluate(const QString& program, const QString& fileName, int lineNumber);
-    QScriptValuePrivate* evaluate(const QScriptProgramPrivate* program);
-    inline JSValueRef evaluate(JSStringRef program, JSStringRef fileName, int lineNumber);
-
-    inline bool hasUncaughtException() const;
-    QScriptValuePrivate* uncaughtException() const;
-    inline void clearExceptions();
-    inline void setException(JSValueRef exception, const /* SetExceptionFlags */ unsigned flags = IgnoreNullException);
-    inline int uncaughtExceptionLineNumber() const;
-    inline QStringList uncaughtExceptionBacktrace() const;
-
-    inline void collectGarbage();
-    inline void reportAdditionalMemoryCost(int cost);
-
-    inline JSValueRef makeJSValue(double number) const;
-    inline JSValueRef makeJSValue(int number) const;
-    inline JSValueRef makeJSValue(uint number) const;
-    inline JSValueRef makeJSValue(const QString& string) 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;
-
-    inline operator JSGlobalContextRef() const;
-
-    inline bool isDate(JSValueRef value) const;
-    inline bool isArray(JSValueRef value) const;
-    inline bool isError(JSValueRef value) const;
-    inline bool objectHasOwnProperty(JSObjectRef object, JSStringRef property) const;
-    inline QVector<JSStringRef> objectGetOwnPropertyNames(JSObjectRef object) const;
-
-private:
-    QScriptEngine* q_ptr;
-    JSGlobalContextRef m_context;
-    JSValueRef m_exception;
-
-    QScriptOriginalGlobalObject m_originalGlobalObject;
-
-    JSClassRef m_nativeFunctionClass;
-    JSClassRef m_nativeFunctionWithArgClass;
-};
-
-
-/*!
-  Evaluates given JavaScript program and returns result of the evaluation.
-  \attention this function doesn't take ownership of the parameters.
-  \internal
-*/
-JSValueRef QScriptEnginePrivate::evaluate(JSStringRef program, JSStringRef fileName, int lineNumber)
-{
-    JSValueRef exception;
-    JSValueRef result = JSEvaluateScript(m_context, program, /* Global Object */ 0, fileName, lineNumber, &exception);
-    if (!result) {
-        setException(exception, NotNullException);
-        return exception; // returns an exception
-    }
-    clearExceptions();
-    return result;
-}
-
-bool QScriptEnginePrivate::hasUncaughtException() const
-{
-    return m_exception;
-}
-
-void QScriptEnginePrivate::clearExceptions()
-{
-    if (m_exception)
-        JSValueUnprotect(m_context, m_exception);
-    m_exception = 0;
-}
-
-void QScriptEnginePrivate::setException(JSValueRef exception, const /* SetExceptionFlags */ unsigned flags)
-{
-    if (!((flags & NotNullException) || exception))
-        return;
-    Q_ASSERT(exception);
-
-    if (m_exception)
-        JSValueUnprotect(m_context, m_exception);
-    JSValueProtect(m_context, exception);
-    m_exception = exception;
-}
-
-int QScriptEnginePrivate::uncaughtExceptionLineNumber() const
-{
-    if (!hasUncaughtException() || !JSValueIsObject(m_context, m_exception))
-        return -1;
-
-    JSValueRef exception = 0;
-    JSRetainPtr<JSStringRef> lineNumberPropertyName(Adopt, QScriptConverter::toString("line"));
-    JSValueRef lineNumber = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), lineNumberPropertyName.get(), &exception);
-    int result = JSValueToNumber(m_context, lineNumber, &exception);
-    return exception ? -1 : result;
-}
-
-QStringList QScriptEnginePrivate::uncaughtExceptionBacktrace() const
-{
-    if (!hasUncaughtException() || !JSValueIsObject(m_context, m_exception))
-        return QStringList();
-
-    JSValueRef exception = 0;
-    JSRetainPtr<JSStringRef> fileNamePropertyName(Adopt, QScriptConverter::toString("sourceURL"));
-    JSRetainPtr<JSStringRef> lineNumberPropertyName(Adopt, QScriptConverter::toString("line"));
-    JSValueRef jsFileName = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), fileNamePropertyName.get(), &exception);
-    JSValueRef jsLineNumber = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), lineNumberPropertyName.get(), &exception);
-    JSRetainPtr<JSStringRef> fileName(Adopt, JSValueToStringCopy(m_context, jsFileName, &exception));
-    int lineNumber = JSValueToNumber(m_context, jsLineNumber, &exception);
-    return QStringList(QString::fromLatin1("<anonymous>()@%0:%1")
-            .arg(QScriptConverter::toString(fileName.get()))
-            .arg(QScriptConverter::toString(exception ? -1 : lineNumber)));
-}
-
-void QScriptEnginePrivate::collectGarbage()
-{
-    JSGarbageCollect(m_context);
-}
-
-void QScriptEnginePrivate::reportAdditionalMemoryCost(int cost)
-{
-    if (cost > 0)
-        JSReportExtraMemoryCost(m_context, cost);
-}
-
-JSValueRef QScriptEnginePrivate::makeJSValue(double number) const
-{
-    return JSValueMakeNumber(m_context, number);
-}
-
-JSValueRef QScriptEnginePrivate::makeJSValue(int number) const
-{
-    return JSValueMakeNumber(m_context, number);
-}
-
-JSValueRef QScriptEnginePrivate::makeJSValue(uint number) const
-{
-    return JSValueMakeNumber(m_context, number);
-}
-
-JSValueRef QScriptEnginePrivate::makeJSValue(const QString& string) const
-{
-    JSStringRef tmp = QScriptConverter::toString(string);
-    JSValueRef result = JSValueMakeString(m_context, tmp);
-    JSStringRelease(tmp);
-    return result;
-}
-
-JSValueRef QScriptEnginePrivate::makeJSValue(bool value) const
-{
-    return JSValueMakeBoolean(m_context, value);
-}
-
-JSValueRef QScriptEnginePrivate::makeJSValue(QScriptValue::SpecialValue value) const
-{
-    if (value == QScriptValue::NullValue)
-        return JSValueMakeNull(m_context);
-    return JSValueMakeUndefined(m_context);
-}
-
-QScriptStringPrivate* QScriptEnginePrivate::toStringHandle(const QString& str) const
-{
-    return new QScriptStringPrivate(str);
-}
-
-QScriptEnginePrivate::operator JSGlobalContextRef() const
-{
-    Q_ASSERT(this);
-    return m_context;
-}
-
-bool QScriptEnginePrivate::isDate(JSValueRef value) const
-{
-    return m_originalGlobalObject.isDate(value);
-}
-
-bool QScriptEnginePrivate::isArray(JSValueRef value) const
-{
-    return m_originalGlobalObject.isArray(value);
-}
-
-bool QScriptEnginePrivate::isError(JSValueRef value) const
-{
-    return m_originalGlobalObject.isError(value);
-}
-
-inline bool QScriptEnginePrivate::objectHasOwnProperty(JSObjectRef object, JSStringRef property) const
-{
-    // FIXME We need a JSC C API function for this.
-    return m_originalGlobalObject.objectHasOwnProperty(object, property);
-}
-
-inline QVector<JSStringRef> QScriptEnginePrivate::objectGetOwnPropertyNames(JSObjectRef object) const
-{
-    // FIXME We can't use C API function JSObjectGetPropertyNames as it returns only enumerable properties.
-    return m_originalGlobalObject.objectGetOwnPropertyNames(object);
-}
-
-#endif
diff --git a/qt/api/qscriptfunction.cpp b/qt/api/qscriptfunction.cpp
deleted file mode 100644 (file)
index 9fe37e6..0000000
+++ /dev/null
@@ -1,145 +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.
-*/
-
-// 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
deleted file mode 100644 (file)
index 65b6046..0000000
+++ /dev/null
@@ -1,57 +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.
-*/
-
-#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
deleted file mode 100644 (file)
index 2bd945f..0000000
+++ /dev/null
@@ -1,209 +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.
-*/
-
-#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
diff --git a/qt/api/qscriptprogram.cpp b/qt/api/qscriptprogram.cpp
deleted file mode 100644 (file)
index d7d4948..0000000
+++ /dev/null
@@ -1,136 +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 "config.h"
-
-#include "qscriptprogram.h"
-
-#include "qscriptprogram_p.h"
-
-/*!
-  \internal
-
-  \class QScriptProgram
-
-  \brief The QScriptProgram class encapsulates a Qt Script program.
-
-  \ingroup script
-
-  QScriptProgram retains the compiled representation of the script if
-  possible. Thus, QScriptProgram can be used to evaluate the same
-  script multiple times more efficiently.
-
-  \code
-  QScriptEngine engine;
-  QScriptProgram program("1 + 2");
-  QScriptValue result = engine.evaluate(program);
-  \endcode
-*/
-
-/*!
-  Constructs a null QScriptProgram.
-*/
-QScriptProgram::QScriptProgram()
-    : d_ptr(new QScriptProgramPrivate)
-{}
-
-/*!
-  Constructs a new QScriptProgram with the given \a sourceCode, \a
-  fileName and \a firstLineNumber.
-*/
-QScriptProgram::QScriptProgram(const QString& sourceCode,
-               const QString fileName,
-               int firstLineNumber)
-    : d_ptr(new QScriptProgramPrivate(sourceCode, fileName, firstLineNumber))
-{}
-
-/*!
-  Destroys this QScriptProgram.
-*/
-QScriptProgram::~QScriptProgram()
-{}
-
-/*!
-  Constructs a new QScriptProgram that is a copy of \a other.
-*/
-QScriptProgram::QScriptProgram(const QScriptProgram& other)
-{
-    d_ptr = other.d_ptr;
-}
-
-/*!
-  Assigns the \a other value to this QScriptProgram.
-*/
-QScriptProgram& QScriptProgram::operator=(const QScriptProgram& other)
-{
-    d_ptr = other.d_ptr;
-    return *this;
-}
-
-/*!
-  Returns true if this QScriptProgram is null; otherwise
-  returns false.
-*/
-bool QScriptProgram::isNull() const
-{
-    return d_ptr->isNull();
-}
-
-/*!
-  Returns the source code of this program.
-*/
-QString QScriptProgram::sourceCode() const
-{
-    return d_ptr->sourceCode();
-}
-
-/*!
-  Returns the filename associated with this program.
-*/
-QString QScriptProgram::fileName() const
-{
-    return d_ptr->fileName();
-}
-
-/*!
-  Returns the line number associated with this program.
-*/
-int QScriptProgram::firstLineNumber() const
-{
-    return d_ptr->firstLineNumber();
-}
-
-/*!
-  Returns true if this QScriptProgram is equal to \a other;
-  otherwise returns false.
-*/
-bool QScriptProgram::operator==(const QScriptProgram& other) const
-{
-    return d_ptr == other.d_ptr || *d_ptr == *other.d_ptr;
-}
-
-/*!
-  Returns true if this QScriptProgram is not equal to \a other;
-  otherwise returns false.
-*/
-bool QScriptProgram::operator!=(const QScriptProgram& other) const
-{
-    return d_ptr != other.d_ptr && *d_ptr != *other.d_ptr;
-}
-
diff --git a/qt/api/qscriptprogram.h b/qt/api/qscriptprogram.h
deleted file mode 100644 (file)
index 93c8a3c..0000000
+++ /dev/null
@@ -1,53 +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.
-*/
-
-#ifndef qscriptprogram_h
-#define qscriptprogram_h
-
-#include "qtscriptglobal.h"
-#include <QtCore/qshareddata.h>
-#include <QtCore/qstring.h>
-
-class QScriptProgramPrivate;
-class Q_JAVASCRIPT_EXPORT QScriptProgram {
-public:
-    QScriptProgram();
-    QScriptProgram(const QString& sourceCode,
-                   const QString fileName = QString(),
-                   int firstLineNumber = 1);
-    QScriptProgram(const QScriptProgram& other);
-    ~QScriptProgram();
-
-    QScriptProgram& operator=(const QScriptProgram& other);
-
-    bool isNull() const;
-
-    QString sourceCode() const;
-    QString fileName() const;
-    int firstLineNumber() const;
-
-    bool operator==(const QScriptProgram& other) const;
-    bool operator!=(const QScriptProgram& other) const;
-
-private:
-    QExplicitlySharedDataPointer<QScriptProgramPrivate> d_ptr;
-    Q_DECLARE_PRIVATE(QScriptProgram)
-};
-
-#endif // qscriptprogram_h
diff --git a/qt/api/qscriptprogram_p.h b/qt/api/qscriptprogram_p.h
deleted file mode 100644 (file)
index f6882c5..0000000
+++ /dev/null
@@ -1,133 +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.
-*/
-
-#ifndef qscriptprogram_p_h
-#define qscriptprogram_p_h
-
-#include "qscriptconverter_p.h"
-#include "qscriptprogram.h"
-#include <JavaScriptCore/JavaScript.h>
-#include <QtCore/qshareddata.h>
-#include <QtCore/qstring.h>
-
-/*
-   FIXME The QScriptProgramPrivate potentially could be much faster. In current implementation we
-   gain CPU time only by avoiding QString -> JSStringRef conversion. In the ideal world we should
-   have a function inside the JSC C API that could provide us "parse once, execute multiple times"
-   functionality.
-*/
-
-class QScriptProgramPrivate : public QSharedData {
-public:
-    inline static QScriptProgramPrivate* get(const QScriptProgram& program);
-    inline QScriptProgramPrivate();
-    inline QScriptProgramPrivate(const QString& sourceCode,
-                   const QString fileName,
-                   int firstLineNumber);
-
-    inline ~QScriptProgramPrivate();
-
-    inline bool isNull() const;
-
-    inline QString sourceCode() const;
-    inline QString fileName() const;
-    inline int firstLineNumber() const;
-
-    inline bool operator==(const QScriptProgramPrivate& other) const;
-    inline bool operator!=(const QScriptProgramPrivate& other) const;
-
-    inline operator JSStringRef() const;
-    inline JSStringRef file() const;
-    inline int line() const;
-private:
-    JSStringRef m_program;
-    JSStringRef m_fileName;
-    int m_line;
-};
-
-QScriptProgramPrivate* QScriptProgramPrivate::get(const QScriptProgram& program)
-{
-    return const_cast<QScriptProgramPrivate*>(program.d_ptr.constData());
-}
-
-QScriptProgramPrivate::QScriptProgramPrivate()
-    : m_program(0)
-    , m_fileName(0)
-    , m_line(-1)
-{}
-
-QScriptProgramPrivate::QScriptProgramPrivate(const QString& sourceCode,
-               const QString fileName,
-               int firstLineNumber)
-                   : m_program(QScriptConverter::toString(sourceCode))
-                   , m_fileName(QScriptConverter::toString(fileName))
-                   , m_line(firstLineNumber)
-{}
-
-QScriptProgramPrivate::~QScriptProgramPrivate()
-{
-    if (!isNull()) {
-        JSStringRelease(m_program);
-        JSStringRelease(m_fileName);
-    }
-}
-
-bool QScriptProgramPrivate::isNull() const
-{
-    return !m_program;
-}
-
-QString QScriptProgramPrivate::sourceCode() const
-{
-    return QScriptConverter::toString(m_program);
-}
-
-QString QScriptProgramPrivate::fileName() const
-{
-    return QScriptConverter::toString(m_fileName);
-}
-
-int QScriptProgramPrivate::firstLineNumber() const
-{
-    return m_line;
-}
-
-bool QScriptProgramPrivate::operator==(const QScriptProgramPrivate& other) const
-{
-    return m_line == other.m_line
-            && JSStringIsEqual(m_fileName, other.m_fileName)
-            && JSStringIsEqual(m_program, other.m_program);
-}
-
-bool QScriptProgramPrivate::operator!=(const QScriptProgramPrivate& other) const
-{
-    return m_line != other.m_line
-            || !JSStringIsEqual(m_fileName, other.m_fileName)
-            || !JSStringIsEqual(m_program, other.m_program);
-}
-
-QScriptProgramPrivate::operator JSStringRef() const
-{
-    return m_program;
-}
-
-JSStringRef QScriptProgramPrivate::file() const {return m_fileName; }
-int QScriptProgramPrivate::line() const { return m_line; }
-
-#endif // qscriptprogram_p_h
diff --git a/qt/api/qscriptstring.cpp b/qt/api/qscriptstring.cpp
deleted file mode 100644 (file)
index 83c03c5..0000000
+++ /dev/null
@@ -1,131 +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 "qscriptstring.h"
-
-#include "qscriptstring_p.h"
-#include <QtCore/qhash.h>
-
-/*!
-  Constructs an invalid QScriptString.
-*/
-QScriptString::QScriptString()
-    : d_ptr(new QScriptStringPrivate())
-{
-}
-/*!
-  Constructs an QScriptString from internal representation
-  \internal
-*/
-QScriptString::QScriptString(QScriptStringPrivate* d)
-    : d_ptr(d)
-{
-}
-
-/*!
-  Constructs a new QScriptString that is a copy of \a other.
-*/
-QScriptString::QScriptString(const QScriptString& other)
-{
-    d_ptr = other.d_ptr;
-}
-
-/*!
-  Destroys this QScriptString.
-*/
-QScriptString::~QScriptString()
-{
-}
-
-/*!
-  Assigns the \a other value to this QScriptString.
-*/
-QScriptString& QScriptString::operator=(const QScriptString& other)
-{
-    d_ptr = other.d_ptr;
-    return *this;
-}
-
-/*!
-  Returns true if this QScriptString is valid; otherwise
-  returns false.
-*/
-bool QScriptString::isValid() const
-{
-    return d_ptr->isValid();
-}
-
-/*!
-  Returns true if this QScriptString is equal to \a other;
-  otherwise returns false.
-*/
-bool QScriptString::operator==(const QScriptString& other) const
-{
-    return d_ptr == other.d_ptr || *d_ptr == *(other.d_ptr);
-}
-
-/*!
-  Returns true if this QScriptString is not equal to \a other;
-  otherwise returns false.
-*/
-bool QScriptString::operator!=(const QScriptString& other) const
-{
-    return d_ptr != other.d_ptr || *d_ptr != *(other.d_ptr);
-}
-
-/*!
-  Attempts to convert this QScriptString to a QtScript array index,
-  and returns the result.
-
-  If a conversion error occurs, *\a{ok} is set to false; otherwise
-  *\a{ok} is set to true.
-*/
-quint32 QScriptString::toArrayIndex(bool* ok) const
-{
-    return d_ptr->toArrayIndex(ok);
-}
-
-/*!
-  Returns the string that this QScriptString represents, or a
-  null string if this QScriptString is not valid.
-
-  \sa isValid()
-*/
-QString QScriptString::toString() const
-{
-    return d_ptr->toString();
-}
-
-/*!
-  Returns the string that this QScriptString represents, or a
-  null string if this QScriptString is not valid.
-
-  \sa toString()
-*/
-QScriptString::operator QString() const
-{
-    return d_ptr->toString();
-}
-
-uint qHash(const QScriptString& key)
-{
-    return qHash(QScriptStringPrivate::get(key)->id());
-}
diff --git a/qt/api/qscriptstring.h b/qt/api/qscriptstring.h
deleted file mode 100644 (file)
index 16593bc..0000000
+++ /dev/null
@@ -1,58 +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.
-*/
-
-#ifndef qscriptstring_h
-#define qscriptstring_h
-
-#include "qtscriptglobal.h"
-#include <QtCore/qshareddata.h>
-#include <QtCore/qstring.h>
-
-class QScriptStringPrivate;
-typedef QExplicitlySharedDataPointer<QScriptStringPrivate> QScriptStringPtr;
-
-class Q_JAVASCRIPT_EXPORT QScriptString {
-public:
-    QScriptString();
-    QScriptString(const QScriptString& other);
-    ~QScriptString();
-
-    QScriptString& operator=(const QScriptString& other);
-
-    bool isValid() const;
-
-    bool operator==(const QScriptString& other) const;
-    bool operator!=(const QScriptString& other) const;
-
-    quint32 toArrayIndex(bool* ok = 0) const;
-
-    QString toString() const;
-    operator QString() const;
-
-private:
-    QScriptString(QScriptStringPrivate* d);
-
-    QScriptStringPtr d_ptr;
-
-    friend class QScriptStringPrivate;
-};
-
-uint qHash(const QScriptString& key);
-
-#endif // qscriptstring_h
diff --git a/qt/api/qscriptstring_p.h b/qt/api/qscriptstring_p.h
deleted file mode 100644 (file)
index fe84f4d..0000000
+++ /dev/null
@@ -1,124 +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.
-*/
-
-#ifndef qscriptstring_p_h
-#define qscriptstring_p_h
-
-#include "qscriptconverter_p.h"
-#include "qscriptstring.h"
-#include <JavaScriptCore/JavaScript.h>
-#include <QtCore/qnumeric.h>
-#include <QtCore/qshareddata.h>
-
-class QScriptStringPrivate : public QSharedData {
-public:
-    inline QScriptStringPrivate();
-    inline QScriptStringPrivate(const QString& qtstring);
-    inline ~QScriptStringPrivate();
-
-    static inline QScriptString get(QScriptStringPrivate* d);
-    static inline QScriptStringPtr get(const QScriptString& p);
-
-    inline bool isValid() const;
-
-    inline bool operator==(const QScriptStringPrivate& other) const;
-    inline bool operator!=(const QScriptStringPrivate& other) const;
-
-    inline quint32 toArrayIndex(bool* ok = 0) const;
-
-    inline QString toString() const;
-
-    inline quint64 id() const;
-
-    inline operator JSStringRef() const;
-
-private:
-    JSStringRef m_string;
-};
-
-
-QScriptStringPrivate::QScriptStringPrivate()
-    : m_string(0)
-{}
-
-QScriptStringPrivate::QScriptStringPrivate(const QString& qtstring)
-    : m_string(QScriptConverter::toString(qtstring))
-{}
-
-QScriptStringPrivate::~QScriptStringPrivate()
-{
-    if (isValid())
-        JSStringRelease(m_string);
-}
-
-QScriptString QScriptStringPrivate::get(QScriptStringPrivate* d)
-{
-    Q_ASSERT(d);
-    return QScriptString(d);
-}
-
-QScriptStringPtr QScriptStringPrivate::get(const QScriptString& p)
-{
-    return p.d_ptr;
-}
-
-bool QScriptStringPrivate::isValid() const
-{
-    return m_string;
-}
-
-bool QScriptStringPrivate::operator==(const QScriptStringPrivate& other) const
-{
-    return isValid() && other.isValid() && JSStringIsEqual(m_string, other.m_string);
-}
-
-bool QScriptStringPrivate::operator!=(const QScriptStringPrivate& other) const
-{
-    return isValid() && other.isValid() && !JSStringIsEqual(m_string, other.m_string);
-}
-
-quint32 QScriptStringPrivate::toArrayIndex(bool* ok) const
-{
-    quint32 idx = QScriptConverter::toArrayIndex(m_string);
-    if (ok)
-        *ok = (idx != 0xffffffff);
-    return idx;
-}
-
-QString QScriptStringPrivate::toString() const
-{
-    return QScriptConverter::toString(m_string);
-}
-
-quint64 QScriptStringPrivate::id() const
-{
-    return reinterpret_cast<quint32>(m_string);
-}
-
-/*!
-    \internal
-    This method should be used for invoking JSC functions.
-    \note This method keeps ownership of an internal JSStringRef.
-*/
-QScriptStringPrivate::operator JSStringRef() const
-{
-    return m_string;
-}
-
-#endif // qscriptstring_p_h
diff --git a/qt/api/qscriptsyntaxcheckresult.cpp b/qt/api/qscriptsyntaxcheckresult.cpp
deleted file mode 100644 (file)
index 3948c5d..0000000
+++ /dev/null
@@ -1,148 +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 "config.h"
-
-#include "qscriptsyntaxcheckresult.h"
-#include "qscriptsyntaxcheckresult_p.h"
-
-/*!
-  \class QScriptSyntaxCheckResult
-
-  \brief The QScriptSyntaxCheckResult class provides the result of a script syntax check.
-
-  \ingroup script
-  \mainclass
-
-  QScriptSyntaxCheckResult is returned by QScriptEngine::checkSyntax() to
-  provide information about the syntactical (in)correctness of a script.
-*/
-
-/*!
-    \enum QScriptSyntaxCheckResult::State
-
-    This enum specifies the state of a syntax check.
-
-    \value Error The program contains a syntax error.
-    \value Intermediate The program is incomplete.
-    \value Valid The program is a syntactically correct Qt Script program.
-*/
-
-/*!
-  Constructs a new QScriptSyntaxCheckResult from the \a other result.
-*/
-QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult& other)
-    : d_ptr(other.d_ptr)
-{}
-
-/*!
-  Constructs a new QScriptSyntaxCheckResult from an internal representation.
-  \internal
-*/
-QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate* d)
-    : d_ptr(d)
-{}
-
-/*!
-  Destroys this QScriptSyntaxCheckResult.
-*/
-QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult()
-{}
-
-/*!
-  Assigns the \a other result to this QScriptSyntaxCheckResult, and returns a
-  reference to this QScriptSyntaxCheckResult.
-*/
-QScriptSyntaxCheckResult& QScriptSyntaxCheckResult::operator=(const QScriptSyntaxCheckResult& other)
-{
-    d_ptr = other.d_ptr;
-    return *this;
-}
-
-/*!
-  Returns the state of this QScriptSyntaxCheckResult.
-*/
-QScriptSyntaxCheckResult::State QScriptSyntaxCheckResult::state() const
-{
-    return d_ptr->state();
-}
-
-/*!
-  Returns the error line number of this QScriptSyntaxCheckResult, or -1 if
-  there is no error.
-
-  \sa state(), errorMessage()
-*/
-int QScriptSyntaxCheckResult::errorLineNumber() const
-{
-    return d_ptr->errorLineNumber();
-}
-
-/*!
-  Returns the error column number of this QScriptSyntaxCheckResult, or -1 if
-  there is no error.
-
-  \sa state(), errorLineNumber()
-*/
-int QScriptSyntaxCheckResult::errorColumnNumber() const
-{
-    return d_ptr->errorColumnNumber();
-}
-
-/*!
-  Returns the error message of this QScriptSyntaxCheckResult, or an empty
-  string if there is no error.
-
-  \sa state(), errorLineNumber()
-*/
-QString QScriptSyntaxCheckResult::errorMessage() const
-{
-    return d_ptr->errorMessage();
-}
-
-QScriptSyntaxCheckResultPrivate::~QScriptSyntaxCheckResultPrivate()
-{
-    if (m_exception)
-        JSValueUnprotect(*m_engine, m_exception);
-}
-
-QString QScriptSyntaxCheckResultPrivate::errorMessage() const
-{
-    if (!m_exception)
-        return QString();
-
-    JSStringRef tmp = JSValueToStringCopy(*m_engine, m_exception, /* exception */ 0);
-    QString message = QScriptConverter::toString(tmp);
-    JSStringRelease(tmp);
-    return message;
-}
-
-int QScriptSyntaxCheckResultPrivate::errorLineNumber() const
-{
-    if (!m_exception)
-        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,
-                                          m_exception,
-                                          lineAttrName,
-                                          /* exceptions */0);
-    JSStringRelease(lineAttrName);
-    return JSValueToNumber(*m_engine, line, /* exceptions */0);
-}
diff --git a/qt/api/qscriptsyntaxcheckresult.h b/qt/api/qscriptsyntaxcheckresult.h
deleted file mode 100644 (file)
index aa57744..0000000
+++ /dev/null
@@ -1,50 +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.
-*/
-
-#ifndef qscriptsyntaxcheckresult_h
-#define qscriptsyntaxcheckresult_h
-
-#include "qtscriptglobal.h"
-#include <QtCore/qshareddata.h>
-
-class QScriptSyntaxCheckResultPrivate;
-class Q_JAVASCRIPT_EXPORT QScriptSyntaxCheckResult {
-public:
-    enum State {
-        Error,
-        Intermediate,
-        Valid
-    };
-
-    QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult& other);
-    ~QScriptSyntaxCheckResult();
-    QScriptSyntaxCheckResult& operator=(const QScriptSyntaxCheckResult& other);
-
-    State state() const;
-    int errorLineNumber() const;
-    int errorColumnNumber() const;
-    QString errorMessage() const;
-
-private:
-    QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate* d);
-    QExplicitlySharedDataPointer<QScriptSyntaxCheckResultPrivate> d_ptr;
-
-    friend class QScriptSyntaxCheckResultPrivate;
-};
-#endif // qscriptsyntaxcheckresult_h
diff --git a/qt/api/qscriptsyntaxcheckresult_p.h b/qt/api/qscriptsyntaxcheckresult_p.h
deleted file mode 100644 (file)
index 6e1a131..0000000
+++ /dev/null
@@ -1,73 +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.
-*/
-
-#ifndef qscriptsyntaxcheckresult_p_h
-#define qscriptsyntaxcheckresult_p_h
-
-#include "qscriptconverter_p.h"
-#include "qscriptengine_p.h"
-#include "qscriptsyntaxcheckresult.h"
-#include <JavaScriptCore/JavaScript.h>
-#include <QtCore/qshareddata.h>
-
-class QScriptSyntaxCheckResultPrivate : public QSharedData {
-public:
-    static inline QScriptSyntaxCheckResult get(QScriptSyntaxCheckResultPrivate* p);
-    inline QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine);
-    inline QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine, JSObjectRef value);
-    ~QScriptSyntaxCheckResultPrivate();
-
-    inline QScriptSyntaxCheckResult::State state() const;
-    int errorLineNumber() const;
-    inline int errorColumnNumber() const;
-    QString errorMessage() const;
-private:
-    JSObjectRef m_exception;
-    QScriptEnginePtr m_engine;
-};
-
-QScriptSyntaxCheckResult QScriptSyntaxCheckResultPrivate::get(QScriptSyntaxCheckResultPrivate* p)
-{
-    return QScriptSyntaxCheckResult(p);
-}
-
-QScriptSyntaxCheckResultPrivate::QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine)
-    : m_exception(0)
-    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-{}
-
-QScriptSyntaxCheckResultPrivate::QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine, JSObjectRef value)
-    : m_exception(value)
-    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-{}
-
-QScriptSyntaxCheckResult::State QScriptSyntaxCheckResultPrivate::state() const
-{
-    // FIXME This function doesn't return QScriptSyntaxCheckResult::Intermediate
-    return m_exception ? QScriptSyntaxCheckResult::Error : QScriptSyntaxCheckResult::Valid;
-}
-
-int QScriptSyntaxCheckResultPrivate::errorColumnNumber() const
-{
-    // FIXME JSC C API doesn't expose the error column number.
-    return m_exception ? 1 : -1;
-}
-
-
-#endif // qscriptsyntaxcheckresult_p_h
diff --git a/qt/api/qscriptvalue.cpp b/qt/api/qscriptvalue.cpp
deleted file mode 100644 (file)
index 8a7a6c4..0000000
+++ /dev/null
@@ -1,802 +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 "qscriptvalue.h"
-
-#include "qscriptengine.h"
-#include "qscriptengine_p.h"
-#include "qscriptvalue_p.h"
-#include <QtCore/qdebug.h>
-
-/*!
-    Constructs an invalid value.
-*/
-QScriptValue::QScriptValue()
-    : d_ptr(new QScriptValuePrivate())
-{
-}
-
-/*!
-  Constructs a new QScriptValue with a boolean \a value.
-*/
-QScriptValue::QScriptValue(bool value)
-    : d_ptr(new QScriptValuePrivate(value))
-{
-}
-
-/*!
-  Constructs a new QScriptValue with a number \a value.
-*/
-QScriptValue::QScriptValue(int value)
-    : d_ptr(new QScriptValuePrivate(value))
-{
-}
-
-/*!
-  Constructs a new QScriptValue with a number \a value.
-*/
-QScriptValue::QScriptValue(uint value)
-    : d_ptr(new QScriptValuePrivate(value))
-{
-}
-
-/*!
-  Constructs a new QScriptValue with a number \a value.
-*/
-QScriptValue::QScriptValue(qsreal value)
-    : d_ptr(new QScriptValuePrivate(value))
-{
-}
-
-/*!
-  Constructs a new QScriptValue with a string \a value.
-*/
-QScriptValue::QScriptValue(const QString& value)
-    : d_ptr(new QScriptValuePrivate(value))
-{
-}
-
-/*!
-  Constructs a new QScriptValue with a special \a value.
-*/
-QScriptValue::QScriptValue(SpecialValue value)
-    : d_ptr(new QScriptValuePrivate(value))
-{
-}
-
-/*!
-  Constructs a new QScriptValue with a string \a value.
-*/
-QScriptValue::QScriptValue(const char* value)
-    : d_ptr(new QScriptValuePrivate(QString::fromUtf8(value)))
-{
-}
-
-/*!
-    Block automatic convertion to bool
-    \internal
-*/
-QScriptValue::QScriptValue(void* d)
-{
-    Q_ASSERT(false);
-}
-
-/*!
-    Constructs a new QScriptValue from private
-    \internal
-*/
-QScriptValue::QScriptValue(QScriptValuePrivate* d)
-    : d_ptr(d)
-{
-}
-
-/*!
-  \obsolete
-
-  Constructs a new QScriptValue with the boolean \a value and
-  registers it with the script \a engine.
-*/
-QScriptValue::QScriptValue(QScriptEngine* engine, bool value)
-{
-    if (engine)
-        d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value);
-    else
-        d_ptr = new QScriptValuePrivate(value);
-}
-
-/*!
-  \obsolete
-
-  Constructs a new QScriptValue with the integer \a value and
-  registers it with the script \a engine.
-*/
-QScriptValue::QScriptValue(QScriptEngine* engine, int value)
-{
-    if (engine)
-        d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value);
-    else
-        d_ptr = new QScriptValuePrivate(value);
-}
-
-/*!
-  \obsolete
-
-  Constructs a new QScriptValue with the unsigned integer \a value and
-  registers it with the script \a engine.
- */
-QScriptValue::QScriptValue(QScriptEngine* engine, uint value)
-{
-    if (engine)
-        d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value);
-    else
-        d_ptr = new QScriptValuePrivate(value);
-}
-
-/*!
-  \obsolete
-
-  Constructs a new QScriptValue with the qsreal \a value and
-  registers it with the script \a engine.
-*/
-QScriptValue::QScriptValue(QScriptEngine* engine, qsreal value)
-{
-    if (engine)
-        d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value);
-    else
-        d_ptr = new QScriptValuePrivate(value);
-}
-
-/*!
-  \obsolete
-
-  Constructs a new QScriptValue with the string \a value and
-  registers it with the script \a engine.
-*/
-QScriptValue::QScriptValue(QScriptEngine* engine, const QString& value)
-{
-    if (engine)
-        d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value);
-    else
-        d_ptr = new QScriptValuePrivate(value);
-}
-
-/*!
-  \obsolete
-
-  Constructs a new QScriptValue with the string \a value and
-  registers it with the script \a engine.
-*/
-QScriptValue::QScriptValue(QScriptEngine* engine, const char* value)
-{
-    if (engine)
-        d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), QString::fromUtf8(value));
-    else
-        d_ptr = new QScriptValuePrivate(QString::fromUtf8(value));
-}
-
-/*!
-  \obsolete
-
-  Constructs a new QScriptValue with the special \a value and
-  registers it with the script \a engine.
-*/
-QScriptValue::QScriptValue(QScriptEngine* engine, SpecialValue value)
-{
-    if (engine)
-        d_ptr = new QScriptValuePrivate(QScriptEnginePrivate::get(engine), value);
-    else
-        d_ptr = new QScriptValuePrivate(value);
-}
-
-/*!
-  Constructs a new QScriptValue that is a copy of \a other.
-
-  Note that if \a other is an object (i.e., isObject() would return
-  true), then only a reference to the underlying object is copied into
-  the new script value (i.e., the object itself is not copied).
-*/
-QScriptValue::QScriptValue(const QScriptValue& other)
-    : d_ptr(other.d_ptr)
-{
-}
-
-/*!
-    Destroys this QScriptValue.
-*/
-QScriptValue::~QScriptValue()
-{
-}
-
-/*!
-  Returns true if this QScriptValue is valid; otherwise returns
-  false.
-*/
-bool QScriptValue::isValid() const
-{
-    return d_ptr->isValid();
-}
-
-/*!
-  Returns true if this QScriptValue is of the primitive type Boolean;
-  otherwise returns false.
-
-  \sa toBool()
-*/
-bool QScriptValue::isBool() const
-{
-    return d_ptr->isBool();
-}
-
-/*!
-  \obsolete
-
-  Use isBool() instead.
-  Returns true if this QScriptValue is of the primitive type Boolean;
-  otherwise returns false.
-*/
-bool QScriptValue::isBoolean() const
-{
-    return d_ptr->isBool();
-}
-
-/*!
-  Returns true if this QScriptValue is of the primitive type Number;
-  otherwise returns false.
-
-  \sa toNumber()
-*/
-bool QScriptValue::isNumber() const
-{
-    return d_ptr->isNumber();
-}
-
-/*!
-  Returns true if this QScriptValue is of the primitive type Null;
-  otherwise returns false.
-
-  \sa QScriptEngine::nullValue()
-*/
-bool QScriptValue::isNull() const
-{
-    return d_ptr->isNull();
-}
-
-/*!
-  Returns true if this QScriptValue is of the primitive type String;
-  otherwise returns false.
-
-  \sa toString()
-*/
-bool QScriptValue::isString() const
-{
-    return d_ptr->isString();
-}
-
-/*!
-  Returns true if this QScriptValue is of the primitive type Undefined;
-  otherwise returns false.
-
-  \sa QScriptEngine::undefinedValue()
-*/
-bool QScriptValue::isUndefined() const
-{
-    return d_ptr->isUndefined();
-}
-
-/*!
-  Returns true if this QScriptValue is an object of the Error class;
-  otherwise returns false.
-
-  \sa QScriptContext::throwError()
-*/
-bool QScriptValue::isError() const
-{
-    return d_ptr->isError();
-}
-
-/*!
-  Returns true if this QScriptValue is an object of the Array class;
-  otherwise returns false.
-
-  \sa QScriptEngine::newArray()
-*/
-bool QScriptValue::isArray() const
-{
-    return d_ptr->isArray();
-}
-
-/*!
-    Returns true if this QScriptValue is an object of the Date class;
-    otherwise returns false.
-
-    \sa QScriptEngine::newDate()
-*/
-bool QScriptValue::isDate() const
-{
-    return d_ptr->isDate();
-}
-
-/*!
-  Returns true if this QScriptValue is of the Object type; otherwise
-  returns false.
-
-  Note that function values, variant values, and QObject values are
-  objects, so this function returns true for such values.
-
-  \sa toObject(), QScriptEngine::newObject()
-*/
-bool QScriptValue::isObject() const
-{
-    return d_ptr->isObject();
-}
-
-/*!
-  Returns true if this QScriptValue is a function; otherwise returns
-  false.
-
-  \sa call()
-*/
-bool QScriptValue::isFunction() const
-{
-    return d_ptr->isFunction();
-}
-
-/*!
-  Returns the string value of this QScriptValue, as defined in
-  \l{ECMA-262} section 9.8, "ToString".
-
-  Note that if this QScriptValue is an object, calling this function
-  has side effects on the script engine, since the engine will call
-  the object's toString() function (and possibly valueOf()) in an
-  attempt to convert the object to a primitive value (possibly
-  resulting in an uncaught script exception).
-
-  \sa isString()
-*/
-QString QScriptValue::toString() const
-{
-    return d_ptr->toString();
-}
-
-/*!
-  Returns the number value of this QScriptValue, as defined in
-  \l{ECMA-262} section 9.3, "ToNumber".
-
-  Note that if this QScriptValue is an object, calling this function
-  has side effects on the script engine, since the engine will call
-  the object's valueOf() function (and possibly toString()) in an
-  attempt to convert the object to a primitive value (possibly
-  resulting in an uncaught script exception).
-
-  \sa isNumber(), toInteger(), toInt32(), toUInt32(), toUInt16()
-*/
-qsreal QScriptValue::toNumber() const
-{
-    return d_ptr->toNumber();
-}
-
-/*!
-  Returns the boolean value of this QScriptValue, using the conversion
-  rules described in \l{ECMA-262} section 9.2, "ToBoolean".
-
-  Note that if this QScriptValue is an object, calling this function
-  has side effects on the script engine, since the engine will call
-  the object's valueOf() function (and possibly toString()) in an
-  attempt to convert the object to a primitive value (possibly
-  resulting in an uncaught script exception).
-
-  \sa isBool()
-*/
-bool QScriptValue::toBool() const
-{
-    return d_ptr->toBool();
-}
-
-/*!
-  \obsolete
-
-  Use toBool() instead.
-*/
-bool QScriptValue::toBoolean() const
-{
-    return d_ptr->toBool();
-}
-
-/*!
-  Returns the integer value of this QScriptValue, using the conversion
-  rules described in \l{ECMA-262} section 9.4, "ToInteger".
-
-  Note that if this QScriptValue is an object, calling this function
-  has side effects on the script engine, since the engine will call
-  the object's valueOf() function (and possibly toString()) in an
-  attempt to convert the object to a primitive value (possibly
-  resulting in an uncaught script exception).
-
-  \sa toNumber()
-*/
-qsreal QScriptValue::toInteger() const
-{
-    return d_ptr->toInteger();
-}
-
-/*!
-  Returns the signed 32-bit integer value of this QScriptValue, using
-  the conversion rules described in \l{ECMA-262} section 9.5, "ToInt32".
-
-  Note that if this QScriptValue is an object, calling this function
-  has side effects on the script engine, since the engine will call
-  the object's valueOf() function (and possibly toString()) in an
-  attempt to convert the object to a primitive value (possibly
-  resulting in an uncaught script exception).
-
-  \sa toNumber(), toUInt32()
-*/
-qint32 QScriptValue::toInt32() const
-{
-    return d_ptr->toInt32();
-}
-
-/*!
-  Returns the unsigned 32-bit integer value of this QScriptValue, using
-  the conversion rules described in \l{ECMA-262} section 9.6, "ToUint32".
-
-  Note that if this QScriptValue is an object, calling this function
-  has side effects on the script engine, since the engine will call
-  the object's valueOf() function (and possibly toString()) in an
-  attempt to convert the object to a primitive value (possibly
-  resulting in an uncaught script exception).
-
-  \sa toNumber(), toInt32()
-*/
-quint32 QScriptValue::toUInt32() const
-{
-    return d_ptr->toUInt32();
-}
-
-/*!
-  Returns the unsigned 16-bit integer value of this QScriptValue, using
-  the conversion rules described in \l{ECMA-262} section 9.7, "ToUint16".
-
-  Note that if this QScriptValue is an object, calling this function
-  has side effects on the script engine, since the engine will call
-  the object's valueOf() function (and possibly toString()) in an
-  attempt to convert the object to a primitive value (possibly
-  resulting in an uncaught script exception).
-
-  \sa toNumber()
-*/
-quint16 QScriptValue::toUInt16() const
-{
-    return d_ptr->toUInt16();
-}
-
-/*!
-  \obsolete
-
-  This function is obsolete; use QScriptEngine::toObject() instead.
-*/
-QScriptValue QScriptValue::toObject() const
-{
-    return QScriptValuePrivate::get(d_ptr->toObject());
-}
-
-/*!
-    Returns a QDateTime representation of this value, in local time.
-    If this QScriptValue is not a date, or the value of the date is
-    NaN (Not-a-Number), an invalid QDateTime is returned.
-
-    \sa isDate()
-*/
-QDateTime QScriptValue::toDateTime() const
-{
-    return d_ptr->toDateTime();
-}
-
-/*!
-  Calls this QScriptValue as a function, using \a thisObject as
-  the `this' object in the function call, and passing \a args
-  as arguments to the function. Returns the value returned from
-  the function.
-
-  If this QScriptValue is not a function, call() does nothing
-  and returns an invalid QScriptValue.
-
-  Note that if \a thisObject is not an object, the global object
-  (see \l{QScriptEngine::globalObject()}) will be used as the
-  `this' object.
-
-  Calling call() can cause an exception to occur in the script engine;
-  in that case, call() returns the value that was thrown (typically an
-  \c{Error} object). You can call
-  QScriptEngine::hasUncaughtException() to determine if an exception
-  occurred.
-
-  \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 2
-
-  \sa construct()
-*/
-QScriptValue QScriptValue::call(const QScriptValue& thisObject, const QScriptValueList& args)
-{
-    return d_ptr->call(thisObject.d_ptr.data(), args);
-}
-
-/*!
-  Returns the QScriptEngine that created this QScriptValue,
-  or 0 if this QScriptValue is invalid or the value is not
-  associated with a particular engine.
-*/
-QScriptEngine* QScriptValue::engine() const
-{
-    QScriptEnginePrivate* engine = d_ptr->engine();
-    if (engine)
-        return QScriptEnginePrivate::get(engine);
-    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.
-
-  Note that if \a other is an object (isObject() returns true),
-  only a reference to the underlying object will be assigned;
-  the object itself will not be copied.
-*/
-QScriptValue& QScriptValue::operator=(const QScriptValue& other)
-{
-    d_ptr = other.d_ptr;
-    return *this;
-}
-
-/*!
-  Returns true if this QScriptValue is equal to \a other, otherwise
-  returns false. The comparison follows the behavior described in
-  \l{ECMA-262} section 11.9.3, "The Abstract Equality Comparison
-  Algorithm".
-
-  This function can return true even if the type of this QScriptValue
-  is different from the type of the \a other value; i.e. the
-  comparison is not strict.  For example, comparing the number 9 to
-  the string "9" returns true; comparing an undefined value to a null
-  value returns true; comparing a \c{Number} object whose primitive
-  value is 6 to a \c{String} object whose primitive value is "6"
-  returns true; and comparing the number 1 to the boolean value
-  \c{true} returns true. If you want to perform a comparison
-  without such implicit value conversion, use strictlyEquals().
-
-  Note that if this QScriptValue or the \a other value are objects,
-  calling this function has side effects on the script engine, since
-  the engine will call the object's valueOf() function (and possibly
-  toString()) in an attempt to convert the object to a primitive value
-  (possibly resulting in an uncaught script exception).
-
-  \sa strictlyEquals(), lessThan()
-*/
-bool QScriptValue::equals(const QScriptValue& other) const
-{
-    return d_ptr->equals(QScriptValuePrivate::get(other));
-}
-
-/*!
-  Returns true if this QScriptValue is equal to \a other using strict
-  comparison (no conversion), otherwise returns false. The comparison
-  follows the behavior described in \l{ECMA-262} section 11.9.6, "The
-  Strict Equality Comparison Algorithm".
-
-  If the type of this QScriptValue is different from the type of the
-  \a other value, this function returns false. If the types are equal,
-  the result depends on the type, as shown in the following table:
-
-    \table
-    \header \o Type \o Result
-    \row    \o Undefined  \o true
-    \row    \o Null       \o true
-    \row    \o Boolean    \o true if both values are true, false otherwise
-    \row    \o Number     \o false if either value is NaN (Not-a-Number); true if values are equal, false otherwise
-    \row    \o String     \o true if both values are exactly the same sequence of characters, false otherwise
-    \row    \o Object     \o true if both values refer to the same object, false otherwise
-    \endtable
-
-  \sa equals()
-*/
-bool QScriptValue::strictlyEquals(const QScriptValue& other) const
-{
-    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);
-}
diff --git a/qt/api/qscriptvalue.h b/qt/api/qscriptvalue.h
deleted file mode 100644 (file)
index bd33849..0000000
+++ /dev/null
@@ -1,140 +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.
-*/
-
-#ifndef qscriptvalue_h
-#define qscriptvalue_h
-
-#include "qscriptstring.h"
-#include <QtCore/qlist.h>
-#include <QtCore/qshareddata.h>
-
-class QScriptEngine;
-class QScriptValuePrivate;
-class QDateTime;
-
-class QScriptValue;
-typedef QList<QScriptValue> QScriptValueList;
-
-typedef double qsreal;
-
-class QScriptValue {
-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
-    };
-
-    QScriptValue();
-    QScriptValue(bool value);
-    QScriptValue(int value);
-    QScriptValue(uint value);
-    QScriptValue(qsreal value);
-    QScriptValue(const QString& value);
-    QScriptValue(const char* value);
-    QScriptValue(SpecialValue value);
-    QScriptValue(const QScriptValue& other);
-
-    QScriptValue(QScriptEngine* engine, bool value);
-    QScriptValue(QScriptEngine* engine, int value);
-    QScriptValue(QScriptEngine* engine, uint value);
-    QScriptValue(QScriptEngine* engine, qsreal value);
-    QScriptValue(QScriptEngine* engine, const QString& value);
-    QScriptValue(QScriptEngine* engine, const char* value);
-    QScriptValue(QScriptEngine* engine, SpecialValue value);
-
-    ~QScriptValue();
-
-    QScriptValue& operator=(const QScriptValue& other);
-
-    QScriptValue prototype() const;
-    void setPrototype(const QScriptValue& prototype);
-
-    bool equals(const QScriptValue& other) const;
-    bool strictlyEquals(const QScriptValue& other) const;
-    bool instanceOf(const QScriptValue& other) const;
-
-    QScriptValue property(const QString& name, const ResolveFlags& mode = ResolvePrototype) const;
-    QScriptValue property(const QScriptString& name, const ResolveFlags& mode = ResolvePrototype) const;
-    QScriptValue property(quint32 arrayIndex, const ResolveFlags& mode = ResolvePrototype) const;
-
-    void setProperty(const QString& name, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
-    void setProperty(quint32 arrayIndex, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
-    void setProperty(const QScriptString& name, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
-
-    PropertyFlags propertyFlags(const QString& name, const ResolveFlags& mode = ResolvePrototype) const;
-    PropertyFlags propertyFlags(const QScriptString& name, const ResolveFlags& mode = ResolvePrototype) const;
-
-    QScriptEngine* engine() const;
-
-    bool isValid() const;
-    bool isBool() const;
-    bool isBoolean() const;
-    bool isNumber() const;
-    bool isFunction() const;
-    bool isNull() const;
-    bool isString() const;
-    bool isUndefined() const;
-    bool isObject() const;
-    bool isError() const;
-    bool isArray() const;
-    bool isDate() const;
-
-    QString toString() const;
-    qsreal toNumber() const;
-    bool toBool() const;
-    bool toBoolean() const;
-    qsreal toInteger() 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());
-private:
-    QScriptValue(void*);
-    QScriptValue(QScriptValuePrivate*);
-
-    QExplicitlySharedDataPointer<QScriptValuePrivate> d_ptr;
-
-    friend class QScriptValuePrivate;
-};
-
-#endif // qscriptvalue_h
diff --git a/qt/api/qscriptvalue_p.h b/qt/api/qscriptvalue_p.h
deleted file mode 100644 (file)
index f98a06a..0000000
+++ /dev/null
@@ -1,1220 +0,0 @@
-/*
-    Copyright (C) 2008 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 qscriptvalue_p_h
-#define qscriptvalue_p_h
-
-#include "qscriptconverter_p.h"
-#include "qscriptengine_p.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/qvarlengtharray.h>
-
-class QScriptEngine;
-class QScriptValue;
-
-/*
-  \internal
-  \class QScriptValuePrivate
-
-  Implementation of QScriptValue.
-  The implementation is based on a state machine. The states names are included in
-  QScriptValuePrivate::State. Each method should check for the current state and then perform a
-  correct action.
-
-  State:
-    Invalid -> QSVP is invalid, no assumptions should be made about class members (apart from m_value).
-    CString -> QSVP is created from QString or const char* and no JSC engine has been associated yet.
-        Current value is kept in m_string,
-    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_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.
-    JSObject -> QSVP is associated with engine, and it is sure that it is a JavaScript object.
-
-  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 {
-public:
-    inline static QScriptValuePrivate* get(const QScriptValue& q);
-    inline static QScriptValue get(const QScriptValuePrivate* d);
-    inline static QScriptValue get(QScriptValuePrivate* d);
-
-    inline ~QScriptValuePrivate();
-
-    inline QScriptValuePrivate();
-    inline QScriptValuePrivate(const QString& string);
-    inline QScriptValuePrivate(bool value);
-    inline QScriptValuePrivate(int number);
-    inline QScriptValuePrivate(uint number);
-    inline QScriptValuePrivate(qsreal number);
-    inline QScriptValuePrivate(QScriptValue::SpecialValue value);
-
-    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, bool value);
-    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, int value);
-    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, uint value);
-    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, qsreal value);
-    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, const QString& value);
-    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, QScriptValue::SpecialValue value);
-
-    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value);
-    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSObjectRef object);
-
-    inline bool isValid() const;
-    inline bool isBool();
-    inline bool isNumber();
-    inline bool isNull();
-    inline bool isString();
-    inline bool isUndefined();
-    inline bool isError();
-    inline bool isObject();
-    inline bool isFunction();
-    inline bool isArray();
-    inline bool isDate();
-
-    inline QString toString() const;
-    inline qsreal toNumber() const;
-    inline bool toBool() const;
-    inline qsreal toInteger() const;
-    inline qint32 toInt32() 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 strictlyEquals(QScriptValuePrivate* other);
-    inline bool instanceOf(QScriptValuePrivate* other);
-    inline bool assignEngine(QScriptEnginePrivate* engine);
-
-    inline QScriptValuePrivate* property(const QString& name, const QScriptValue::ResolveFlags& mode);
-    inline QScriptValuePrivate* property(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode);
-    inline QScriptValuePrivate* property(quint32 arrayIndex, const QScriptValue::ResolveFlags& mode);
-    inline JSValueRef property(quint32 property, JSValueRef* exception);
-    inline JSValueRef property(JSStringRef property, JSValueRef* exception);
-    inline bool hasOwnProperty(quint32 property);
-    inline bool hasOwnProperty(JSStringRef property);
-    template<typename T>
-    inline QScriptValuePrivate* property(T name, const QScriptValue::ResolveFlags& mode);
-
-    inline void setProperty(const QString& name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
-    inline void setProperty(const QScriptStringPrivate* name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
-    inline void setProperty(const quint32 indexArray, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
-    inline void setProperty(quint32 property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception);
-    inline void setProperty(JSStringRef property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception);
-    inline void deleteProperty(quint32 property, JSValueRef* exception);
-    inline void deleteProperty(JSStringRef property, JSValueRef* exception);
-    template<typename T>
-    inline void setProperty(T name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
-
-    QScriptValue::PropertyFlags propertyFlags(const QString& name, const QScriptValue::ResolveFlags& mode);
-    QScriptValue::PropertyFlags propertyFlags(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode);
-    QScriptValue::PropertyFlags propertyFlags(const JSStringRef name, const QScriptValue::ResolveFlags& mode);
-
-    inline QScriptValuePrivate* call(const QScriptValuePrivate* , const QScriptValueList& args);
-
-    inline operator JSValueRef() const;
-    inline operator JSObjectRef() const;
-
-    inline QScriptEnginePrivate* engine() const;
-
-private:
-    // Please, update class documentation when you change the enum.
-    enum State {
-        Invalid = 0,
-        CString = 0x1000,
-        CNumber,
-        CBool,
-        CNull,
-        CUndefined,
-        JSValue = 0x2000, // JS values are equal or higher then this value.
-        JSPrimitive,
-        JSObject
-    } m_state;
-    QScriptEnginePtr m_engine;
-    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 State refinedJSValue();
-
-    inline bool isJSBased() const;
-    inline bool isNumberBased() const;
-    inline bool isStringBased() const;
-};
-
-QScriptValuePrivate* QScriptValuePrivate::get(const QScriptValue& q) { return q.d_ptr.data(); }
-
-QScriptValue QScriptValuePrivate::get(const QScriptValuePrivate* d)
-{
-    return QScriptValue(const_cast<QScriptValuePrivate*>(d));
-}
-
-QScriptValue QScriptValuePrivate::get(QScriptValuePrivate* d)
-{
-    return QScriptValue(d);
-}
-
-QScriptValuePrivate::~QScriptValuePrivate()
-{
-    if (isJSBased())
-        JSValueUnprotect(*m_engine, u.m_value);
-    else if (isStringBased())
-        delete u.m_string;
-}
-
-QScriptValuePrivate::QScriptValuePrivate()
-    : m_state(Invalid)
-{
-}
-
-QScriptValuePrivate::QScriptValuePrivate(const QString& string)
-    : m_state(CString)
-    , u(new QString(string))
-{
-}
-
-QScriptValuePrivate::QScriptValuePrivate(bool value)
-    : m_state(CBool)
-    , u(value)
-{
-}
-
-QScriptValuePrivate::QScriptValuePrivate(int number)
-    : m_state(CNumber)
-    , u(number)
-{
-}
-
-QScriptValuePrivate::QScriptValuePrivate(uint number)
-    : m_state(CNumber)
-    , u(number)
-{
-}
-
-QScriptValuePrivate::QScriptValuePrivate(qsreal number)
-    : m_state(CNumber)
-    , u(number)
-{
-}
-
-QScriptValuePrivate::QScriptValuePrivate(QScriptValue::SpecialValue value)
-    : m_state(value == QScriptValue::NullValue ? CNull : CUndefined)
-{
-}
-
-QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, bool value)
-    : m_state(JSPrimitive)
-    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , u(engine->makeJSValue(value))
-{
-    Q_ASSERT(engine);
-    JSValueProtect(*m_engine, u.m_value);
-}
-
-QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, int value)
-    : m_state(JSPrimitive)
-    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , u(m_engine->makeJSValue(value))
-{
-    Q_ASSERT(engine);
-    JSValueProtect(*m_engine, u.m_value);
-}
-
-QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, uint value)
-    : m_state(JSPrimitive)
-    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , u(m_engine->makeJSValue(value))
-{
-    Q_ASSERT(engine);
-    JSValueProtect(*m_engine, u.m_value);
-}
-
-QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, qsreal value)
-    : m_state(JSPrimitive)
-    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , u(m_engine->makeJSValue(value))
-{
-    Q_ASSERT(engine);
-    JSValueProtect(*m_engine, u.m_value);
-}
-
-QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, const QString& value)
-    : m_state(JSPrimitive)
-    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , u(m_engine->makeJSValue(value))
-{
-    Q_ASSERT(engine);
-    JSValueProtect(*m_engine, u.m_value);
-}
-
-QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, QScriptValue::SpecialValue value)
-    : m_state(JSPrimitive)
-    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , u(m_engine->makeJSValue(value))
-{
-    Q_ASSERT(engine);
-    JSValueProtect(*m_engine, u.m_value);
-}
-
-QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value)
-    : m_state(JSValue)
-    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , u(value)
-{
-    Q_ASSERT(engine);
-    Q_ASSERT(value);
-    JSValueProtect(*m_engine, u.m_value);
-}
-
-QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSObjectRef object)
-    : m_state(JSObject)
-    , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , u(object)
-{
-    Q_ASSERT(engine);
-    Q_ASSERT(object);
-    JSValueProtect(*m_engine, object);
-}
-
-bool QScriptValuePrivate::isValid() const { return m_state != Invalid; }
-
-bool QScriptValuePrivate::isBool()
-{
-    switch (m_state) {
-    case CBool:
-        return true;
-    case JSValue:
-        if (refinedJSValue() != JSPrimitive)
-            return false;
-        // Fall-through.
-    case JSPrimitive:
-        return JSValueIsBoolean(*m_engine, *this);
-    default:
-        return false;
-    }
-}
-
-bool QScriptValuePrivate::isNumber()
-{
-    switch (m_state) {
-    case CNumber:
-        return true;
-    case JSValue:
-        if (refinedJSValue() != JSPrimitive)
-            return false;
-        // Fall-through.
-    case JSPrimitive:
-        return JSValueIsNumber(*m_engine, *this);
-    default:
-        return false;
-    }
-}
-
-bool QScriptValuePrivate::isNull()
-{
-    switch (m_state) {
-    case CNull:
-        return true;
-    case JSValue:
-        if (refinedJSValue() != JSPrimitive)
-            return false;
-        // Fall-through.
-    case JSPrimitive:
-        return JSValueIsNull(*m_engine, *this);
-    default:
-        return false;
-    }
-}
-
-bool QScriptValuePrivate::isString()
-{
-    switch (m_state) {
-    case CString:
-        return true;
-    case JSValue:
-        if (refinedJSValue() != JSPrimitive)
-            return false;
-        // Fall-through.
-    case JSPrimitive:
-        return JSValueIsString(*m_engine, *this);
-    default:
-        return false;
-    }
-}
-
-bool QScriptValuePrivate::isUndefined()
-{
-    switch (m_state) {
-    case CUndefined:
-        return true;
-    case JSValue:
-        if (refinedJSValue() != JSPrimitive)
-            return false;
-        // Fall-through.
-    case JSPrimitive:
-        return JSValueIsUndefined(*m_engine, *this);
-    default:
-        return false;
-    }
-}
-
-bool QScriptValuePrivate::isError()
-{
-    switch (m_state) {
-    case JSValue:
-        if (refinedJSValue() != JSObject)
-            return false;
-        // Fall-through.
-    case JSObject:
-        return m_engine->isError(*this);
-    default:
-        return false;
-    }
-}
-
-bool QScriptValuePrivate::isObject()
-{
-    switch (m_state) {
-    case JSValue:
-        return refinedJSValue() == JSObject;
-    case JSObject:
-        return true;
-
-    default:
-        return false;
-    }
-}
-
-bool QScriptValuePrivate::isFunction()
-{
-    switch (m_state) {
-    case JSValue:
-        if (refinedJSValue() != JSObject)
-            return false;
-        // Fall-through.
-    case JSObject:
-        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;
-    }
-}
-
-QString QScriptValuePrivate::toString() const
-{
-    switch (m_state) {
-    case Invalid:
-        return QString();
-    case CBool:
-        return u.m_bool ? QString::fromLatin1("true") : QString::fromLatin1("false");
-    case CString:
-        return *u.m_string;
-    case CNumber:
-        return QScriptConverter::toString(u.m_number);
-    case CNull:
-        return QString::fromLatin1("null");
-    case CUndefined:
-        return QString::fromLatin1("undefined");
-    case JSValue:
-    case JSPrimitive:
-    case JSObject:
-        JSValueRef exception = 0;
-        JSRetainPtr<JSStringRef> ptr(Adopt, JSValueToStringCopy(*m_engine, *this, &exception));
-        m_engine->setException(exception);
-        return QScriptConverter::toString(ptr.get());
-    }
-
-    Q_ASSERT_X(false, "toString()", "Not all states are included in the previous switch statement.");
-    return QString(); // Avoid compiler warning.
-}
-
-qsreal QScriptValuePrivate::toNumber() const
-{
-    switch (m_state) {
-    case JSValue:
-    case JSPrimitive:
-    case JSObject:
-        {
-            JSValueRef exception = 0;
-            qsreal result = JSValueToNumber(*m_engine, *this, &exception);
-            m_engine->setException(exception);
-            return result;
-        }
-    case CNumber:
-        return u.m_number;
-    case CBool:
-        return u.m_bool ? 1 : 0;
-    case CNull:
-    case Invalid:
-        return 0;
-    case CUndefined:
-        return qQNaN();
-    case CString:
-        bool ok;
-        qsreal result = u.m_string->toDouble(&ok);
-        if (ok)
-            return result;
-        result = u.m_string->toInt(&ok, 0); // Try other bases.
-        if (ok)
-            return result;
-        if (*u.m_string == "Infinity" || *u.m_string == "-Infinity")
-            return qInf();
-        return u.m_string->length() ? qQNaN() : 0;
-    }
-
-    Q_ASSERT_X(false, "toNumber()", "Not all states are included in the previous switch statement.");
-    return 0; // Avoid compiler warning.
-}
-
-bool QScriptValuePrivate::toBool() const
-{
-    switch (m_state) {
-    case JSValue:
-    case JSPrimitive:
-        return JSValueToBoolean(*m_engine, *this);
-    case JSObject:
-        return true;
-    case CNumber:
-        return !(qIsNaN(u.m_number) || !u.m_number);
-    case CBool:
-        return u.m_bool;
-    case Invalid:
-    case CNull:
-    case CUndefined:
-        return false;
-    case CString:
-        return u.m_string->length();
-    }
-
-    Q_ASSERT_X(false, "toBool()", "Not all states are included in the previous switch statement.");
-    return false; // Avoid compiler warning.
-}
-
-qsreal QScriptValuePrivate::toInteger() const
-{
-    qsreal result = toNumber();
-    if (qIsNaN(result))
-        return 0;
-    if (qIsInf(result))
-        return result;
-    return (result > 0) ? qFloor(result) : -1 * qFloor(-result);
-}
-
-qint32 QScriptValuePrivate::toInt32() const
-{
-    qsreal result = toInteger();
-    // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but
-    // some of these operation are invoked in toInteger subcall.
-    if (qIsInf(result))
-        return 0;
-    return result;
-}
-
-quint32 QScriptValuePrivate::toUInt32() const
-{
-    qsreal result = toInteger();
-    // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but
-    // some of these operation are invoked in toInteger subcall.
-    if (qIsInf(result))
-        return 0;
-    return result;
-}
-
-quint16 QScriptValuePrivate::toUInt16() const
-{
-    return toInt32();
-}
-
-/*!
-  Creates a copy of this value and converts it to an object. If this value is an object
-  then pointer to this value will be returned.
-  \attention it should not happen but if this value is bounded to a different engine that the given, the first
-  one will be used.
-  \internal
-  */
-QScriptValuePrivate* QScriptValuePrivate::toObject(QScriptEnginePrivate* engine)
-{
-    switch (m_state) {
-    case Invalid:
-    case CNull:
-    case CUndefined:
-        return new QScriptValuePrivate;
-    case CString:
-        {
-            // Exception can't occur here.
-            JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(*u.m_string), /* exception */ 0);
-            Q_ASSERT(object);
-            return new QScriptValuePrivate(engine, object);
-        }
-    case CNumber:
-        {
-            // Exception can't occur here.
-            JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(u.m_number), /* exception */ 0);
-            Q_ASSERT(object);
-            return new QScriptValuePrivate(engine, object);
-        }
-    case CBool:
-        {
-            // Exception can't occure here.
-            JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(u.m_bool), /* exception */ 0);
-            Q_ASSERT(object);
-            return new QScriptValuePrivate(engine, object);
-        }
-    case JSValue:
-        if (refinedJSValue() != JSPrimitive)
-            break;
-        // Fall-through.
-    case JSPrimitive:
-        {
-            if (engine != this->engine())
-                qWarning("QScriptEngine::toObject: cannot convert value created in a different engine");
-            JSValueRef exception = 0;
-            JSObjectRef object = JSValueToObject(*m_engine, *this, &exception);
-            if (object)
-                return new QScriptValuePrivate(m_engine.constData(), object);
-            else
-                m_engine->setException(exception, QScriptEnginePrivate::NotNullException);
-
-        }
-        return new QScriptValuePrivate;
-    case JSObject:
-        break;
-    }
-
-    if (engine != this->engine())
-        qWarning("QScriptEngine::toObject: cannot convert value created in a different engine");
-    Q_ASSERT(m_state == JSObject);
-    return this;
-}
-
-/*!
-  This method is created only for QScriptValue::toObject() purpose which is obsolete.
-  \internal
- */
-QScriptValuePrivate* QScriptValuePrivate::toObject()
-{
-    if (isJSBased())
-        return toObject(m_engine.data());
-
-    // Without an engine there is not much we can do.
-    return new QScriptValuePrivate;
-}
-
-QDateTime QScriptValuePrivate::toDateTime()
-{
-    if (!isDate())
-        return QDateTime();
-
-    JSValueRef exception = 0;
-    qsreal t = JSValueToNumber(*m_engine, *this, &exception);
-
-    if (exception) {
-        m_engine->setException(exception, QScriptEnginePrivate::NotNullException);
-        return QDateTime();
-    }
-
-    QDateTime result;
-    result.setMSecsSinceEpoch(qint64(t));
-    return result;
-}
-
-inline QScriptValuePrivate* QScriptValuePrivate::prototype()
-{
-    if (isObject()) {
-        JSValueRef prototype = JSObjectGetPrototype(*m_engine, *this);
-        if (JSValueIsNull(*m_engine, prototype))
-            return new QScriptValuePrivate(engine(), prototype);
-        // The prototype could be either a null or a JSObject, so it is safe to cast the prototype
-        // to the JSObjectRef here.
-        return new QScriptValuePrivate(engine(), const_cast<JSObjectRef>(prototype));
-    }
-    return new QScriptValuePrivate;
-}
-
-inline void QScriptValuePrivate::setPrototype(QScriptValuePrivate* prototype)
-{
-    if (isObject() && prototype->isValid() && (prototype->isObject() || prototype->isNull())) {
-        if (engine() != prototype->engine()) {
-            qWarning("QScriptValue::setPrototype() failed: cannot set a prototype created in a different engine");
-            return;
-        }
-        // FIXME: This could be replaced by a new, faster API
-        // look at https://bugs.webkit.org/show_bug.cgi?id=40060
-        JSObjectSetPrototype(*m_engine, *this, *prototype);
-        JSValueRef proto = JSObjectGetPrototype(*m_engine, *this);
-        if (!JSValueIsStrictEqual(*m_engine, proto, *prototype))
-            qWarning("QScriptValue::setPrototype() failed: cyclic prototype value");
-    }
-}
-
-bool QScriptValuePrivate::equals(QScriptValuePrivate* other)
-{
-    if (!isValid())
-        return !other->isValid();
-
-    if (!other->isValid())
-        return false;
-
-    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 (!other->assignEngine(engine())) {
-            qWarning("equals(): Cannot compare to a value created in a different engine");
-            return false;
-        }
-    } else if (!isJSBased() && other->isJSBased()) {
-        if (!assignEngine(other->engine())) {
-            qWarning("equals(): Cannot compare to a value created in a different engine");
-            return false;
-        }
-    }
-
-    JSValueRef exception = 0;
-    bool result = JSValueIsEqual(*m_engine, *this, *other, &exception);
-    m_engine->setException(exception);
-    return result;
-}
-
-bool QScriptValuePrivate::strictlyEquals(QScriptValuePrivate* other)
-{
-    if (isJSBased()) {
-        // We can't compare these two values without binding to the same engine.
-        if (!other->isJSBased()) {
-            if (other->assignEngine(engine()))
-                return JSValueIsStrictEqual(*m_engine, *this, *other);
-            return false;
-        }
-        if (other->engine() != engine()) {
-            qWarning("strictlyEquals(): Cannot compare to a value created in a different engine");
-            return false;
-        }
-        return JSValueIsStrictEqual(*m_engine, *this, *other);
-    }
-    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;
-}
-
-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;
-}
-
-/*!
-  Tries to assign \a engine to this value. Returns true on success; otherwise returns false.
-*/
-bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
-{
-    Q_ASSERT(engine);
-    JSValueRef value;
-    switch (m_state) {
-    case CBool:
-        value = engine->makeJSValue(u.m_bool);
-        break;
-    case CString:
-        value = engine->makeJSValue(*u.m_string);
-        delete u.m_string;
-        break;
-    case CNumber:
-        value = engine->makeJSValue(u.m_number);
-        break;
-    case CNull:
-        value = engine->makeJSValue(QScriptValue::NullValue);
-        break;
-    case CUndefined:
-        value = engine->makeJSValue(QScriptValue::UndefinedValue);
-        break;
-    default:
-        if (!isJSBased())
-            Q_ASSERT_X(!isJSBased(), "assignEngine()", "Not all states are included in the previous switch statement.");
-        else
-            qWarning("JSValue can't be rassigned to an another engine.");
-        return false;
-    }
-    m_engine = engine;
-    m_state = JSPrimitive;
-    u.m_value = value;
-    JSValueProtect(*m_engine, value);
-    return true;
-}
-
-inline QScriptValuePrivate* QScriptValuePrivate::property(const QString& name, const QScriptValue::ResolveFlags& mode)
-{
-    JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
-    return property<JSStringRef>(propertyName.get(), mode);
-}
-
-inline QScriptValuePrivate* QScriptValuePrivate::property(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode)
-{
-    return property<JSStringRef>(*name, mode);
-}
-
-inline QScriptValuePrivate* QScriptValuePrivate::property(quint32 arrayIndex, const QScriptValue::ResolveFlags& mode)
-{
-    return property<quint32>(arrayIndex, mode);
-}
-
-/*!
-    \internal
-    This method was created to unify access to the JSObjectGetPropertyAtIndex and the JSObjectGetProperty.
-*/
-inline JSValueRef QScriptValuePrivate::property(quint32 property, JSValueRef* exception)
-{
-    return JSObjectGetPropertyAtIndex(*m_engine, *this, property, exception);
-}
-
-/*!
-    \internal
-    This method was created to unify access to the JSObjectGetPropertyAtIndex and the JSObjectGetProperty.
-*/
-inline JSValueRef QScriptValuePrivate::property(JSStringRef property, JSValueRef* exception)
-{
-    return JSObjectGetProperty(*m_engine, *this, property, exception);
-}
-
-/*!
-    \internal
-    This method was created to unify acccess to hasOwnProperty, same function for an array index
-    and a property name access.
-*/
-inline bool QScriptValuePrivate::hasOwnProperty(quint32 property)
-{
-    Q_ASSERT(isObject());
-    // FIXME it could be faster, but JSC C API doesn't expose needed functionality.
-    JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
-    return hasOwnProperty(propertyName.get());
-}
-
-/*!
-    \internal
-    This method was created to unify acccess to hasOwnProperty, same function for an array index
-    and a property name access.
-*/
-inline bool QScriptValuePrivate::hasOwnProperty(JSStringRef property)
-{
-    Q_ASSERT(isObject());
-    return m_engine->objectHasOwnProperty(*this, property);
-}
-
-/*!
-    \internal
-    This function gets property of an object.
-    \arg propertyName could be type of quint32 (an array index) or JSStringRef (a property name).
-*/
-template<typename T>
-inline QScriptValuePrivate* QScriptValuePrivate::property(T propertyName, const QScriptValue::ResolveFlags& mode)
-{
-    if (!isObject())
-        return new QScriptValuePrivate();
-
-    if ((mode == QScriptValue::ResolveLocal) && (!hasOwnProperty(propertyName)))
-        return new QScriptValuePrivate();
-
-    JSValueRef exception = 0;
-    JSValueRef value = property(propertyName, &exception);
-
-    if (exception) {
-        m_engine->setException(exception, QScriptEnginePrivate::NotNullException);
-        return new QScriptValuePrivate(engine(), exception);
-    }
-    if (JSValueIsUndefined(*m_engine, value))
-        return new QScriptValuePrivate;
-    return new QScriptValuePrivate(engine(), value);
-}
-
-inline void QScriptValuePrivate::setProperty(const QString& name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
-{
-    JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
-    setProperty<JSStringRef>(propertyName.get(), value, flags);
-}
-
-inline void QScriptValuePrivate::setProperty(quint32 arrayIndex, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
-{
-    setProperty<quint32>(arrayIndex, value, flags);
-}
-
-inline void QScriptValuePrivate::setProperty(const QScriptStringPrivate* name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
-{
-    setProperty<JSStringRef>(*name, value, flags);
-}
-
-/*!
-    \internal
-    This method was created to unify access to the JSObjectSetPropertyAtIndex and the JSObjectSetProperty.
-*/
-inline void QScriptValuePrivate::setProperty(quint32 property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception)
-{
-    Q_ASSERT(isObject());
-    if (flags) {
-        // FIXME This could be better, but JSC C API doesn't expose needed functionality. It is
-        // not possible to create / modify a property attribute via an array index.
-        JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
-        JSObjectSetProperty(*m_engine, *this, propertyName.get(), value, flags, exception);
-        return;
-    }
-    JSObjectSetPropertyAtIndex(*m_engine, *this, property, value, exception);
-}
-
-/*!
-    \internal
-    This method was created to unify access to the JSObjectSetPropertyAtIndex and the JSObjectSetProperty.
-*/
-inline void QScriptValuePrivate::setProperty(JSStringRef property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception)
-{
-    Q_ASSERT(isObject());
-    JSObjectSetProperty(*m_engine, *this, property, value, flags, exception);
-}
-
-/*!
-    \internal
-    This method was created to unify access to the JSObjectDeleteProperty and a teoretical JSObjectDeletePropertyAtIndex
-    which doesn't exist now.
-*/
-inline void QScriptValuePrivate::deleteProperty(quint32 property, JSValueRef* exception)
-{
-    // FIXME It could be faster, we need a JSC C API for deleting array index properties.
-    JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
-    JSObjectDeleteProperty(*m_engine, *this, propertyName.get(), exception);
-}
-
-/*!
-    \internal
-    This method was created to unify access to the JSObjectDeleteProperty and a teoretical JSObjectDeletePropertyAtIndex.
-*/
-inline void QScriptValuePrivate::deleteProperty(JSStringRef property, JSValueRef* exception)
-{
-    Q_ASSERT(isObject());
-    JSObjectDeleteProperty(*m_engine, *this, property, exception);
-}
-
-template<typename T>
-inline void QScriptValuePrivate::setProperty(T name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
-{
-    if (!isObject())
-        return;
-
-    if (!value->isJSBased())
-        value->assignEngine(engine());
-
-    JSValueRef exception = 0;
-    if (!value->isValid()) {
-        // Remove the property.
-        deleteProperty(name, &exception);
-        m_engine->setException(exception);
-        return;
-    }
-    if (m_engine != value->m_engine) {
-        qWarning("QScriptValue::setProperty() failed: cannot set value created in a different engine");
-        return;
-    }
-
-    setProperty(name, *value, QScriptConverter::toPropertyFlags(flags), &exception);
-    m_engine->setException(exception);
-}
-
-inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const QString& name, const QScriptValue::ResolveFlags& mode)
-{
-    JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
-    return propertyFlags(propertyName.get(), mode);
-}
-
-inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode)
-{
-    return propertyFlags(*name, mode);
-}
-
-inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(JSStringRef name, const QScriptValue::ResolveFlags& mode)
-{
-    unsigned flags = 0;
-    if (!isObject())
-        return QScriptValue::PropertyFlags(flags);
-
-    // FIXME It could be faster and nicer, but new JSC C API should be created.
-    static JSStringRef objectName = QScriptConverter::toString("Object");
-    static JSStringRef propertyDescriptorName = QScriptConverter::toString("getOwnPropertyDescriptor");
-
-    // FIXME This is dangerous if global object was modified (bug 41839).
-    JSValueRef exception = 0;
-    JSObjectRef globalObject = JSContextGetGlobalObject(*m_engine);
-    JSValueRef objectConstructor = JSObjectGetProperty(*m_engine, globalObject, objectName, &exception);
-    Q_ASSERT(JSValueIsObject(*m_engine, objectConstructor));
-    JSValueRef propertyDescriptorGetter = JSObjectGetProperty(*m_engine, const_cast<JSObjectRef>(objectConstructor), propertyDescriptorName, &exception);
-    Q_ASSERT(JSValueIsObject(*m_engine, propertyDescriptorGetter));
-
-    JSValueRef arguments[] = { *this, JSValueMakeString(*m_engine, name) };
-    JSObjectRef propertyDescriptor
-            = const_cast<JSObjectRef>(JSObjectCallAsFunction(*m_engine,
-                                                            const_cast<JSObjectRef>(propertyDescriptorGetter),
-                                                            /* thisObject */ 0,
-                                                            /* argumentCount */ 2,
-                                                            arguments,
-                                                            &exception));
-    if (exception) {
-        // Invalid property.
-        return QScriptValue::PropertyFlags(flags);
-    }
-
-    if (!JSValueIsObject(*m_engine, propertyDescriptor)) {
-        // Property isn't owned by this object.
-        JSObjectRef proto;
-        if (mode == QScriptValue::ResolveLocal
-                || ((proto = const_cast<JSObjectRef>(JSObjectGetPrototype(*m_engine, *this))) && JSValueIsNull(*m_engine, proto))) {
-            return QScriptValue::PropertyFlags(flags);
-        }
-        QScriptValuePrivate p(engine(), proto);
-        return p.propertyFlags(name, QScriptValue::ResolvePrototype);
-    }
-
-    static JSStringRef writableName = QScriptConverter::toString("writable");
-    static JSStringRef configurableName = QScriptConverter::toString("configurable");
-    static JSStringRef enumerableName = QScriptConverter::toString("enumerable");
-
-    bool readOnly = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, writableName, &exception));
-    if (!exception && readOnly)
-        flags |= QScriptValue::ReadOnly;
-    bool undeletable = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, configurableName, &exception));
-    if (!exception && undeletable)
-        flags |= QScriptValue::Undeletable;
-    bool skipInEnum = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, enumerableName, &exception));
-    if (!exception && skipInEnum)
-        flags |= QScriptValue::SkipInEnumeration;
-
-    return QScriptValue::PropertyFlags(flags);
-}
-
-QScriptValuePrivate* QScriptValuePrivate::call(const QScriptValuePrivate*, const QScriptValueList& args)
-{
-    switch (m_state) {
-    case JSValue:
-        if (refinedJSValue() != JSObject)
-            return new QScriptValuePrivate;
-        // Fall-through.
-    case JSObject:
-        {
-            // Convert all arguments and bind to the engine.
-            int argc = args.size();
-            QVarLengthArray<JSValueRef, 8> argv(argc);
-            QScriptValueList::const_iterator i = args.constBegin();
-            for (int j = 0; i != args.constEnd(); j++, i++) {
-                QScriptValuePrivate* value = QScriptValuePrivate::get(*i);
-                if (!value->assignEngine(engine())) {
-                    qWarning("QScriptValue::call() failed: cannot call function with values created in a different engine");
-                    return new QScriptValuePrivate;
-                }
-                argv[j] = *value;
-            }
-
-            // Make the call
-            JSValueRef exception = 0;
-            JSValueRef result = JSObjectCallAsFunction(*m_engine, *this, /* thisObject */ 0, argc, argv.constData(), &exception);
-            if (!result && exception) {
-                m_engine->setException(exception);
-                return new QScriptValuePrivate(engine(), exception);
-            }
-            if (result && !exception)
-                return new QScriptValuePrivate(engine(), result);
-        }
-        // this QSV is not a function <-- !result && !exception. Fall-through.
-    default:
-        return new QScriptValuePrivate;
-    }
-}
-
-QScriptEnginePrivate* QScriptValuePrivate::engine() const
-{
-    // As long as m_engine is an autoinitializated pointer we can safely return it without
-    // checking current state.
-    return m_engine.data();
-}
-
-QScriptValuePrivate::operator JSValueRef() const
-{
-    Q_ASSERT(isJSBased());
-    Q_ASSERT(u.m_value);
-    return u.m_value;
-}
-
-QScriptValuePrivate::operator JSObjectRef() const
-{
-    Q_ASSERT(m_state == JSObject);
-    Q_ASSERT(u.m_object);
-    return u.m_object;
-}
-
-/*!
-  \internal
-  Refines the state of this QScriptValuePrivate. Returns the new state.
-*/
-QScriptValuePrivate::State QScriptValuePrivate::refinedJSValue()
-{
-    Q_ASSERT(m_state == JSValue);
-    if (!JSValueIsObject(*m_engine, *this)) {
-        m_state = JSPrimitive;
-    } else {
-        // Difference between JSValueRef and JSObjectRef is only in their type, binarywise it is the same.
-        // As m_value and m_object are stored in the u union, it is enough to change the m_state only.
-        m_state = JSObject;
-    }
-    return m_state;
-}
-
-/*!
-  \internal
-  Returns true if QSV have an engine associated.
-*/
-bool QScriptValuePrivate::isJSBased() const { return m_state >= JSValue; }
-
-/*!
-  \internal
-  Returns true if current value of QSV is placed in m_number.
-*/
-bool QScriptValuePrivate::isNumberBased() const { return m_state == CNumber || m_state == CBool; }
-
-/*!
-  \internal
-  Returns true if current value of QSV is placed in m_string.
-*/
-bool QScriptValuePrivate::isStringBased() const { return m_state == CString; }
-
-#endif // qscriptvalue_p_h
diff --git a/qt/api/qscriptvalueiterator.cpp b/qt/api/qscriptvalueiterator.cpp
deleted file mode 100644 (file)
index f1caa61..0000000
+++ /dev/null
@@ -1,226 +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 "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
deleted file mode 100644 (file)
index 0c90661..0000000
+++ /dev/null
@@ -1,63 +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.
-*/
-
-#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
deleted file mode 100644 (file)
index b93b518..0000000
+++ /dev/null
@@ -1,172 +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.
-*/
-
-#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/api/qtscriptglobal.h b/qt/api/qtscriptglobal.h
deleted file mode 100644 (file)
index efdfc50..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-    Copyright (C) 2008 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 qtscriptglobal_h
-#define qtscriptglobal_h
-
-#include <QtCore/qglobal.h>
-
-#if defined(QT_MAKEDLL)        /* create a Qt DLL library */
-#  if defined(QT_BUILD_JAVASCRIPT_LIB)
-#    define Q_JAVASCRIPT_EXPORT Q_DECL_EXPORT
-#  else
-#    define Q_JAVASCRIPT_EXPORT Q_DECL_IMPORT
-#  endif
-#elif defined(QT_DLL) /* use a Qt DLL library */
-#  define Q_JAVASCRIPT_EXPORT
-#endif
-
-#if !defined(Q_JAVASCRIPT_EXPORT)
-#  if defined(QT_SHARED)
-#    define Q_JAVASCRIPT_EXPORT Q_DECL_EXPORT
-#  else
-#    define Q_JAVASCRIPT_EXPORT
-#  endif
-#endif
-
-#endif
diff --git a/qt/benchmarks/benchmarks.pri b/qt/benchmarks/benchmarks.pri
deleted file mode 100644 (file)
index 5af3383..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-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
deleted file mode 100644 (file)
index 85fa82c..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS =   qscriptengine \
-            qscriptvalue \
-
diff --git a/qt/benchmarks/qscriptengine/qscriptengine.pro b/qt/benchmarks/qscriptengine/qscriptengine.pro
deleted file mode 100644 (file)
index e94137d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-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
deleted file mode 100644 (file)
index 0c447c6..0000000
+++ /dev/null
@@ -1,142 +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 "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
deleted file mode 100644 (file)
index 673fe65..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-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
deleted file mode 100644 (file)
index 7c39b8e..0000000
+++ /dev/null
@@ -1,442 +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 "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"
diff --git a/qt/tests/qscriptengine/qscriptengine.pro b/qt/tests/qscriptengine/qscriptengine.pro
deleted file mode 100644 (file)
index d521dd8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-TEMPLATE = app
-TARGET = tst_qscriptengine
-QT += testlib
-isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../..
-include(../tests.pri)
-
-SOURCES += tst_qscriptengine.cpp
-
diff --git a/qt/tests/qscriptengine/tst_qscriptengine.cpp b/qt/tests/qscriptengine/tst_qscriptengine.cpp
deleted file mode 100644 (file)
index dabcfb2..0000000
+++ /dev/null
@@ -1,734 +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 "qscriptengine.h"
-#include "qscriptprogram.h"
-#include "qscriptsyntaxcheckresult.h"
-#include "qscriptvalue.h"
-#include <QtCore/qnumeric.h>
-#include <QtTest/qtest.h>
-
-class tst_QScriptEngine : public QObject {
-    Q_OBJECT
-
-public:
-    tst_QScriptEngine() {}
-    virtual ~tst_QScriptEngine() {}
-
-public slots:
-    void init() {}
-    void cleanup() {}
-
-private slots:
-    void newFunction();
-    void newObject();
-    void globalObject();
-    void evaluate();
-    void collectGarbage();
-    void reportAdditionalMemoryCost();
-    void nullValue();
-    void undefinedValue();
-    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. */
-void tst_QScriptEngine::evaluate()
-{
-    QScriptEngine engine;
-    QVERIFY2(engine.evaluate("1+1").isValid(), "the expression should be evaluated and an valid result should be returned");
-    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;
-    QScriptValue global = engine.globalObject();
-    QScriptValue self = engine.evaluate("this");
-    QVERIFY(global.isObject());
-    QVERIFY(engine.globalObject().equals(engine.evaluate("this")));
-    QVERIFY(engine.globalObject().strictlyEquals(self));
-}
-
-/* Test garbage collection, at least try to not crash. */
-void tst_QScriptEngine::collectGarbage()
-{
-    QScriptEngine engine;
-    QScriptValue foo = engine.evaluate("( function foo() {return 'pong';} )");
-    QVERIFY(foo.isFunction());
-    engine.collectGarbage();
-    QCOMPARE(foo.call().toString(), QString::fromAscii("pong"));
-}
-
-void tst_QScriptEngine::reportAdditionalMemoryCost()
-{
-    // There isn't any easy way to test the responsiveness of the GC;
-    // just try to call the function a few times with various sizes.
-    QScriptEngine eng;
-    for (int i = 0; i < 100; ++i) {
-        eng.reportAdditionalMemoryCost(0);
-        eng.reportAdditionalMemoryCost(10);
-        eng.reportAdditionalMemoryCost(1000);
-        eng.reportAdditionalMemoryCost(10000);
-        eng.reportAdditionalMemoryCost(100000);
-        eng.reportAdditionalMemoryCost(1000000);
-        eng.reportAdditionalMemoryCost(10000000);
-        eng.reportAdditionalMemoryCost(-1);
-        eng.reportAdditionalMemoryCost(-1000);
-        QScriptValue obj = eng.evaluate("new Object");
-        eng.collectGarbage();
-    }
-}
-
-void tst_QScriptEngine::nullValue()
-{
-    QScriptEngine engine;
-    QScriptValue value = engine.nullValue();
-    QVERIFY(value.isValid());
-    QVERIFY(value.isNull());
-}
-
-void tst_QScriptEngine::undefinedValue()
-{
-    QScriptEngine engine;
-    QScriptValue value = engine.undefinedValue();
-    QVERIFY(value.isValid());
-    QVERIFY(value.isUndefined());
-}
-
-void tst_QScriptEngine::evaluateProgram()
-{
-    QScriptEngine eng;
-    {
-        QString code("1 + 2");
-        QString fileName("hello.js");
-        int lineNumber = 123;
-        QScriptProgram program(code, fileName, lineNumber);
-        QVERIFY(!program.isNull());
-        QCOMPARE(program.sourceCode(), code);
-        QCOMPARE(program.fileName(), fileName);
-        QCOMPARE(program.firstLineNumber(), lineNumber);
-
-        QScriptValue expected = eng.evaluate(code);
-        for (int x = 0; x < 10; ++x) {
-            QScriptValue ret = eng.evaluate(program);
-            QVERIFY(ret.equals(expected));
-        }
-
-        // operator=
-        QScriptProgram sameProgram = program;
-        QVERIFY(sameProgram == program);
-        QVERIFY(eng.evaluate(sameProgram).equals(expected));
-
-        // copy constructor
-        QScriptProgram sameProgram2(program);
-        QVERIFY(sameProgram2 == program);
-        QVERIFY(eng.evaluate(sameProgram2).equals(expected));
-
-        QScriptProgram differentProgram("2 + 3");
-        QVERIFY(differentProgram != program);
-        QVERIFY(!eng.evaluate(differentProgram).equals(expected));
-    }
-
-    // Program that accesses variable in the scope
-    {
-        QScriptProgram program("a");
-        QVERIFY(!program.isNull());
-        {
-            QScriptValue ret = eng.evaluate(program);
-            QVERIFY(ret.isError());
-            QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: a"));
-        }
-        {
-            QScriptValue ret = eng.evaluate(program);
-            QVERIFY(ret.isError());
-        }
-        eng.evaluate("a = 456");
-        {
-            QScriptValue ret = eng.evaluate(program);
-            QVERIFY(!ret.isError());
-            QCOMPARE(ret.toNumber(), 456.0);
-        }
-    }
-
-    // Program that creates closure
-    {
-        QScriptProgram program("(function() { var count = 0; return function() { return count++; }; })");
-        QVERIFY(!program.isNull());
-        QScriptValue createCounter = eng.evaluate(program);
-        QVERIFY(createCounter.isFunction());
-        QScriptValue counter = createCounter.call();
-        QVERIFY(counter.isFunction());
-        {
-            QScriptValue ret = counter.call();
-            QVERIFY(ret.isNumber());
-        }
-        QScriptValue counter2 = createCounter.call();
-        QVERIFY(counter2.isFunction());
-        QVERIFY(!counter2.equals(counter));
-        {
-            QScriptValue ret = counter2.call();
-            QVERIFY(ret.isNumber());
-        }
-    }
-
-    // Same program run in different engines
-    {
-        QString code("1 + 2");
-        QScriptProgram program(code);
-        QVERIFY(!program.isNull());
-        double expected = eng.evaluate(program).toNumber();
-        for (int x = 0; x < 2; ++x) {
-            QScriptEngine eng2;
-            for (int y = 0; y < 2; ++y) {
-                double ret = eng2.evaluate(program).toNumber();
-                QCOMPARE(ret, expected);
-            }
-        }
-    }
-
-    // No program
-    {
-        QScriptProgram program;
-        QVERIFY(program.isNull());
-        QScriptValue ret = eng.evaluate(program);
-        QVERIFY(!ret.isValid());
-    }
-}
-
-void tst_QScriptEngine::checkSyntax_data()
-{
-    QTest::addColumn<QString>("code");
-    QTest::addColumn<int>("expectedState");
-    QTest::addColumn<int>("errorLineNumber");
-    QTest::addColumn<int>("errorColumnNumber");
-    QTest::addColumn<QString>("errorMessage");
-
-    QTest::newRow("0")
-        << QString("0") << int(QScriptSyntaxCheckResult::Valid)
-        << -1 << -1 << "";
-    QTest::newRow("if (")
-        << QString("if (\n") << int(QScriptSyntaxCheckResult::Intermediate)
-        << 1 << 4 << "";
-    QTest::newRow("if else")
-        << QString("\nif else") << int(QScriptSyntaxCheckResult::Error)
-        << 2 << 4 << "SyntaxError: Parse error";
-    QTest::newRow("{if}")
-            << QString("{\n{\nif\n}\n") << int(QScriptSyntaxCheckResult::Error)
-        << 4 << 1 << "SyntaxError: Parse error";
-    QTest::newRow("foo[")
-        << QString("foo[") << int(QScriptSyntaxCheckResult::Error)
-        << 1 << 4 << "SyntaxError: Parse error";
-    QTest::newRow("foo['bar']")
-        << QString("foo['bar']") << int(QScriptSyntaxCheckResult::Valid)
-        << -1 << -1 << "";
-
-    QTest::newRow("/*")
-        << QString("/*") << int(QScriptSyntaxCheckResult::Intermediate)
-        << 1 << 1 << "Unclosed comment at end of file";
-    QTest::newRow("/*\nMy comment")
-        << QString("/*\nMy comment") << int(QScriptSyntaxCheckResult::Intermediate)
-        << 1 << 1 << "Unclosed comment at end of file";
-    QTest::newRow("/*\nMy comment */\nfoo = 10")
-        << QString("/*\nMy comment */\nfoo = 10") << int(QScriptSyntaxCheckResult::Valid)
-        << -1 << -1 << "";
-    QTest::newRow("foo = 10 /*")
-        << QString("foo = 10 /*") << int(QScriptSyntaxCheckResult::Intermediate)
-        << -1 << -1 << "";
-    QTest::newRow("foo = 10; /*")
-        << QString("foo = 10; /*") << int(QScriptSyntaxCheckResult::Intermediate)
-        << 1 << 11 << "Expected `end of file'";
-    QTest::newRow("foo = 10 /* My comment */")
-        << QString("foo = 10 /* My comment */") << int(QScriptSyntaxCheckResult::Valid)
-        << -1 << -1 << "";
-
-    QTest::newRow("/=/")
-        << QString("/=/") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
-    QTest::newRow("/=/g")
-        << QString("/=/g") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
-    QTest::newRow("/a/")
-        << QString("/a/") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
-    QTest::newRow("/a/g")
-        << QString("/a/g") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
-}
-
-void tst_QScriptEngine::checkSyntax()
-{
-    QFETCH(QString, code);
-    QFETCH(int, expectedState);
-    QFETCH(int, errorLineNumber);
-    QFETCH(int, errorColumnNumber);
-    QFETCH(QString, errorMessage);
-
-    QScriptSyntaxCheckResult result = QScriptEngine::checkSyntax(code);
-
-    // assignment
-    {
-        QScriptSyntaxCheckResult copy = result;
-        QCOMPARE(copy.state(), result.state());
-        QCOMPARE(copy.errorLineNumber(), result.errorLineNumber());
-        QCOMPARE(copy.errorColumnNumber(), result.errorColumnNumber());
-        QCOMPARE(copy.errorMessage(), result.errorMessage());
-    }
-    {
-        QScriptSyntaxCheckResult copy(result);
-        QCOMPARE(copy.state(), result.state());
-        QCOMPARE(copy.errorLineNumber(), result.errorLineNumber());
-        QCOMPARE(copy.errorColumnNumber(), result.errorColumnNumber());
-        QCOMPARE(copy.errorMessage(), result.errorMessage());
-    }
-
-    if (expectedState == QScriptSyntaxCheckResult::Intermediate)
-        QEXPECT_FAIL("", "QScriptSyntaxCheckResult::state() doesn't return the Intermediate state", Abort);
-    QCOMPARE(result.state(), QScriptSyntaxCheckResult::State(expectedState));
-    QCOMPARE(result.errorLineNumber(), errorLineNumber);
-    if (expectedState != QScriptSyntaxCheckResult::Valid && errorColumnNumber != 1)
-            QEXPECT_FAIL("", "QScriptSyntaxCheckResult::errorColumnNumber() doesn't return correct value", Continue);
-    QCOMPARE(result.errorColumnNumber(), errorColumnNumber);
-    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"
diff --git a/qt/tests/qscriptstring/qscriptstring.pro b/qt/tests/qscriptstring/qscriptstring.pro
deleted file mode 100644 (file)
index 5ad9b7c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-TEMPLATE = app
-TARGET = tst_qscriptstring
-QT += testlib
-include(../tests.pri)
-
-SOURCES += tst_qscriptstring.cpp
-
diff --git a/qt/tests/qscriptstring/tst_qscriptstring.cpp b/qt/tests/qscriptstring/tst_qscriptstring.cpp
deleted file mode 100644 (file)
index ff31835..0000000
+++ /dev/null
@@ -1,175 +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.
-*/
-
-#ifndef tst_qscriptstring_h
-#define tst_qscriptstring_h
-
-#include "qscriptengine.h"
-#include "qscriptstring.h"
-#include <QtCore/qhash.h>
-#include <QtTest/QtTest>
-
-class tst_QScriptString : public QObject {
-    Q_OBJECT
-
-public:
-    tst_QScriptString();
-    virtual ~tst_QScriptString();
-
-private slots:
-    void test();
-    void hash();
-    void toArrayIndex_data();
-    void toArrayIndex();
-};
-
-tst_QScriptString::tst_QScriptString()
-{
-}
-
-tst_QScriptString::~tst_QScriptString()
-{
-}
-
-void tst_QScriptString::test()
-{
-    QScriptEngine eng;
-    {
-        QScriptString str;
-        QVERIFY(!str.isValid());
-        QVERIFY(str == str);
-        QVERIFY(!(str != str));
-        QVERIFY(str.toString().isNull());
-
-        QScriptString str1(str);
-        QVERIFY(!str1.isValid());
-
-        QScriptString str2 = str;
-        QVERIFY(!str2.isValid());
-
-        QCOMPARE(str.toArrayIndex(), quint32(0xffffffff));
-    }
-    for (int x = 0; x < 2; ++x) {
-        QString ciao = QString::fromLatin1("ciao");
-        QScriptString str = eng.toStringHandle(ciao);
-        QVERIFY(str.isValid());
-        QVERIFY(str == str);
-        QVERIFY(!(str != str));
-        QCOMPARE(str.toString(), ciao);
-
-        QScriptString str1(str);
-        QCOMPARE(str, str1);
-
-        QScriptString str2 = str;
-        QCOMPARE(str, str2);
-
-        QScriptString str3 = eng.toStringHandle(ciao);
-        QVERIFY(str3.isValid());
-        QCOMPARE(str, str3);
-
-        eng.collectGarbage();
-
-        QVERIFY(str.isValid());
-        QCOMPARE(str.toString(), ciao);
-        QVERIFY(str1.isValid());
-        QCOMPARE(str1.toString(), ciao);
-        QVERIFY(str2.isValid());
-        QCOMPARE(str2.toString(), ciao);
-        QVERIFY(str3.isValid());
-        QCOMPARE(str3.toString(), ciao);
-    }
-    {
-        QScriptEngine* eng2 = new QScriptEngine;
-        QString one = QString::fromLatin1("one");
-        QString two = QString::fromLatin1("two");
-        QScriptString oneInterned = eng2->toStringHandle(one);
-        QCOMPARE(oneInterned.toString(), one);
-        QScriptString twoInterned = eng2->toStringHandle(two);
-        QCOMPARE(twoInterned.toString(), two);
-        QVERIFY(oneInterned != twoInterned);
-        QVERIFY(!(oneInterned == twoInterned));
-
-        delete eng2;
-    }
-}
-
-void tst_QScriptString::hash()
-{
-    QScriptEngine engine;
-    QHash<QScriptString, int> stringToInt;
-    QScriptString foo = engine.toStringHandle("foo");
-
-    QScriptString bar = engine.toStringHandle("bar");
-    QVERIFY(!stringToInt.contains(foo));
-    for (int i = 0; i < 1000000; ++i)
-        stringToInt.insert(foo, 123);
-    QCOMPARE(stringToInt.value(foo), 123);
-    QVERIFY(!stringToInt.contains(bar));
-    stringToInt.insert(bar, 456);
-    QCOMPARE(stringToInt.value(bar), 456);
-    QCOMPARE(stringToInt.value(foo), 123);
-}
-
-void tst_QScriptString::toArrayIndex_data()
-{
-    QTest::addColumn<QString>("input");
-    QTest::addColumn<bool>("expectSuccess");
-    QTest::addColumn<quint32>("expectedIndex");
-    QTest::newRow("foo") << QString::fromLatin1("foo") << false << quint32(0xffffffff);
-    QTest::newRow("empty") << QString::fromLatin1("") << false << quint32(0xffffffff);
-    QTest::newRow("0") << QString::fromLatin1("0") << true << quint32(0);
-    QTest::newRow("00") << QString::fromLatin1("00") << false << quint32(0xffffffff);
-    QTest::newRow("1") << QString::fromLatin1("1") << true << quint32(1);
-    QTest::newRow("123") << QString::fromLatin1("123") << true << quint32(123);
-    QTest::newRow("-1") << QString::fromLatin1("-1") << false << quint32(0xffffffff);
-    QTest::newRow("0a") << QString::fromLatin1("0a") << false << quint32(0xffffffff);
-    QTest::newRow("0x1") << QString::fromLatin1("0x1") << false << quint32(0xffffffff);
-    QTest::newRow("01") << QString::fromLatin1("01") << false << quint32(0xffffffff);
-    QTest::newRow("101a") << QString::fromLatin1("101a") << false << quint32(0xffffffff);
-    QTest::newRow("4294967294") << QString::fromLatin1("4294967294") << true << quint32(0xfffffffe);
-    QTest::newRow("4294967295") << QString::fromLatin1("4294967295") << false << quint32(0xffffffff);
-    QTest::newRow("11111111111") << QString::fromLatin1("11111111111") << false << quint32(0xffffffff);
-    QTest::newRow("0.0") << QString::fromLatin1("0.0") << false << quint32(0xffffffff);
-    QTest::newRow("1.0") << QString::fromLatin1("1.0") << false << quint32(0xffffffff);
-    QTest::newRow("1.5") << QString::fromLatin1("1.5") << false << quint32(0xffffffff);
-    QTest::newRow("1.") << QString::fromLatin1("1.") << false << quint32(0xffffffff);
-    QTest::newRow(".1") << QString::fromLatin1(".1") << false << quint32(0xffffffff);
-    QTest::newRow("1e0") << QString::fromLatin1("1e0") << false << quint32(0xffffffff);
-}
-
-void tst_QScriptString::toArrayIndex()
-{
-    QFETCH(QString, input);
-    QFETCH(bool, expectSuccess);
-    QFETCH(quint32, expectedIndex);
-    QScriptEngine engine;
-    for (int x = 0; x < 2; ++x) {
-        bool isArrayIndex;
-        bool* ptr = (!x) ? &isArrayIndex : (bool*)0;
-        quint32 result = engine.toStringHandle(input).toArrayIndex(ptr);
-        if (!x)
-            QCOMPARE(isArrayIndex, expectSuccess);
-        QCOMPARE(result, expectedIndex);
-    }
-}
-
-QTEST_MAIN(tst_QScriptString)
-#include "tst_qscriptstring.moc"
-
-#endif // tst_qscriptstring_h
diff --git a/qt/tests/qscriptvalue/qscriptvalue.pro b/qt/tests/qscriptvalue/qscriptvalue.pro
deleted file mode 100644 (file)
index 02e94ec..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-TEMPLATE = app
-TARGET = tst_qscriptvalue
-QT += testlib
-isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../..
-include(../tests.pri)
-
-SOURCES += \
-    tst_qscriptvalue.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
diff --git a/qt/tests/qscriptvalue/tst_qscriptvalue.cpp b/qt/tests/qscriptvalue/tst_qscriptvalue.cpp
deleted file mode 100644 (file)
index e04d3e9..0000000
+++ /dev/null
@@ -1,1296 +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 "tst_qscriptvalue.h"
-#include <QtCore/qnumeric.h>
-
-tst_QScriptValue::tst_QScriptValue()
-    : m_engine(0)
-{
-}
-
-tst_QScriptValue::~tst_QScriptValue()
-{
-    delete m_engine;
-}
-
-void tst_QScriptValue::ctor()
-{
-    QScriptEngine eng;
-    {
-        QScriptValue v;
-        QCOMPARE(v.isValid(), false);
-        QCOMPARE(v.engine(), (QScriptEngine*)0);
-    }
-    {
-        QScriptValue v(&eng, QScriptValue::UndefinedValue);
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isUndefined(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.engine(), &eng);
-    }
-    {
-        QScriptValue v(&eng, QScriptValue::NullValue);
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isNull(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.engine(), &eng);
-    }
-    {
-        QScriptValue v(&eng, false);
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isBoolean(), true);
-        QCOMPARE(v.isBool(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toBoolean(), false);
-        QCOMPARE(v.engine(), &eng);
-    }
-    {
-        QScriptValue v(&eng, int(1));
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isNumber(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toNumber(), 1.0);
-        QCOMPARE(v.engine(), &eng);
-    }
-    {
-        QScriptValue v(int(0x43211234));
-        QVERIFY(v.isNumber());
-        QCOMPARE(v.toInt32(), 0x43211234);
-    }
-    {
-        QScriptValue v(&eng, uint(1));
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isNumber(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toNumber(), 1.0);
-        QCOMPARE(v.engine(), &eng);
-    }
-    {
-        QScriptValue v(uint(0x43211234));
-        QVERIFY(v.isNumber());
-        QCOMPARE(v.toUInt32(), uint(0x43211234));
-    }
-    {
-        QScriptValue v(&eng, 1.0);
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isNumber(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toNumber(), 1.0);
-        QCOMPARE(v.engine(), &eng);
-    }
-    {
-        QScriptValue v(12345678910.5);
-        QVERIFY(v.isNumber());
-        QCOMPARE(v.toNumber(), 12345678910.5);
-    }
-    {
-        QScriptValue v(&eng, "ciao");
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isString(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toString(), QLatin1String("ciao"));
-        QCOMPARE(v.engine(), &eng);
-    }
-    {
-        QScriptValue v(&eng, QString("ciao"));
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isString(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toString(), QLatin1String("ciao"));
-        QCOMPARE(v.engine(), &eng);
-    }
-    // copy constructor, operator=
-    {
-        QScriptValue v(&eng, 1.0);
-        QScriptValue v2(v);
-        QCOMPARE(v2.strictlyEquals(v), true);
-        QCOMPARE(v2.engine(), &eng);
-
-        QScriptValue v3(v);
-        QCOMPARE(v3.strictlyEquals(v), true);
-        QCOMPARE(v3.strictlyEquals(v2), true);
-        QCOMPARE(v3.engine(), &eng);
-
-        QScriptValue v4(&eng, 2.0);
-        QCOMPARE(v4.strictlyEquals(v), false);
-        v3 = v4;
-        QCOMPARE(v3.strictlyEquals(v), false);
-        QCOMPARE(v3.strictlyEquals(v4), true);
-
-        v2 = QScriptValue();
-        QCOMPARE(v2.strictlyEquals(v), false);
-        QCOMPARE(v.toNumber(), 1.0);
-
-        QScriptValue v5(v);
-        QCOMPARE(v5.strictlyEquals(v), true);
-        v = QScriptValue();
-        QCOMPARE(v5.strictlyEquals(v), false);
-        QCOMPARE(v5.toNumber(), 1.0);
-    }
-
-    // constructors that take no engine argument
-    {
-        QScriptValue v(QScriptValue::UndefinedValue);
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isUndefined(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.engine(), (QScriptEngine*)0);
-    }
-    {
-        QScriptValue v(QScriptValue::NullValue);
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isNull(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.engine(), (QScriptEngine*)0);
-    }
-    {
-        QScriptValue v(false);
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isBoolean(), true);
-        QCOMPARE(v.isBool(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toBoolean(), false);
-        QCOMPARE(v.engine(), (QScriptEngine*)0);
-    }
-    {
-        QScriptValue v(int(1));
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isNumber(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toNumber(), 1.0);
-        QCOMPARE(v.engine(), (QScriptEngine*)0);
-    }
-    {
-        QScriptValue v(uint(1));
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isNumber(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toNumber(), 1.0);
-        QCOMPARE(v.engine(), (QScriptEngine*)0);
-    }
-    {
-        QScriptValue v(1.0);
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isNumber(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toNumber(), 1.0);
-        QCOMPARE(v.engine(), (QScriptEngine*)0);
-    }
-    {
-        QScriptValue v("ciao");
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isString(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toString(), QLatin1String("ciao"));
-        QCOMPARE(v.engine(), (QScriptEngine*)0);
-    }
-    {
-        QScriptValue v(QString("ciao"));
-        QCOMPARE(v.isValid(), true);
-        QCOMPARE(v.isString(), true);
-        QCOMPARE(v.isObject(), false);
-        QCOMPARE(v.toString(), QLatin1String("ciao"));
-        QCOMPARE(v.engine(), (QScriptEngine*)0);
-    }
-    // copy constructor, operator=
-    {
-        QScriptValue v(1.0);
-        QScriptValue v2(v);
-        QCOMPARE(v2.strictlyEquals(v), true);
-        QCOMPARE(v2.engine(), (QScriptEngine*)0);
-
-        QScriptValue v3(v);
-        QCOMPARE(v3.strictlyEquals(v), true);
-        QCOMPARE(v3.strictlyEquals(v2), true);
-        QCOMPARE(v3.engine(), (QScriptEngine*)0);
-
-        QScriptValue v4(2.0);
-        QCOMPARE(v4.strictlyEquals(v), false);
-        v3 = v4;
-        QCOMPARE(v3.strictlyEquals(v), false);
-        QCOMPARE(v3.strictlyEquals(v4), true);
-
-        v2 = QScriptValue();
-        QCOMPARE(v2.strictlyEquals(v), false);
-        QCOMPARE(v.toNumber(), 1.0);
-
-        QScriptValue v5(v);
-        QCOMPARE(v5.strictlyEquals(v), true);
-        v = QScriptValue();
-        QCOMPARE(v5.strictlyEquals(v), false);
-        QCOMPARE(v5.toNumber(), 1.0);
-    }
-
-    // 0 engine
-    QVERIFY(QScriptValue(0, QScriptValue::UndefinedValue).isUndefined());
-    QVERIFY(QScriptValue(0, QScriptValue::NullValue).isNull());
-    QVERIFY(QScriptValue(0, false).isBool());
-    QVERIFY(QScriptValue(0, int(1)).isNumber());
-    QVERIFY(QScriptValue(0, uint(1)).isNumber());
-    QVERIFY(QScriptValue(0, 1.0).isNumber());
-    QVERIFY(QScriptValue(0, "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");
-    QTest::addColumn<QString>("result");
-
-    QTest::newRow("string") << QString::fromAscii("'hello'") << QString::fromAscii("hello");
-    QTest::newRow("string utf") << QString::fromUtf8("'ąśćżźółńę'") << QString::fromUtf8("ąśćżźółńę");
-    QTest::newRow("expression") << QString::fromAscii("1 + 4") << QString::fromAscii("5");
-    QTest::newRow("null") << QString::fromAscii("null") << QString::fromAscii("null");
-    QTest::newRow("boolean") << QString::fromAscii("false") << QString::fromAscii("false");
-    QTest::newRow("undefined") << QString::fromAscii("undefined") << QString::fromAscii("undefined");
-    QTest::newRow("object") << QString::fromAscii("new Object") << QString::fromAscii("[object Object]");
-}
-
-/* Test conversion to string from different JSC types */
-void tst_QScriptValue::toStringSimple()
-{
-    QFETCH(QString, code);
-    QFETCH(QString, result);
-
-    QScriptEngine engine;
-    QCOMPARE(engine.evaluate(code).toString(), result);
-}
-
-void tst_QScriptValue::copyConstructor_data()
-{
-    QScriptEngine engine;
-    QScriptValue nnumber(123);
-    QScriptValue nstring("ping");
-    QScriptValue number(engine.evaluate("1"));
-    QScriptValue string(engine.evaluate("'foo'"));
-    QScriptValue object(engine.evaluate("new Object"));
-    QScriptValue undefined(engine.evaluate("undefined"));
-    QScriptValue null(engine.evaluate("null"));
-
-    QTest::addColumn<QScriptValue>("value");
-    QTest::addColumn<QString>("result");
-
-    QTest::newRow("native number") << nnumber << QString::number(123);
-    QTest::newRow("native string") << nstring << QString("ping");
-    QTest::newRow("number") << number << QString::fromAscii("1");
-    QTest::newRow("string") << string << QString::fromAscii("foo");
-    QTest::newRow("object") << object << QString::fromAscii("[object Object]");
-    QTest::newRow("undefined") << undefined << QString::fromAscii("undefined");
-    QTest::newRow("null") << null << QString::fromAscii("null");
-}
-
-void tst_QScriptValue::copyConstructor()
-{
-    QFETCH(QScriptValue, value);
-    QFETCH(QString, result);
-
-    QVERIFY(value.isValid());
-    QScriptValue tmp(value);
-    QVERIFY(tmp.isValid());
-    QCOMPARE(tmp.toString(), result);
-}
-
-void tst_QScriptValue::assignOperator_data()
-{
-    copyConstructor_data();
-}
-
-void tst_QScriptValue::assignOperator()
-{
-    QFETCH(QScriptValue, value);
-    QFETCH(QString, result);
-
-    QScriptValue tmp;
-    tmp = value;
-    QVERIFY(tmp.isValid());
-    QCOMPARE(tmp.toString(), result);
-}
-
-/* Test internal data sharing between a diffrenet QScriptValue. */
-void tst_QScriptValue::dataSharing()
-{
-    QScriptEngine engine;
-    QScriptValue v1;
-    QScriptValue v2(v1);
-
-    v1 = engine.evaluate("1"); // v1 == 1 ; v2 invalid.
-    QVERIFY(v1.isValid());
-    QVERIFY(!v2.isValid());
-
-    v2 = v1; // v1 == 1; v2 == 1.
-    QVERIFY(v1.isValid());
-    QVERIFY(v2.isValid());
-
-    v1 = engine.evaluate("obj = new Date"); // v1 == [object Date] ; v2 == 1.
-    QVERIFY(v1.isValid());
-    QVERIFY(v2.isValid());
-    QVERIFY(v2.toString() != v1.toString());
-
-    // TODO add object manipulation (v1 and v2 point to the same object).
-}
-
-void tst_QScriptValue::constructors_data()
-{
-    QScriptEngine engine;
-
-    QTest::addColumn<QScriptValue>("value");
-    QTest::addColumn<QString>("string");
-    QTest::addColumn<bool>("valid");
-    QTest::addColumn<bool>("object");
-
-    QTest::newRow("invalid") << QScriptValue() << QString() << false << false;
-    QTest::newRow("number") << QScriptValue(-21) << QString::number(-21) << true << false;
-    QTest::newRow("bool") << QScriptValue(true) << QString::fromAscii("true") << true << false;
-    QTest::newRow("double") << QScriptValue(21.12) << QString::number(21.12) << true << false;
-    QTest::newRow("string") << QScriptValue("AlaMaKota") << QString::fromAscii("AlaMaKota") << true << false;
-    QTest::newRow("object") << engine.evaluate("new Object") << QString::fromAscii("[object Object]") << true << true;
-    QTest::newRow("null") << QScriptValue(QScriptValue::NullValue)<< QString::fromAscii("null") << true << false;
-    QTest::newRow("undef") << QScriptValue(QScriptValue::UndefinedValue)<< QString::fromAscii("undefined") << true << false;
-}
-
-void tst_QScriptValue::constructors()
-{
-    QFETCH(QScriptValue, value);
-    QFETCH(QString, string);
-    QFETCH(bool, valid);
-    QFETCH(bool, object);
-
-    QCOMPARE(value.isValid(), valid);
-    QCOMPARE(value.toString(), string);
-    QCOMPARE(value.isObject(), object);
-}
-
-void tst_QScriptValue::call()
-{
-    QScriptEngine engine;
-    QScriptValue ping = engine.evaluate("( function() {return 'ping';} )");
-    QScriptValue incr = engine.evaluate("( function(i) {return i + 1;} )");
-    QScriptValue one(1);
-    QScriptValue five(5);
-    QScriptValue result;
-
-    QVERIFY(one.isValid());
-    QVERIFY(five.isValid());
-
-    QVERIFY(ping.isValid());
-    QVERIFY(ping.isFunction());
-    result = ping.call();
-    QVERIFY(result.isValid());
-    QCOMPARE(result.toString(), QString::fromUtf8("ping"));
-
-    QVERIFY(incr.isValid());
-    QVERIFY(incr.isFunction());
-    result = incr.call(QScriptValue(), QScriptValueList() << one);
-    QVERIFY(result.isValid());
-    QCOMPARE(result.toString(), QString("2"));
-
-    QCOMPARE(incr.call(QScriptValue(), QScriptValueList() << five).toString(), QString::fromAscii("6"));
-
-    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)
diff --git a/qt/tests/qscriptvalue/tst_qscriptvalue.h b/qt/tests/qscriptvalue/tst_qscriptvalue.h
deleted file mode 100644 (file)
index 7b7d9bc..0000000
+++ /dev/null
@@ -1,143 +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.
-*/
-
-#ifndef tst_qscriptvalue_h
-#define tst_qscriptvalue_h
-
-#include "qscriptengine.h"
-#include "qscriptvalue.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);
-typedef QPair<QString, QScriptValue> QPairQStringAndQScriptValue;
-Q_DECLARE_METATYPE(QPairQStringAndQScriptValue);
-
-class tst_QScriptValue : public QObject {
-    Q_OBJECT
-
-public:
-    tst_QScriptValue();
-    virtual ~tst_QScriptValue();
-
-private slots:
-    void toStringSimple_data();
-    void toStringSimple();
-    void copyConstructor_data();
-    void copyConstructor();
-    void assignOperator_data();
-    void assignOperator();
-    void dataSharing();
-    void constructors_data();
-    void constructors();
-    void getSetPrototype();
-    void call();
-    void ctor();
-    void toObjectSimple();
-    void getPropertySimple_data();
-    void getPropertySimple();
-    void setPropertySimple();
-    void setProperty_data();
-    void setProperty();
-    void getSetProperty();
-    void getPropertyResolveFlag();
-    void propertyFlag_data();
-    void propertyFlag();
-    void globalObjectChanges();
-    void assignAndCopyConstruct_data();
-    void assignAndCopyConstruct();
-
-    // Generated test functions.
-    void isArray_data();
-    void isArray();
-
-    void isBool_data();
-    void isBool();
-
-    void isBoolean_data();
-    void isBoolean();
-
-    void isError_data();
-    void isError();
-
-    void isNumber_data();
-    void isNumber();
-
-    void isFunction_data();
-    void isFunction();
-
-    void isNull_data();
-    void isNull();
-
-    void isObject_data();
-    void isObject();
-
-    void isString_data();
-    void isString();
-
-    void isUndefined_data();
-    void isUndefined();
-
-    void isValid_data();
-    void isValid();
-
-    void toString_data();
-    void toString();
-
-    void toNumber_data();
-    void toNumber();
-
-    void toBool_data();
-    void toBool();
-
-    void toBoolean_data();
-    void toBoolean();
-
-    void toInteger_data();
-    void toInteger();
-
-    void toInt32_data();
-    void toInt32();
-
-    void toUInt32_data();
-    void toUInt32();
-
-    void toUInt16_data();
-    void toUInt16();
-
-    void equals_data();
-    void equals();
-
-    void strictlyEquals_data();
-    void strictlyEquals();
-
-    void instanceOf_data();
-    void instanceOf();
-
-private:
-    // Generated function
-    QPair<QString, QScriptValue> initScriptValues(uint idx);
-
-    QScriptEngine* m_engine;
-};
-
-#endif // tst_qscriptvalue_h
diff --git a/qt/tests/qscriptvalue/tst_qscriptvalue_generated_comparison.cpp b/qt/tests/qscriptvalue/tst_qscriptvalue_generated_comparison.cpp
deleted file mode 100644 (file)
index 3209530..0000000
+++ /dev/null
@@ -1,1799 +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.
-*/
-
-/****************************************************************************
-*************** 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
deleted file mode 100644 (file)
index 4c97dd4..0000000
+++ /dev/null
@@ -1,169 +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.
-*/
-
-/****************************************************************************
-*************** 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
deleted file mode 100644 (file)
index 433597f..0000000
+++ /dev/null
@@ -1,622 +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.
-*/
-
-
-/****************************************************************************
-*************** 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
deleted file mode 100644 (file)
index eaa5d14..0000000
+++ /dev/null
@@ -1,1786 +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.
-*/
-
-/****************************************************************************
-*************** 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
deleted file mode 100644 (file)
index 5314ec9..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-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
deleted file mode 100644 (file)
index 43d0042..0000000
+++ /dev/null
@@ -1,531 +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.
-*/
-
-#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
diff --git a/qt/tests/tests.pri b/qt/tests/tests.pri
deleted file mode 100644 (file)
index 5af3383..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-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/tests/tests.pro b/qt/tests/tests.pro
deleted file mode 100644 (file)
index 6d5559b..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS =   qscriptengine \
-            qscriptvalue \
-            qscriptvalueiterator \
-            qscriptstring
index c1aa9dd7a6935e6b98059c043bb3c4c80b4f46fb..873ddc2da51fe8699e68a43e66ef127dc1c97866 100644 (file)
@@ -21,8 +21,8 @@
 #include "config.h"
 #include "ArgList.h"
 
 #include "config.h"
 #include "ArgList.h"
 
+#include "HeapRootVisitor.h"
 #include "JSValue.h"
 #include "JSValue.h"
-#include "JSCell.h"
 #include "JSObject.h"
 #include "ScopeChain.h"
 
 #include "JSObject.h"
 #include "ScopeChain.h"
 
@@ -32,50 +32,58 @@ namespace JSC {
 
 void ArgList::getSlice(int startIndex, ArgList& result) const
 {
 
 void ArgList::getSlice(int startIndex, ArgList& result) const
 {
-    if (startIndex <= 0 || static_cast<unsigned>(startIndex) >= m_argCount) {
-        result = ArgList(m_args, 0);
+    if (startIndex <= 0 || startIndex >= m_argCount) {
+        result = ArgList();
         return;
     }
         return;
     }
-    result = ArgList(m_args + startIndex, m_argCount - startIndex);
+
+    result.m_args = m_args - startIndex;
+    result.m_argCount =  m_argCount - startIndex;
 }
 
 }
 
-void MarkedArgumentBuffer::markLists(HeapRootVisitor& heapRootMarker, ListSet& markSet)
+void MarkedArgumentBuffer::markLists(HeapRootVisitor& heapRootVisitor, 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;
-        heapRootMarker.mark(reinterpret_cast<JSValue*>(list->m_buffer), list->m_size);
+        for (int i = 0; i < list->m_size; ++i)
+            heapRootVisitor.visit(reinterpret_cast<JSValue*>(&list->slotFor(i)));
     }
 }
 
 void MarkedArgumentBuffer::slowAppend(JSValue v)
 {
     }
 }
 
 void MarkedArgumentBuffer::slowAppend(JSValue v)
 {
+    int newCapacity = m_capacity * 4;
+    EncodedJSValue* newBuffer = &(new EncodedJSValue[newCapacity])[newCapacity - 1];
+    for (int i = 0; i < m_capacity; ++i)
+        newBuffer[-i] = m_buffer[-i];
+
+    if (EncodedJSValue* base = mallocBase())
+        delete [] base;
+
+    m_buffer = newBuffer;
+    m_capacity = newCapacity;
+
+    slotFor(m_size) = JSValue::encode(v);
+    ++m_size;
+
+    if (m_markSet)
+        return;
+
     // As long as our size stays within our Vector's inline 
     // capacity, all our values are allocated on the stack, and 
     // therefore don't need explicit marking. Once our size exceeds
     // our Vector's inline capacity, though, our values move to the 
     // heap, where they do need explicit marking.
     // As long as our size stays within our Vector's inline 
     // capacity, all our values are allocated on the stack, and 
     // therefore don't need explicit marking. Once our size exceeds
     // our Vector's inline capacity, though, our values move to the 
     // heap, where they do need explicit marking.
-    if (!m_markSet) {
-        // 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);
-            m_markSet = &markSet;
-        }
-    }
+    for (int i = 0; i < m_size; ++i) {
+        Heap* heap = Heap::heap(JSValue::decode(slotFor(i)));
+        if (!heap)
+            continue;
 
 
-    if (m_vector.size() < m_vector.capacity()) {
-        m_vector.uncheckedAppend(v);
-        return;
+        m_markSet = &heap->markListSet();
+        m_markSet->add(this);
+        break;
     }
     }
-
-    // 4x growth would be excessive for a normal vector, but it's OK for Lists 
-    // because they're short-lived.
-    m_vector.reserveCapacity(m_vector.capacity() * 4);
-    
-    m_vector.uncheckedAppend(v);
-    m_buffer = m_vector.data();
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index ef7809fe8fc5682162e22cfb3e213aa86c230033..1512a0fa1522ed015cd522605c80f73e38be8f35 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class MarkStack;
-    typedef MarkStack SlotVisitor;
+    class SlotVisitor;
 
     class MarkedArgumentBuffer {
         WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer);
 
     class MarkedArgumentBuffer {
         WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer);
+        friend class JSGlobalData;
+        friend class ArgList;
+
     private:
     private:
-        static const unsigned inlineCapacity = 8;
+        static const size_t inlineCapacity = 8;
         typedef Vector<Register, inlineCapacity> VectorType;
         typedef HashSet<MarkedArgumentBuffer*> ListSet;
 
     public:
         typedef Vector<Register, inlineCapacity> VectorType;
         typedef HashSet<MarkedArgumentBuffer*> ListSet;
 
     public:
-        typedef VectorType::iterator iterator;
-        typedef VectorType::const_iterator const_iterator;
-
         // Constructor for a read-write list, to which you may append values.
         // FIXME: Remove all clients of this API, then remove this API.
         MarkedArgumentBuffer()
         // Constructor for a read-write list, to which you may append values.
         // FIXME: Remove all clients of this API, then remove this API.
         MarkedArgumentBuffer()
-            : m_isUsingInlineBuffer(true)
+            : m_size(0)
+            , m_capacity(inlineCapacity)
+            , m_buffer(&m_inlineBuffer[m_capacity - 1])
             , m_markSet(0)
             , m_markSet(0)
-#ifndef NDEBUG
-            , m_isReadOnly(false)
-#endif
-        {
-            m_buffer = m_vector.data();
-            m_size = 0;
-        }
-
-        // Constructor for a read-only list whose data has already been allocated elsewhere.
-        MarkedArgumentBuffer(Register* buffer, size_t size)
-            : m_buffer(buffer)
-            , m_size(size)
-            , m_isUsingInlineBuffer(true)
-            , m_markSet(0)
-#ifndef NDEBUG
-            , m_isReadOnly(true)
-#endif
-        {
-        }
-
-        void initialize(WriteBarrier<Unknown>* buffer, size_t size)
         {
         {
-            ASSERT(!m_markSet);
-            ASSERT(isEmpty());
-
-            m_buffer = reinterpret_cast<Register*>(buffer);
-            m_size = size;
-#ifndef NDEBUG
-            m_isReadOnly = true;
-#endif
         }
 
         ~MarkedArgumentBuffer()
         {
             if (m_markSet)
                 m_markSet->remove(this);
         }
 
         ~MarkedArgumentBuffer()
         {
             if (m_markSet)
                 m_markSet->remove(this);
+
+            if (EncodedJSValue* base = mallocBase())
+                delete [] base;
         }
 
         size_t size() const { return m_size; }
         bool isEmpty() const { return !m_size; }
 
         }
 
         size_t size() const { return m_size; }
         bool isEmpty() const { return !m_size; }
 
-        JSValue at(size_t i) const
+        JSValue at(int i) const
         {
         {
-            if (i < m_size)
-                return m_buffer[i].jsValue();
-            return jsUndefined();
+            if (i >= m_size)
+                return jsUndefined();
+
+            return JSValue::decode(slotFor(i));
         }
 
         void clear()
         {
         }
 
         void clear()
         {
-            m_vector.clear();
-            m_buffer = 0;
             m_size = 0;
         }
 
         void append(JSValue v)
         {
             m_size = 0;
         }
 
         void append(JSValue v)
         {
-            ASSERT(!m_isReadOnly);
-
-#if ENABLE(JSC_ZOMBIES)
-            ASSERT(!v.isZombie());
-#endif
-
-            if (m_isUsingInlineBuffer && m_size < inlineCapacity) {
-                m_vector.uncheckedAppend(v);
-                ++m_size;
-            } else {
-                // Putting this case all in one function measurably improves
-                // the performance of the fast "just append to inline buffer" case.
-                slowAppend(v);
-                ++m_size;
-                m_isUsingInlineBuffer = false;
-            }
+            if (m_size >= m_capacity)
+                return slowAppend(v);
+
+            slotFor(m_size) = JSValue::encode(v);
+            ++m_size;
         }
 
         void removeLast()
         { 
             ASSERT(m_size);
             m_size--;
         }
 
         void removeLast()
         { 
             ASSERT(m_size);
             m_size--;
-            m_vector.removeLast();
         }
 
         JSValue last() 
         {
             ASSERT(m_size);
         }
 
         JSValue last() 
         {
             ASSERT(m_size);
-            return m_buffer[m_size - 1].jsValue();
+            return JSValue::decode(slotFor(m_size - 1));
         }
         
         }
         
-        iterator begin() { return m_buffer; }
-        iterator end() { return m_buffer + m_size; }
-
-        const_iterator begin() const { return m_buffer; }
-        const_iterator end() const { return m_buffer + m_size; }
-
         static void markLists(HeapRootVisitor&, ListSet&);
 
     private:
         static void markLists(HeapRootVisitor&, ListSet&);
 
     private:
-        void slowAppend(JSValue);
+        JS_EXPORT_PRIVATE void slowAppend(JSValue);
         
         
-        Register* m_buffer;
-        size_t m_size;
-        bool m_isUsingInlineBuffer;
-
-        VectorType m_vector;
+        EncodedJSValue& slotFor(int item) const
+        {
+            return m_buffer[-item];
+        }
+        
+        EncodedJSValue* mallocBase()
+        {
+            if (m_capacity == static_cast<int>(inlineCapacity))
+                return 0;
+            return &slotFor(m_capacity - 1);
+        }
+        
+        int m_size;
+        int m_capacity;
+        EncodedJSValue m_inlineBuffer[inlineCapacity];
+        EncodedJSValue* m_buffer;
         ListSet* m_markSet;
         ListSet* m_markSet;
-#ifndef NDEBUG
-        bool m_isReadOnly;
-#endif
 
     private:
         // Prohibits new / delete, which would break GC.
 
     private:
         // Prohibits new / delete, which would break GC.
-        friend class JSGlobalData;
-        
         void* operator new(size_t size)
         {
             return fastMalloc(size);
         void* operator new(size_t size)
         {
             return fastMalloc(size);
@@ -181,65 +143,39 @@ namespace JSC {
     class ArgList {
         friend class JIT;
     public:
     class ArgList {
         friend class JIT;
     public:
-        typedef JSValue* iterator;
-        typedef const JSValue* const_iterator;
-
         ArgList()
             : m_args(0)
             , m_argCount(0)
         {
         }
         ArgList()
             : m_args(0)
             , m_argCount(0)
         {
         }
-        
+
         ArgList(ExecState* exec)
         ArgList(ExecState* exec)
-            : m_args(reinterpret_cast<JSValue*>(&exec[exec->hostThisRegister() + 1]))
+            : m_args(reinterpret_cast<JSValue*>(&exec[CallFrame::argumentOffset(0)]))
             , m_argCount(exec->argumentCount())
         {
         }
             , m_argCount(exec->argumentCount())
         {
         }
-        
-        ArgList(JSValue* args, unsigned argCount)
-            : m_args(args)
-            , m_argCount(argCount)
-        {
-#if ENABLE(JSC_ZOMBIES)
-            for (size_t i = 0; i < argCount; i++)
-                ASSERT(!m_args[i].isZombie());
-#endif
-        }
-        
-        ArgList(Register* args, int argCount)
-            : m_args(reinterpret_cast<JSValue*>(args))
-            , m_argCount(argCount)
-        {
-            ASSERT(argCount >= 0);
-        }
 
         ArgList(const MarkedArgumentBuffer& args)
 
         ArgList(const MarkedArgumentBuffer& args)
-            : m_args(reinterpret_cast<JSValue*>(const_cast<Register*>(args.begin())))
+            : m_args(reinterpret_cast<JSValue*>(args.m_buffer))
             , m_argCount(args.size())
         {
         }
 
             , m_argCount(args.size())
         {
         }
 
-        JSValue at(size_t idx) const
+        JSValue at(int i) const
         {
         {
-            if (idx < m_argCount)
-                return m_args[idx];
-            return jsUndefined();
+            if (i >= m_argCount)
+                return jsUndefined();
+            return m_args[-i];
         }
 
         bool isEmpty() const { return !m_argCount; }
         }
 
         bool isEmpty() const { return !m_argCount; }
-
         size_t size() const { return m_argCount; }
         
         size_t size() const { return m_argCount; }
         
-        iterator begin() { return m_args; }
-        iterator end() { return m_args + m_argCount; }
-        
-        const_iterator begin() const { return m_args; }
-        const_iterator end() const { return m_args + m_argCount; }
+        JS_EXPORT_PRIVATE void getSlice(int startIndex, ArgList& result) const;
 
 
-        void getSlice(int startIndex, ArgList& result) const;
     private:
         JSValue* m_args;
     private:
         JSValue* m_args;
-        size_t m_argCount;
+        int m_argCount;
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index ec6cc8f1c7207da83af151426b9f581b19846c49..9a3d7257b497a2647f195bff435f738b5208b456 100644 (file)
@@ -35,67 +35,42 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(Arguments);
 
 
 ASSERT_CLASS_FITS_IN_CELL(Arguments);
 
-const ClassInfo Arguments::s_info = { "Arguments", &JSNonFinalObject::s_info, 0, 0 };
+const ClassInfo Arguments::s_info = { "Arguments", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(Arguments) };
 
 
-Arguments::~Arguments()
+void Arguments::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    if (d->extraArguments != d->extraArgumentsFixedBuffer)
-        delete [] d->extraArguments;
+    Arguments* thisObject = jsCast<Arguments*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    JSObject::visitChildren(thisObject, visitor);
+
+    if (thisObject->d->registerArray)
+        visitor.appendValues(thisObject->d->registerArray.get(), thisObject->d->numArguments);
+    visitor.append(&thisObject->d->callee);
+    if (thisObject->d->activation)
+        visitor.append(&thisObject->d->activation);
 }
 
 }
 
-void Arguments::visitChildren(SlotVisitor& visitor)
+void Arguments::destroy(JSCell* cell)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
-    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
-    JSObject::visitChildren(visitor);
-
-    if (d->registerArray)
-        visitor.appendValues(d->registerArray.get(), d->numParameters);
-
-    if (d->extraArguments) {
-        unsigned numExtraArguments = d->numArguments - d->numParameters;
-        visitor.appendValues(d->extraArguments, numExtraArguments);
-    }
-
-    visitor.append(&d->callee);
-
-    if (d->activation)
-        visitor.append(&d->activation);
+    jsCast<Arguments*>(cell)->Arguments::~Arguments();
 }
 
 }
 
-void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
+void Arguments::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t length)
 {
     if (UNLIKELY(d->overrodeLength)) {
 {
     if (UNLIKELY(d->overrodeLength)) {
-        unsigned length = min(get(exec, exec->propertyNames().length).toUInt32(exec), maxSize);
+        length = min(get(exec, exec->propertyNames().length).toUInt32(exec), length);
         for (unsigned i = 0; i < length; i++)
         for (unsigned i = 0; i < length; i++)
-            buffer[i] = get(exec, i);
+            callFrame->setArgument(i, get(exec, i));
         return;
     }
         return;
     }
-
-    if (LIKELY(!d->deletedArguments)) {
-        unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
-        unsigned i = 0;
-        for (; i < parametersLength; ++i)
-            buffer[i] = d->registers[d->firstParameterIndex + i].get();
-        for (; i < d->numArguments; ++i)
-            buffer[i] = d->extraArguments[i - d->numParameters].get();
-        return;
-    }
-    
-    unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
-    unsigned i = 0;
-    for (; i < parametersLength; ++i) {
-        if (!d->deletedArguments[i])
-            buffer[i] = d->registers[d->firstParameterIndex + i].get();
+    ASSERT(length == this->length(exec));
+    for (size_t i = 0; i < length; ++i) {
+        if (!d->deletedArguments || !d->deletedArguments[i])
+            callFrame->setArgument(i, argument(i).get());
         else
         else
-            buffer[i] = get(exec, i);
-    }
-    for (; i < d->numArguments; ++i) {
-        if (!d->deletedArguments[i])
-            buffer[i] = d->extraArguments[i - d->numParameters].get();
-        else
-            buffer[i] = get(exec, i);
+            callFrame->setArgument(i, get(exec, i));
     }
 }
 
     }
 }
 
@@ -107,54 +82,24 @@ void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
             args.append(get(exec, i)); 
         return;
     }
             args.append(get(exec, i)); 
         return;
     }
-
-    if (LIKELY(!d->deletedArguments)) {
-        if (LIKELY(!d->numParameters)) {
-            args.initialize(d->extraArguments, d->numArguments);
-            return;
-        }
-
-        if (d->numParameters == d->numArguments) {
-            args.initialize(&d->registers[d->firstParameterIndex], d->numArguments);
-            return;
-        }
-
-        unsigned parametersLength = min(d->numParameters, d->numArguments);
-        unsigned i = 0;
-        for (; i < parametersLength; ++i)
-            args.append(d->registers[d->firstParameterIndex + i].get());
-        for (; i < d->numArguments; ++i)
-            args.append(d->extraArguments[i - d->numParameters].get());
-        return;
-    }
-
-    unsigned parametersLength = min(d->numParameters, d->numArguments);
-    unsigned i = 0;
-    for (; i < parametersLength; ++i) {
-        if (!d->deletedArguments[i])
-            args.append(d->registers[d->firstParameterIndex + i].get());
-        else
-            args.append(get(exec, i));
-    }
-    for (; i < d->numArguments; ++i) {
-        if (!d->deletedArguments[i])
-            args.append(d->extraArguments[i - d->numParameters].get());
+    uint32_t length = this->length(exec);
+    for (size_t i = 0; i < length; ++i) {
+        if (!d->deletedArguments || !d->deletedArguments[i])
+            args.append(argument(i).get());
         else
             args.append(get(exec, i));
     }
 }
 
         else
             args.append(get(exec, i));
     }
 }
 
-bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
+bool Arguments::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned i, PropertySlot& slot)
 {
 {
-    if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
-        if (i < d->numParameters) {
-            slot.setValue(d->registers[d->firstParameterIndex + i].get());
-        } else
-            slot.setValue(d->extraArguments[i - d->numParameters].get());
+    Arguments* thisObject = jsCast<Arguments*>(cell);
+    if (i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
+        slot.setValue(thisObject->argument(i).get());
         return true;
     }
 
         return true;
     }
 
-    return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::number(i)), slot);
+    return JSObject::getOwnPropertySlot(thisObject, exec, Identifier(exec, UString::number(i)), slot);
 }
     
 void Arguments::createStrictModeCallerIfNecessary(ExecState* exec)
 }
     
 void Arguments::createStrictModeCallerIfNecessary(ExecState* exec)
@@ -164,9 +109,8 @@ void Arguments::createStrictModeCallerIfNecessary(ExecState* exec)
 
     d->overrodeCaller = true;
     PropertyDescriptor descriptor;
 
     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);
+    descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Accessor);
+    methodTable()->defineOwnProperty(this, exec, exec->propertyNames().caller, descriptor, false);
 }
 
 void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec)
 }
 
 void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec)
@@ -176,181 +120,292 @@ void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec)
     
     d->overrodeCallee = true;
     PropertyDescriptor descriptor;
     
     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);
+    descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Accessor);
+    methodTable()->defineOwnProperty(this, exec, exec->propertyNames().callee, descriptor, false);
 }
 
 }
 
-bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+bool Arguments::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
+    Arguments* thisObject = jsCast<Arguments*>(cell);
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
-    if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
-        if (i < d->numParameters) {
-            slot.setValue(d->registers[d->firstParameterIndex + i].get());
-        } else
-            slot.setValue(d->extraArguments[i - d->numParameters].get());
+    if (isArrayIndex && i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
+        slot.setValue(thisObject->argument(i).get());
         return true;
     }
 
         return true;
     }
 
-    if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
-        slot.setValue(jsNumber(d->numArguments));
+    if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->d->overrodeLength)) {
+        slot.setValue(jsNumber(thisObject->d->numArguments));
         return true;
     }
 
         return true;
     }
 
-    if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
-        if (!d->isStrictMode) {
-            slot.setValue(d->callee.get());
+    if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->d->overrodeCallee)) {
+        if (!thisObject->d->isStrictMode) {
+            slot.setValue(thisObject->d->callee.get());
             return true;
         }
             return true;
         }
-        createStrictModeCalleeIfNecessary(exec);
+        thisObject->createStrictModeCalleeIfNecessary(exec);
     }
 
     }
 
-    if (propertyName == exec->propertyNames().caller && d->isStrictMode)
-        createStrictModeCallerIfNecessary(exec);
+    if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode)
+        thisObject->createStrictModeCallerIfNecessary(exec);
 
 
-    return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+    return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
 }
 
 }
 
-bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool Arguments::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
+    Arguments* thisObject = jsCast<Arguments*>(object);
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
-    if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
-        if (i < d->numParameters) {
-            descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].get(), DontEnum);
-        } else
-            descriptor.setDescriptor(d->extraArguments[i - d->numParameters].get(), DontEnum);
+    if (isArrayIndex && i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
+        descriptor.setDescriptor(thisObject->argument(i).get(), None);
         return true;
     }
     
         return true;
     }
     
-    if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
-        descriptor.setDescriptor(jsNumber(d->numArguments), DontEnum);
+    if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->d->overrodeLength)) {
+        descriptor.setDescriptor(jsNumber(thisObject->d->numArguments), DontEnum);
         return true;
     }
     
         return true;
     }
     
-    if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
-        if (!d->isStrictMode) {
-            descriptor.setDescriptor(d->callee.get(), DontEnum);
+    if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->d->overrodeCallee)) {
+        if (!thisObject->d->isStrictMode) {
+            descriptor.setDescriptor(thisObject->d->callee.get(), DontEnum);
             return true;
         }
             return true;
         }
-        createStrictModeCalleeIfNecessary(exec);
+        thisObject->createStrictModeCalleeIfNecessary(exec);
     }
 
     }
 
-    if (propertyName == exec->propertyNames().caller && d->isStrictMode)
-        createStrictModeCallerIfNecessary(exec);
+    if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode)
+        thisObject->createStrictModeCallerIfNecessary(exec);
     
     
-    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    return JSObject::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
 }
 
 }
 
-void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void Arguments::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
+    Arguments* thisObject = jsCast<Arguments*>(object);
+    for (unsigned i = 0; i < thisObject->d->numArguments; ++i) {
+        if (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])
+            propertyNames.add(Identifier(exec, UString::number(i)));
+    }
     if (mode == IncludeDontEnumProperties) {
     if (mode == IncludeDontEnumProperties) {
-        for (unsigned i = 0; i < d->numArguments; ++i) {
-            if (!d->deletedArguments || !d->deletedArguments[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);
     }
-    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+    JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
 }
 
 }
 
-void Arguments::put(ExecState* exec, unsigned i, JSValue value)
+void Arguments::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value, bool shouldThrow)
 {
 {
-    if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
-        if (i < d->numParameters)
-            d->registers[d->firstParameterIndex + i].set(exec->globalData(), d->activation ? static_cast<JSCell*>(d->activation.get()) : static_cast<JSCell*>(this), value);
-        else
-            d->extraArguments[i - d->numParameters].set(exec->globalData(), this, value);
+    Arguments* thisObject = jsCast<Arguments*>(cell);
+    if (i < static_cast<unsigned>(thisObject->d->numArguments) && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
+        thisObject->argument(i).set(exec->globalData(), thisObject, value);
         return;
     }
 
         return;
     }
 
-    PutPropertySlot slot;
-    JSObject::put(exec, Identifier(exec, UString::number(i)), value, slot);
+    PutPropertySlot slot(shouldThrow);
+    JSObject::put(thisObject, exec, Identifier(exec, UString::number(i)), value, slot);
 }
 
 }
 
-void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void Arguments::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
+    Arguments* thisObject = jsCast<Arguments*>(cell);
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
-    if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
-        if (i < d->numParameters)
-            d->registers[d->firstParameterIndex + i].set(exec->globalData(), d->activation ? static_cast<JSCell*>(d->activation.get()) : static_cast<JSCell*>(this), value);
-        else
-            d->extraArguments[i - d->numParameters].set(exec->globalData(), this, value);
+    if (isArrayIndex && i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
+        thisObject->argument(i).set(exec->globalData(), thisObject, value);
         return;
     }
 
         return;
     }
 
-    if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
-        d->overrodeLength = true;
-        putDirect(exec->globalData(), propertyName, value, DontEnum);
+    if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) {
+        thisObject->d->overrodeLength = true;
+        thisObject->putDirect(exec->globalData(), propertyName, value, DontEnum);
         return;
     }
 
         return;
     }
 
-    if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
-        if (!d->isStrictMode) {
-            d->overrodeCallee = true;
-            putDirect(exec->globalData(), propertyName, value, DontEnum);
+    if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) {
+        if (!thisObject->d->isStrictMode) {
+            thisObject->d->overrodeCallee = true;
+            thisObject->putDirect(exec->globalData(), propertyName, value, DontEnum);
             return;
         }
             return;
         }
-        createStrictModeCalleeIfNecessary(exec);
+        thisObject->createStrictModeCalleeIfNecessary(exec);
     }
 
     }
 
-    if (propertyName == exec->propertyNames().caller && d->isStrictMode)
-        createStrictModeCallerIfNecessary(exec);
+    if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode)
+        thisObject->createStrictModeCallerIfNecessary(exec);
 
 
-    JSObject::put(exec, propertyName, value, slot);
+    JSObject::put(thisObject, exec, propertyName, value, slot);
 }
 
 }
 
-bool Arguments::deleteProperty(ExecState* exec, unsigned i) 
+bool Arguments::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) 
 {
 {
-    if (i < d->numArguments) {
-        if (!d->deletedArguments) {
-            d->deletedArguments = adoptArrayPtr(new bool[d->numArguments]);
-            memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
+    Arguments* thisObject = jsCast<Arguments*>(cell);
+    if (i < thisObject->d->numArguments) {
+        if (!Base::deletePropertyByIndex(cell, exec, i))
+            return false;
+
+        if (!thisObject->d->deletedArguments) {
+            thisObject->d->deletedArguments = adoptArrayPtr(new bool[thisObject->d->numArguments]);
+            memset(thisObject->d->deletedArguments.get(), 0, sizeof(bool) * thisObject->d->numArguments);
         }
         }
-        if (!d->deletedArguments[i]) {
-            d->deletedArguments[i] = true;
+        if (!thisObject->d->deletedArguments[i]) {
+            thisObject->d->deletedArguments[i] = true;
             return true;
         }
     }
 
             return true;
         }
     }
 
-    return JSObject::deleteProperty(exec, Identifier(exec, UString::number(i)));
+    return JSObject::deleteProperty(thisObject, exec, Identifier(exec, UString::number(i)));
 }
 
 }
 
-bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) 
+bool Arguments::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName) 
 {
 {
+    if (exec->globalData().isInDefineOwnProperty())
+        return Base::deleteProperty(cell, exec, propertyName);
+
+    Arguments* thisObject = jsCast<Arguments*>(cell);
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
-    if (isArrayIndex && i < d->numArguments) {
-        if (!d->deletedArguments) {
-            d->deletedArguments = adoptArrayPtr(new bool[d->numArguments]);
-            memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
+    if (isArrayIndex && i < thisObject->d->numArguments) {
+        if (!Base::deleteProperty(cell, exec, propertyName))
+            return false;
+
+        if (!thisObject->d->deletedArguments) {
+            thisObject->d->deletedArguments = adoptArrayPtr(new bool[thisObject->d->numArguments]);
+            memset(thisObject->d->deletedArguments.get(), 0, sizeof(bool) * thisObject->d->numArguments);
         }
         }
-        if (!d->deletedArguments[i]) {
-            d->deletedArguments[i] = true;
+        if (!thisObject->d->deletedArguments[i]) {
+            thisObject->d->deletedArguments[i] = true;
             return true;
         }
     }
 
             return true;
         }
     }
 
-    if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
-        d->overrodeLength = true;
+    if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) {
+        thisObject->d->overrodeLength = true;
         return true;
     }
 
         return true;
     }
 
-    if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
-        if (!d->isStrictMode) {
-            d->overrodeCallee = true;
+    if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) {
+        if (!thisObject->d->isStrictMode) {
+            thisObject->d->overrodeCallee = true;
             return true;
         }
             return true;
         }
-        createStrictModeCalleeIfNecessary(exec);
+        thisObject->createStrictModeCalleeIfNecessary(exec);
     }
     
     }
     
-    if (propertyName == exec->propertyNames().caller && !d->isStrictMode)
-        createStrictModeCallerIfNecessary(exec);
+    if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode)
+        thisObject->createStrictModeCallerIfNecessary(exec);
+
+    return JSObject::deleteProperty(thisObject, exec, propertyName);
+}
+
+bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
+{
+    Arguments* thisObject = jsCast<Arguments*>(object);
+    bool isArrayIndex;
+    unsigned i = propertyName.toArrayIndex(isArrayIndex);
+    if (isArrayIndex && i < thisObject->d->numArguments) {
+        // If the property is not yet present on the object, and is not yet marked as deleted, then add it now.
+        PropertySlot slot;
+        if ((!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i]) && !JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot))
+            object->putDirect(exec->globalData(), propertyName, thisObject->argument(i).get(), 0);
+        if (!Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow))
+            return false;
+
+        if (!thisObject->d->deletedArguments) {
+            thisObject->d->deletedArguments = adoptArrayPtr(new bool[thisObject->d->numArguments]);
+            memset(thisObject->d->deletedArguments.get(), 0, sizeof(bool) * thisObject->d->numArguments);
+        }
+        // From ES 5.1, 10.6 Arguments Object
+        // 5. If the value of isMapped is not undefined, then
+        if (!thisObject->d->deletedArguments[i]) {
+            // a. If IsAccessorDescriptor(Desc) is true, then
+            if (descriptor.isAccessorDescriptor()) {
+                // i. Call the [[Delete]] internal method of map passing P, and false as the arguments.
+                thisObject->d->deletedArguments[i] = true;
+            } else { // b. Else
+                // i. If Desc.[[Value]] is present, then
+                // 1. Call the [[Put]] internal method of map passing P, Desc.[[Value]], and Throw as the arguments.
+                if (descriptor.value())
+                    thisObject->argument(i).set(exec->globalData(), thisObject, descriptor.value());
+                // ii. If Desc.[[Writable]] is present and its value is false, then
+                // 1. Call the [[Delete]] internal method of map passing P and false as arguments.
+                if (descriptor.writablePresent() && !descriptor.writable())
+                    thisObject->d->deletedArguments[i] = true;
+            }
+        }
+        return true;
+    }
 
 
-    return JSObject::deleteProperty(exec, propertyName);
+    if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) {
+        thisObject->putDirect(exec->globalData(), propertyName, jsNumber(thisObject->d->numArguments), DontEnum);
+        thisObject->d->overrodeLength = true;
+    } else if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) {
+        thisObject->putDirect(exec->globalData(), propertyName, thisObject->d->callee.get(), DontEnum);
+        thisObject->d->overrodeCallee = true;
+    } else if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode)
+        thisObject->createStrictModeCallerIfNecessary(exec);
+
+    return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
+}
+
+void Arguments::tearOff(CallFrame* callFrame)
+{
+    if (isTornOff())
+        return;
+
+    if (!d->numArguments)
+        return;
+
+    d->registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[d->numArguments]);
+    d->registers = d->registerArray.get() + CallFrame::offsetFor(d->numArguments + 1);
+
+    if (!callFrame->isInlineCallFrame()) {
+        for (size_t i = 0; i < d->numArguments; ++i)
+            argument(i).set(callFrame->globalData(), this, callFrame->argument(i));
+        return;
+    }
+
+    InlineCallFrame* inlineCallFrame = callFrame->inlineCallFrame();
+    for (size_t i = 0; i < d->numArguments; ++i) {
+        ValueRecovery& recovery = inlineCallFrame->arguments[i + 1];
+        // In the future we'll support displaced recoveries (indicating that the
+        // argument was flushed to a different location), but for now we don't do
+        // that so this code will fail if that were to happen. On the other hand,
+        // it's much less likely that we'll support in-register recoveries since
+        // this code does not (easily) have access to registers.
+        JSValue value;
+        Register* location = &callFrame->registers()[CallFrame::argumentOffset(i)];
+        switch (recovery.technique()) {
+        case AlreadyInRegisterFile:
+            value = location->jsValue();
+            break;
+        case AlreadyInRegisterFileAsUnboxedInt32:
+            value = jsNumber(location->unboxedInt32());
+            break;
+        case AlreadyInRegisterFileAsUnboxedCell:
+            value = location->unboxedCell();
+            break;
+        case AlreadyInRegisterFileAsUnboxedBoolean:
+            value = jsBoolean(location->unboxedBoolean());
+            break;
+        case AlreadyInRegisterFileAsUnboxedDouble:
+#if USE(JSVALUE64)
+            value = jsNumber(*bitwise_cast<double*>(location));
+#else
+            value = location->jsValue();
+#endif
+            break;
+        case Constant:
+            value = recovery.constant();
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+            break;
+        }
+        argument(i).set(callFrame->globalData(), this, value);
+    }
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 9686d8b6cfea2054c37bac95b2311278f2363a75..a1f36de5601f58b8d8d8af8f2c028574f276daa8 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef Arguments_h
 #define Arguments_h
 
 #ifndef Arguments_h
 #define Arguments_h
 
+#include "CodeOrigin.h"
 #include "JSActivation.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "JSActivation.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
@@ -38,16 +39,12 @@ namespace JSC {
         ArgumentsData() { }
         WriteBarrier<JSActivation> activation;
 
         ArgumentsData() { }
         WriteBarrier<JSActivation> activation;
 
-        unsigned numParameters;
-        ptrdiff_t firstParameterIndex;
         unsigned numArguments;
 
         WriteBarrier<Unknown>* registers;
         OwnArrayPtr<WriteBarrier<Unknown> > registerArray;
 
         unsigned numArguments;
 
         WriteBarrier<Unknown>* registers;
         OwnArrayPtr<WriteBarrier<Unknown> > registerArray;
 
-        WriteBarrier<Unknown>* extraArguments;
         OwnArrayPtr<bool> deletedArguments;
         OwnArrayPtr<bool> deletedArguments;
-        WriteBarrier<Unknown> extraArgumentsFixedBuffer[4];
 
         WriteBarrier<JSFunction> callee;
         bool overrodeLength : 1;
 
         WriteBarrier<JSFunction> callee;
         bool overrodeLength : 1;
@@ -56,63 +53,76 @@ namespace JSC {
         bool isStrictMode : 1;
     };
 
         bool isStrictMode : 1;
     };
 
-
     class Arguments : public JSNonFinalObject {
     public:
     class Arguments : public JSNonFinalObject {
     public:
-        // Use an enum because otherwise gcc insists on doing a memory
-        // read.
+        typedef JSNonFinalObject Base;
+
+        static Arguments* create(JSGlobalData& globalData, CallFrame* callFrame)
+        {
+            Arguments* arguments = new (NotNull, allocateCell<Arguments>(globalData.heap)) Arguments(callFrame);
+            arguments->finishCreation(callFrame);
+            return arguments;
+        }
+
         enum { MaxArguments = 0x10000 };
 
         enum { MaxArguments = 0x10000 };
 
+    private:
         enum NoParametersType { NoParameters };
         enum NoParametersType { NoParameters };
-
+        
         Arguments(CallFrame*);
         Arguments(CallFrame*, NoParametersType);
         Arguments(CallFrame*);
         Arguments(CallFrame*, NoParametersType);
-        virtual ~Arguments();
 
 
+    public:
         static const ClassInfo s_info;
 
         static const ClassInfo s_info;
 
-        virtual void visitChildren(SlotVisitor&);
+        static void visitChildren(JSCell*, SlotVisitor&);
 
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
 
 
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
 
-        uint32_t numProvidedArguments(ExecState* exec) const 
+        uint32_t length(ExecState* exec) const 
         {
             if (UNLIKELY(d->overrodeLength))
                 return get(exec, exec->propertyNames().length).toUInt32(exec);
             return d->numArguments; 
         }
         
         {
             if (UNLIKELY(d->overrodeLength))
                 return get(exec, exec->propertyNames().length).toUInt32(exec);
             return d->numArguments; 
         }
         
-        void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
-        void copyRegisters(JSGlobalData&);
+        void copyToArguments(ExecState*, CallFrame*, uint32_t length);
+        void tearOff(CallFrame*);
         bool isTornOff() const { return d->registerArray; }
         bool isTornOff() const { return d->registerArray; }
-        void setActivation(JSGlobalData& globalData, JSActivation* activation)
+        void didTearOffActivation(JSGlobalData& globalData, JSActivation* activation)
         {
         {
-            ASSERT(!d->registerArray);
+            if (isTornOff())
+                return;
             d->activation.set(globalData, this, activation);
             d->registers = &activation->registerAt(0);
         }
 
             d->activation.set(globalData, this, activation);
             d->registers = &activation->registerAt(0);
         }
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) 
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 
         { 
         { 
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); 
         }
 
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
 
         }
 
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
 
+        void finishCreation(CallFrame*);
+
     private:
     private:
-        void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
-        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, 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 void put(ExecState*, unsigned propertyName, JSValue);
-        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
-        virtual bool deleteProperty(ExecState*, unsigned propertyName);
+        static void destroy(JSCell*);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
+        static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+        static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+        static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+        static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
+        static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
+        static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
+        static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
         void createStrictModeCallerIfNecessary(ExecState*);
         void createStrictModeCalleeIfNecessary(ExecState*);
 
         void createStrictModeCallerIfNecessary(ExecState*);
         void createStrictModeCalleeIfNecessary(ExecState*);
 
+        WriteBarrier<Unknown>& argument(size_t);
+
         void init(CallFrame*);
 
         OwnPtr<ArgumentsData> d;
         void init(CallFrame*);
 
         OwnPtr<ArgumentsData> d;
@@ -126,130 +136,41 @@ namespace JSC {
         return static_cast<Arguments*>(asObject(value));
     }
 
         return static_cast<Arguments*>(asObject(value));
     }
 
-    ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
-    {
-        function = asFunction(callFrame->callee());
-
-        int numParameters = function->jsExecutable()->parameterCount();
-        argc = callFrame->argumentCountIncludingThis();
-
-        if (argc <= numParameters)
-            argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
-        else
-            argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc;
-
-        argc -= 1; // - 1 to skip "this"
-        firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters;
-    }
-
     inline Arguments::Arguments(CallFrame* callFrame)
         : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
         , d(adoptPtr(new ArgumentsData))
     {
     inline Arguments::Arguments(CallFrame* callFrame)
         : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
         , d(adoptPtr(new ArgumentsData))
     {
-        ASSERT(inherits(&s_info));
-
-        JSFunction* callee;
-        ptrdiff_t firstParameterIndex;
-        Register* argv;
-        int numArguments;
-        getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
-
-        d->numParameters = callee->jsExecutable()->parameterCount();
-        d->firstParameterIndex = firstParameterIndex;
-        d->numArguments = numArguments;
-
-        d->registers = reinterpret_cast<WriteBarrier<Unknown>*>(callFrame->registers());
-
-        WriteBarrier<Unknown>* extraArguments;
-        if (d->numArguments <= d->numParameters)
-            extraArguments = 0;
-        else {
-            unsigned numExtraArguments = d->numArguments - d->numParameters;
-            if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(WriteBarrier<Unknown>))
-                extraArguments = new WriteBarrier<Unknown>[numExtraArguments];
-            else
-                extraArguments = d->extraArgumentsFixedBuffer;
-            for (unsigned i = 0; i < numExtraArguments; ++i)
-                extraArguments[i].set(callFrame->globalData(), this, argv[d->numParameters + i].jsValue());
-        }
-
-        d->extraArguments = extraArguments;
-
-        d->callee.set(callFrame->globalData(), this, callee);
-        d->overrodeLength = false;
-        d->overrodeCallee = false;
-        d->overrodeCaller = false;
-        d->isStrictMode = callFrame->codeBlock()->isStrictMode();
-        if (d->isStrictMode)
-            copyRegisters(callFrame->globalData());
     }
 
     inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
         : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
         , d(adoptPtr(new ArgumentsData))
     {
     }
 
     inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
         : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
         , d(adoptPtr(new ArgumentsData))
     {
-        ASSERT(inherits(&s_info));
-        ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount());
-
-        unsigned numArguments = callFrame->argumentCount();
-
-        d->numParameters = 0;
-        d->numArguments = numArguments;
-
-        WriteBarrier<Unknown>* extraArguments;
-        if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
-            extraArguments = new WriteBarrier<Unknown>[numArguments];
-        else
-            extraArguments = d->extraArgumentsFixedBuffer;
-
-        Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
-        for (unsigned i = 0; i < numArguments; ++i)
-            extraArguments[i].set(callFrame->globalData(), this, argv[i].jsValue());
-
-        d->extraArguments = extraArguments;
-
-        d->callee.set(callFrame->globalData(), this, asFunction(callFrame->callee()));
-        d->overrodeLength = false;
-        d->overrodeCallee = false;
-        d->overrodeCaller = false;
-        d->isStrictMode = callFrame->codeBlock()->isStrictMode();
-        if (d->isStrictMode)
-            copyRegisters(callFrame->globalData());
     }
 
     }
 
-    inline void Arguments::copyRegisters(JSGlobalData& globalData)
+    inline WriteBarrier<Unknown>& Arguments::argument(size_t i)
     {
     {
-        ASSERT(!isTornOff());
-
-        if (!d->numParameters)
-            return;
-
-        int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
-        size_t registerArraySize = d->numParameters;
-
-        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();
+        return d->registers[CallFrame::argumentOffset(i)];
     }
 
     }
 
-    // This JSActivation function is defined here so it can get at Arguments::setRegisters.
-    inline void JSActivation::copyRegisters(JSGlobalData& globalData)
+    inline void Arguments::finishCreation(CallFrame* callFrame)
     {
     {
-        ASSERT(!m_registerArray);
-
-        size_t numLocals = m_numCapturedVars + m_numParametersMinusThis;
-
-        if (!numLocals)
-            return;
+        Base::finishCreation(callFrame->globalData());
+        ASSERT(inherits(&s_info));
 
 
-        int registerOffset = m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
-        size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
+        JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
+        d->numArguments = callFrame->argumentCount();
+        d->registers = reinterpret_cast<WriteBarrier<Unknown>*>(callFrame->registers());
+        d->callee.set(callFrame->globalData(), this, callee);
+        d->overrodeLength = false;
+        d->overrodeCallee = false;
+        d->overrodeCaller = false;
+        d->isStrictMode = callFrame->codeBlock()->isStrictMode();
 
 
-        OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, m_registers - registerOffset, registerArraySize, m_numParametersMinusThis + 1);
-        WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset;
-        setRegisters(registers, registerArray.release());
+        // The bytecode generator omits op_tear_off_activation in cases of no
+        // declared parameters, so we need to tear off immediately.
+        if (d->isStrictMode || !callee->jsExecutable()->parameterCount())
+            tearOff(callFrame);
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
index a4df41193d25e25f88a47ec602f7cc6e2605a5de..ebcc43781c6017ac457d037d7fb3e12209e9570a 100644 (file)
@@ -41,7 +41,9 @@ static EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*);
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo ArrayConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::arrayConstructorTable };
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ArrayConstructor);
+
+const ClassInfo ArrayConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::arrayConstructorTable, CREATE_METHOD_TABLE(ArrayConstructor) };
 
 /* Source for ArrayConstructor.lut.h
 @begin arrayConstructorTable
 
 /* Source for ArrayConstructor.lut.h
 @begin arrayConstructorTable
@@ -51,21 +53,26 @@ const ClassInfo ArrayConstructor::s_info = { "Function", &InternalFunction::s_in
 
 ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor);
 
 
 ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor);
 
-ArrayConstructor::ArrayConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ArrayPrototype* arrayPrototype)
-    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, arrayPrototype->classInfo()->className))
+ArrayConstructor::ArrayConstructor(JSGlobalObject* globalObject, Structure* structure)
+    : InternalFunction(globalObject, structure)
+{
+}
+
+void ArrayConstructor::finishCreation(ExecState* exec, ArrayPrototype* arrayPrototype)
 {
 {
+    Base::finishCreation(exec->globalData(), Identifier(exec, arrayPrototype->classInfo()->className));
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
 
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
 
-bool ArrayConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+bool ArrayConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 {
-    return getStaticFunctionSlot<InternalFunction>(exec, ExecState::arrayConstructorTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<InternalFunction>(exec, ExecState::arrayConstructorTable(exec), jsCast<ArrayConstructor*>(cell), propertyName, slot);
 }
 
 }
 
-bool ArrayConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool ArrayConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<InternalFunction>(exec, ExecState::arrayConstructorTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<InternalFunction>(exec, ExecState::arrayConstructorTable(exec), jsCast<ArrayConstructor*>(object), propertyName, descriptor);
 }
 
 // ------------------------------ Functions ---------------------------
 }
 
 // ------------------------------ Functions ---------------------------
@@ -79,11 +86,11 @@ static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgLi
         uint32_t n = args.at(0).toUInt32(exec);
         if (n != args.at(0).toNumber(exec))
             return throwError(exec, createRangeError(exec, "Array size is not a small enough positive integer."));
         uint32_t n = args.at(0).toUInt32(exec);
         if (n != args.at(0).toNumber(exec))
             return throwError(exec, createRangeError(exec, "Array size is not a small enough positive integer."));
-        return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), n, CreateInitialized);
+        return constructEmptyArray(exec, globalObject, n);
     }
 
     // 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->globalData(), globalObject->arrayStructure(), args);
+    return constructArray(exec, globalObject, args);
 }
 
 static EncodedJSValue JSC_HOST_CALL constructWithArrayConstructor(ExecState* exec)
 }
 
 static EncodedJSValue JSC_HOST_CALL constructWithArrayConstructor(ExecState* exec)
@@ -92,7 +99,7 @@ static EncodedJSValue JSC_HOST_CALL constructWithArrayConstructor(ExecState* exe
     return JSValue::encode(constructArrayWithSizeQuirk(exec, args));
 }
 
     return JSValue::encode(constructArrayWithSizeQuirk(exec, args));
 }
 
-ConstructType ArrayConstructor::getConstructData(ConstructData& constructData)
+ConstructType ArrayConstructor::getConstructData(JSCell*, ConstructData& constructData)
 {
     constructData.native.function = constructWithArrayConstructor;
     return ConstructTypeHost;
 {
     constructData.native.function = constructWithArrayConstructor;
     return ConstructTypeHost;
@@ -104,7 +111,7 @@ static EncodedJSValue JSC_HOST_CALL callArrayConstructor(ExecState* exec)
     return JSValue::encode(constructArrayWithSizeQuirk(exec, args));
 }
 
     return JSValue::encode(constructArrayWithSizeQuirk(exec, args));
 }
 
-CallType ArrayConstructor::getCallData(CallData& callData)
+CallType ArrayConstructor::getCallData(JSCell*, CallData& callData)
 {
     // equivalent to 'new Array(....)'
     callData.native.function = callArrayConstructor;
 {
     // equivalent to 'new Array(....)'
     callData.native.function = callArrayConstructor;
index dc0df2455e05a8d3f532318af6a005e12e8db818..c60571fbd2f9c02c18d27167efc879a3341a160c 100644 (file)
@@ -29,24 +29,34 @@ namespace JSC {
 
     class ArrayConstructor : public InternalFunction {
     public:
 
     class ArrayConstructor : public InternalFunction {
     public:
-        ArrayConstructor(ExecState*, JSGlobalObject*, Structure*, ArrayPrototype*);
+        typedef InternalFunction Base;
+
+        static ArrayConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ArrayPrototype* arrayPrototype)
+        {
+            ArrayConstructor* constructor = new (NotNull, allocateCell<ArrayConstructor>(*exec->heap())) ArrayConstructor(globalObject, structure);
+            constructor->finishCreation(exec, arrayPrototype);
+            return constructor;
+        }
 
         static const ClassInfo s_info;
 
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
+        void finishCreation(ExecState*, ArrayPrototype*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
 
     private:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
 
     private:
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        ArrayConstructor(JSGlobalObject*, Structure*);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
 
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 8b2393ce890bda356e6f063e5593f006dff8867a..6df58b773e90a478accd50e754aede1ced258650 100644 (file)
@@ -29,6 +29,7 @@
 #include "Interpreter.h"
 #include "JIT.h"
 #include "JSStringBuilder.h"
 #include "Interpreter.h"
 #include "JIT.h"
 #include "JSStringBuilder.h"
+#include "JSStringJoiner.h"
 #include "Lookup.h"
 #include "ObjectPrototype.h"
 #include "Operations.h"
 #include "Lookup.h"
 #include "ObjectPrototype.h"
 #include "Operations.h"
@@ -85,7 +86,7 @@ static inline bool isNumericCompareFunction(ExecState* exec, CallType callType,
 
 // ------------------------------ ArrayPrototype ----------------------------
 
 
 // ------------------------------ ArrayPrototype ----------------------------
 
-const ClassInfo ArrayPrototype::s_info = {"Array", &JSArray::s_info, 0, ExecState::arrayPrototypeTable};
+const ClassInfo ArrayPrototype::s_info = {"Array", &JSArray::s_info, 0, ExecState::arrayPrototypeTable, CREATE_METHOD_TABLE(ArrayPrototype)};
 
 /* Source for ArrayPrototype.lut.h
 @begin arrayPrototypeTable 16
 
 /* Source for ArrayPrototype.lut.h
 @begin arrayPrototypeTable 16
@@ -117,18 +118,22 @@ const ClassInfo ArrayPrototype::s_info = {"Array", &JSArray::s_info, 0, ExecStat
 ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, Structure* structure)
     : JSArray(globalObject->globalData(), structure)
 {
 ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, Structure* structure)
     : JSArray(globalObject->globalData(), structure)
 {
+}
+
+void ArrayPrototype::finishCreation(JSGlobalObject* globalObject)
+{
+    Base::finishCreation(globalObject->globalData());
     ASSERT(inherits(&s_info));
     ASSERT(inherits(&s_info));
-    putAnonymousValue(globalObject->globalData(), 0, globalObject);
 }
 
 }
 
-bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+bool ArrayPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
-    return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayPrototypeTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayPrototypeTable(exec), jsCast<ArrayPrototype*>(cell), propertyName, slot);
 }
 
 }
 
-bool ArrayPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool ArrayPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<JSArray>(exec, ExecState::arrayPrototypeTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<JSArray>(exec, ExecState::arrayPrototypeTable(exec), jsCast<ArrayPrototype*>(object), propertyName, descriptor);
 }
 
 // ------------------------------ Array Functions ----------------------------
 }
 
 // ------------------------------ Array Functions ----------------------------
@@ -145,7 +150,7 @@ static JSValue getProperty(ExecState* exec, JSObject* obj, unsigned index)
 static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValue value)
 {
     PutPropertySlot slot;
 static void putProperty(ExecState* exec, JSObject* obj, const Identifier& propertyName, JSValue value)
 {
     PutPropertySlot slot;
-    obj->put(exec, propertyName, value, slot);
+    obj->methodTable()->put(obj, exec, propertyName, value, slot);
 }
 
 static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0)
 }
 
 static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0)
@@ -162,13 +167,115 @@ static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument
     return indexDouble > length ? length : static_cast<unsigned>(indexDouble);
 }
 
     return indexDouble > length ? length : static_cast<unsigned>(indexDouble);
 }
 
+
+// The shift/unshift function implement the shift/unshift behaviour required
+// by the corresponding array prototype methods, and by splice. In both cases,
+// the methods are operating an an array or array like object.
+//
+//  header  currentCount  (remainder)
+// [------][------------][-----------]
+//  header  resultCount  (remainder)
+// [------][-----------][-----------]
+//
+// The set of properties in the range 'header' must be unchanged. The set of
+// properties in the range 'remainder' (where remainder = length - header -
+// currentCount) will be shifted to the left or right as appropriate; in the
+// case of shift this must be removing values, in the case of unshift this
+// must be introducing new values.
+static inline void shift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length)
+{
+    ASSERT(currentCount > resultCount);
+    unsigned count = currentCount - resultCount;
+
+    ASSERT(header <= length);
+    ASSERT(currentCount <= (length - header));
+
+    if (!header && isJSArray(thisObj) && asArray(thisObj)->shiftCount(exec, count))
+        return;
+
+    for (unsigned k = header; k < length - currentCount; ++k) {
+        unsigned from = k + currentCount;
+        unsigned to = k + resultCount;
+        PropertySlot slot(thisObj);
+        if (thisObj->getPropertySlot(exec, from, slot)) {
+            JSValue value = slot.getValue(exec, from);
+            if (exec->hadException())
+                return;
+            thisObj->methodTable()->putByIndex(thisObj, exec, to, value, true);
+            if (exec->hadException())
+                return;
+        } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) {
+            throwTypeError(exec, "Unable to delete property.");
+            return;
+        }
+    }
+    for (unsigned k = length; k > length - count; --k) {
+        if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1)) {
+            throwTypeError(exec, "Unable to delete property.");
+            return;
+        }
+    }
+}
+static inline void unshift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length)
+{
+    ASSERT(resultCount > currentCount);
+    unsigned count = resultCount - currentCount;
+
+    ASSERT(header <= length);
+    ASSERT(currentCount <= (length - header));
+
+    // Guard against overflow.
+    if (count > (UINT_MAX - length)) {
+        throwOutOfMemoryError(exec);
+        return;
+    }
+
+    if (!header && isJSArray(thisObj) && asArray(thisObj)->unshiftCount(exec, count))
+        return;
+
+    for (unsigned k = length - currentCount; k > header; --k) {
+        unsigned from = k + currentCount - 1;
+        unsigned to = k + resultCount - 1;
+        PropertySlot slot(thisObj);
+        if (thisObj->getPropertySlot(exec, from, slot)) {
+            JSValue value = slot.getValue(exec, from);
+            if (exec->hadException())
+                return;
+            thisObj->methodTable()->putByIndex(thisObj, exec, to, value, true);
+        } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) {
+            throwTypeError(exec, "Unable to delete property.");
+            return;
+        }
+        if (exec->hadException())
+            return;
+    }
+}
+
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 
-    bool isRealArray = isJSArray(&exec->globalData(), thisValue);
-    if (!isRealArray && !thisValue.inherits(&JSArray::s_info))
-        return throwVMTypeError(exec);
+    // 1. Let array be the result of calling ToObject on the this value.
+    JSObject* thisObject = thisValue.toObject(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+    
+    // 2. Let func be the result of calling the [[Get]] internal method of array with argument "join".
+    JSValue function = JSValue(thisObject).get(exec, exec->propertyNames().join);
+
+    // 3. If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2).
+    if (!function.isCell())
+        return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisObject->methodTable()->className(thisObject), "]"));
+    CallData callData;
+    CallType callType = getCallData(function, callData);
+    if (callType == CallTypeNone)
+        return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisObject->methodTable()->className(thisObject), "]"));
+
+    // 4. Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list.
+    if (!isJSArray(thisObject) || callType != CallTypeHost || callData.native.function != arrayProtoFuncJoin)
+        return JSValue::encode(call(exec, function, callType, callData, thisObject, exec->emptyList()));
+
+    ASSERT(isJSArray(thisValue));
     JSArray* thisObj = asArray(thisValue);
     
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     JSArray* thisObj = asArray(thisValue);
     
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
@@ -176,21 +283,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
         return JSValue::encode(jsUndefined());
 
     StringRecursionChecker checker(exec, thisObj);
         return JSValue::encode(jsUndefined());
 
     StringRecursionChecker checker(exec, thisObj);
-    if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
-        return earlyReturnValue;
+    if (JSValue earlyReturnValue = checker.earlyReturnValue())
+        return JSValue::encode(earlyReturnValue);
 
     unsigned totalSize = length ? length - 1 : 0;
 
     unsigned totalSize = length ? length - 1 : 0;
-#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);
     Vector<RefPtr<StringImpl>, 256> strBuffer(length);
-#endif    
+    bool allStrings8Bit = true;
+
     for (unsigned k = 0; k < length; k++) {
         JSValue element;
     for (unsigned k = 0; k < length; k++) {
         JSValue element;
-        if (isRealArray && thisObj->canGetIndex(k))
+        if (thisObj->canGetIndex(k))
             element = thisObj->getIndex(k);
         else
             element = thisObj->get(exec, k);
             element = thisObj->getIndex(k);
         else
             element = thisObj->get(exec, k);
@@ -198,9 +300,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
         if (element.isUndefinedOrNull())
             continue;
         
         if (element.isUndefinedOrNull())
             continue;
         
-        UString str = element.toString(exec);
+        UString str = element.toUString(exec);
         strBuffer[k] = str.impl();
         totalSize += str.length();
         strBuffer[k] = str.impl();
         totalSize += str.length();
+        allStrings8Bit = allStrings8Bit && str.is8Bit();
         
         if (!strBuffer.data()) {
             throwOutOfMemoryError(exec);
         
         if (!strBuffer.data()) {
             throwOutOfMemoryError(exec);
@@ -211,6 +314,23 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
     }
     if (!totalSize)
         return JSValue::encode(jsEmptyString(exec));
     }
     if (!totalSize)
         return JSValue::encode(jsEmptyString(exec));
+
+    if (allStrings8Bit) {
+        Vector<LChar> buffer;
+        buffer.reserveCapacity(totalSize);
+        if (!buffer.data())
+            return JSValue::encode(throwOutOfMemoryError(exec));
+        
+        for (unsigned i = 0; i < length; i++) {
+            if (i)
+                buffer.append(',');
+            if (RefPtr<StringImpl> rep = strBuffer[i])
+                buffer.append(rep->characters8(), rep->length());
+        }
+        ASSERT(buffer.size() == totalSize);
+        return JSValue::encode(jsString(exec, UString::adopt(buffer)));        
+    }
+
     Vector<UChar> buffer;
     buffer.reserveCapacity(totalSize);
     if (!buffer.data())
     Vector<UChar> buffer;
     buffer.reserveCapacity(totalSize);
     if (!buffer.data())
@@ -239,97 +359,80 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
         return JSValue::encode(jsUndefined());
 
     StringRecursionChecker checker(exec, thisObj);
         return JSValue::encode(jsUndefined());
 
     StringRecursionChecker checker(exec, thisObj);
-    if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
-        return earlyReturnValue;
+    if (JSValue earlyReturnValue = checker.earlyReturnValue())
+        return JSValue::encode(earlyReturnValue);
 
 
-    JSStringBuilder strBuffer;
+    UString separator(",");
+    JSStringJoiner stringJoiner(separator, length);
     for (unsigned k = 0; k < length; k++) {
     for (unsigned k = 0; k < length; k++) {
-        if (k >= 1)
-            strBuffer.append(',');
-
         JSValue element = thisObj->get(exec, k);
         JSValue element = thisObj->get(exec, k);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
         if (!element.isUndefinedOrNull()) {
             JSObject* o = element.toObject(exec);
             JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
         if (!element.isUndefinedOrNull()) {
             JSObject* o = element.toObject(exec);
             JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
+            if (exec->hadException())
+                return JSValue::encode(jsUndefined());
             UString str;
             CallData callData;
             CallType callType = getCallData(conversionFunction, callData);
             if (callType != CallTypeNone)
             UString str;
             CallData callData;
             CallType callType = getCallData(conversionFunction, callData);
             if (callType != CallTypeNone)
-                str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec);
+                str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toUString(exec);
             else
             else
-                str = element.toString(exec);
-            strBuffer.append(str);
+                str = element.toUString(exec);
+            if (exec->hadException())
+                return JSValue::encode(jsUndefined());
+            stringJoiner.append(str);
         }
     }
 
         }
     }
 
-    return JSValue::encode(strBuffer.build(exec));
+    return JSValue::encode(stringJoiner.build(exec));
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
 {
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
     StringRecursionChecker checker(exec, thisObj);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
     StringRecursionChecker checker(exec, thisObj);
-    if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
-        return earlyReturnValue;
-
-    JSStringBuilder strBuffer;
+    if (JSValue earlyReturnValue = checker.earlyReturnValue())
+        return JSValue::encode(earlyReturnValue);
 
     UString separator;
     if (!exec->argument(0).isUndefined())
 
     UString separator;
     if (!exec->argument(0).isUndefined())
-        separator = exec->argument(0).toString(exec);
+        separator = exec->argument(0).toUString(exec);
+    if (separator.isNull())
+        separator = UString(",");
+
+    JSStringJoiner stringJoiner(separator, length);
 
     unsigned k = 0;
 
     unsigned k = 0;
-    if (isJSArray(&exec->globalData(), thisObj)) {
+    if (isJSArray(thisObj)) {
         JSArray* array = asArray(thisObj);
 
         JSArray* array = asArray(thisObj);
 
-        if (length) {
-            if (!array->canGetIndex(k)) 
-                goto skipFirstLoop;
+        for (; k < length; k++) {
+            if (!array->canGetIndex(k))
+                break;
+
             JSValue element = array->getIndex(k);
             if (!element.isUndefinedOrNull())
             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())
-                strBuffer.append(',');
+                stringJoiner.append(element.toUStringInline(exec));
             else
             else
-                strBuffer.append(separator);
+                stringJoiner.append(UString());
         }
         }
+    }
 
 
+    for (; k < length; k++) {
         JSValue element = thisObj->get(exec, k);
         if (!element.isUndefinedOrNull())
         JSValue element = thisObj->get(exec, k);
         if (!element.isUndefinedOrNull())
-            strBuffer.append(element.toString(exec));
+            stringJoiner.append(element.toUStringInline(exec));
+        else
+            stringJoiner.append(UString());
     }
 
     }
 
-    return JSValue::encode(strBuffer.build(exec));
+    return JSValue::encode(stringJoiner.build(exec));
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec)
@@ -337,7 +440,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     JSArray* arr = constructEmptyArray(exec);
     unsigned n = 0;
     JSValue thisValue = exec->hostThisValue();
     JSArray* arr = constructEmptyArray(exec);
     unsigned n = 0;
-    JSValue curArg = thisValue.toThisObject(exec);
+    JSValue curArg = thisValue.toObject(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
     size_t i = 0;
     size_t argCount = exec->argumentCount();
     while (1) {
     size_t i = 0;
     size_t argCount = exec->argumentCount();
     while (1) {
@@ -345,12 +450,15 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec)
             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) {
-                if (JSValue v = getProperty(exec, curObject, k))
-                    arr->put(exec, n, v);
+                JSValue v = getProperty(exec, curObject, k);
+                if (exec->hadException())
+                    return JSValue::encode(jsUndefined());
+                if (v)
+                    arr->putDirectIndex(exec, n, v);
                 n++;
             }
         } else {
                 n++;
             }
         } else {
-            arr->put(exec, n, curArg);
+            arr->putDirectIndex(exec, n, curArg);
             n++;
         }
         if (i == argCount)
             n++;
         }
         if (i == argCount)
@@ -358,7 +466,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec)
         curArg = (exec->argument(i));
         ++i;
     }
         curArg = (exec->argument(i));
         ++i;
     }
-    arr->setLength(n);
+    arr->setLength(exec, n);
     return JSValue::encode(arr);
 }
 
     return JSValue::encode(arr);
 }
 
@@ -366,10 +474,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 
 {
     JSValue thisValue = exec->hostThisValue();
 
-    if (isJSArray(&exec->globalData(), thisValue))
-        return JSValue::encode(asArray(thisValue)->pop());
+    if (isJSArray(thisValue))
+        return JSValue::encode(asArray(thisValue)->pop(exec));
 
 
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = thisValue.toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -380,7 +488,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
         result = jsUndefined();
     } else {
         result = thisObj->get(exec, length - 1);
         result = jsUndefined();
     } else {
         result = thisObj->get(exec, length - 1);
-        thisObj->deleteProperty(exec, length - 1);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+        if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1)) {
+            throwTypeError(exec, "Unable to delete property.");
+            return JSValue::encode(jsUndefined());
+        }
         putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
     }
     return JSValue::encode(result);
         putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
     }
     return JSValue::encode(result);
@@ -390,27 +503,37 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 
 {
     JSValue thisValue = exec->hostThisValue();
 
-    if (isJSArray(&exec->globalData(), thisValue) && exec->argumentCount() == 1) {
+    if (isJSArray(thisValue) && exec->argumentCount() == 1) {
         JSArray* array = asArray(thisValue);
         array->push(exec, exec->argument(0));
         return JSValue::encode(jsNumber(array->length()));
     }
 
         JSArray* array = asArray(thisValue);
         array->push(exec, exec->argument(0));
         return JSValue::encode(jsNumber(array->length()));
     }
 
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = thisValue.toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     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));
+    for (unsigned n = 0; n < exec->argumentCount(); n++) {
+        // Check for integer overflow; where safe we can do a fast put by index.
+        if (length + n >= length)
+            thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n), true);
+        else {
+            PutPropertySlot slot;
+            Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toUString(exec));
+            thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot);
+        }
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+    }
+    JSValue newLength(static_cast<int64_t>(length) + static_cast<int64_t>(exec->argumentCount()));
+    putProperty(exec, thisObj, exec->propertyNames().length, newLength);
+    return JSValue::encode(newLength);
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
 {
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -419,46 +542,49 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
     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);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
         JSValue obj = getProperty(exec, thisObj, k);
         JSValue obj = getProperty(exec, thisObj, k);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
 
 
-        if (obj2)
-            thisObj->put(exec, k, obj2);
-        else
-            thisObj->deleteProperty(exec, k);
+        if (obj2) {
+            thisObj->methodTable()->putByIndex(thisObj, exec, k, obj2, true);
+            if (exec->hadException())
+                return JSValue::encode(jsUndefined());
+        } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k)) {
+            throwTypeError(exec, "Unable to delete property.");
+            return JSValue::encode(jsUndefined());
+        }
 
 
-        if (obj)
-            thisObj->put(exec, lk1, obj);
-        else
-            thisObj->deleteProperty(exec, lk1);
+        if (obj) {
+            thisObj->methodTable()->putByIndex(thisObj, exec, lk1, obj, true);
+            if (exec->hadException())
+                return JSValue::encode(jsUndefined());
+        } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, lk1)) {
+            throwTypeError(exec, "Unable to delete property.");
+            return JSValue::encode(jsUndefined());
+        }
     }
     return JSValue::encode(thisObj);
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
 {
     }
     return JSValue::encode(thisObj);
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
-    JSValue result;
-
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
+    JSValue result;
     if (length == 0) {
         putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length));
         result = jsUndefined();
     } else {
         result = thisObj->get(exec, 0);
     if (length == 0) {
         putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length));
         result = jsUndefined();
     } else {
         result = thisObj->get(exec, 0);
-        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);
-        }
+        shift(exec, thisObj, 0, 1, 0, length);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
         putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
     }
     return JSValue::encode(result);
         putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
     }
     return JSValue::encode(result);
@@ -467,31 +593,33 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
 {
     // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
 {
     // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
     // We return a new array
     JSArray* resObj = constructEmptyArray(exec);
     JSValue result = resObj;
 
 
     // We return a new array
     JSArray* resObj = constructEmptyArray(exec);
     JSValue result = resObj;
 
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-    if (exec->hadException())
-        return JSValue::encode(jsUndefined());
-
     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);
 
     unsigned n = 0;
     for (unsigned k = begin; k < end; k++, n++) {
     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);
 
     unsigned n = 0;
     for (unsigned k = begin; k < end; k++, n++) {
-        if (JSValue v = getProperty(exec, thisObj, k))
-            resObj->put(exec, n, v);
+        JSValue v = getProperty(exec, thisObj, k);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+        if (v)
+            resObj->putDirectIndex(exec, n, v);
     }
     }
-    resObj->setLength(n);
+    resObj->setLength(exec, n);
     return JSValue::encode(result);
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
 {
     return JSValue::encode(result);
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (!length || exec->hadException())
         return JSValue::encode(thisObj);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (!length || exec->hadException())
         return JSValue::encode(thisObj);
@@ -500,7 +628,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
     CallData callData;
     CallType callType = getCallData(function, callData);
 
     CallData callData;
     CallType callType = getCallData(function, callData);
 
-    if (thisObj->classInfo() == &JSArray::s_info) {
+    if (thisObj->classInfo() == &JSArray::s_info && !asArray(thisObj)->inSparseMode()) {
         if (isNumericCompareFunction(exec, callType, callData))
             asArray(thisObj)->sortNumeric(exec, function, callType, callData);
         else if (callType != CallTypeNone)
         if (isNumericCompareFunction(exec, callType, callData))
             asArray(thisObj)->sortNumeric(exec, function, callType, callData);
         else if (callType != CallTypeNone)
@@ -531,9 +659,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
                 MarkedArgumentBuffer l;
                 l.append(jObj);
                 l.append(minObj);
                 MarkedArgumentBuffer l;
                 l.append(jObj);
                 l.append(minObj);
-                compareResult = call(exec, function, callType, callData, exec->globalThisValue(), l).toNumber(exec);
+                compareResult = call(exec, function, callType, callData, jsUndefined(), l).toNumber(exec);
             } else
             } else
-                compareResult = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1;
+                compareResult = (jObj.toUStringInline(exec) < minObj.toUStringInline(exec)) ? -1 : 1;
 
             if (compareResult < 0) {
                 themin = j;
 
             if (compareResult < 0) {
                 themin = j;
@@ -542,8 +670,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
         }
         // Swap themin and i
         if (themin > i) {
         }
         // Swap themin and i
         if (themin > i) {
-            thisObj->put(exec, i, minObj);
-            thisObj->put(exec, themin, iObj);
+            thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj, true);
+            if (exec->hadException())
+                return JSValue::encode(jsUndefined());
+            thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj, true);
+            if (exec->hadException())
+                return JSValue::encode(jsUndefined());
         }
     }
     return JSValue::encode(thisObj);
         }
     }
     return JSValue::encode(thisObj);
@@ -553,7 +685,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
 {
     // 15.4.4.12
 
 {
     // 15.4.4.12
 
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -574,44 +706,35 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
             deleteCount = static_cast<unsigned>(deleteDouble);
     }
 
             deleteCount = static_cast<unsigned>(deleteDouble);
     }
 
-    JSArray* resObj = new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), deleteCount, CreateCompact);
+    JSArray* resObj = JSArray::tryCreateUninitialized(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), deleteCount);
+    if (!resObj)
+        return JSValue::encode(throwOutOfMemoryError(exec));
+
     JSValue result = resObj;
     JSGlobalData& globalData = exec->globalData();
     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);
+    for (unsigned k = 0; k < deleteCount; k++) {
+        JSValue v = getProperty(exec, thisObj, k + begin);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+        resObj->initializeIndex(globalData, k, v);
+    }
+    resObj->completeInitialization(deleteCount);
 
     unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0);
 
     unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0);
-    if (additionalArgs != deleteCount) {
-        if (additionalArgs < deleteCount) {
-            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);
-            }
-        } else {
-            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);
-                }
-            }
-        }
+    if (additionalArgs < deleteCount) {
+        shift(exec, thisObj, begin, deleteCount, additionalArgs, length);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+    } else if (additionalArgs > deleteCount) {
+        unshift(exec, thisObj, begin, deleteCount, additionalArgs, length);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+    }
+    for (unsigned k = 0; k < additionalArgs; ++k) {
+        thisObj->methodTable()->putByIndex(thisObj, exec, k + begin, exec->argument(k + 2), true);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
     }
     }
-    for (unsigned k = 0; k < additionalArgs; ++k)
-        thisObj->put(exec, k + begin, exec->argument(k + 2));
 
     putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs));
     return JSValue::encode(result);
 
     putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs));
     return JSValue::encode(result);
@@ -621,26 +744,22 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec)
 {
     // 15.4.4.13
 
 {
     // 15.4.4.13
 
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
     unsigned nrArgs = exec->argumentCount();
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     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);
-            }
-        }
+    if (nrArgs) {
+        unshift(exec, thisObj, 0, 0, nrArgs, length);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+    }
+    for (unsigned k = 0; k < nrArgs; ++k) {
+        thisObj->methodTable()->putByIndex(thisObj, exec, k, exec->argument(k), true);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
     }
     }
-    for (unsigned k = 0; k < nrArgs; ++k)
-        thisObj->put(exec, k, exec->argument(k));
     JSValue result = jsNumber(length + nrArgs);
     putProperty(exec, thisObj, exec->propertyNames().length, result);
     return JSValue::encode(result);
     JSValue result = jsNumber(length + nrArgs);
     putProperty(exec, thisObj, exec->propertyNames().length, result);
     return JSValue::encode(result);
@@ -648,7 +767,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
 {
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -659,13 +778,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
     if (callType == CallTypeNone)
         return throwVMTypeError(exec);
 
     if (callType == CallTypeNone)
         return throwVMTypeError(exec);
 
-    JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
+    JSValue applyThis = exec->argument(1);
     JSArray* resultArray = constructEmptyArray(exec);
 
     unsigned filterIndex = 0;
     unsigned k = 0;
     JSArray* resultArray = constructEmptyArray(exec);
 
     unsigned filterIndex = 0;
     unsigned k = 0;
-    if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
-        JSFunction* f = asFunction(function);
+    if (callType == CallTypeJS && isJSArray(thisObj)) {
+        JSFunction* f = jsCast<JSFunction*>(function);
         JSArray* array = asArray(thisObj);
         CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
         JSArray* array = asArray(thisObj);
         CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
@@ -679,7 +798,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
             
             JSValue result = cachedCall.call();
             if (result.toBoolean(exec))
             
             JSValue result = cachedCall.call();
             if (result.toBoolean(exec))
-                resultArray->put(exec, filterIndex++, v);
+                resultArray->putDirectIndex(exec, filterIndex++, v);
         }
         if (k == length)
             return JSValue::encode(resultArray);
         }
         if (k == length)
             return JSValue::encode(resultArray);
@@ -700,14 +819,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
 
         JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
         if (result.toBoolean(exec))
 
         JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
         if (result.toBoolean(exec))
-            resultArray->put(exec, filterIndex++, v);
+            resultArray->putDirectIndex(exec, filterIndex++, v);
     }
     return JSValue::encode(resultArray);
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
 {
     }
     return JSValue::encode(resultArray);
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -718,12 +837,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
     if (callType == CallTypeNone)
         return throwVMTypeError(exec);
 
     if (callType == CallTypeNone)
         return throwVMTypeError(exec);
 
-    JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
+    JSValue applyThis = exec->argument(1);
 
     JSArray* resultArray = constructEmptyArray(exec, length);
     unsigned k = 0;
 
     JSArray* resultArray = constructEmptyArray(exec, length);
     unsigned k = 0;
-    if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
-        JSFunction* f = asFunction(function);
+    if (callType == CallTypeJS && isJSArray(thisObj)) {
+        JSFunction* f = jsCast<JSFunction*>(function);
         JSArray* array = asArray(thisObj);
         CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
         JSArray* array = asArray(thisObj);
         CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
@@ -735,7 +854,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
             cachedCall.setArgument(1, jsNumber(k));
             cachedCall.setArgument(2, thisObj);
 
             cachedCall.setArgument(1, jsNumber(k));
             cachedCall.setArgument(2, thisObj);
 
-            resultArray->JSArray::put(exec, k, cachedCall.call());
+            resultArray->putDirectIndex(exec, k, cachedCall.call());
         }
     }
     for (; k < length && !exec->hadException(); ++k) {
         }
     }
     for (; k < length && !exec->hadException(); ++k) {
@@ -756,7 +875,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
             return JSValue::encode(jsUndefined());
 
         JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
             return JSValue::encode(jsUndefined());
 
         JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
-        resultArray->put(exec, k, result);
+        resultArray->putDirectIndex(exec, k, result);
     }
 
     return JSValue::encode(resultArray);
     }
 
     return JSValue::encode(resultArray);
@@ -769,7 +888,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec)
 {
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -780,13 +899,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec)
     if (callType == CallTypeNone)
         return throwVMTypeError(exec);
 
     if (callType == CallTypeNone)
         return throwVMTypeError(exec);
 
-    JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
+    JSValue applyThis = exec->argument(1);
 
     JSValue result = jsBoolean(true);
 
     unsigned k = 0;
 
     JSValue result = jsBoolean(true);
 
     unsigned k = 0;
-    if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
-        JSFunction* f = asFunction(function);
+    if (callType == CallTypeJS && isJSArray(thisObj)) {
+        JSFunction* f = jsCast<JSFunction*>(function);
         JSArray* array = asArray(thisObj);
         CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
         JSArray* array = asArray(thisObj);
         CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
@@ -827,7 +946,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec)
 {
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -838,11 +957,11 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec)
     if (callType == CallTypeNone)
         return throwVMTypeError(exec);
 
     if (callType == CallTypeNone)
         return throwVMTypeError(exec);
 
-    JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
+    JSValue applyThis = exec->argument(1);
 
     unsigned k = 0;
 
     unsigned k = 0;
-    if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
-        JSFunction* f = asFunction(function);
+    if (callType == CallTypeJS && isJSArray(thisObj)) {
+        JSFunction* f = jsCast<JSFunction*>(function);
         JSArray* array = asArray(thisObj);
         CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
         JSArray* array = asArray(thisObj);
         CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
@@ -877,7 +996,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec)
 {
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -888,13 +1007,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec)
     if (callType == CallTypeNone)
         return throwVMTypeError(exec);
 
     if (callType == CallTypeNone)
         return throwVMTypeError(exec);
 
-    JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
+    JSValue applyThis = exec->argument(1);
 
     JSValue result = jsBoolean(false);
 
     unsigned k = 0;
 
     JSValue result = jsBoolean(false);
 
     unsigned k = 0;
-    if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
-        JSFunction* f = asFunction(function);
+    if (callType == CallTypeJS && isJSArray(thisObj)) {
+        JSFunction* f = jsCast<JSFunction*>(function);
         JSArray* array = asArray(thisObj);
         CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
         JSArray* array = asArray(thisObj);
         CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
@@ -934,7 +1053,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
 {
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -951,7 +1070,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
         return throwVMTypeError(exec);
 
     JSArray* array = 0;
         return throwVMTypeError(exec);
 
     JSArray* array = 0;
-    if (isJSArray(&exec->globalData(), thisObj))
+    if (isJSArray(thisObj))
         array = asArray(thisObj);
 
     if (exec->argumentCount() >= 2)
         array = asArray(thisObj);
 
     if (exec->argumentCount() >= 2)
@@ -962,6 +1081,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
     } else {
         for (i = 0; i < length; i++) {
             rv = getProperty(exec, thisObj, i);
     } else {
         for (i = 0; i < length; i++) {
             rv = getProperty(exec, thisObj, i);
+            if (exec->hadException())
+                return JSValue::encode(jsUndefined());
             if (rv)
                 break;
         }
             if (rv)
                 break;
         }
@@ -971,9 +1092,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
     }
 
     if (callType == CallTypeJS && array) {
     }
 
     if (callType == CallTypeJS && array) {
-        CachedCall cachedCall(exec, asFunction(function), 4);
+        CachedCall cachedCall(exec, jsCast<JSFunction*>(function), 4);
         for (; i < length && !exec->hadException(); ++i) {
         for (; i < length && !exec->hadException(); ++i) {
-            cachedCall.setThis(jsNull());
+            cachedCall.setThis(jsUndefined());
             cachedCall.setArgument(0, rv);
             JSValue v;
             if (LIKELY(array->canGetIndex(i)))
             cachedCall.setArgument(0, rv);
             JSValue v;
             if (LIKELY(array->canGetIndex(i)))
@@ -1002,14 +1123,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
         eachArguments.append(jsNumber(i));
         eachArguments.append(thisObj);
         
         eachArguments.append(jsNumber(i));
         eachArguments.append(thisObj);
         
-        rv = call(exec, function, callType, callData, jsNull(), eachArguments);
+        rv = call(exec, function, callType, callData, jsUndefined(), eachArguments);
     }
     return JSValue::encode(rv);
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
 {
     }
     return JSValue::encode(rv);
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -1026,7 +1147,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
         return throwVMTypeError(exec);
 
     JSArray* array = 0;
         return throwVMTypeError(exec);
 
     JSArray* array = 0;
-    if (isJSArray(&exec->globalData(), thisObj))
+    if (isJSArray(thisObj))
         array = asArray(thisObj);
     
     if (exec->argumentCount() >= 2)
         array = asArray(thisObj);
     
     if (exec->argumentCount() >= 2)
@@ -1037,6 +1158,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
     } else {
         for (i = 0; i < length; i++) {
             rv = getProperty(exec, thisObj, length - i - 1);
     } else {
         for (i = 0; i < length; i++) {
             rv = getProperty(exec, thisObj, length - i - 1);
+            if (exec->hadException())
+                return JSValue::encode(jsUndefined());
             if (rv)
                 break;
         }
             if (rv)
                 break;
         }
@@ -1046,10 +1169,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
     }
     
     if (callType == CallTypeJS && array) {
     }
     
     if (callType == CallTypeJS && array) {
-        CachedCall cachedCall(exec, asFunction(function), 4);
+        CachedCall cachedCall(exec, jsCast<JSFunction*>(function), 4);
         for (; i < length && !exec->hadException(); ++i) {
             unsigned idx = length - i - 1;
         for (; i < length && !exec->hadException(); ++i) {
             unsigned idx = length - i - 1;
-            cachedCall.setThis(jsNull());
+            cachedCall.setThis(jsUndefined());
             cachedCall.setArgument(0, rv);
             if (UNLIKELY(!array->canGetIndex(idx)))
                 break; // length has been made unsafe while we enumerate fallback to slow path
             cachedCall.setArgument(0, rv);
             if (UNLIKELY(!array->canGetIndex(idx)))
                 break; // length has been made unsafe while we enumerate fallback to slow path
@@ -1076,7 +1199,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
         eachArguments.append(jsNumber(idx));
         eachArguments.append(thisObj);
         
         eachArguments.append(jsNumber(idx));
         eachArguments.append(thisObj);
         
-        rv = call(exec, function, callType, callData, jsNull(), eachArguments);
+        rv = call(exec, function, callType, callData, jsUndefined(), eachArguments);
     }
     return JSValue::encode(rv);        
 }
     }
     return JSValue::encode(rv);        
 }
@@ -1084,7 +1207,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
 {
     // 15.4.4.14
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
 {
     // 15.4.4.14
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -1093,6 +1216,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
     JSValue searchElement = exec->argument(0);
     for (; index < length; ++index) {
         JSValue e = getProperty(exec, thisObj, index);
     JSValue searchElement = exec->argument(0);
     for (; index < length; ++index) {
         JSValue e = getProperty(exec, thisObj, index);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
         if (!e)
             continue;
         if (JSValue::strictEqual(exec, searchElement, e))
         if (!e)
             continue;
         if (JSValue::strictEqual(exec, searchElement, e))
@@ -1105,14 +1230,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec)
 {
     // 15.4.4.15
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec)
 {
     // 15.4.4.15
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (!length)
         return JSValue::encode(jsNumber(-1));
 
     unsigned index = length - 1;
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     if (!length)
         return JSValue::encode(jsNumber(-1));
 
     unsigned index = length - 1;
-    JSValue fromValue = exec->argument(1);
-    if (!fromValue.isUndefined()) {
+    if (exec->argumentCount() >= 2) {
+        JSValue fromValue = exec->argument(1);
         double fromDouble = fromValue.toInteger(exec);
         if (fromDouble < 0) {
             fromDouble += length;
         double fromDouble = fromValue.toInteger(exec);
         if (fromDouble < 0) {
             fromDouble += length;
@@ -1127,6 +1252,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec)
     do {
         ASSERT(index < length);
         JSValue e = getProperty(exec, thisObj, index);
     do {
         ASSERT(index < length);
         JSValue e = getProperty(exec, thisObj, index);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
         if (!e)
             continue;
         if (JSValue::strictEqual(exec, searchElement, e))
         if (!e)
             continue;
         if (JSValue::strictEqual(exec, searchElement, e))
index bbc170ca76af4ba94d9c75e2cc3950606aa28db8..f49a9a667107623fe522543e185a6537e024733b 100644 (file)
 namespace JSC {
 
     class ArrayPrototype : public JSArray {
 namespace JSC {
 
     class ArrayPrototype : public JSArray {
+    private:
+        ArrayPrototype(JSGlobalObject*, Structure*);
+
     public:
     public:
-        explicit ArrayPrototype(JSGlobalObject*, Structure*);
+        typedef JSArray Base;
 
 
-        bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static ArrayPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+        {
+            ArrayPrototype* prototype = new (NotNull, allocateCell<ArrayPrototype>(*exec->heap())) ArrayPrototype(globalObject, structure);
+            prototype->finishCreation(globalObject);
+            return prototype;
+        }
+        
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
         static const ClassInfo s_info;
 
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
-        static const unsigned AnonymousSlotCount = JSArray::AnonymousSlotCount + 1;
+        void finishCreation(JSGlobalObject*);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
diff --git a/runtime/BigInteger.h b/runtime/BigInteger.h
new file mode 100644 (file)
index 0000000..833829d
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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 BigInteger_h
+#define BigInteger_h
+
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+// This is used in converting the integer part of a number to a string.
+class BigInteger {
+public:
+    BigInteger(double number)
+    {
+        ASSERT(isfinite(number) && !signbit(number));
+        ASSERT(number == floor(number));
+
+        bool sign;
+        int32_t exponent;
+        uint64_t mantissa;
+        decomposeDouble(number, sign, exponent, mantissa);
+        ASSERT(!sign && exponent >= 0);
+
+        int32_t zeroBits = exponent - 52;
+
+        if (zeroBits < 0) {
+            mantissa >>= -zeroBits;
+            zeroBits = 0;
+        }
+
+        while (zeroBits >= 32) {
+            m_values.append(0);
+            zeroBits -= 32;
+        }
+
+        // Left align the 53 bits of the mantissa within 96 bits.
+        uint32_t values[3];
+        values[0] = static_cast<uint32_t>(mantissa);
+        values[1] = static_cast<uint32_t>(mantissa >> 32);
+        values[2] = 0;
+        // Shift based on the remainder of the exponent.
+        if (zeroBits) {
+            values[2] = values[1] >> (32 - zeroBits);
+            values[1] = (values[1] << zeroBits) | (values[0] >> (32 - zeroBits));
+            values[0] = (values[0] << zeroBits);
+        }
+        m_values.append(values[0]);
+        m_values.append(values[1]);
+        m_values.append(values[2]);
+
+        // Canonicalize; remove all trailing zeros.
+        while (m_values.size() && !m_values.last())
+            m_values.removeLast();
+    }
+
+    uint32_t divide(uint32_t divisor)
+    {
+        uint32_t carry = 0;
+
+        for (size_t i = m_values.size(); i; ) {
+            --i;
+            uint64_t dividend = (static_cast<uint64_t>(carry) << 32) + static_cast<uint64_t>(m_values[i]);
+
+            uint64_t result = dividend / static_cast<uint64_t>(divisor);
+            ASSERT(result == static_cast<uint32_t>(result));
+            uint64_t remainder = dividend % static_cast<uint64_t>(divisor);
+            ASSERT(remainder == static_cast<uint32_t>(remainder));
+            
+            m_values[i] = static_cast<uint32_t>(result);
+            carry = static_cast<uint32_t>(remainder);
+        }
+
+        // Canonicalize; remove all trailing zeros.
+        while (m_values.size() && !m_values.last())
+            m_values.removeLast();
+
+        return carry;
+    }
+
+    bool operator!() { return !m_values.size(); }
+
+private:
+    Vector<uint32_t, 36> m_values;
+};
+
+}
+
+#endif
+
index a1a4ed48bfb2c8ddb6ea881cbe79157bb8025b0e..a54d281a7e0ba47eeea0b777596b78b271d38bef 100644 (file)
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanConstructor);
 
 
-BooleanConstructor::BooleanConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, BooleanPrototype* booleanPrototype)
-    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, booleanPrototype->classInfo()->className))
+const ClassInfo BooleanConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(BooleanConstructor) };
+
+BooleanConstructor::BooleanConstructor(JSGlobalObject* globalObject, Structure* structure)
+    : InternalFunction(globalObject, structure)
+{
+}
+
+void BooleanConstructor::finishCreation(ExecState* exec, BooleanPrototype* booleanPrototype)
 {
 {
+    Base::finishCreation(exec->globalData(), Identifier(exec, booleanPrototype->classInfo()->className));
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
 
     // no. of arguments for constructor
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
 
     // no. of arguments for constructor
@@ -40,7 +48,7 @@ BooleanConstructor::BooleanConstructor(ExecState* exec, JSGlobalObject* globalOb
 // 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->globalData(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure());
+    BooleanObject* obj = BooleanObject::create(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure());
     obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean(exec)));
     return obj;
 }
     obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean(exec)));
     return obj;
 }
@@ -51,7 +59,7 @@ static EncodedJSValue JSC_HOST_CALL constructWithBooleanConstructor(ExecState* e
     return JSValue::encode(constructBoolean(exec, args));
 }
 
     return JSValue::encode(constructBoolean(exec, args));
 }
 
-ConstructType BooleanConstructor::getConstructData(ConstructData& constructData)
+ConstructType BooleanConstructor::getConstructData(JSCell*, ConstructData& constructData)
 {
     constructData.native.function = constructWithBooleanConstructor;
     return ConstructTypeHost;
 {
     constructData.native.function = constructWithBooleanConstructor;
     return ConstructTypeHost;
@@ -63,7 +71,7 @@ static EncodedJSValue JSC_HOST_CALL callBooleanConstructor(ExecState* exec)
     return JSValue::encode(jsBoolean(exec->argument(0).toBoolean(exec)));
 }
 
     return JSValue::encode(jsBoolean(exec->argument(0).toBoolean(exec)));
 }
 
-CallType BooleanConstructor::getCallData(CallData& callData)
+CallType BooleanConstructor::getCallData(JSCell*, CallData& callData)
 {
     callData.native.function = callBooleanConstructor;
     return CallTypeHost;
 {
     callData.native.function = callBooleanConstructor;
     return CallTypeHost;
@@ -71,7 +79,7 @@ CallType BooleanConstructor::getCallData(CallData& callData)
 
 JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSGlobalObject* globalObject, JSValue immediateBooleanValue)
 {
 
 JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSGlobalObject* globalObject, JSValue immediateBooleanValue)
 {
-    BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), globalObject->booleanObjectStructure());
+    BooleanObject* obj = BooleanObject::create(exec->globalData(), globalObject->booleanObjectStructure());
     obj->setInternalValue(exec->globalData(), immediateBooleanValue);
     return obj;
 }
     obj->setInternalValue(exec->globalData(), immediateBooleanValue);
     return obj;
 }
index fa0d05e5887f10126961f13ac2e811153884222f..2b6bafa2f4b5ac64e57805793ba867f7cf5aca0a 100644 (file)
@@ -29,11 +29,29 @@ namespace JSC {
 
     class BooleanConstructor : public InternalFunction {
     public:
 
     class BooleanConstructor : public InternalFunction {
     public:
-        BooleanConstructor(ExecState*, JSGlobalObject*, Structure*, BooleanPrototype*);
+        typedef InternalFunction Base;
+
+        static BooleanConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, BooleanPrototype* booleanPrototype)
+        {
+            BooleanConstructor* constructor = new (NotNull, allocateCell<BooleanConstructor>(*exec->heap())) BooleanConstructor(globalObject, structure);
+            constructor->finishCreation(exec, booleanPrototype);
+            return constructor;
+        }
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 
+        { 
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); 
+        }
+
+    protected:
+        void finishCreation(ExecState*, BooleanPrototype*);
 
     private:
 
     private:
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
+        BooleanConstructor(JSGlobalObject*, Structure*);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
     };
 
     JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSGlobalObject*, JSValue);
     };
 
     JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSGlobalObject*, JSValue);
index e24a30a4bb54ae500ed0e9d7165fc9ce7a5d9a63..37c6eab0ddece3f54c3ecac92ad892f3fd5280b8 100644 (file)
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanObject);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanObject);
 
 
-const ClassInfo BooleanObject::s_info = { "Boolean", &JSWrapperObject::s_info, 0, 0 };
+const ClassInfo BooleanObject::s_info = { "Boolean", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(BooleanObject) };
 
 BooleanObject::BooleanObject(JSGlobalData& globalData, Structure* structure)
     : JSWrapperObject(globalData, structure)
 {
 
 BooleanObject::BooleanObject(JSGlobalData& globalData, Structure* structure)
     : JSWrapperObject(globalData, structure)
 {
+}
+
+void BooleanObject::finishCreation(JSGlobalData& globalData)
+{
+    Base::finishCreation(globalData);
     ASSERT(inherits(&s_info));
 }
 
     ASSERT(inherits(&s_info));
 }
 
index def44b44dcd84fce03269190ff67cabb500272b2..2704ff3cd4f92a34eff18a4f0c1cf40466ca5249 100644 (file)
 namespace JSC {
 
     class BooleanObject : public JSWrapperObject {
 namespace JSC {
 
     class BooleanObject : public JSWrapperObject {
+    protected:
+        BooleanObject(JSGlobalData&, Structure*);
+        void finishCreation(JSGlobalData&);
+
     public:
     public:
-        explicit BooleanObject(JSGlobalData&, Structure*);
+        typedef JSWrapperObject Base;
 
 
+        static BooleanObject* create(JSGlobalData& globalData, Structure* structure)
+        {
+            BooleanObject* boolean = new (NotNull, allocateCell<BooleanObject>(globalData.heap)) BooleanObject(globalData, structure);
+            boolean->finishCreation(globalData);
+            return boolean;
+        }
+        
         static const ClassInfo s_info;
         
         static const ClassInfo s_info;
         
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
     };
 
         }
     };
 
index dd0194f3f5d092b08eac266ea96995d5b6310f1b..b9605d0cfc7ff08a200eb9d539cb186c1abf08f7 100644 (file)
@@ -38,7 +38,7 @@ static EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*);
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo BooleanPrototype::s_info = { "Boolean", &BooleanObject::s_info, 0, ExecState::booleanPrototypeTable };
+const ClassInfo BooleanPrototype::s_info = { "Boolean", &BooleanObject::s_info, 0, ExecState::booleanPrototypeTable, CREATE_METHOD_TABLE(BooleanPrototype) };
 
 /* Source for BooleanPrototype.lut.h
 @begin booleanPrototypeTable
 
 /* Source for BooleanPrototype.lut.h
 @begin booleanPrototypeTable
@@ -48,24 +48,29 @@ const ClassInfo BooleanPrototype::s_info = { "Boolean", &BooleanObject::s_info,
 */
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanPrototype);
 */
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanPrototype);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanPrototype);
 
 
-BooleanPrototype::BooleanPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+BooleanPrototype::BooleanPrototype(ExecState* exec, Structure* structure)
     : BooleanObject(exec->globalData(), structure)
 {
     : BooleanObject(exec->globalData(), structure)
 {
+}
+
+void BooleanPrototype::finishCreation(ExecState* exec, JSGlobalObject*)
+{
+    Base::finishCreation(exec->globalData());
     setInternalValue(exec->globalData(), jsBoolean(false));
 
     ASSERT(inherits(&s_info));
     setInternalValue(exec->globalData(), jsBoolean(false));
 
     ASSERT(inherits(&s_info));
-    putAnonymousValue(globalObject->globalData(), 0, globalObject);
 }
 
 }
 
-bool BooleanPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+bool BooleanPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 {
-    return getStaticFunctionSlot<BooleanObject>(exec, ExecState::booleanPrototypeTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<BooleanObject>(exec, ExecState::booleanPrototypeTable(exec), jsCast<BooleanPrototype*>(cell), propertyName, slot);
 }
 
 }
 
-bool BooleanPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool BooleanPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<BooleanObject>(exec, ExecState::booleanPrototypeTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<BooleanObject>(exec, ExecState::booleanPrototypeTable(exec), jsCast<BooleanPrototype*>(object), propertyName, descriptor);
 }
 
 // ------------------------------ Functions ---------------------------
 }
 
 // ------------------------------ Functions ---------------------------
index 2341c1147a4384d6ae8ab5d2b3a0fe56639ce009..f35d586e63e5524c307a74dae0a825c48d9b010f 100644 (file)
@@ -27,22 +27,31 @@ namespace JSC {
 
     class BooleanPrototype : public BooleanObject {
     public:
 
     class BooleanPrototype : public BooleanObject {
     public:
-        BooleanPrototype(ExecState*, JSGlobalObject*, Structure*);
+        typedef BooleanObject Base;
 
 
+        static BooleanPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+        {
+            BooleanPrototype* prototype = new (NotNull, allocateCell<BooleanPrototype>(*exec->heap())) BooleanPrototype(exec, structure);
+            prototype->finishCreation(exec, globalObject);
+            return prototype;
+        }
+        
         static const ClassInfo s_info;
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
+        void finishCreation(ExecState*, JSGlobalObject*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | BooleanObject::StructureFlags;
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | BooleanObject::StructureFlags;
-        static const unsigned AnonymousSlotCount = BooleanObject::AnonymousSlotCount + 1;
 
     private:
 
     private:
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        BooleanPrototype(ExecState*, Structure*);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 67c7af8b9405df1435bc7ee45db737932eb8249d..f31b4a07f2ddc2ab1767f5cb94f0aea7b1b48335 100644 (file)
@@ -30,8 +30,6 @@
 
 namespace JSC {
 
 
 namespace JSC {
 
-extern const double NaN;
-
 typedef double (*TranscendentalFunctionPtr)(double);
 
 // CachedTranscendentalFunction provides a generic mechanism to cache results
 typedef double (*TranscendentalFunctionPtr)(double);
 
 // CachedTranscendentalFunction provides a generic mechanism to cache results
@@ -76,8 +74,8 @@ private:
         // Lazily allocate the table, populate with NaN->NaN mapping.
         m_cache = static_cast<CacheEntry*>(fastMalloc(s_cacheSize * sizeof(CacheEntry)));
         for (unsigned x = 0; x < s_cacheSize; ++x) {
         // Lazily allocate the table, populate with NaN->NaN mapping.
         m_cache = static_cast<CacheEntry*>(fastMalloc(s_cacheSize * sizeof(CacheEntry)));
         for (unsigned x = 0; x < s_cacheSize; ++x) {
-            m_cache[x].operand = NaN;
-            m_cache[x].result = NaN;
+            m_cache[x].operand = std::numeric_limits<double>::quiet_NaN();
+            m_cache[x].result = std::numeric_limits<double>::quiet_NaN();
         }
     }
 
         }
     }
 
index 018e2ca34b516be6bc691d31fac9a91f17c707e1..ff71fa0cbb6d52211195b084887e3d3453956757 100644 (file)
@@ -35,6 +35,7 @@ namespace JSC {
 JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
 {
     ASSERT(callType == CallTypeJS || callType == CallTypeHost);
 JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
 {
     ASSERT(callType == CallTypeJS || callType == CallTypeHost);
+    ASSERT(isValidThisObject(thisValue, exec));
     return exec->interpreter()->executeCall(exec, asObject(functionObject), callType, callData, thisValue, args);
 }
 
     return exec->interpreter()->executeCall(exec, asObject(functionObject), callType, callData, thisValue, args);
 }
 
index b138f548405c24fa3c59f15838f90864f6b53fe7..15a6a0a48fb8641bd98e7f59ca85f3fcb3e65968 100644 (file)
@@ -57,7 +57,7 @@ namespace JSC {
         } js;
     };
 
         } js;
     };
 
-    JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&);
+    JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&);
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index acec4e78ddbf798607ca78a0098e03c7d3d84de2..eb4a6f9cd40e931311ae41d93426ddad8a80fada 100644 (file)
 #define ClassInfo_h
 
 #include "CallFrame.h"
 #define ClassInfo_h
 
 #include "CallFrame.h"
+#include "ConstructData.h"
+#include "JSCell.h"
 
 namespace JSC {
 
     class HashEntry;
     struct HashTable;
 
 
 namespace JSC {
 
     class HashEntry;
     struct HashTable;
 
+    struct MethodTable {
+        typedef void (*DestroyFunctionPtr)(JSCell*);
+        DestroyFunctionPtr destroy;
+
+        typedef void (*VisitChildrenFunctionPtr)(JSCell*, SlotVisitor&);
+        VisitChildrenFunctionPtr visitChildren;
+
+        typedef CallType (*GetCallDataFunctionPtr)(JSCell*, CallData&);
+        GetCallDataFunctionPtr getCallData;
+
+        typedef ConstructType (*GetConstructDataFunctionPtr)(JSCell*, ConstructData&);
+        GetConstructDataFunctionPtr getConstructData;
+
+        typedef void (*PutFunctionPtr)(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+        PutFunctionPtr put;
+
+        typedef void (*PutByIndexFunctionPtr)(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
+        PutByIndexFunctionPtr putByIndex;
+
+        typedef bool (*DeletePropertyFunctionPtr)(JSCell*, ExecState*, const Identifier&);
+        DeletePropertyFunctionPtr deleteProperty;
+
+        typedef bool (*DeletePropertyByIndexFunctionPtr)(JSCell*, ExecState*, unsigned);
+        DeletePropertyByIndexFunctionPtr deletePropertyByIndex;
+
+        typedef bool (*GetOwnPropertySlotFunctionPtr)(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        GetOwnPropertySlotFunctionPtr getOwnPropertySlot;
+
+        typedef bool (*GetOwnPropertySlotByIndexFunctionPtr)(JSCell*, ExecState*, unsigned, PropertySlot&);
+        GetOwnPropertySlotByIndexFunctionPtr getOwnPropertySlotByIndex;
+
+        typedef JSObject* (*ToThisObjectFunctionPtr)(JSCell*, ExecState*);
+        ToThisObjectFunctionPtr toThisObject;
+
+        typedef JSValue (*DefaultValueFunctionPtr)(const JSObject*, ExecState*, PreferredPrimitiveType);
+        DefaultValueFunctionPtr defaultValue;
+
+        typedef void (*GetOwnPropertyNamesFunctionPtr)(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+        GetOwnPropertyNamesFunctionPtr getOwnPropertyNames;
+
+        typedef void (*GetPropertyNamesFunctionPtr)(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+        GetPropertyNamesFunctionPtr getPropertyNames;
+
+        typedef UString (*ClassNameFunctionPtr)(const JSObject*);
+        ClassNameFunctionPtr className;
+
+        typedef bool (*HasInstanceFunctionPtr)(JSObject*, ExecState*, JSValue, JSValue);
+        HasInstanceFunctionPtr hasInstance;
+
+        typedef void (*PutWithAttributesFunctionPtr)(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
+        PutWithAttributesFunctionPtr putDirectVirtual;
+
+        typedef bool (*DefineOwnPropertyFunctionPtr)(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool);
+        DefineOwnPropertyFunctionPtr defineOwnProperty;
+
+        typedef bool (*GetOwnPropertyDescriptorFunctionPtr)(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+        GetOwnPropertyDescriptorFunctionPtr getOwnPropertyDescriptor;
+    };
+
+#define CREATE_MEMBER_CHECKER(member) \
+template <typename T> \
+struct MemberCheck##member { \
+    struct Fallback { \
+        void member(...); \
+    }; \
+    struct Derived : T, Fallback { }; \
+    template <typename U, U> struct Check; \
+    typedef char Yes[2]; \
+    typedef char No[1]; \
+    template <typename U> \
+    static No &func(Check<void (Fallback::*)(...), &U::member>*); \
+    template <typename U> \
+    static Yes &func(...); \
+    enum { has = sizeof(func<Derived>(0)) == sizeof(Yes) }; \
+}
+
+#define HAS_MEMBER_NAMED(klass, name) (MemberCheck##name<klass>::has)
+
+#define CREATE_METHOD_TABLE(ClassName) { \
+        &ClassName::destroy, \
+        &ClassName::visitChildren, \
+        &ClassName::getCallData, \
+        &ClassName::getConstructData, \
+        &ClassName::put, \
+        &ClassName::putByIndex, \
+        &ClassName::deleteProperty, \
+        &ClassName::deletePropertyByIndex, \
+        &ClassName::getOwnPropertySlot, \
+        &ClassName::getOwnPropertySlotByIndex, \
+        &ClassName::toThisObject, \
+        &ClassName::defaultValue, \
+        &ClassName::getOwnPropertyNames, \
+        &ClassName::getPropertyNames, \
+        &ClassName::className, \
+        &ClassName::hasInstance, \
+        &ClassName::putDirectVirtual, \
+        &ClassName::defineOwnProperty, \
+        &ClassName::getOwnPropertyDescriptor, \
+    }, \
+    ClassName::TypedArrayStorageType
+
     struct ClassInfo {
         /**
          * A string denoting the class name. Example: "Window".
     struct ClassInfo {
         /**
          * A string denoting the class name. Example: "Window".
@@ -51,10 +154,32 @@ namespace JSC {
                 return classPropHashTableGetterFunction(exec);
             return staticPropHashTable;
         }
                 return classPropHashTableGetterFunction(exec);
             return staticPropHashTable;
         }
+        
+        bool isSubClassOf(const ClassInfo* other) const
+        {
+            for (const ClassInfo* ci = this; ci; ci = ci->parentClass) {
+                if (ci == other)
+                    return true;
+            }
+            return false;
+        }
+
+        bool hasStaticProperties() const
+        {
+            for (const ClassInfo* ci = this; ci; ci = ci->parentClass) {
+                if (ci->staticPropHashTable || ci->classPropHashTableGetterFunction)
+                    return true;
+            }
+            return false;
+        }
 
         const HashTable* staticPropHashTable;
         typedef const HashTable* (*ClassPropHashTableGetterFunction)(ExecState*);
         const ClassPropHashTableGetterFunction classPropHashTableGetterFunction;
 
         const HashTable* staticPropHashTable;
         typedef const HashTable* (*ClassPropHashTableGetterFunction)(ExecState*);
         const ClassPropHashTableGetterFunction classPropHashTableGetterFunction;
+
+        MethodTable methodTable;
+
+        TypedArrayType typedArrayStorageType;
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
diff --git a/runtime/CodeSpecializationKind.h b/runtime/CodeSpecializationKind.h
new file mode 100644 (file)
index 0000000..ba2a54f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CodeSpecializationKind_h
+#define CodeSpecializationKind_h
+
+namespace JSC {
+
+enum CodeSpecializationKind { CodeForCall, CodeForConstruct };
+
+} // namespace JSC
+
+#endif // CodeSpecializationKind_h
+
index f74a84344a0a9167b0877f9c20d6007f590d1996..e15335ef08f60832559305a696d51494799212d8 100644 (file)
 // MarkedArgumentBuffer of property names, passed to a macro so we can do set them up various
 // ways without repeating the list.
 #define JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
 // MarkedArgumentBuffer of property names, passed to a macro so we can do set them up various
 // ways without repeating the list.
 #define JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
-    macro(__defineGetter__) \
-    macro(__defineSetter__) \
-    macro(__lookupGetter__) \
-    macro(__lookupSetter__) \
     macro(apply) \
     macro(arguments) \
     macro(apply) \
     macro(arguments) \
+    macro(bind) \
     macro(call) \
     macro(callee) \
     macro(caller) \
     macro(call) \
     macro(callee) \
     macro(caller) \
@@ -51,6 +48,7 @@
     macro(input) \
     macro(isArray) \
     macro(isPrototypeOf) \
     macro(input) \
     macro(isArray) \
     macro(isPrototypeOf) \
+    macro(lastIndex) \
     macro(length) \
     macro(message) \
     macro(multiline) \
     macro(length) \
     macro(message) \
     macro(multiline) \
@@ -61,6 +59,7 @@
     macro(prototype) \
     macro(set) \
     macro(source) \
     macro(prototype) \
     macro(set) \
     macro(source) \
+    macro(stack) \
     macro(test) \
     macro(toExponential) \
     macro(toFixed) \
     macro(test) \
     macro(toExponential) \
     macro(toFixed) \
     macro(value) \
     macro(valueOf) \
     macro(writable) \
     macro(value) \
     macro(valueOf) \
     macro(writable) \
-    macro(displayName)
+    macro(displayName) \
+    macro(join)
 
 #define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \
     macro(null) \
 
 #define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \
     macro(null) \
+    macro(undefined) \
     macro(true) \
     macro(false) \
     macro(break) \
     macro(true) \
     macro(false) \
     macro(break) \
     macro(export) \
     macro(extends) \
     macro(import) \
     macro(export) \
     macro(extends) \
     macro(import) \
-    macro(super)
+    macro(super) \
+    macro(implements) \
+    macro(interface) \
+    macro(let) \
+    macro(package) \
+    macro(private) \
+    macro(protected) \
+    macro(public) \
+    macro(static) \
+    macro(yield)
 
 namespace JSC {
 
 
 namespace JSC {
 
diff --git a/runtime/CommonSlowPaths.h b/runtime/CommonSlowPaths.h
new file mode 100644 (file)
index 0000000..c41ced7
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CommonSlowPaths_h
+#define CommonSlowPaths_h
+
+#include "CodeBlock.h"
+#include "CodeSpecializationKind.h"
+#include "ExceptionHelpers.h"
+#include "JSArray.h"
+
+namespace JSC {
+
+// The purpose of this namespace is to include slow paths that are shared
+// between the interpreter and baseline JIT. They are written to be agnostic
+// with respect to the slow-path calling convention, but they do rely on the
+// JS code being executed more-or-less directly from bytecode (so the call
+// frame layout is unmodified, making it potentially awkward to use these
+// from any optimizing JIT, like the DFG).
+
+namespace CommonSlowPaths {
+
+ALWAYS_INLINE ExecState* arityCheckFor(ExecState* exec, RegisterFile* registerFile, CodeSpecializationKind kind)
+{
+    JSFunction* callee = jsCast<JSFunction*>(exec->callee());
+    ASSERT(!callee->isHostFunction());
+    CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeFor(kind);
+    int argumentCountIncludingThis = exec->argumentCountIncludingThis();
+
+    // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
+    if (!registerFile->grow(exec->registers() + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters))
+        return 0;
+
+    ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters());
+
+    // Too few arguments -- copy call frame and arguments, then fill in missing arguments with undefined.
+    size_t delta = newCodeBlock->numParameters() - argumentCountIncludingThis;
+    Register* src = exec->registers();
+    Register* dst = exec->registers() + delta;
+
+    int i;
+    int end = -ExecState::offsetFor(argumentCountIncludingThis);
+    for (i = -1; i >= end; --i)
+        dst[i] = src[i];
+
+    end -= delta;
+    for ( ; i >= end; --i)
+        dst[i] = jsUndefined();
+
+    ExecState* newExec = ExecState::create(dst);
+    ASSERT((void*)newExec <= registerFile->end());
+    return newExec;
+}
+
+ALWAYS_INLINE bool opInstanceOfSlow(ExecState* exec, JSValue value, JSValue baseVal, JSValue proto)
+{
+    ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell()
+           || !value.isObject() || !baseVal.isObject() || !proto.isObject() 
+           || !asObject(baseVal)->structure()->typeInfo().implementsDefaultHasInstance());
+
+
+    // 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).
+    TypeInfo typeInfo(UnspecifiedType);
+    if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) {
+        exec->globalData().exception = createInvalidParamError(exec, "instanceof", baseVal);
+        return false;
+    }
+    ASSERT(typeInfo.type() != UnspecifiedType);
+
+    if (!typeInfo.overridesHasInstance() && !value.isObject())
+        return false;
+
+    return asObject(baseVal)->methodTable()->hasInstance(asObject(baseVal), exec, value, proto);
+}
+
+inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal)
+{
+    if (!baseVal.isObject()) {
+        exec->globalData().exception = createInvalidParamError(exec, "in", baseVal);
+        return false;
+    }
+
+    JSObject* baseObj = asObject(baseVal);
+
+    uint32_t i;
+    if (propName.getUInt32(i))
+        return baseObj->hasProperty(exec, i);
+
+    Identifier property(exec, propName.toString(exec)->value(exec));
+    if (exec->globalData().exception)
+        return false;
+    return baseObj->hasProperty(exec, property);
+}
+
+ALWAYS_INLINE JSValue opResolve(ExecState* exec, Identifier& ident)
+{
+    ScopeChainNode* scopeChain = exec->scopeChain();
+
+    ScopeChainIterator iter = scopeChain->begin();
+    ScopeChainIterator end = scopeChain->end();
+    ASSERT(iter != end);
+    
+    do {
+        JSObject* o = iter->get();
+        PropertySlot slot(o);
+        if (o->getPropertySlot(exec, ident, slot))
+            return slot.getValue(exec, ident);
+    } while (++iter != end);
+
+    exec->globalData().exception = createUndefinedVariableError(exec, ident);
+    return JSValue();
+}
+
+ALWAYS_INLINE JSValue opResolveSkip(ExecState* exec, Identifier& ident, int skip)
+{
+    ScopeChainNode* scopeChain = exec->scopeChain();
+
+    ScopeChainIterator iter = scopeChain->begin();
+    ScopeChainIterator end = scopeChain->end();
+    ASSERT(iter != end);
+    CodeBlock* codeBlock = exec->codeBlock();
+    bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        if (exec->uncheckedR(codeBlock->activationRegister()).jsValue())
+            ++iter;
+    }
+    while (skip--) {
+        ++iter;
+        ASSERT(iter != end);
+    }
+    do {
+        JSObject* o = iter->get();
+        PropertySlot slot(o);
+        if (o->getPropertySlot(exec, ident, slot))
+            return slot.getValue(exec, ident);
+    } while (++iter != end);
+
+    exec->globalData().exception = createUndefinedVariableError(exec, ident);
+    return JSValue();
+}
+
+ALWAYS_INLINE JSValue opResolveWithBase(ExecState* exec, Identifier& ident, Register& baseSlot)
+{
+    ScopeChainNode* scopeChain = exec->scopeChain();
+
+    ScopeChainIterator iter = scopeChain->begin();
+    ScopeChainIterator end = scopeChain->end();
+
+    // FIXME: add scopeDepthIsZero optimization
+
+    ASSERT(iter != end);
+
+    JSObject* base;
+    do {
+        base = iter->get();
+        PropertySlot slot(base);
+        if (base->getPropertySlot(exec, ident, slot)) {
+            JSValue result = slot.getValue(exec, ident);
+            if (exec->globalData().exception)
+                return JSValue();
+
+            baseSlot = JSValue(base);
+            return result;
+        }
+        ++iter;
+    } while (iter != end);
+
+    exec->globalData().exception = createUndefinedVariableError(exec, ident);
+    return JSValue();
+}
+
+ALWAYS_INLINE JSValue opResolveWithThis(ExecState* exec, Identifier& ident, Register& baseSlot)
+{
+    ScopeChainNode* scopeChain = exec->scopeChain();
+
+    ScopeChainIterator iter = scopeChain->begin();
+    ScopeChainIterator end = scopeChain->end();
+
+    // FIXME: add scopeDepthIsZero optimization
+
+    ASSERT(iter != end);
+
+    JSObject* base;
+    do {
+        base = iter->get();
+        ++iter;
+        PropertySlot slot(base);
+        if (base->getPropertySlot(exec, ident, slot)) {
+            JSValue result = slot.getValue(exec, ident);
+            if (exec->globalData().exception)
+                return JSValue();
+
+            // All entries on the scope chain should be EnvironmentRecords (activations etc),
+            // other then 'with' object, which are directly referenced from the scope chain,
+            // and the global object. If we hit either an EnvironmentRecord or a global
+            // object at the end of the scope chain, this is undefined. If we hit a non-
+            // EnvironmentRecord within the scope chain, pass the base as the this value.
+            if (iter == end || base->structure()->typeInfo().isEnvironmentRecord())
+                baseSlot = jsUndefined();
+            else
+                baseSlot = JSValue(base);
+            return result;
+        }
+    } while (iter != end);
+
+    exec->globalData().exception = createUndefinedVariableError(exec, ident);
+    return JSValue();
+}
+
+} } // namespace JSC::CommonSlowPaths
+
+#endif // CommonSlowPaths_h
+
index ac19705c0aa9699707106e103bbe6eb33b385914..1c35b9626733afdfec9bc94fc12f1b7e0e85f16e 100644 (file)
 #include "Completion.h"
 
 #include "CallFrame.h"
 #include "Completion.h"
 
 #include "CallFrame.h"
+#include "CodeProfiling.h"
 #include "JSGlobalObject.h"
 #include "JSLock.h"
 #include "Interpreter.h"
 #include "Parser.h"
 #include "Debugger.h"
 #include "JSGlobalObject.h"
 #include "JSLock.h"
 #include "Interpreter.h"
 #include "Parser.h"
 #include "Debugger.h"
-#include "WTFThreadData.h"
+#include <wtf/WTFThreadData.h>
 #include <stdio.h>
 
 namespace JSC {
 
 #include <stdio.h>
 
 namespace JSC {
 
-Completion checkSyntax(ExecState* exec, const SourceCode& source)
+bool checkSyntax(ExecState* exec, const SourceCode& source, JSValue* returnedException)
 {
 {
-    JSLock lock(exec);
+    JSLockHolder lock(exec);
     ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
 
     ProgramExecutable* program = ProgramExecutable::create(exec, source);
     JSObject* error = program->checkSyntax(exec);
     ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
 
     ProgramExecutable* program = ProgramExecutable::create(exec, source);
     JSObject* error = program->checkSyntax(exec);
-    if (error)
-        return Completion(Throw, error);
+    if (error) {
+        if (returnedException)
+            *returnedException = error;
+        return false;
+    }
 
 
-    return Completion(Normal);
+    return true;
 }
 
 }
 
-Completion evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCode& source, JSValue thisValue)
+JSValue evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCode& source, JSValue thisValue, JSValue* returnedException)
 {
 {
-    JSLock lock(exec);
+    JSLockHolder lock(exec);
     ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
     ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
+    if (exec->globalData().isCollectorBusy())
+        CRASH();
+
+    CodeProfiling profile(source);
 
     ProgramExecutable* program = ProgramExecutable::create(exec, source);
     if (!program) {
 
     ProgramExecutable* program = ProgramExecutable::create(exec, source);
     if (!program) {
-        JSValue exception = exec->globalData().exception;
+        if (returnedException)
+            *returnedException = exec->globalData().exception;
+
         exec->globalData().exception = JSValue();
         exec->globalData().exception = JSValue();
-        return Completion(Throw, exception);
+        return jsUndefined();
     }
 
     }
 
-    JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
-
+    if (!thisValue || thisValue.isUndefinedOrNull())
+        thisValue = exec->dynamicGlobalObject();
+    JSObject* thisObj = thisValue.toThisObject(exec);
     JSValue result = exec->interpreter()->execute(program, exec, scopeChain, thisObj);
 
     if (exec->hadException()) {
     JSValue result = exec->interpreter()->execute(program, exec, scopeChain, thisObj);
 
     if (exec->hadException()) {
-        JSValue exception = exec->exception();
-        exec->clearException();
+        if (returnedException)
+            *returnedException = exec->exception();
 
 
-        ComplType exceptionType = Throw;
-        if (exception.isObject())
-            exceptionType = asObject(exception)->exceptionType();
-        return Completion(exceptionType, exception);
+        exec->clearException();
+        return jsUndefined();
     }
     }
-    return Completion(Normal, result);
+
+    ASSERT(result);
+    return result;
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 1dd25fd11ae3fdc2e85783ad1524c6f2b0acb66a..3d3b86fe44dc5f3573cfc6d86bf64dd147e77004 100644 (file)
@@ -31,32 +31,8 @@ namespace JSC {
     class ScopeChainNode;
     class SourceCode;
 
     class ScopeChainNode;
     class SourceCode;
 
-    enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted, Terminated };
-
-    /*
-     * Completion objects are used to convey the return status and value
-     * from functions.
-     */
-    class Completion {
-    public:
-        Completion(ComplType type = Normal, JSValue value = JSValue())
-            : m_type(type)
-            , m_value(value)
-        {
-        }
-
-        ComplType complType() const { return m_type; }
-        JSValue value() const { return m_value; }
-        void setValue(JSValue v) { m_value = v; }
-        bool isValueCompletion() const { return m_value; }
-
-    private:
-        ComplType m_type;
-        JSValue m_value;
-    };
-
-    Completion checkSyntax(ExecState*, const SourceCode&);
-    Completion evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue());
+    JS_EXPORT_PRIVATE bool checkSyntax(ExecState*, const SourceCode&, JSValue* exception = 0);
+    JS_EXPORT_PRIVATE JSValue evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue(), JSValue* exception = 0);
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index 3d5f732a2210cfe2622ddaa22016053dc53f2ffe..d7a3c73d3d76d7bcd16411f1f6db9a7267653643 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef ConstructData_h
 #define ConstructData_h
 
 #ifndef ConstructData_h
 #define ConstructData_h
 
+#include "CallData.h"
 #include "JSValue.h"
 
 namespace JSC {
 #include "JSValue.h"
 
 namespace JSC {
@@ -45,11 +46,9 @@ namespace JSC {
         ConstructTypeJS
     };
 
         ConstructTypeJS
     };
 
-    typedef EncodedJSValue (JSC_HOST_CALL *NativeConstructor)(ExecState*);
-
     union ConstructData {
         struct {
     union ConstructData {
         struct {
-            NativeConstructor function;
+            NativeFunction function;
         } native;
         struct {
             FunctionExecutable* functionExecutable;
         } native;
         struct {
             FunctionExecutable* functionExecutable;
@@ -57,7 +56,7 @@ namespace JSC {
         } js;
     };
 
         } js;
     };
 
-    JSObject* construct(ExecState*, JSValue constructor, ConstructType, const ConstructData&, const ArgList&);
+    JS_EXPORT_PRIVATE JSObject* construct(ExecState*, JSValue constructor, ConstructType, const ConstructData&, const ArgList&);
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index 8fb5aef44abc83d1c021c760a854dfb3e1b57bc6..66f0baea5d43c361af1d50b40d6295b0d6a100ad 100644 (file)
@@ -25,6 +25,7 @@
 #include "DateConversion.h"
 #include "DateInstance.h"
 #include "DatePrototype.h"
 #include "DateConversion.h"
 #include "DateInstance.h"
 #include "DatePrototype.h"
+#include "JSDateMath.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
@@ -32,7 +33,6 @@
 #include "ObjectPrototype.h"
 #include <math.h>
 #include <time.h>
 #include "ObjectPrototype.h"
 #include <math.h>
 #include <time.h>
-#include <wtf/DateMath.h>
 #include <wtf/MathExtras.h>
 
 #if OS(WINCE) && !PLATFORM(QT)
 #include <wtf/MathExtras.h>
 
 #if OS(WINCE) && !PLATFORM(QT)
@@ -61,7 +61,7 @@ static EncodedJSValue JSC_HOST_CALL dateUTC(ExecState*);
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo DateConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::dateConstructorTable };
+const ClassInfo DateConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::dateConstructorTable, CREATE_METHOD_TABLE(DateConstructor) };
 
 /* Source for DateConstructor.lut.h
 @begin dateConstructorTable
 
 /* Source for DateConstructor.lut.h
 @begin dateConstructorTable
@@ -72,22 +72,28 @@ const ClassInfo DateConstructor::s_info = { "Function", &InternalFunction::s_inf
 */
 
 ASSERT_CLASS_FITS_IN_CELL(DateConstructor);
 */
 
 ASSERT_CLASS_FITS_IN_CELL(DateConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(DateConstructor);
 
 
-DateConstructor::DateConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, DatePrototype* datePrototype)
-    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, datePrototype->classInfo()->className))
+DateConstructor::DateConstructor(JSGlobalObject* globalObject, Structure* structure)
+    : InternalFunction(globalObject, structure) 
 {
 {
+}
+
+void DateConstructor::finishCreation(ExecState* exec, DatePrototype* datePrototype)
+{
+    Base::finishCreation(exec->globalData(), Identifier(exec, datePrototype->classInfo()->className));
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, datePrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(7), ReadOnly | DontEnum | DontDelete);
 }
 
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, datePrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(7), ReadOnly | DontEnum | DontDelete);
 }
 
-bool DateConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+bool DateConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 {
-    return getStaticFunctionSlot<InternalFunction>(exec, ExecState::dateConstructorTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<InternalFunction>(exec, ExecState::dateConstructorTable(exec), jsCast<DateConstructor*>(cell), propertyName, slot);
 }
 
 }
 
-bool DateConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool DateConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<InternalFunction>(exec, ExecState::dateConstructorTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<InternalFunction>(exec, ExecState::dateConstructorTable(exec), jsCast<DateConstructor*>(object), propertyName, descriptor);
 }
 
 // ECMA 15.9.3
 }
 
 // ECMA 15.9.3
@@ -119,14 +125,14 @@ JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const Arg
             args.at(5).toNumber(exec), 
             args.at(6).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;
+        if (!isfinite(doubleArguments[0])
+            || !isfinite(doubleArguments[1])
+            || (numArgs >= 3 && !isfinite(doubleArguments[2]))
+            || (numArgs >= 4 && !isfinite(doubleArguments[3]))
+            || (numArgs >= 5 && !isfinite(doubleArguments[4]))
+            || (numArgs >= 6 && !isfinite(doubleArguments[5]))
+            || (numArgs >= 7 && !isfinite(doubleArguments[6])))
+            value = std::numeric_limits<double>::quiet_NaN();
         else {
             GregorianDateTime t;
             int year = JSC::toInt32(doubleArguments[0]);
         else {
             GregorianDateTime t;
             int year = JSC::toInt32(doubleArguments[0]);
@@ -142,7 +148,7 @@ JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const Arg
         }
     }
 
         }
     }
 
-    return new (exec) DateInstance(exec, globalObject->dateStructure(), value);
+    return DateInstance::create(exec, globalObject->dateStructure(), value);
 }
     
 static EncodedJSValue JSC_HOST_CALL constructWithDateConstructor(ExecState* exec)
 }
     
 static EncodedJSValue JSC_HOST_CALL constructWithDateConstructor(ExecState* exec)
@@ -151,7 +157,7 @@ static EncodedJSValue JSC_HOST_CALL constructWithDateConstructor(ExecState* exec
     return JSValue::encode(constructDate(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
     return JSValue::encode(constructDate(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
-ConstructType DateConstructor::getConstructData(ConstructData& constructData)
+ConstructType DateConstructor::getConstructData(JSCell*, ConstructData& constructData)
 {
     constructData.native.function = constructWithDateConstructor;
     return ConstructTypeHost;
 {
     constructData.native.function = constructWithDateConstructor;
     return ConstructTypeHost;
@@ -160,10 +166,8 @@ ConstructType DateConstructor::getConstructData(ConstructData& constructData)
 // ECMA 15.9.2
 static EncodedJSValue JSC_HOST_CALL callDate(ExecState* exec)
 {
 // ECMA 15.9.2
 static EncodedJSValue JSC_HOST_CALL callDate(ExecState* exec)
 {
-    time_t localTime = time(0);
-    tm localTM;
-    getLocalTime(&localTime, &localTM);
-    GregorianDateTime ts(exec, localTM);
+    GregorianDateTime ts;
+    msToGregorianDateTime(exec, currentTimeMS(), false, ts);
     DateConversionBuffer date;
     DateConversionBuffer time;
     formatDate(ts, date);
     DateConversionBuffer date;
     DateConversionBuffer time;
     formatDate(ts, date);
@@ -171,7 +175,7 @@ static EncodedJSValue JSC_HOST_CALL callDate(ExecState* exec)
     return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time));
 }
 
     return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time));
 }
 
-CallType DateConstructor::getCallData(CallData& callData)
+CallType DateConstructor::getCallData(JSCell*, CallData& callData)
 {
     callData.native.function = callDate;
     return CallTypeHost;
 {
     callData.native.function = callDate;
     return CallTypeHost;
@@ -179,7 +183,7 @@ CallType DateConstructor::getCallData(CallData& callData)
 
 static EncodedJSValue JSC_HOST_CALL dateParse(ExecState* exec)
 {
 
 static EncodedJSValue JSC_HOST_CALL dateParse(ExecState* exec)
 {
-    return JSValue::encode(jsNumber(parseDate(exec, exec->argument(0).toString(exec))));
+    return JSValue::encode(jsNumber(parseDate(exec, exec->argument(0).toString(exec)->value(exec))));
 }
 
 static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*)
 }
 
 static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*)
index 63e78cf9a1d02974cb5c57275008edb3f9223ecf..fe6597418ceec6f2122d20a1f2d38792fb4cae75 100644 (file)
@@ -29,24 +29,34 @@ namespace JSC {
 
     class DateConstructor : public InternalFunction {
     public:
 
     class DateConstructor : public InternalFunction {
     public:
-        DateConstructor(ExecState*, JSGlobalObject*, Structure*, DatePrototype*);
+        typedef InternalFunction Base;
+
+        static DateConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, DatePrototype* datePrototype)
+        {
+            DateConstructor* constructor = new (NotNull, allocateCell<DateConstructor>(*exec->heap())) DateConstructor(globalObject, structure);
+            constructor->finishCreation(exec, datePrototype);
+            return constructor;
+        }
 
         static const ClassInfo s_info;
 
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
+        void finishCreation(ExecState*, DatePrototype*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
 
     private:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
 
     private:
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
+        DateConstructor(JSGlobalObject*, Structure*);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
+
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
     JSObject* constructDate(ExecState*, JSGlobalObject*, const ArgList&);
     };
 
     JSObject* constructDate(ExecState*, JSGlobalObject*, const ArgList&);
index 1418876ed1492c1dce52ad9d7a80936a6ca8bc1e..7bc0cbc0fa59cf552909e30bf7d3aba780a858b8 100644 (file)
 #include "DateConversion.h"
 
 #include "CallFrame.h"
 #include "DateConversion.h"
 
 #include "CallFrame.h"
+#include "JSDateMath.h"
 #include "JSObject.h"
 #include "ScopeChain.h"
 #include "UString.h"
 #include "JSObject.h"
 #include "ScopeChain.h"
 #include "UString.h"
-#include <wtf/DateMath.h>
 #include <wtf/StringExtras.h>
 #include <wtf/text/CString.h>
 
 #include <wtf/StringExtras.h>
 #include <wtf/text/CString.h>
 
index d8ca072491b8583dfc81e1295a2d8b392a6447df..a502770c87508b72e4f2498dd9c76275ccb78feb 100644 (file)
 #include "config.h"
 #include "DateInstance.h"
 
 #include "config.h"
 #include "DateInstance.h"
 
+#include "JSDateMath.h"
 #include "JSGlobalObject.h"
 
 #include <math.h>
 #include "JSGlobalObject.h"
 
 #include <math.h>
-#include <wtf/DateMath.h>
 #include <wtf/MathExtras.h>
 
 using namespace WTF;
 
 namespace JSC {
 
 #include <wtf/MathExtras.h>
 
 using namespace WTF;
 
 namespace JSC {
 
-const ClassInfo DateInstance::s_info = {"Date", &JSWrapperObject::s_info, 0, 0};
+const ClassInfo DateInstance::s_info = {"Date", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(DateInstance)};
 
 DateInstance::DateInstance(ExecState* exec, Structure* structure)
     : JSWrapperObject(exec->globalData(), structure)
 {
 
 DateInstance::DateInstance(ExecState* exec, Structure* structure)
     : JSWrapperObject(exec->globalData(), structure)
 {
+}
+
+void DateInstance::finishCreation(JSGlobalData& globalData)
+{
+    Base::finishCreation(globalData);
     ASSERT(inherits(&s_info));
     ASSERT(inherits(&s_info));
-    setInternalValue(exec->globalData(), jsNaN());
+    setInternalValue(globalData, jsNaN());
 }
 
 }
 
-DateInstance::DateInstance(ExecState* exec, Structure* structure, double time)
-    : JSWrapperObject(exec->globalData(), structure)
+void DateInstance::finishCreation(JSGlobalData& globalData, double time)
 {
 {
+    Base::finishCreation(globalData);
     ASSERT(inherits(&s_info));
     ASSERT(inherits(&s_info));
-    setInternalValue(exec->globalData(), jsNumber(timeClip(time)));
+    setInternalValue(globalData, jsNumber(timeClip(time)));
+}
+
+void DateInstance::destroy(JSCell* cell)
+{
+    jsCast<DateInstance*>(cell)->DateInstance::~DateInstance();
 }
 
 const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exec) const
 }
 
 const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exec) const
index 6195c8549f5534c575fe880ebfc1c7fdc2a93669..7c976a514a6d3a93e642cd1a5805e412986136c5 100644 (file)
@@ -30,11 +30,31 @@ namespace WTF {
 namespace JSC {
 
     class DateInstance : public JSWrapperObject {
 namespace JSC {
 
     class DateInstance : public JSWrapperObject {
+    protected:
+        JS_EXPORT_PRIVATE DateInstance(ExecState*, Structure*);
+        void finishCreation(JSGlobalData&);
+        JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, double);
+
+        static void destroy(JSCell*);
     public:
     public:
-        DateInstance(ExecState*, Structure*, double);
-        explicit DateInstance(ExecState*, Structure*);
+        typedef JSWrapperObject Base;
+
+        static DateInstance* create(ExecState* exec, Structure* structure, double date)
+        {
+            DateInstance* instance = new (NotNull, allocateCell<DateInstance>(*exec->heap())) DateInstance(exec, structure);
+            instance->finishCreation(exec->globalData(), date);
+            return instance;
+        }
+
+        static DateInstance* create(ExecState* exec, Structure* structure)
+        {
+            DateInstance* instance = new (NotNull, allocateCell<DateInstance>(*exec->heap())) DateInstance(exec, structure);
+            instance->finishCreation(exec->globalData());
+            return instance;
+        }
 
 
-        double internalNumber() const { return internalValue().uncheckedGetNumber(); }
+        double internalNumber() const { return internalValue().asNumber(); }
 
         static JS_EXPORTDATA const ClassInfo s_info;
 
 
         static JS_EXPORTDATA const ClassInfo s_info;
 
@@ -52,9 +72,9 @@ namespace JSC {
             return calculateGregorianDateTimeUTC(exec);
         }
 
             return calculateGregorianDateTimeUTC(exec);
         }
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     private:
         }
 
     private:
index b60c29a60eed3d72b64d0430be285ae48bdf81ec..153582f6740eece156810ee6f4d819bca1fbf689 100644 (file)
 #ifndef DateInstanceCache_h
 #define DateInstanceCache_h
 
 #ifndef DateInstanceCache_h
 #define DateInstanceCache_h
 
-#include <wtf/DateMath.h>
+#include "JSDateMath.h"
+#include <wtf/FixedArray.h>
 #include <wtf/HashFunctions.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 
 namespace JSC {
 
 #include <wtf/HashFunctions.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 
 namespace JSC {
 
-    extern const double NaN;
-
     class DateInstanceData : public RefCounted<DateInstanceData> {
     public:
         static PassRefPtr<DateInstanceData> create() { return adoptRef(new DateInstanceData); }
     class DateInstanceData : public RefCounted<DateInstanceData> {
     public:
         static PassRefPtr<DateInstanceData> create() { return adoptRef(new DateInstanceData); }
@@ -46,8 +45,8 @@ namespace JSC {
 
     private:
         DateInstanceData()
 
     private:
         DateInstanceData()
-            : m_gregorianDateTimeCachedForMS(NaN)
-            , m_gregorianDateTimeUTCCachedForMS(NaN)
+            : m_gregorianDateTimeCachedForMS(std::numeric_limits<double>::quiet_NaN())
+            , m_gregorianDateTimeUTCCachedForMS(std::numeric_limits<double>::quiet_NaN())
         {
         }
     };
         {
         }
     };
@@ -62,7 +61,7 @@ namespace JSC {
         void reset()
         {
             for (size_t i = 0; i < cacheSize; ++i)
         void reset()
         {
             for (size_t i = 0; i < cacheSize; ++i)
-                m_cache[i].key = NaN;
+                m_cache[i].key = std::numeric_limits<double>::quiet_NaN();
         }
         
         DateInstanceData* add(double d)
         }
         
         DateInstanceData* add(double d)
index 0dd67460f45ae03f048153869b53bcd005c12546..74f8f6700a9a6c28fe0949a4675d7115c2cd3bef 100644 (file)
@@ -27,6 +27,8 @@
 #include "DateConversion.h"
 #include "DateInstance.h"
 #include "Error.h"
 #include "DateConversion.h"
 #include "DateInstance.h"
 #include "Error.h"
+#include "JSDateMath.h"
+#include "JSGlobalObject.h"
 #include "JSString.h"
 #include "JSStringBuilder.h"
 #include "Lookup.h"
 #include "JSString.h"
 #include "JSStringBuilder.h"
 #include "Lookup.h"
@@ -42,7 +44,6 @@
 #include <stdlib.h>
 #include <time.h>
 #include <wtf/Assertions.h>
 #include <stdlib.h>
 #include <time.h>
 #include <wtf/Assertions.h>
-#include <wtf/DateMath.h>
 #include <wtf/MathExtras.h>
 #include <wtf/StringExtras.h>
 #include <wtf/UnusedParam.h>
 #include <wtf/MathExtras.h>
 #include <wtf/StringExtras.h>
 #include <wtf/UnusedParam.h>
@@ -125,7 +126,6 @@ namespace JSC {
 
 enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
  
 
 enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
  
-
 // FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
 // Instead we should consider using this whenever USE(CF) is true.
 
 // FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
 // Instead we should consider using this whenever USE(CF) is true.
 
@@ -150,13 +150,13 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil
     bool useCustomFormat = false;
     UString customFormatString;
 
     bool useCustomFormat = false;
     UString customFormatString;
 
-    UString arg0String = exec->argument(0).toString(exec);
+    UString arg0String = exec->argument(0).toString(exec)->value(exec);
     if (arg0String == "custom" && !exec->argument(1).isUndefined()) {
         useCustomFormat = true;
     if (arg0String == "custom" && !exec->argument(1).isUndefined()) {
         useCustomFormat = true;
-        customFormatString = exec->argument(1).toString(exec);
+        customFormatString = exec->argument(1).toString(exec)->value(exec);
     } else if (format == LocaleDateAndTime && !exec->argument(1).isUndefined()) {
         dateStyle = styleFromArgString(arg0String, dateStyle);
     } else if (format == LocaleDateAndTime && !exec->argument(1).isUndefined()) {
         dateStyle = styleFromArgString(arg0String, dateStyle);
-        timeStyle = styleFromArgString(exec->argument(1).toString(exec), timeStyle);
+        timeStyle = styleFromArgString(exec->argument(1).toString(exec)->value(exec), timeStyle);
     } else if (format != LocaleTime && !exec->argument(0).isUndefined())
         dateStyle = styleFromArgString(arg0String, dateStyle);
     else if (format != LocaleDate && !exec->argument(0).isUndefined())
     } else if (format != LocaleTime && !exec->argument(0).isUndefined())
         dateStyle = styleFromArgString(arg0String, dateStyle);
     else if (format != LocaleDate && !exec->argument(0).isUndefined())
@@ -191,7 +191,6 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil
     return jsNontrivialString(exec, UString(buffer, length));
 }
 
     return jsNontrivialString(exec, UString(buffer, length));
 }
 
-
 // Converts a list of arguments sent to a Date member function into milliseconds, updating
 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
 //
 // Converts a list of arguments sent to a Date member function into milliseconds, updating
 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
 //
@@ -283,7 +282,7 @@ static bool fillStructuresUsingDateArgs(ExecState *exec, int maxArgs, double *ms
     return ok;
 }
 
     return ok;
 }
 
-const ClassInfo DatePrototype::s_info = {"Date", &DateInstance::s_info, 0, ExecState::dateTable};
+const ClassInfo DatePrototype::s_info = {"Date", &DateInstance::s_info, 0, ExecState::dateTable, CREATE_METHOD_TABLE(DatePrototype)};
 
 /* Source for DatePrototype.lut.h
 @begin dateTable
 
 /* Source for DatePrototype.lut.h
 @begin dateTable
@@ -338,24 +337,27 @@ const ClassInfo DatePrototype::s_info = {"Date", &DateInstance::s_info, 0, ExecS
 
 // ECMA 15.9.4
 
 
 // ECMA 15.9.4
 
-DatePrototype::DatePrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+DatePrototype::DatePrototype(ExecState* exec, Structure* structure)
     : DateInstance(exec, structure)
 {
     : DateInstance(exec, structure)
 {
+}
+
+void DatePrototype::finishCreation(ExecState* exec, JSGlobalObject*)
+{
+    Base::finishCreation(exec->globalData());
     ASSERT(inherits(&s_info));
 
     // The constructor will be added later, after DateConstructor has been built.
     ASSERT(inherits(&s_info));
 
     // The constructor will be added later, after DateConstructor has been built.
-    putAnonymousValue(exec->globalData(), 0, globalObject);
 }
 
 }
 
-bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+bool DatePrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
-    return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), jsCast<DatePrototype*>(cell), propertyName, slot);
 }
 
 }
 
-
-bool DatePrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool DatePrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::dateTable(exec), jsCast<DatePrototype*>(object), propertyName, descriptor);
 }
 
 // Functions
 }
 
 // Functions
@@ -403,14 +405,23 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec)
         return throwVMTypeError(exec);
     
     DateInstance* thisDateObj = asDateInstance(thisValue); 
         return throwVMTypeError(exec);
     
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    
+    if (!isfinite(thisDateObj->internalNumber()))
+        return throwVMError(exec, createRangeError(exec, "Invalid Date"));
+
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
         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)));
+    // Maximum amount of space we need in buffer: 7 (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 = 28. We add one extra character to allow us to force null termination.
+    char buffer[29];
+    // If the year is outside the bounds of 0 and 9999 inclusive we want to use the extended year format (ES 15.9.1.15.1).
+    int ms = static_cast<int>(fmod(thisDateObj->internalNumber(), msPerSecond));
+    if (ms < 0)
+        ms += msPerSecond;
+    if (gregorianDateTime->year > 8099 || gregorianDateTime->year < -1900)
+        snprintf(buffer, sizeof(buffer) - 1, "%+07d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year, gregorianDateTime->month + 1, gregorianDateTime->monthDay, gregorianDateTime->hour, gregorianDateTime->minute, gregorianDateTime->second, ms);
+    else
+        snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year, gregorianDateTime->month + 1, gregorianDateTime->monthDay, gregorianDateTime->hour, gregorianDateTime->minute, gregorianDateTime->second, ms);
     buffer[sizeof(buffer) - 1] = 0;
     return JSValue::encode(jsNontrivialString(exec, buffer));
 }
     buffer[sizeof(buffer) - 1] = 0;
     return JSValue::encode(jsNontrivialString(exec, buffer));
 }
index 2e1030dffbd186973e2bb9d9406d4f04cd304312..90eec28a17c6e306fcf74201e9d8d9bdfa6bee50 100644 (file)
@@ -28,24 +28,32 @@ namespace JSC {
     class ObjectPrototype;
 
     class DatePrototype : public DateInstance {
     class ObjectPrototype;
 
     class DatePrototype : public DateInstance {
+    private:
+        DatePrototype(ExecState*, Structure*);
+
     public:
     public:
-        DatePrototype(ExecState*, JSGlobalObject*, Structure*);
+        typedef DateInstance Base;
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static DatePrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+        {
+            DatePrototype* prototype = new (NotNull, allocateCell<DatePrototype>(*exec->heap())) DatePrototype(exec, structure);
+            prototype->finishCreation(exec, globalObject);
+            return prototype;
+        }
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
         static const ClassInfo s_info;
 
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
+        void finishCreation(ExecState*, JSGlobalObject*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | DateInstance::StructureFlags;
         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 7eda19f54bc650f021b760a641a9f216bead74f8..bae07448b3118892d933958864f3a48959fdaf3d 100644 (file)
@@ -26,6 +26,9 @@
 
 #include "ConstructData.h"
 #include "ErrorConstructor.h"
 
 #include "ConstructData.h"
 #include "ErrorConstructor.h"
+#include "ExceptionHelpers.h"
+#include "FunctionPrototype.h"
+#include "JSArray.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "JSObject.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "JSObject.h"
 #include "NativeErrorConstructor.h"
 #include "SourceCode.h"
 
 #include "NativeErrorConstructor.h"
 #include "SourceCode.h"
 
+#include <wtf/text/StringBuilder.h>
+
 namespace JSC {
 
 static const char* linePropertyName = "line";
 namespace JSC {
 
 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());
 static const char* sourceURLPropertyName = "sourceURL";
 
 JSObject* createError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
-    return ErrorInstance::create(&globalObject->globalData(), globalObject->errorStructure(), message);
+    return ErrorInstance::create(globalObject->globalData(), globalObject->errorStructure(), message);
 }
 
 JSObject* createEvalError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
 }
 
 JSObject* createEvalError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
-    return ErrorInstance::create(&globalObject->globalData(), globalObject->evalErrorConstructor()->errorStructure(), message);
+    return ErrorInstance::create(globalObject->globalData(), globalObject->evalErrorConstructor()->errorStructure(), message);
 }
 
 JSObject* createRangeError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
 }
 
 JSObject* createRangeError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
-    return ErrorInstance::create(&globalObject->globalData(), globalObject->rangeErrorConstructor()->errorStructure(), message);
+    return ErrorInstance::create(globalObject->globalData(), globalObject->rangeErrorConstructor()->errorStructure(), message);
 }
 
 JSObject* createReferenceError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
 }
 
 JSObject* createReferenceError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
-    return ErrorInstance::create(&globalObject->globalData(), globalObject->referenceErrorConstructor()->errorStructure(), message);
+    return ErrorInstance::create(globalObject->globalData(), globalObject->referenceErrorConstructor()->errorStructure(), message);
 }
 
 JSObject* createSyntaxError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
 }
 
 JSObject* createSyntaxError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
-    return ErrorInstance::create(&globalObject->globalData(), globalObject->syntaxErrorConstructor()->errorStructure(), message);
+    return ErrorInstance::create(globalObject->globalData(), globalObject->syntaxErrorConstructor()->errorStructure(), message);
 }
 
 JSObject* createTypeError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
 }
 
 JSObject* createTypeError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
-    return ErrorInstance::create(&globalObject->globalData(), globalObject->typeErrorConstructor()->errorStructure(), message);
+    return ErrorInstance::create(globalObject->globalData(), globalObject->typeErrorConstructor()->errorStructure(), message);
+}
+
+JSObject* createNotEnoughArgumentsError(JSGlobalObject* globalObject)
+{
+    return createTypeError(globalObject, "Not enough arguments");
 }
 
 JSObject* createURIError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
 }
 
 JSObject* createURIError(JSGlobalObject* globalObject, const UString& message)
 {
     ASSERT(!message.isEmpty());
-    return ErrorInstance::create(&globalObject->globalData(), globalObject->URIErrorConstructor()->errorStructure(), message);
+    return ErrorInstance::create(globalObject->globalData(), globalObject->URIErrorConstructor()->errorStructure(), message);
 }
 
 JSObject* createError(ExecState* exec, const UString& message)
 }
 
 JSObject* createError(ExecState* exec, const UString& message)
@@ -111,46 +120,49 @@ JSObject* createTypeError(ExecState* exec, const UString& message)
     return createTypeError(exec->lexicalGlobalObject(), message);
 }
 
     return createTypeError(exec->lexicalGlobalObject(), message);
 }
 
+JSObject* createNotEnoughArgumentsError(ExecState* exec)
+{
+    return createNotEnoughArgumentsError(exec->lexicalGlobalObject());
+}
+
 JSObject* createURIError(ExecState* exec, const UString& message)
 {
     return createURIError(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)
+JSObject* addErrorInfo(CallFrame* callFrame, JSObject* error, int line, const SourceCode& source)
 {
 {
-    intptr_t sourceID = source.provider()->asID();
+    JSGlobalData* globalData = &callFrame->globalData();
     const UString& sourceURL = source.provider()->url();
 
     if (line != -1)
     const UString& sourceURL = source.provider()->url();
 
     if (line != -1)
-        error->putWithAttributes(globalData, Identifier(globalData, linePropertyName), jsNumber(line), ReadOnly | DontDelete);
-    if (sourceID != -1)
-        error->putWithAttributes(globalData, Identifier(globalData, sourceIdPropertyName), jsNumber((double)sourceID), ReadOnly | DontDelete);
+        error->putDirect(*globalData, Identifier(globalData, linePropertyName), jsNumber(line), ReadOnly | DontDelete);
     if (!sourceURL.isNull())
     if (!sourceURL.isNull())
-        error->putWithAttributes(globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete);
+        error->putDirect(*globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete);
+
+    globalData->interpreter->addStackTraceIfNecessary(callFrame, error);
 
     return error;
 }
 
 
     return error;
 }
 
-JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source)
-{
-    return addErrorInfo(&exec->globalData(), error, line, source);
-}
 
 bool hasErrorInfo(ExecState* exec, JSObject* error)
 {
     return error->hasProperty(exec, Identifier(exec, linePropertyName))
 
 bool hasErrorInfo(ExecState* exec, JSObject* error)
 {
     return error->hasProperty(exec, Identifier(exec, linePropertyName))
-        || error->hasProperty(exec, Identifier(exec, sourceIdPropertyName))
         || error->hasProperty(exec, Identifier(exec, sourceURLPropertyName));
 }
 
 JSValue throwError(ExecState* exec, JSValue error)
 {
         || error->hasProperty(exec, Identifier(exec, sourceURLPropertyName));
 }
 
 JSValue throwError(ExecState* exec, JSValue error)
 {
+    if (error.isObject())
+        return throwError(exec, asObject(error));
     exec->globalData().exception = error;
     return error;
 }
 
 JSObject* throwError(ExecState* exec, JSObject* error)
 {
     exec->globalData().exception = error;
     return error;
 }
 
 JSObject* throwError(ExecState* exec, JSObject* error)
 {
+    Interpreter::addStackTraceIfNecessary(exec, error);
     exec->globalData().exception = error;
     return error;
 }
     exec->globalData().exception = error;
     return error;
 }
@@ -165,47 +177,13 @@ JSObject* throwSyntaxError(ExecState* exec)
     return throwError(exec, createSyntaxError(exec, "Syntax 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);
 
 ASSERT_CLASS_FITS_IN_CELL(StrictModeTypeErrorFunction);
 
-JSValue createTypeErrorFunction(ExecState* exec, const UString& message)
+const ClassInfo StrictModeTypeErrorFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(StrictModeTypeErrorFunction) };
+
+void StrictModeTypeErrorFunction::destroy(JSCell* cell)
 {
 {
-    return new (exec) StrictModeTypeErrorFunction(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->internalFunctionStructure(), message);
+    jsCast<StrictModeTypeErrorFunction*>(cell)->StrictModeTypeErrorFunction::~StrictModeTypeErrorFunction();
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index c0f9d32098b1666adf39bdb40d3f84bf100f7d8c..79617655e6cac15aa7c327c94f2514a405987a62 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef Error_h
 #define Error_h
 
 #ifndef Error_h
 #define Error_h
 
+#include "InternalFunction.h"
+#include "Interpreter.h"
 #include "JSObject.h"
 #include <stdint.h>
 
 #include "JSObject.h"
 #include <stdint.h>
 
@@ -43,36 +45,90 @@ namespace JSC {
     JSObject* createReferenceError(JSGlobalObject*, const UString&);
     JSObject* createSyntaxError(JSGlobalObject*, const UString&);
     JSObject* createTypeError(JSGlobalObject*, const UString&);
     JSObject* createReferenceError(JSGlobalObject*, const UString&);
     JSObject* createSyntaxError(JSGlobalObject*, const UString&);
     JSObject* createTypeError(JSGlobalObject*, const UString&);
+    JSObject* createNotEnoughArgumentsError(JSGlobalObject*);
     JSObject* createURIError(JSGlobalObject*, const UString&);
     // ExecState wrappers.
     JSObject* createURIError(JSGlobalObject*, const UString&);
     // ExecState wrappers.
-    JSObject* createError(ExecState*, const UString&);
+    JS_EXPORT_PRIVATE JSObject* createError(ExecState*, const UString&);
     JSObject* createEvalError(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&);
+    JS_EXPORT_PRIVATE JSObject* createRangeError(ExecState*, const UString&);
+    JS_EXPORT_PRIVATE JSObject* createReferenceError(ExecState*, const UString&);
+    JS_EXPORT_PRIVATE JSObject* createSyntaxError(ExecState*, const UString&);
+    JS_EXPORT_PRIVATE JSObject* createTypeError(ExecState*, const UString&);
+    JS_EXPORT_PRIVATE JSObject* createNotEnoughArgumentsError(ExecState*);
     JSObject* createURIError(ExecState*, const UString&);
 
     // Methods to add 
     bool hasErrorInfo(ExecState*, JSObject* error);
     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&);
 
     // Methods to throw Errors.
     // ExecState wrappers.
     JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&);
 
     // Methods to throw Errors.
-    JSValue throwError(ExecState*, JSValue);
-    JSObject* throwError(ExecState*, JSObject*);
+    JS_EXPORT_PRIVATE JSValue throwError(ExecState*, JSValue);
+    JS_EXPORT_PRIVATE JSObject* throwError(ExecState*, JSObject*);
 
     // Convenience wrappers, create an throw an exception with a default message.
 
     // Convenience wrappers, create an throw an exception with a default message.
-    JSObject* throwTypeError(ExecState*);
-    JSObject* throwSyntaxError(ExecState*);
+    JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*);
+    JS_EXPORT_PRIVATE 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)); }
 
 
     // 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);
+    class StrictModeTypeErrorFunction : public InternalFunction {
+    private:
+        StrictModeTypeErrorFunction(JSGlobalObject* globalObject, Structure* structure, const UString& message)
+            : InternalFunction(globalObject, structure)
+            , m_message(message)
+        {
+        }
+
+        static void destroy(JSCell*);
+
+    public:
+        typedef InternalFunction Base;
+
+        static StrictModeTypeErrorFunction* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const UString& message)
+        {
+            StrictModeTypeErrorFunction* function = new (NotNull, allocateCell<StrictModeTypeErrorFunction>(*exec->heap())) StrictModeTypeErrorFunction(globalObject, structure, message);
+            function->finishCreation(exec->globalData(), exec->globalData().propertyNames->emptyIdentifier);
+            return function;
+        }
+    
+        static EncodedJSValue JSC_HOST_CALL constructThrowTypeError(ExecState* exec)
+        {
+            throwTypeError(exec, static_cast<StrictModeTypeErrorFunction*>(exec->callee())->m_message);
+            return JSValue::encode(jsNull());
+        }
+    
+        static ConstructType getConstructData(JSCell*, 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());
+        }
+
+        static CallType getCallData(JSCell*, CallData& callData)
+        {
+            callData.native.function = callThrowTypeError;
+            return CallTypeHost;
+        }
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 
+        { 
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); 
+        }
+
+    private:
+        UString m_message;
+    };
+
 } // namespace JSC
 
 #endif // Error_h
 } // namespace JSC
 
 #endif // Error_h
index df112dd2221f9c98f7bde90bc0bc8e913024be11..c8f93ba323cc5dc7a7e38f7527b0f23dcc88f30a 100644 (file)
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ErrorConstructor);
 
 
-ErrorConstructor::ErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ErrorPrototype* errorPrototype)
-    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, errorPrototype->classInfo()->className))
+const ClassInfo ErrorConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(ErrorConstructor) };
+
+ErrorConstructor::ErrorConstructor(JSGlobalObject* globalObject, Structure* structure)
+    : InternalFunction(globalObject, structure)
+{
+}
+
+void ErrorConstructor::finishCreation(ExecState* exec, ErrorPrototype* errorPrototype)
 {
 {
+    Base::finishCreation(exec->globalData(), Identifier(exec, errorPrototype->classInfo()->className));
     // ECMA 15.11.3.1 Error.prototype
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
     // ECMA 15.11.3.1 Error.prototype
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
@@ -46,7 +54,7 @@ static EncodedJSValue JSC_HOST_CALL constructWithErrorConstructor(ExecState* exe
     return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
     return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
-ConstructType ErrorConstructor::getConstructData(ConstructData& constructData)
+ConstructType ErrorConstructor::getConstructData(JSCell*, ConstructData& constructData)
 {
     constructData.native.function = constructWithErrorConstructor;
     return ConstructTypeHost;
 {
     constructData.native.function = constructWithErrorConstructor;
     return ConstructTypeHost;
@@ -59,7 +67,7 @@ static EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState* exec)
     return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
     return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
-CallType ErrorConstructor::getCallData(CallData& callData)
+CallType ErrorConstructor::getCallData(JSCell*, CallData& callData)
 {
     callData.native.function = callErrorConstructor;
     return CallTypeHost;
 {
     callData.native.function = callErrorConstructor;
     return CallTypeHost;
index ceec005be802fd3529141146072bf21c537eaf82..58399a9bca93051651ae4fc311460e97e433a502 100644 (file)
@@ -30,11 +30,29 @@ namespace JSC {
 
     class ErrorConstructor : public InternalFunction {
     public:
 
     class ErrorConstructor : public InternalFunction {
     public:
-        ErrorConstructor(ExecState*, JSGlobalObject*, Structure*, ErrorPrototype*);
+        typedef InternalFunction Base;
 
 
+        static ErrorConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ErrorPrototype* errorPrototype)
+        {
+            ErrorConstructor* constructor = new (NotNull, allocateCell<ErrorConstructor>(*exec->heap())) ErrorConstructor(globalObject, structure);
+            constructor->finishCreation(exec, errorPrototype);
+            return constructor;
+        }
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 
+        { 
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); 
+        }
+
+    protected:
+        void finishCreation(ExecState*, ErrorPrototype*);
+        
     private:
     private:
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
+        ErrorConstructor(JSGlobalObject*, Structure*);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index ed95ba4a1778def2a4aae986e40e2b0f82154791..91a6fc40eab8117d6c51c90fb2d083aeb38ccb8c 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo ErrorInstance::s_info = { "Error", &JSNonFinalObject::s_info, 0, 0 };
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ErrorInstance);
 
 
-ErrorInstance::ErrorInstance(JSGlobalData* globalData, Structure* structure)
-    : JSNonFinalObject(*globalData, structure)
-    , m_appendSourceToMessage(false)
-{
-    ASSERT(inherits(&s_info));
-    putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, ""));
-}
+const ClassInfo ErrorInstance::s_info = { "Error", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(ErrorInstance) };
 
 
-ErrorInstance::ErrorInstance(JSGlobalData* globalData, Structure* structure, const UString& message)
-    : JSNonFinalObject(*globalData, structure)
+ErrorInstance::ErrorInstance(JSGlobalData& globalData, Structure* structure)
+    : JSNonFinalObject(globalData, structure)
     , m_appendSourceToMessage(false)
 {
     , 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 afcf158ad3ae7e70ce384dca44c54e574ef9e85d..d6fa32f99cf3b3dc4b0f1249397f5d607556527d 100644 (file)
@@ -27,26 +27,41 @@ namespace JSC {
 
     class ErrorInstance : public JSNonFinalObject {
     public:
 
     class ErrorInstance : public JSNonFinalObject {
     public:
+        typedef JSNonFinalObject Base;
+
         static const ClassInfo s_info;
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ErrorInstanceType, StructureFlags), &s_info);
         }
 
         }
 
-        static ErrorInstance* create(JSGlobalData*, Structure*, const UString&);
-        static ErrorInstance* create(ExecState*, Structure*, JSValue message);
+        static ErrorInstance* create(JSGlobalData& globalData, Structure* structure, const UString& message)
+        {
+            ErrorInstance* instance = new (NotNull, allocateCell<ErrorInstance>(globalData.heap)) ErrorInstance(globalData, structure);
+            instance->finishCreation(globalData, message);
+            return instance;
+        }
 
 
+        static ErrorInstance* create(ExecState* exec, Structure* structure, JSValue message)
+        {
+            return create(exec->globalData(), structure, message.isUndefined() ? UString() : message.toString(exec)->value(exec));
+        }
 
         bool appendSourceToMessage() { return m_appendSourceToMessage; }
         void setAppendSourceToMessage() { m_appendSourceToMessage = true; }
         void clearAppendSourceToMessage() { m_appendSourceToMessage = false; }
 
 
         bool appendSourceToMessage() { return m_appendSourceToMessage; }
         void setAppendSourceToMessage() { m_appendSourceToMessage = true; }
         void clearAppendSourceToMessage() { m_appendSourceToMessage = false; }
 
-        virtual bool isErrorInstance() const { return true; }
-
     protected:
     protected:
-        explicit ErrorInstance(JSGlobalData*, Structure*);
-        explicit ErrorInstance(JSGlobalData*, Structure*, const UString&);
+        explicit ErrorInstance(JSGlobalData&, Structure*);
+
+        void finishCreation(JSGlobalData& globalData, const UString& message)
+        {
+            Base::finishCreation(globalData);
+            ASSERT(inherits(&s_info));
+            if (!message.isNull())
+                putDirect(globalData, globalData.propertyNames->message, jsString(&globalData, message), DontEnum);
+        }
 
         bool m_appendSourceToMessage;
     };
 
         bool m_appendSourceToMessage;
     };
index 2a513d59c7ae9ff12695098d08f77fc4916656e1..7af29478294732aa65df84bbabae9567046a2957 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "ErrorPrototype.h"
 
 #include "config.h"
 #include "ErrorPrototype.h"
 
+#include "Error.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSStringBuilder.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSStringBuilder.h"
@@ -40,7 +41,7 @@ static EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*);
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo ErrorPrototype::s_info = { "Error", &ErrorInstance::s_info, 0, ExecState::errorPrototypeTable };
+const ClassInfo ErrorPrototype::s_info = { "Error", &ErrorInstance::s_info, 0, ExecState::errorPrototypeTable, CREATE_METHOD_TABLE(ErrorPrototype) };
 
 /* Source for ErrorPrototype.lut.h
 @begin errorPrototypeTable
 
 /* Source for ErrorPrototype.lut.h
 @begin errorPrototypeTable
@@ -50,48 +51,88 @@ const ClassInfo ErrorPrototype::s_info = { "Error", &ErrorInstance::s_info, 0, E
 
 ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype);
 
 
 ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype);
 
-ErrorPrototype::ErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
-    : ErrorInstance(&exec->globalData(), structure)
+ErrorPrototype::ErrorPrototype(ExecState* exec, Structure* structure)
+    : ErrorInstance(exec->globalData(), structure)
 {
 {
-    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().name, jsNontrivialString(exec, "Error"), DontEnum);
+}
 
 
+void ErrorPrototype::finishCreation(ExecState* exec, JSGlobalObject*)
+{
+    Base::finishCreation(exec->globalData(), "");
     ASSERT(inherits(&s_info));
     ASSERT(inherits(&s_info));
-    putAnonymousValue(globalObject->globalData(), 0, globalObject);
+    putDirect(exec->globalData(), exec->propertyNames().name, jsNontrivialString(exec, "Error"), DontEnum);
 }
 
 }
 
-bool ErrorPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+bool ErrorPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 {
-    return getStaticFunctionSlot<ErrorInstance>(exec, ExecState::errorPrototypeTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<ErrorInstance>(exec, ExecState::errorPrototypeTable(exec), jsCast<ErrorPrototype*>(cell), propertyName, slot);
 }
 
 }
 
-bool ErrorPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool ErrorPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<ErrorInstance>(exec, ExecState::errorPrototypeTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<ErrorInstance>(exec, ExecState::errorPrototypeTable(exec), jsCast<ErrorPrototype*>(object), propertyName, descriptor);
 }
 
 // ------------------------------ Functions ---------------------------
 
 }
 
 // ------------------------------ Functions ---------------------------
 
+// ECMA-262 5.1, 15.11.4.4
 EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
 {
 EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    // 1. Let O be the this value.
+    JSValue thisValue = exec->hostThisValue();
 
 
+    // 2. If Type(O) is not Object, throw a TypeError exception.
+    if (!thisValue.isObject())
+        return throwVMTypeError(exec);
+    JSObject* thisObj = asObject(thisValue);
+
+    // Guard against recursion!
     StringRecursionChecker checker(exec, thisObj);
     StringRecursionChecker checker(exec, thisObj);
-    if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
-        return earlyReturnValue;
+    if (JSValue earlyReturnValue = checker.earlyReturnValue())
+        return JSValue::encode(earlyReturnValue);
 
 
+    // 3. Let name be the result of calling the [[Get]] internal method of O with argument "name".
     JSValue name = thisObj->get(exec, exec->propertyNames().name);
     JSValue name = thisObj->get(exec, exec->propertyNames().name);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    // 4. If name is undefined, then let name be "Error"; else let name be ToString(name).
+    UString nameString;
+    if (name.isUndefined())
+        nameString = "Error";
+    else {
+        nameString = name.toString(exec)->value(exec);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+    }
+
+    // 5. Let msg be the result of calling the [[Get]] internal method of O with argument "message".
     JSValue message = thisObj->get(exec, exec->propertyNames().message);
     JSValue message = thisObj->get(exec, exec->propertyNames().message);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    // (sic)
+    // 6. If msg is undefined, then let msg be the empty String; else let msg be ToString(msg).
+    // 7. If msg is undefined, then let msg be the empty String; else let msg be ToString(msg).
+    UString messageString;
+    if (message.isUndefined())
+        messageString = "";
+    else {
+        messageString = message.toString(exec)->value(exec);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+    }
 
 
-    // Mozilla-compatible format.
+    // 8. If name is the empty String, return msg.
+    if (!nameString.length())
+        return JSValue::encode(message.isString() ? message : jsString(exec, messageString));
 
 
-    if (!name.isUndefined()) {
-        if (!message.isUndefined())
-            return JSValue::encode(jsMakeNontrivialString(exec, name.toString(exec), ": ", message.toString(exec)));
-        return JSValue::encode(jsNontrivialString(exec, name.toString(exec)));
-    }
-    if (!message.isUndefined())
-        return JSValue::encode(jsMakeNontrivialString(exec, "Error: ", message.toString(exec)));
-    return JSValue::encode(jsNontrivialString(exec, "Error"));
+    // 9. If msg is the empty String, return name.
+    if (!messageString.length())
+        return JSValue::encode(name.isString() ? name : jsNontrivialString(exec, nameString));
+
+    // 10. Return the result of concatenating name, ":", a single space character, and msg.
+    return JSValue::encode(jsMakeNontrivialString(exec, nameString, ": ", messageString));
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index a5c88634fb7cfa1dcc18538641779654aefd577b..6f02583a6822f0a9cfd56ff16c56b6c3edda9d7c 100644 (file)
@@ -29,22 +29,31 @@ namespace JSC {
 
     class ErrorPrototype : public ErrorInstance {
     public:
 
     class ErrorPrototype : public ErrorInstance {
     public:
-        ErrorPrototype(ExecState*, JSGlobalObject*, Structure*);
+        typedef ErrorInstance Base;
 
 
+        static ErrorPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+        {
+            ErrorPrototype* prototype = new (NotNull, allocateCell<ErrorPrototype>(*exec->heap())) ErrorPrototype(exec, structure);
+            prototype->finishCreation(exec, globalObject);
+            return prototype;
+        }
+        
         static const ClassInfo s_info;
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ErrorInstanceType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
+        ErrorPrototype(ExecState*, Structure*);
+        void finishCreation(ExecState*, JSGlobalObject*);
+
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ErrorInstance::StructureFlags;
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ErrorInstance::StructureFlags;
-        static const unsigned AnonymousSlotCount = ErrorInstance::AnonymousSlotCount + 1;
 
     private:
 
     private:
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 1d743153ca176ae51513aacdffdb2d62887bc736..ce63ae9af4ef4647c5c176637cc43cfdd87f8b94 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-class InterruptedExecutionError : public JSNonFinalObject {
-public:
-    InterruptedExecutionError(JSGlobalData* globalData)
-        : JSNonFinalObject(*globalData, globalData->interruptedExecutionErrorStructure.get())
-    {
-    }
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(InterruptedExecutionError);
 
 
-    virtual ComplType exceptionType() const { return Interrupted; }
+const ClassInfo InterruptedExecutionError::s_info = { "InterruptedExecutionError", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(InterruptedExecutionError) };
 
 
-    virtual UString toString(ExecState*) const { return "JavaScript execution exceeded timeout."; }
-};
+JSValue InterruptedExecutionError::defaultValue(const JSObject*, ExecState* exec, PreferredPrimitiveType hint)
+{
+    if (hint == PreferString)
+        return jsNontrivialString(exec, "JavaScript execution exceeded timeout.");
+    return JSValue(std::numeric_limits<double>::quiet_NaN());
+}
 
 JSObject* createInterruptedExecutionException(JSGlobalData* globalData)
 {
 
 JSObject* createInterruptedExecutionException(JSGlobalData* globalData)
 {
-    return new (globalData) InterruptedExecutionError(globalData);
+    return InterruptedExecutionError::create(*globalData);
+}
+
+bool isInterruptedExecutionException(JSObject* object)
+{
+    return object->inherits(&InterruptedExecutionError::s_info);
 }
 
 }
 
-class TerminatedExecutionError : public JSNonFinalObject {
-public:
-    TerminatedExecutionError(JSGlobalData* globalData)
-        : JSNonFinalObject(*globalData, globalData->terminatedExecutionErrorStructure.get())
-    {
-    }
+bool isInterruptedExecutionException(JSValue value)
+{
+    return value.inherits(&InterruptedExecutionError::s_info);
+}
+
+
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(TerminatedExecutionError);
 
 
-    virtual ComplType exceptionType() const { return Terminated; }
+const ClassInfo TerminatedExecutionError::s_info = { "TerminatedExecutionError", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(TerminatedExecutionError) };
 
 
-    virtual UString toString(ExecState*) const { return "JavaScript execution terminated."; }
-};
+JSValue TerminatedExecutionError::defaultValue(const JSObject*, ExecState* exec, PreferredPrimitiveType hint)
+{
+    if (hint == PreferString)
+        return jsNontrivialString(exec, "JavaScript execution terminated.");
+    return JSValue(std::numeric_limits<double>::quiet_NaN());
+}
 
 JSObject* createTerminatedExecutionException(JSGlobalData* globalData)
 {
 
 JSObject* createTerminatedExecutionException(JSGlobalData* globalData)
 {
-    return new (globalData) TerminatedExecutionError(globalData);
+    return TerminatedExecutionError::create(*globalData);
+}
+
+bool isTerminatedExecutionException(JSObject* object)
+{
+    return object->inherits(&TerminatedExecutionError::s_info);
 }
 
 }
 
+bool isTerminatedExecutionException(JSValue value)
+{
+    return value.inherits(&TerminatedExecutionError::s_info);
+}
+
+
 JSObject* createStackOverflowError(ExecState* exec)
 {
     return createRangeError(exec, "Maximum call stack size exceeded.");
 JSObject* createStackOverflowError(ExecState* exec)
 {
     return createRangeError(exec, "Maximum call stack size exceeded.");
@@ -93,7 +113,7 @@ JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident)
     
 JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value)
 {
     
 JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value)
 {
-    UString errorMessage = makeUString("'", value.toString(exec), "' is not a valid argument for '", op, "'");
+    UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a valid argument for '", op, "'");
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
@@ -102,7 +122,7 @@ JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value
 
 JSObject* createNotAConstructorError(ExecState* exec, JSValue value)
 {
 
 JSObject* createNotAConstructorError(ExecState* exec, JSValue value)
 {
-    UString errorMessage = makeUString("'", value.toString(exec), "' is not a constructor");
+    UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a constructor");
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
@@ -111,7 +131,7 @@ JSObject* createNotAConstructorError(ExecState* exec, JSValue value)
 
 JSObject* createNotAFunctionError(ExecState* exec, JSValue value)
 {
 
 JSObject* createNotAFunctionError(ExecState* exec, JSValue value)
 {
-    UString errorMessage = makeUString("'", value.toString(exec), "' is not a function");
+    UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a function");
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
@@ -120,7 +140,7 @@ JSObject* createNotAFunctionError(ExecState* exec, JSValue value)
 
 JSObject* createNotAnObjectError(ExecState* exec, JSValue value)
 {
 
 JSObject* createNotAnObjectError(ExecState* exec, JSValue value)
 {
-    UString errorMessage = makeUString("'", value.toString(exec), "' is not an object");
+    UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not an object");
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
     JSObject* exception = createTypeError(exec, errorMessage);
     ASSERT(exception->isErrorInstance());
     static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
index 5f1ec6f1c24443558239ff69e804a5f7249c1480..7bffd294b356874fac14bd944cc4c92bb2c7b728 100644 (file)
 #ifndef ExceptionHelpers_h
 #define ExceptionHelpers_h
 
 #ifndef ExceptionHelpers_h
 #define ExceptionHelpers_h
 
-#include "JSValue.h"
+#include "JSObject.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class CodeBlock;
-    class ExecState;
-    class Identifier;
-    class JSGlobalData;
-    class JSGlobalObject;
-    class JSNotAnObjectErrorStub;
-    class JSObject;
-    class Node;
-    struct Instruction;
-    
-    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*);
+JS_EXPORT_PRIVATE JSObject* createInterruptedExecutionException(JSGlobalData*);
+bool isInterruptedExecutionException(JSObject*);
+bool isInterruptedExecutionException(JSValue);
+
+JSObject* createTerminatedExecutionException(JSGlobalData*);
+bool isTerminatedExecutionException(JSObject*);
+JS_EXPORT_PRIVATE bool isTerminatedExecutionException(JSValue);
+
+JS_EXPORT_PRIVATE 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*);
+
+
+class InterruptedExecutionError : public JSNonFinalObject {
+private:
+    InterruptedExecutionError(JSGlobalData& globalData)
+        : JSNonFinalObject(globalData, globalData.interruptedExecutionErrorStructure.get())
+    {
+    }
+
+    static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
+
+public:
+    typedef JSNonFinalObject Base;
+
+    static InterruptedExecutionError* create(JSGlobalData& globalData)
+    {
+        InterruptedExecutionError* error = new (NotNull, allocateCell<InterruptedExecutionError>(globalData.heap)) InterruptedExecutionError(globalData);
+        error->finishCreation(globalData);
+        return error;
+    }
+
+    static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
+    }
+
+    static const ClassInfo s_info;
+};
+
+class TerminatedExecutionError : public JSNonFinalObject {
+private:
+    TerminatedExecutionError(JSGlobalData& globalData)
+        : JSNonFinalObject(globalData, globalData.terminatedExecutionErrorStructure.get())
+    {
+    }
+
+    static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
+
+public:
+    typedef JSNonFinalObject Base;
+
+    static TerminatedExecutionError* create(JSGlobalData& globalData)
+    {
+        TerminatedExecutionError* error = new (NotNull, allocateCell<TerminatedExecutionError>(globalData.heap)) TerminatedExecutionError(globalData);
+        error->finishCreation(globalData);
+        return error;
+    }
+
+    static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
+    }
+
+    static JS_EXPORTDATA const ClassInfo s_info;
+};
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index 5fa560eee8ec45fcce07ba19db9cc9e0689b0909..3690c2c33cb3d773963fd5b9b2fae1b6d1f7b037 100644 (file)
 
 #include "BytecodeGenerator.h"
 #include "CodeBlock.h"
 
 #include "BytecodeGenerator.h"
 #include "CodeBlock.h"
+#include "DFGDriver.h"
+#include "ExecutionHarness.h"
 #include "JIT.h"
 #include "JIT.h"
+#include "JITDriver.h"
 #include "Parser.h"
 #include "UStringBuilder.h"
 #include "Parser.h"
 #include "UStringBuilder.h"
-#include "Vector.h"
+#include <wtf/Vector.h>
 
 
-#if ENABLE(DFG_JIT)
-#include "DFGByteCodeParser.h"
-#include "DFGJITCompiler.h"
+namespace JSC {
+
+const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
+
+#if ENABLE(JIT)
+void ExecutableBase::destroy(JSCell* cell)
+{
+    jsCast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
+}
 #endif
 
 #endif
 
-namespace JSC {
+inline void ExecutableBase::clearCode()
+{
+#if ENABLE(JIT)
+    m_jitCodeForCall.clear();
+    m_jitCodeForConstruct.clear();
+    m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
+    m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
+#endif
+    m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
+    m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
+}
 
 
-const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0 };
+#if ENABLE(DFG_JIT)
+Intrinsic ExecutableBase::intrinsic() const
+{
+    if (const NativeExecutable* nativeExecutable = jsDynamicCast<const NativeExecutable*>(this))
+        return nativeExecutable->intrinsic();
+    return NoIntrinsic;
+}
+#endif
+
+const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(NativeExecutable) };
 
 #if ENABLE(JIT)
 
 #if ENABLE(JIT)
-class ExecutableFinalizer : public WeakHandleOwner {
-    virtual void finalize(Handle<Unknown> handle, void*)
-    {
-        Weak<ExecutableBase> executable(Weak<ExecutableBase>::Adopt, handle);
-        executable->clearExecutableCode();
-    }
-};
+void NativeExecutable::destroy(JSCell* cell)
+{
+    jsCast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
+}
+#endif
+
+#if ENABLE(DFG_JIT)
+Intrinsic NativeExecutable::intrinsic() const
+{
+    return m_intrinsic;
+}
+#endif
 
 
-WeakHandleOwner* ExecutableBase::executableFinalizer()
+#if ENABLE(JIT)
+// Utility method used for jettisoning code blocks.
+template<typename T>
+static void jettisonCodeBlock(JSGlobalData& globalData, OwnPtr<T>& codeBlock)
 {
 {
-    DEFINE_STATIC_LOCAL(ExecutableFinalizer, finalizer, ());
-    return &finalizer;
+    ASSERT(JITCode::isOptimizingJIT(codeBlock->getJITType()));
+    ASSERT(codeBlock->alternative());
+    OwnPtr<T> codeBlockToJettison = codeBlock.release();
+    codeBlock = static_pointer_cast<T>(codeBlockToJettison->releaseAlternative());
+    codeBlockToJettison->unlinkIncomingCalls();
+    globalData.heap.jettisonDFGCodeBlock(static_pointer_cast<CodeBlock>(codeBlockToJettison.release()));
 }
 #endif
 }
 #endif
-    
-const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0 };
 
 
-NativeExecutable::~NativeExecutable()
+void NativeExecutable::finalize(JSCell* cell)
 {
 {
+    jsCast<NativeExecutable*>(cell)->clearCode();
 }
 
 }
 
-const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0 };
+const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
 
 
-const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0 };
+#if ENABLE(JIT)
+void ScriptExecutable::destroy(JSCell* cell)
+{
+    jsCast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
+}
+#endif
+
+const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
 
 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
     : ScriptExecutable(exec->globalData().evalExecutableStructure.get(), exec, source, inStrictContext)
 {
 }
 
 
 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
     : ScriptExecutable(exec->globalData().evalExecutableStructure.get(), exec, source, inStrictContext)
 {
 }
 
-EvalExecutable::~EvalExecutable()
+void EvalExecutable::destroy(JSCell* cell)
 {
 {
+    jsCast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
 }
 
 }
 
-const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0 };
+const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
 
 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
     : ScriptExecutable(exec->globalData().programExecutableStructure.get(), exec, source, false)
 {
 }
 
 
 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
     : ScriptExecutable(exec->globalData().programExecutableStructure.get(), exec, source, false)
 {
 }
 
-ProgramExecutable::~ProgramExecutable()
+void ProgramExecutable::destroy(JSCell* cell)
 {
 {
+    jsCast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
 }
 
 }
 
-const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0 };
+const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
 
 
-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)
+FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
+    : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, source, inStrictContext)
     , m_numCapturedVariables(0)
     , m_forceUsesArguments(forceUsesArguments)
     , m_parameters(parameters)
     , m_name(name)
     , m_numCapturedVariables(0)
     , m_forceUsesArguments(forceUsesArguments)
     , m_parameters(parameters)
     , m_name(name)
+    , m_inferredName(inferredName.isNull() ? globalData.propertyNames->emptyIdentifier : inferredName)
     , m_symbolTable(0)
     , m_symbolTable(0)
+    , m_next(0)
+    , m_prev(0)
 {
 {
-    m_firstLine = firstLine;
-    m_lastLine = lastLine;
 }
 
 }
 
-FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine)
+FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
     : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext)
     , m_numCapturedVariables(0)
     , m_forceUsesArguments(forceUsesArguments)
     , m_parameters(parameters)
     , m_name(name)
     : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext)
     , m_numCapturedVariables(0)
     , m_forceUsesArguments(forceUsesArguments)
     , m_parameters(parameters)
     , m_name(name)
+    , m_inferredName(inferredName.isNull() ? exec->globalData().propertyNames->emptyIdentifier : inferredName)
     , m_symbolTable(0)
     , m_symbolTable(0)
+    , m_next(0)
+    , m_prev(0)
+{
+}
+
+void FunctionExecutable::destroy(JSCell* cell)
+{
+    jsCast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
+}
+
+JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
 {
 {
-    m_firstLine = firstLine;
-    m_lastLine = lastLine;
+    ASSERT(exec->globalData().dynamicGlobalObject);
+    ASSERT(!!m_evalCodeBlock);
+    JSObject* error = 0;
+    if (m_evalCodeBlock->getJITType() != JITCode::topTierJIT())
+        error = compileInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_evalCodeBlock->getJITType()));
+    ASSERT(!!m_evalCodeBlock);
+    return error;
 }
 
 }
 
+#if ENABLE(JIT)
+bool EvalExecutable::jitCompile(JSGlobalData& globalData)
+{
+    return jitCompileIfAppropriate(globalData, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail);
+}
+#endif
+
+inline const char* samplingDescription(JITCode::JITType jitType)
+{
+    switch (jitType) {
+    case JITCode::InterpreterThunk:
+        return "Interpreter Compilation (TOTAL)";
+    case JITCode::BaselineJIT:
+        return "Baseline Compilation (TOTAL)";
+    case JITCode::DFGJIT:
+        return "DFG Compilation (TOTAL)";
+    default:
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+}
 
 
-JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
+JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
 {
 {
+    SamplingRegion samplingRegion(samplingDescription(jitType));
+    
+#if !ENABLE(JIT)
+    UNUSED_PARAM(jitType);
+#endif
     JSObject* exception = 0;
     JSGlobalData* globalData = &exec->globalData();
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
     JSObject* exception = 0;
     JSGlobalData* globalData = &exec->globalData();
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
-    if (!lexicalGlobalObject->isEvalEnabled())
-        return throwError(exec, createEvalError(exec, "Eval is disabled"));
-    RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
-    if (!evalNode) {
-        ASSERT(exception);
-        return exception;
-    }
-    recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine());
-
-    JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
-
-    ASSERT(!m_evalCodeBlock);
-    m_evalCodeBlock = 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();
+    
+    if (!!m_evalCodeBlock) {
+        OwnPtr<EvalCodeBlock> newCodeBlock = adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock));
+        newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release()));
+        m_evalCodeBlock = newCodeBlock.release();
+    } else {
+        if (!lexicalGlobalObject->evalEnabled())
+            return throwError(exec, createEvalError(exec, "Eval is disabled"));
+        RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
+        if (!evalNode) {
+            ASSERT(exception);
+            return exception;
+        }
+        recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine());
+        
+        JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
+        
+        OwnPtr<CodeBlock> previousCodeBlock = m_evalCodeBlock.release();
+        ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
+        m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChainNode->localDepth(), previousCodeBlock.release()));
+        OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), scopeChainNode, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get(), !!m_evalCodeBlock->alternative() ? OptimizingCompilation : FirstCompilation)));
+        if ((exception = generator->generate())) {
+            m_evalCodeBlock = static_pointer_cast<EvalCodeBlock>(m_evalCodeBlock->releaseAlternative());
+            evalNode->destroyData();
+            return exception;
+        }
+        
         evalNode->destroyData();
         evalNode->destroyData();
-        return exception;
+        m_evalCodeBlock->copyPostParseDataFromAlternative();
     }
 
     }
 
-    evalNode->destroyData();
-
 #if ENABLE(JIT)
 #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
-    }
+    if (!prepareForExecution(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType))
+        return 0;
 #endif
 
 #if ENABLE(JIT)
 #endif
 
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
     if (!m_jitCodeForCall)
         Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock));
     else
     if (!m_jitCodeForCall)
         Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock));
     else
@@ -166,14 +262,24 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
     return 0;
 }
 
     return 0;
 }
 
-void EvalExecutable::visitChildren(SlotVisitor& visitor)
+#if ENABLE(JIT)
+void EvalExecutable::jettisonOptimizedCode(JSGlobalData& globalData)
+{
+    jettisonCodeBlock(globalData, m_evalCodeBlock);
+    m_jitCodeForCall = m_evalCodeBlock->getJITCode();
+    ASSERT(!m_jitCodeForCallWithArityCheck);
+}
+#endif
+
+void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
-    ScriptExecutable::visitChildren(visitor);
-    if (m_evalCodeBlock)
-        m_evalCodeBlock->visitAggregate(visitor);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    ScriptExecutable::visitChildren(thisObject, visitor);
+    if (thisObject->m_evalCodeBlock)
+        thisObject->m_evalCodeBlock->visitAggregate(visitor);
 }
 
 void EvalExecutable::unlinkCalls()
 }
 
 void EvalExecutable::unlinkCalls()
@@ -186,56 +292,96 @@ void EvalExecutable::unlinkCalls()
 #endif
 }
 
 #endif
 }
 
+void EvalExecutable::finalize(JSCell* cell)
+{
+    jsCast<EvalExecutable*>(cell)->clearCode();
+}
+
+inline void EvalExecutable::clearCode()
+{
+    if (m_evalCodeBlock) {
+        m_evalCodeBlock->clearEvalCache();
+        m_evalCodeBlock.clear();
+    }
+    Base::clearCode();
+}
+
 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
 {
     JSObject* exception = 0;
     JSGlobalData* globalData = &exec->globalData();
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
 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);
+    RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
     if (programNode)
         return 0;
     ASSERT(exception);
     return exception;
 }
 
     if (programNode)
         return 0;
     ASSERT(exception);
     return exception;
 }
 
-JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
+JSObject* ProgramExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
 {
 {
-    ASSERT(!m_programCodeBlock);
+    ASSERT(exec->globalData().dynamicGlobalObject);
+    ASSERT(!!m_programCodeBlock);
+    JSObject* error = 0;
+    if (m_programCodeBlock->getJITType() != JITCode::topTierJIT())
+        error = compileInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_programCodeBlock->getJITType()));
+    ASSERT(!!m_programCodeBlock);
+    return error;
+}
 
 
+#if ENABLE(JIT)
+bool ProgramExecutable::jitCompile(JSGlobalData& globalData)
+{
+    return jitCompileIfAppropriate(globalData, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail);
+}
+#endif
+
+JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
+{
+    SamplingRegion samplingRegion(samplingDescription(jitType));
+    
+#if !ENABLE(JIT)
+    UNUSED_PARAM(jitType);
+#endif
     JSObject* exception = 0;
     JSGlobalData* globalData = &exec->globalData();
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
     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());
-
-    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();
+    if (!!m_programCodeBlock) {
+        OwnPtr<ProgramCodeBlock> newCodeBlock = adoptPtr(new ProgramCodeBlock(CodeBlock::CopyParsedBlock, *m_programCodeBlock));
+        newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_programCodeBlock.release()));
+        m_programCodeBlock = newCodeBlock.release();
+    } else {
+        RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
+        if (!programNode) {
+            ASSERT(exception);
+            return exception;
+        }
+        recordParse(programNode->features(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine());
+
+        JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
+    
+        OwnPtr<CodeBlock> previousCodeBlock = m_programCodeBlock.release();
+        ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
+        m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider(), previousCodeBlock.release()));
+        OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), scopeChainNode, &globalObject->symbolTable(), m_programCodeBlock.get(), !!m_programCodeBlock->alternative() ? OptimizingCompilation : FirstCompilation)));
+        if ((exception = generator->generate())) {
+            m_programCodeBlock = static_pointer_cast<ProgramCodeBlock>(m_programCodeBlock->releaseAlternative());
+            programNode->destroyData();
+            return exception;
+        }
+
         programNode->destroyData();
         programNode->destroyData();
-        return exception;
+        m_programCodeBlock->copyPostParseDataFromAlternative();
     }
 
     }
 
-    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
-    }
+    if (!prepareForExecution(*globalData, m_programCodeBlock, m_jitCodeForCall, jitType))
+        return 0;
 #endif
 
 #if ENABLE(JIT)
 #endif
 
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
     if (!m_jitCodeForCall)
         Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock));
     else
     if (!m_jitCodeForCall)
         Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock));
     else
@@ -248,6 +394,15 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc
     return 0;
 }
 
     return 0;
 }
 
+#if ENABLE(JIT)
+void ProgramExecutable::jettisonOptimizedCode(JSGlobalData& globalData)
+{
+    jettisonCodeBlock(globalData, m_programCodeBlock);
+    m_jitCodeForCall = m_programCodeBlock->getJITCode();
+    ASSERT(!m_jitCodeForCallWithArityCheck);
+}
+#endif
+
 void ProgramExecutable::unlinkCalls()
 {
 #if ENABLE(JIT)
 void ProgramExecutable::unlinkCalls()
 {
 #if ENABLE(JIT)
@@ -258,91 +413,150 @@ void ProgramExecutable::unlinkCalls()
 #endif
 }
 
 #endif
 }
 
-#if ENABLE(JIT)
-static bool tryDFGCompile(JSGlobalData* globalData, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
+void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-#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
+    ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    ScriptExecutable::visitChildren(thisObject, visitor);
+    if (thisObject->m_programCodeBlock)
+        thisObject->m_programCodeBlock->visitAggregate(visitor);
+}
 
 
-    DFG::Graph dfg(codeBlock->m_numParameters, codeBlock->m_numVars);
-    if (!parse(dfg, globalData, codeBlock))
-        return false;
+void ProgramExecutable::finalize(JSCell* cell)
+{
+    jsCast<ProgramExecutable*>(cell)->clearCode();
+}
 
 
-    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
+inline void ProgramExecutable::clearCode()
+{
+    if (m_programCodeBlock) {
+        m_programCodeBlock->clearEvalCache();
+        m_programCodeBlock.clear();
+    }
+    Base::clearCode();
+}
+
+FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)
+{
+    FunctionCodeBlock* result;
+    if (kind == CodeForCall)
+        result = m_codeBlockForCall.get();
+    else {
+        ASSERT(kind == CodeForConstruct);
+        result = m_codeBlockForConstruct.get();
+    }
+    if (!result)
+        return 0;
+    while (result->alternative())
+        result = static_cast<FunctionCodeBlock*>(result->alternative());
+    ASSERT(result);
+    ASSERT(JITCode::isBaselineCode(result->getJITType()));
+    return result;
+}
+
+JSObject* FunctionExecutable::compileOptimizedForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+    ASSERT(exec->globalData().dynamicGlobalObject);
+    ASSERT(!!m_codeBlockForCall);
+    JSObject* error = 0;
+    if (m_codeBlockForCall->getJITType() != JITCode::topTierJIT())
+        error = compileForCallInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_codeBlockForCall->getJITType()));
+    ASSERT(!!m_codeBlockForCall);
+    return error;
+}
+
+JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+    ASSERT(exec->globalData().dynamicGlobalObject);
+    ASSERT(!!m_codeBlockForConstruct);
+    JSObject* error = 0;
+    if (m_codeBlockForConstruct->getJITType() != JITCode::topTierJIT())
+        error = compileForConstructInternal(exec, scopeChainNode, JITCode::nextTierJIT(m_codeBlockForConstruct->getJITType()));
+    ASSERT(!!m_codeBlockForConstruct);
+    return error;
+}
+
+#if ENABLE(JIT)
+bool FunctionExecutable::jitCompileForCall(JSGlobalData& globalData)
+{
+    return jitCompileFunctionIfAppropriate(globalData, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail);
+}
+
+bool FunctionExecutable::jitCompileForConstruct(JSGlobalData& globalData)
+{
+    return jitCompileFunctionIfAppropriate(globalData, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail);
 }
 #endif
 
 }
 #endif
 
-void ProgramExecutable::visitChildren(SlotVisitor& visitor)
+FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializationKind kind)
 {
 {
-    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);
+    return baselineCodeBlockFor(kind);
 }
 
 }
 
-JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
+PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(ScopeChainNode* scopeChainNode, CompilationKind compilationKind, CodeSpecializationKind specializationKind, JSObject*& exception)
 {
 {
-    JSObject* exception = 0;
+    if (!!codeBlockFor(specializationKind))
+        return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
+    
+    exception = 0;
     JSGlobalData* globalData = scopeChainNode->globalData;
     JSGlobalData* globalData = scopeChainNode->globalData;
-    RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
+    JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
+    RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(globalData, globalObject, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, FunctionBodyNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, 0, 0, &exception);
+
     if (!body) {
         ASSERT(exception);
     if (!body) {
         ASSERT(exception);
-        return exception;
+        return nullptr;
     }
     if (m_forceUsesArguments)
         body->setUsesArguments();
     body->finishParsing(m_parameters, m_name);
     recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
 
     }
     if (m_forceUsesArguments)
         body->setUsesArguments();
     body->finishParsing(m_parameters, m_name);
     recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
 
-    JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
+    OwnPtr<FunctionCodeBlock> result;
+    ASSERT((compilationKind == FirstCompilation) == !codeBlockFor(specializationKind));
+    result = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), specializationKind == CodeForConstruct));
+    OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChainNode, result->symbolTable(), result.get(), compilationKind)));
+    exception = generator->generate();
+    body->destroyData();
+    if (exception)
+        return nullptr;
 
 
-    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();
+    result->copyPostParseDataFrom(codeBlockFor(specializationKind).get());
+    return result.release();
+}
+
+JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
+{
+    SamplingRegion samplingRegion(samplingDescription(jitType));
+    
+#if !ENABLE(JIT)
+    UNUSED_PARAM(exec);
+    UNUSED_PARAM(jitType);
+    UNUSED_PARAM(exec);
+#endif
+    ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForCall);
+    JSObject* exception;
+    OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scopeChainNode, !!m_codeBlockForCall ? OptimizingCompilation : FirstCompilation, CodeForCall, exception);
+    if (!newCodeBlock)
         return exception;
         return exception;
-    }
 
 
-    m_numParametersForCall = m_codeBlockForCall->m_numParameters;
+    newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_codeBlockForCall.release()));
+    m_codeBlockForCall = newCodeBlock.release();
+    
+    m_numParametersForCall = m_codeBlockForCall->numParameters();
     ASSERT(m_numParametersForCall);
     m_numCapturedVariables = m_codeBlockForCall->m_numCapturedVars;
     m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
 
     ASSERT(m_numParametersForCall);
     m_numCapturedVariables = m_codeBlockForCall->m_numCapturedVars;
     m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
 
-    body->destroyData();
-
 #if ENABLE(JIT)
 #if ENABLE(JIT)
-    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
-    }
+    if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType, CodeForCall))
+        return 0;
 #endif
 
 #if ENABLE(JIT)
 #endif
 
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
     if (!m_jitCodeForCall)
         Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall));
     else
     if (!m_jitCodeForCall)
         Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall));
     else
@@ -355,50 +569,36 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain
     return 0;
 }
 
     return 0;
 }
 
-JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
+JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
 {
 {
-    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());
-
-    JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
-
-    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();
+    SamplingRegion samplingRegion(samplingDescription(jitType));
+    
+#if !ENABLE(JIT)
+    UNUSED_PARAM(jitType);
+    UNUSED_PARAM(exec);
+#endif
+    
+    ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForConstruct);
+    JSObject* exception;
+    OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scopeChainNode, !!m_codeBlockForConstruct ? OptimizingCompilation : FirstCompilation, CodeForConstruct, exception);
+    if (!newCodeBlock)
         return exception;
         return exception;
-    }
 
 
-    m_numParametersForConstruct = m_codeBlockForConstruct->m_numParameters;
+    newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_codeBlockForConstruct.release()));
+    m_codeBlockForConstruct = newCodeBlock.release();
+    
+    m_numParametersForConstruct = m_codeBlockForConstruct->numParameters();
     ASSERT(m_numParametersForConstruct);
     m_numCapturedVariables = m_codeBlockForConstruct->m_numCapturedVars;
     m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
 
     ASSERT(m_numParametersForConstruct);
     m_numCapturedVariables = m_codeBlockForConstruct->m_numCapturedVars;
     m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
 
-    body->destroyData();
-
 #if ENABLE(JIT)
 #if ENABLE(JIT)
-    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
-    }
+    if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType, CodeForConstruct))
+        return 0;
 #endif
 
 #if ENABLE(JIT)
 #endif
 
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
     if (!m_jitCodeForConstruct)
         Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct));
     else
     if (!m_jitCodeForConstruct)
         Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct));
     else
@@ -411,16 +611,35 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope
     return 0;
 }
 
     return 0;
 }
 
-void FunctionExecutable::visitChildren(SlotVisitor& visitor)
+#if ENABLE(JIT)
+void FunctionExecutable::jettisonOptimizedCodeForCall(JSGlobalData& globalData)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    jettisonCodeBlock(globalData, m_codeBlockForCall);
+    m_jitCodeForCall = m_codeBlockForCall->getJITCode();
+    m_jitCodeForCallWithArityCheck = m_codeBlockForCall->getJITCodeWithArityCheck();
+}
+
+void FunctionExecutable::jettisonOptimizedCodeForConstruct(JSGlobalData& globalData)
+{
+    jettisonCodeBlock(globalData, m_codeBlockForConstruct);
+    m_jitCodeForConstruct = m_codeBlockForConstruct->getJITCode();
+    m_jitCodeForConstructWithArityCheck = m_codeBlockForConstruct->getJITCodeWithArityCheck();
+}
+#endif
+
+void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     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);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    ScriptExecutable::visitChildren(thisObject, visitor);
+    if (thisObject->m_nameValue)
+        visitor.append(&thisObject->m_nameValue);
+    if (thisObject->m_codeBlockForCall)
+        thisObject->m_codeBlockForCall->visitAggregate(visitor);
+    if (thisObject->m_codeBlockForConstruct)
+        thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
 }
 
 void FunctionExecutable::discardCode()
 }
 
 void FunctionExecutable::discardCode()
@@ -433,20 +652,28 @@ void FunctionExecutable::discardCode()
         return;
     if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
         return;
         return;
     if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
         return;
-    m_jitCodeForCall = JITCode();
-    m_jitCodeForConstruct = JITCode();
-    m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
-    m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
 #endif
 #endif
-    if (m_codeBlockForCall)
+    clearCode();
+}
+
+void FunctionExecutable::finalize(JSCell* cell)
+{
+    FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
+    Heap::heap(executable)->removeFunctionExecutable(executable);
+    executable->clearCode();
+}
+
+inline void FunctionExecutable::clearCode()
+{
+    if (m_codeBlockForCall) {
         m_codeBlockForCall->clearEvalCache();
         m_codeBlockForCall->clearEvalCache();
-    m_codeBlockForCall.clear();
-    if (m_codeBlockForConstruct)
+        m_codeBlockForCall.clear();
+    }
+    if (m_codeBlockForConstruct) {
         m_codeBlockForConstruct->clearEvalCache();
         m_codeBlockForConstruct->clearEvalCache();
-    m_codeBlockForConstruct.clear();
-    m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
-    m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
-
+        m_codeBlockForConstruct.clear();
+    }
+    Base::clearCode();
 }
 
 void FunctionExecutable::unlinkCalls()
 }
 
 void FunctionExecutable::unlinkCalls()
@@ -466,7 +693,7 @@ void FunctionExecutable::unlinkCalls()
 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
 {
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
 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);
+    RefPtr<ProgramNode> program = parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, source, 0, JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, debugger, exec, exception);
     if (!program) {
         ASSERT(*exception);
         return 0;
     if (!program) {
         ASSERT(*exception);
         return 0;
@@ -482,7 +709,7 @@ FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functio
     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->isStrictMode(), body->lineNo(), body->lastLine());
+    return FunctionExecutable::create(exec->globalData(), functionName, functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
 }
 
 UString FunctionExecutable::paramString() const
 }
 
 UString FunctionExecutable::paramString() const
index e795fbfc3123e3f72b25f7aa320832b5d2a22520..4179a880f4d55c1d5217eb7667dda7c67265c3f4 100644 (file)
@@ -27,6 +27,7 @@
 #define Executable_h
 
 #include "CallData.h"
 #define Executable_h
 
 #include "CallData.h"
+#include "CodeSpecializationKind.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
 #include "Nodes.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
 #include "Nodes.h"
@@ -39,10 +40,19 @@ namespace JSC {
     class Debugger;
     class EvalCodeBlock;
     class FunctionCodeBlock;
     class Debugger;
     class EvalCodeBlock;
     class FunctionCodeBlock;
+    class LLIntOffsetsExtractor;
     class ProgramCodeBlock;
     class ScopeChainNode;
     class ProgramCodeBlock;
     class ScopeChainNode;
+    
+    enum CompilationKind { FirstCompilation, OptimizingCompilation };
 
 
-    struct ExceptionInfo;
+    inline bool isCall(CodeSpecializationKind kind)
+    {
+        if (kind == CodeForCall)
+            return true;
+        ASSERT(kind == CodeForConstruct);
+        return false;
+    }
 
     class ExecutableBase : public JSCell {
         friend class JIT;
 
     class ExecutableBase : public JSCell {
         friend class JIT;
@@ -50,18 +60,25 @@ namespace JSC {
     protected:
         static const int NUM_PARAMETERS_IS_HOST = 0;
         static const int NUM_PARAMETERS_NOT_COMPILED = -1;
     protected:
         static const int NUM_PARAMETERS_IS_HOST = 0;
         static const int NUM_PARAMETERS_NOT_COMPILED = -1;
-    
-    public:
+
         ExecutableBase(JSGlobalData& globalData, Structure* structure, int numParameters)
             : JSCell(globalData, structure)
             , m_numParametersForCall(numParameters)
             , m_numParametersForConstruct(numParameters)
         {
         ExecutableBase(JSGlobalData& globalData, Structure* structure, int numParameters)
             : JSCell(globalData, structure)
             , m_numParametersForCall(numParameters)
             , m_numParametersForConstruct(numParameters)
         {
+        }
+
+        void finishCreation(JSGlobalData& globalData)
+        {
+            Base::finishCreation(globalData);
+        }
+
+    public:
+        typedef JSCell Base;
+
 #if ENABLE(JIT)
 #if ENABLE(JIT)
-            Weak<ExecutableBase> finalizer(globalData, this, executableFinalizer());
-            finalizer.leakHandle();
+        static void destroy(JSCell*);
 #endif
 #endif
-        }
 
         bool isHostFunction() const
         {
 
         bool isHostFunction() const
         {
@@ -69,9 +86,9 @@ namespace JSC {
             return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
         }
 
             return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
         }
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); }
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
         
         
-        static const ClassInfo s_info;
+        static JS_EXPORTDATA const ClassInfo s_info;
 
     protected:
         static const unsigned StructureFlags = 0;
 
     protected:
         static const unsigned StructureFlags = 0;
@@ -91,11 +108,63 @@ namespace JSC {
             ASSERT(m_jitCodeForConstruct);
             return m_jitCodeForConstruct;
         }
             ASSERT(m_jitCodeForConstruct);
             return m_jitCodeForConstruct;
         }
+        
+        JITCode& generatedJITCodeFor(CodeSpecializationKind kind)
+        {
+            if (kind == CodeForCall)
+                return generatedJITCodeForCall();
+            ASSERT(kind == CodeForConstruct);
+            return generatedJITCodeForConstruct();
+        }
 
 
-        void clearExecutableCode()
+        MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
         {
         {
-            m_jitCodeForCall.clear();
-            m_jitCodeForConstruct.clear();
+            ASSERT(m_jitCodeForCall);
+            ASSERT(m_jitCodeForCallWithArityCheck);
+            return m_jitCodeForCallWithArityCheck;
+        }
+
+        MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck()
+        {
+            ASSERT(m_jitCodeForConstruct);
+            ASSERT(m_jitCodeForConstructWithArityCheck);
+            return m_jitCodeForConstructWithArityCheck;
+        }
+        
+        MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind)
+        {
+            if (kind == CodeForCall)
+                return generatedJITCodeForCallWithArityCheck();
+            ASSERT(kind == CodeForConstruct);
+            return generatedJITCodeForConstructWithArityCheck();
+        }
+        
+        bool hasJITCodeForCall() const
+        {
+            return m_numParametersForCall >= 0;
+        }
+        
+        bool hasJITCodeForConstruct() const
+        {
+            return m_numParametersForConstruct >= 0;
+        }
+        
+        bool hasJITCodeFor(CodeSpecializationKind kind) const
+        {
+            if (kind == CodeForCall)
+                return hasJITCodeForCall();
+            ASSERT(kind == CodeForConstruct);
+            return hasJITCodeForConstruct();
+        }
+
+        // Intrinsics are only for calls, currently.
+        Intrinsic intrinsic() const;
+        
+        Intrinsic intrinsicFor(CodeSpecializationKind kind) const
+        {
+            if (isCall(kind))
+                return intrinsic();
+            return NoIntrinsic;
         }
 
     protected:
         }
 
     protected:
@@ -103,78 +172,105 @@ namespace JSC {
         JITCode m_jitCodeForConstruct;
         MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
         MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
         JITCode m_jitCodeForConstruct;
         MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
         MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
-        
-    private:
-        static WeakHandleOwner* executableFinalizer();
 #endif
 #endif
+        void clearCode();
     };
 
     class NativeExecutable : public ExecutableBase {
         friend class JIT;
     };
 
     class NativeExecutable : public ExecutableBase {
         friend class JIT;
+        friend class LLIntOffsetsExtractor;
     public:
     public:
+        typedef ExecutableBase Base;
+
 #if ENABLE(JIT)
 #if ENABLE(JIT)
-        static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodePtr callThunk, NativeFunction function, MacroAssemblerCodePtr constructThunk, NativeFunction constructor)
-        {
-            if (!callThunk)
-                return new (&globalData) NativeExecutable(globalData, JITCode(), function, JITCode(), constructor);
-            return new (&globalData) NativeExecutable(globalData, JITCode::HostFunction(callThunk), function, JITCode::HostFunction(constructThunk), constructor);
+        static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic)
+        {
+            ASSERT(!globalData.interpreter->classicEnabled());
+            NativeExecutable* executable;
+            if (!callThunk) {
+                executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
+                executable->finishCreation(globalData, JITCode(), JITCode(), intrinsic);
+            } else {
+                executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
+                executable->finishCreation(globalData, JITCode::HostFunction(callThunk), JITCode::HostFunction(constructThunk), intrinsic);
+            }
+            globalData.heap.addFinalizer(executable, &finalize);
+            return executable;
         }
         }
-#else
+#endif
+
+#if ENABLE(CLASSIC_INTERPRETER)
         static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
         {
         static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
         {
-            return new (&globalData) NativeExecutable(globalData, function, constructor);
+            ASSERT(!globalData.canUseJIT());
+            NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
+            executable->finishCreation(globalData);
+            globalData.heap.addFinalizer(executable, &finalize);
+            return executable;
         }
 #endif
 
         }
 #endif
 
-        ~NativeExecutable();
+#if ENABLE(JIT)
+        static void destroy(JSCell*);
+#endif
 
         NativeFunction function() { return m_function; }
 
         NativeFunction function() { return m_function; }
+        NativeFunction constructor() { return m_constructor; }
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(LeafType, StructureFlags), AnonymousSlotCount, &s_info); }
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); }
         
         static const ClassInfo s_info;
         
         static const ClassInfo s_info;
-    
-    private:
+
+        Intrinsic intrinsic() const;
+
+    protected:
 #if ENABLE(JIT)
 #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)
+        void finishCreation(JSGlobalData& globalData, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic)
         {
         {
+            ASSERT(!globalData.interpreter->classicEnabled());
+            Base::finishCreation(globalData);
             m_jitCodeForCall = callThunk;
             m_jitCodeForConstruct = constructThunk;
             m_jitCodeForCallWithArityCheck = callThunk.addressForCall();
             m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall();
             m_jitCodeForCall = callThunk;
             m_jitCodeForConstruct = constructThunk;
             m_jitCodeForCallWithArityCheck = callThunk.addressForCall();
             m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall();
+            m_intrinsic = intrinsic;
+        }
+#endif
+
+#if ENABLE(CLASSIC_INTERPRETER)
+        void finishCreation(JSGlobalData& globalData)
+        {
+            ASSERT(!globalData.canUseJIT());
+            Base::finishCreation(globalData);
+            m_intrinsic = NoIntrinsic;
         }
         }
-#else
+#endif
+
+        static void finalize(JSCell*);
+    private:
         NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
             : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
             , m_function(function)
             , m_constructor(constructor)
         {
         }
         NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
             : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
             , m_function(function)
             , m_constructor(constructor)
         {
         }
-#endif
 
         NativeFunction m_function;
 
         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;
         NativeFunction m_constructor;
+        
+        Intrinsic m_intrinsic;
     };
 
     class ScriptExecutable : public ExecutableBase {
     public:
     };
 
     class ScriptExecutable : public ExecutableBase {
     public:
-        ScriptExecutable(Structure* structure, JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext)
-            : ExecutableBase(*globalData, structure, NUM_PARAMETERS_NOT_COMPILED)
+        typedef ExecutableBase Base;
+
+        ScriptExecutable(Structure* structure, JSGlobalData& globalData, const SourceCode& source, bool isInStrictContext)
+            : ExecutableBase(globalData, structure, NUM_PARAMETERS_NOT_COMPILED)
             , m_source(source)
             , m_features(isInStrictContext ? StrictModeFeature : 0)
         {
             , m_source(source)
             , m_features(isInStrictContext ? StrictModeFeature : 0)
         {
-#if ENABLE(CODEBLOCK_SAMPLING)
-            relaxAdoptionRequirement();
-            if (SamplingTool* sampler = globalData->interpreter->sampler())
-                sampler->notifyOfScope(this);
-#else
-            UNUSED_PARAM(globalData);
-#endif
         }
 
         ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
         }
 
         ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
@@ -182,17 +278,14 @@ namespace JSC {
             , m_source(source)
             , m_features(isInStrictContext ? StrictModeFeature : 0)
         {
             , m_source(source)
             , m_features(isInStrictContext ? StrictModeFeature : 0)
         {
-#if ENABLE(CODEBLOCK_SAMPLING)
-            relaxAdoptionRequirement();
-            if (SamplingTool* sampler = exec->globalData().interpreter->sampler())
-                sampler->notifyOfScope(this);
-#else
-            UNUSED_PARAM(exec);
-#endif
         }
 
         }
 
+#if ENABLE(JIT)
+        static void destroy(JSCell*);
+#endif
+
         const SourceCode& source() { return m_source; }
         const SourceCode& source() { return m_source; }
-        intptr_t sourceID() const { return m_source.provider()->asID(); }
+        intptr_t sourceID() const { return m_source.providerID(); }
         const UString& sourceURL() const { return m_source.provider()->url(); }
         int lineNo() const { return m_firstLine; }
         int lastLine() const { return m_lastLine; }
         const UString& sourceURL() const { return m_source.provider()->url(); }
         int lineNo() const { return m_firstLine; }
         int lastLine() const { return m_lastLine; }
@@ -202,10 +295,20 @@ namespace JSC {
         bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
         bool isStrictMode() const { return m_features & StrictModeFeature; }
 
         bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
         bool isStrictMode() const { return m_features & StrictModeFeature; }
 
-        virtual void unlinkCalls() = 0;
+        void unlinkCalls();
         
         static const ClassInfo s_info;
         
         static const ClassInfo s_info;
+
     protected:
     protected:
+        void finishCreation(JSGlobalData& globalData)
+        {
+            Base::finishCreation(globalData);
+#if ENABLE(CODEBLOCK_SAMPLING)
+            if (SamplingTool* sampler = globalData.interpreter->sampler())
+                sampler->notifyOfScope(globalData, this);
+#endif
+        }
+
         void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
         {
             m_features = features;
         void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
         {
             m_features = features;
@@ -222,19 +325,28 @@ namespace JSC {
     };
 
     class EvalExecutable : public ScriptExecutable {
     };
 
     class EvalExecutable : public ScriptExecutable {
+        friend class LLIntOffsetsExtractor;
     public:
     public:
+        typedef ScriptExecutable Base;
 
 
-        ~EvalExecutable();
+        static void destroy(JSCell*);
 
         JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
         {
             ASSERT(exec->globalData().dynamicGlobalObject);
             JSObject* error = 0;
             if (!m_evalCodeBlock)
 
         JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
         {
             ASSERT(exec->globalData().dynamicGlobalObject);
             JSObject* error = 0;
             if (!m_evalCodeBlock)
-                error = compileInternal(exec, scopeChainNode);
+                error = compileInternal(exec, scopeChainNode, JITCode::bottomTierJIT());
             ASSERT(!error == !!m_evalCodeBlock);
             return error;
         }
             ASSERT(!error == !!m_evalCodeBlock);
             return error;
         }
+        
+        JSObject* compileOptimized(ExecState*, ScopeChainNode*);
+        
+#if ENABLE(JIT)
+        void jettisonOptimizedCode(JSGlobalData&);
+        bool jitCompile(JSGlobalData&);
+#endif
 
         EvalCodeBlock& generatedBytecode()
         {
 
         EvalCodeBlock& generatedBytecode()
         {
@@ -242,7 +354,13 @@ namespace JSC {
             return *m_evalCodeBlock;
         }
 
             return *m_evalCodeBlock;
         }
 
-        static EvalExecutable* create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return new (exec) EvalExecutable(exec, source, isInStrictContext); }
+        static EvalExecutable* create(ExecState* exec, const SourceCode& source, bool isInStrictContext) 
+        {
+            EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
+            executable->finishCreation(exec->globalData());
+            exec->globalData().heap.addFinalizer(executable, &finalize);
+            return executable;
+        }
 
 #if ENABLE(JIT)
         JITCode& generatedJITCode()
 
 #if ENABLE(JIT)
         JITCode& generatedJITCode()
@@ -250,42 +368,61 @@ namespace JSC {
             return generatedJITCodeForCall();
         }
 #endif
             return generatedJITCodeForCall();
         }
 #endif
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
         {
         {
-            return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info);
         }
         
         static const ClassInfo s_info;
         }
         
         static const ClassInfo s_info;
+
+        void unlinkCalls();
+
+    protected:
+        void clearCode();
+        static void finalize(JSCell*);
+
     private:
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
         EvalExecutable(ExecState*, const SourceCode&, bool);
 
     private:
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
         EvalExecutable(ExecState*, const SourceCode&, bool);
 
-        JSObject* compileInternal(ExecState*, ScopeChainNode*);
-        virtual void visitChildren(SlotVisitor&);
-        void unlinkCalls();
+        JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
+        static void visitChildren(JSCell*, SlotVisitor&);
 
         OwnPtr<EvalCodeBlock> m_evalCodeBlock;
     };
 
     class ProgramExecutable : public ScriptExecutable {
 
         OwnPtr<EvalCodeBlock> m_evalCodeBlock;
     };
 
     class ProgramExecutable : public ScriptExecutable {
+        friend class LLIntOffsetsExtractor;
     public:
     public:
+        typedef ScriptExecutable Base;
+
         static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
         {
         static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
         {
-            return new (exec) ProgramExecutable(exec, source);
+            ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
+            executable->finishCreation(exec->globalData());
+            exec->globalData().heap.addFinalizer(executable, &finalize);
+            return executable;
         }
 
         }
 
-        ~ProgramExecutable();
+        static void destroy(JSCell*);
 
         JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
         {
             ASSERT(exec->globalData().dynamicGlobalObject);
             JSObject* error = 0;
             if (!m_programCodeBlock)
 
         JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
         {
             ASSERT(exec->globalData().dynamicGlobalObject);
             JSObject* error = 0;
             if (!m_programCodeBlock)
-                error = compileInternal(exec, scopeChainNode);
+                error = compileInternal(exec, scopeChainNode, JITCode::bottomTierJIT());
             ASSERT(!error == !!m_programCodeBlock);
             return error;
         }
 
             ASSERT(!error == !!m_programCodeBlock);
             return error;
         }
 
+        JSObject* compileOptimized(ExecState*, ScopeChainNode*);
+        
+#if ENABLE(JIT)
+        void jettisonOptimizedCode(JSGlobalData&);
+        bool jitCompile(JSGlobalData&);
+#endif
+
         ProgramCodeBlock& generatedBytecode()
         {
             ASSERT(m_programCodeBlock);
         ProgramCodeBlock& generatedBytecode()
         {
             ASSERT(m_programCodeBlock);
@@ -301,40 +438,59 @@ namespace JSC {
         }
 #endif
         
         }
 #endif
         
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
         {
         {
-            return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info);
         }
         
         static const ClassInfo s_info;
         }
         
         static const ClassInfo s_info;
+        
+        void unlinkCalls();
+
+    protected:
+        void clearCode();
+        static void finalize(JSCell*);
 
     private:
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
         ProgramExecutable(ExecState*, const SourceCode&);
 
 
     private:
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
         ProgramExecutable(ExecState*, const SourceCode&);
 
-        JSObject* compileInternal(ExecState*, ScopeChainNode*);
-        virtual void visitChildren(SlotVisitor&);
-        void unlinkCalls();
+        JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
+        static void visitChildren(JSCell*, SlotVisitor&);
 
         OwnPtr<ProgramCodeBlock> m_programCodeBlock;
     };
 
 
         OwnPtr<ProgramCodeBlock> m_programCodeBlock;
     };
 
-    class FunctionExecutable : public ScriptExecutable {
+    class FunctionExecutable : public ScriptExecutable, public DoublyLinkedListNode<FunctionExecutable> {
         friend class JIT;
         friend class JIT;
+        friend class LLIntOffsetsExtractor;
+        friend class WTF::DoublyLinkedListNode<FunctionExecutable>;
     public:
     public:
-        static FunctionExecutable* create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
+        typedef ScriptExecutable Base;
+
+        static FunctionExecutable* create(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
         {
         {
-            return new (exec) FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine);
+            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
+            executable->finishCreation(exec->globalData(), name, firstLine, lastLine);
+            exec->globalData().heap.addFunctionExecutable(executable);
+            exec->globalData().heap.addFinalizer(executable, &finalize);
+            return executable;
         }
 
         }
 
-        static FunctionExecutable* create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
+        static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
         {
         {
-            return new (globalData) FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine);
+            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
+            executable->finishCreation(globalData, name, firstLine, lastLine);
+            globalData.heap.addFunctionExecutable(executable);
+            globalData.heap.addFinalizer(executable, &finalize);
+            return executable;
         }
 
         }
 
+        static void destroy(JSCell*);
+
         JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
         {
         JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
         {
-            return new (exec) JSFunction(exec, this, scopeChain);
+            return JSFunction::create(exec, this, scopeChain);
         }
         
         // Returns either call or construct bytecode. This can be appropriate
         }
         
         // Returns either call or construct bytecode. This can be appropriate
@@ -347,17 +503,28 @@ namespace JSC {
             ASSERT(m_codeBlockForConstruct);
             return *m_codeBlockForConstruct;
         }
             ASSERT(m_codeBlockForConstruct);
             return *m_codeBlockForConstruct;
         }
+        
+        FunctionCodeBlock* codeBlockWithBytecodeFor(CodeSpecializationKind);
+        
+        PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(ScopeChainNode*, CompilationKind, CodeSpecializationKind, JSObject*& exception);
 
         JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
         {
             ASSERT(exec->globalData().dynamicGlobalObject);
             JSObject* error = 0;
             if (!m_codeBlockForCall)
 
         JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
         {
             ASSERT(exec->globalData().dynamicGlobalObject);
             JSObject* error = 0;
             if (!m_codeBlockForCall)
-                error = compileForCallInternal(exec, scopeChainNode);
+                error = compileForCallInternal(exec, scopeChainNode, JITCode::bottomTierJIT());
             ASSERT(!error == !!m_codeBlockForCall);
             return error;
         }
 
             ASSERT(!error == !!m_codeBlockForCall);
             return error;
         }
 
+        JSObject* compileOptimizedForCall(ExecState*, ScopeChainNode*);
+        
+#if ENABLE(JIT)
+        void jettisonOptimizedCodeForCall(JSGlobalData&);
+        bool jitCompileForCall(JSGlobalData&);
+#endif
+
         bool isGeneratedForCall() const
         {
             return m_codeBlockForCall;
         bool isGeneratedForCall() const
         {
             return m_codeBlockForCall;
@@ -374,11 +541,18 @@ namespace JSC {
             ASSERT(exec->globalData().dynamicGlobalObject);
             JSObject* error = 0;
             if (!m_codeBlockForConstruct)
             ASSERT(exec->globalData().dynamicGlobalObject);
             JSObject* error = 0;
             if (!m_codeBlockForConstruct)
-                error = compileForConstructInternal(exec, scopeChainNode);
+                error = compileForConstructInternal(exec, scopeChainNode, JITCode::bottomTierJIT());
             ASSERT(!error == !!m_codeBlockForConstruct);
             return error;
         }
 
             ASSERT(!error == !!m_codeBlockForConstruct);
             return error;
         }
 
+        JSObject* compileOptimizedForConstruct(ExecState*, ScopeChainNode*);
+        
+#if ENABLE(JIT)
+        void jettisonOptimizedCodeForConstruct(JSGlobalData&);
+        bool jitCompileForConstruct(JSGlobalData&);
+#endif
+
         bool isGeneratedForConstruct() const
         {
             return m_codeBlockForConstruct;
         bool isGeneratedForConstruct() const
         {
             return m_codeBlockForConstruct;
@@ -389,57 +563,135 @@ namespace JSC {
             ASSERT(m_codeBlockForConstruct);
             return *m_codeBlockForConstruct;
         }
             ASSERT(m_codeBlockForConstruct);
             return *m_codeBlockForConstruct;
         }
+        
+        JSObject* compileFor(ExecState* exec, ScopeChainNode* scopeChainNode, CodeSpecializationKind kind)
+        {
+            ASSERT(exec->callee());
+            ASSERT(exec->callee()->inherits(&JSFunction::s_info));
+            ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
+
+            if (kind == CodeForCall)
+                return compileForCall(exec, scopeChainNode);
+            ASSERT(kind == CodeForConstruct);
+            return compileForConstruct(exec, scopeChainNode);
+        }
+        
+        JSObject* compileOptimizedFor(ExecState* exec, ScopeChainNode* scopeChainNode, CodeSpecializationKind kind)
+        {
+            ASSERT(exec->callee());
+            ASSERT(exec->callee()->inherits(&JSFunction::s_info));
+            ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this);
+            
+            if (kind == CodeForCall)
+                return compileOptimizedForCall(exec, scopeChainNode);
+            ASSERT(kind == CodeForConstruct);
+            return compileOptimizedForConstruct(exec, scopeChainNode);
+        }
+
+        
+#if ENABLE(JIT)
+        void jettisonOptimizedCodeFor(JSGlobalData& globalData, CodeSpecializationKind kind)
+        {
+            if (kind == CodeForCall) 
+                jettisonOptimizedCodeForCall(globalData);
+            else {
+                ASSERT(kind == CodeForConstruct);
+                jettisonOptimizedCodeForConstruct(globalData);
+            }
+        }
+        
+        bool jitCompileFor(JSGlobalData& globalData, CodeSpecializationKind kind)
+        {
+            if (kind == CodeForCall)
+                return jitCompileForCall(globalData);
+            ASSERT(kind == CodeForConstruct);
+            return jitCompileForConstruct(globalData);
+        }
+#endif
+        
+        bool isGeneratedFor(CodeSpecializationKind kind)
+        {
+            if (kind == CodeForCall)
+                return isGeneratedForCall();
+            ASSERT(kind == CodeForConstruct);
+            return isGeneratedForConstruct();
+        }
+        
+        FunctionCodeBlock& generatedBytecodeFor(CodeSpecializationKind kind)
+        {
+            if (kind == CodeForCall)
+                return generatedBytecodeForCall();
+            ASSERT(kind == CodeForConstruct);
+            return generatedBytecodeForConstruct();
+        }
 
 
+        FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
+        
+        FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
+        {
+            return baselineCodeBlockFor(kind);
+        }
+        
         const Identifier& name() { return m_name; }
         const Identifier& name() { return m_name; }
-        size_t parameterCount() const { return m_parameters->size(); }
+        const Identifier& inferredName() { return m_inferredName; }
+        JSString* nameValue() const { return m_nameValue.get(); }
+        size_t parameterCount() const { return m_parameters->size(); } // Excluding 'this'!
         unsigned capturedVariableCount() const { return m_numCapturedVariables; }
         UString paramString() const;
         SharedSymbolTable* symbolTable() const { return m_symbolTable; }
 
         void discardCode();
         unsigned capturedVariableCount() const { return m_numCapturedVariables; }
         UString paramString() const;
         SharedSymbolTable* symbolTable() const { return m_symbolTable; }
 
         void discardCode();
-        void visitChildren(SlotVisitor&);
+        static void visitChildren(JSCell*, SlotVisitor&);
         static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
         static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
         {
         {
-            return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
         }
         
         static const ClassInfo s_info;
         }
         
         static const ClassInfo s_info;
+        
+        void unlinkCalls();
+
+    protected:
+        void clearCode();
+        static void finalize(JSCell*);
+
+        void finishCreation(JSGlobalData& globalData, const Identifier& name, int firstLine, int lastLine)
+        {
+            Base::finishCreation(globalData);
+            m_firstLine = firstLine;
+            m_lastLine = lastLine;
+            m_nameValue.set(globalData, this, jsString(&globalData, name.ustring()));
+        }
 
     private:
 
     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);
+        FunctionExecutable(JSGlobalData&, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
+        FunctionExecutable(ExecState*, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
 
 
-        JSObject* compileForCallInternal(ExecState*, ScopeChainNode*);
-        JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*);
+        JSObject* compileForCallInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
+        JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*, JITCode::JITType);
+        
+        OwnPtr<FunctionCodeBlock>& codeBlockFor(CodeSpecializationKind kind)
+        {
+            if (kind == CodeForCall)
+                return m_codeBlockForCall;
+            ASSERT(kind == CodeForConstruct);
+            return m_codeBlockForConstruct;
+        }
         
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
         unsigned m_numCapturedVariables : 31;
         bool m_forceUsesArguments : 1;
         
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
         unsigned m_numCapturedVariables : 31;
         bool m_forceUsesArguments : 1;
-        void unlinkCalls();
 
         RefPtr<FunctionParameters> m_parameters;
         OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
         OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
         Identifier m_name;
 
         RefPtr<FunctionParameters> m_parameters;
         OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
         OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
         Identifier m_name;
+        Identifier m_inferredName;
+        WriteBarrier<JSString> m_nameValue;
         SharedSymbolTable* m_symbolTable;
         SharedSymbolTable* m_symbolTable;
-
-#if ENABLE(JIT)
-    public:
-        MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
-        {
-            ASSERT(m_jitCodeForCall);
-            ASSERT(m_jitCodeForCallWithArityCheck);
-            return m_jitCodeForCallWithArityCheck;
-        }
-
-        MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck()
-        {
-            ASSERT(m_jitCodeForConstruct);
-            ASSERT(m_jitCodeForConstructWithArityCheck);
-            return m_jitCodeForConstructWithArityCheck;
-        }
-#endif
+        FunctionExecutable* m_next;
+        FunctionExecutable* m_prev;
     };
 
     inline FunctionExecutable* JSFunction::jsExecutable() const
     };
 
     inline FunctionExecutable* JSFunction::jsExecutable() const
@@ -459,6 +711,35 @@ namespace JSC {
         ASSERT(isHostFunction());
         return static_cast<NativeExecutable*>(m_executable.get())->function();
     }
         ASSERT(isHostFunction());
         return static_cast<NativeExecutable*>(m_executable.get())->function();
     }
+
+    inline NativeFunction JSFunction::nativeConstructor()
+    {
+        ASSERT(isHostFunction());
+        return static_cast<NativeExecutable*>(m_executable.get())->constructor();
+    }
+
+    inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
+    {
+        JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
+        if (!function || !function->isHostFunction())
+            return false;
+        return function->nativeFunction() == nativeFunction;
+    }
+
+    inline void ScriptExecutable::unlinkCalls()
+    {
+        switch (structure()->typeInfo().type()) {
+        case EvalExecutableType:
+            return jsCast<EvalExecutable*>(this)->unlinkCalls();
+        case ProgramExecutableType:
+            return jsCast<ProgramExecutable*>(this)->unlinkCalls();
+        case FunctionExecutableType:
+            return jsCast<FunctionExecutable*>(this)->unlinkCalls();
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
 }
 
 #endif
 }
 
 #endif
diff --git a/runtime/ExecutionHarness.h b/runtime/ExecutionHarness.h
new file mode 100644 (file)
index 0000000..e58e6fc
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef ExecutionHarness_h
+#define ExecutionHarness_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#include "JITDriver.h"
+#include "LLIntEntrypoints.h"
+
+namespace JSC {
+
+template<typename CodeBlockType>
+inline bool prepareForExecution(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType)
+{
+#if ENABLE(LLINT)
+    if (JITCode::isBaselineCode(jitType)) {
+        // Start off in the low level interpreter.
+        LLInt::getEntrypoint(globalData, codeBlock.get(), jitCode);
+        codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr());
+        return true;
+    }
+#endif // ENABLE(LLINT)
+    return jitCompileIfAppropriate(globalData, codeBlock, jitCode, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
+}
+
+inline bool prepareFunctionForExecution(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, CodeSpecializationKind kind)
+{
+#if ENABLE(LLINT)
+    if (JITCode::isBaselineCode(jitType)) {
+        // Start off in the low level interpreter.
+        LLInt::getFunctionEntrypoint(globalData, kind, jitCode, jitCodeWithArityCheck);
+        codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
+        return true;
+    }
+#else
+    UNUSED_PARAM(kind);
+#endif // ENABLE(LLINT)
+    return jitCompileFunctionIfAppropriate(globalData, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // ExecutionHarness_h
+
index 348d04ea4fe3b23b94604c41d3b18c8a61e641b8..956b2161d0113ca3943d72bf80247f7c423a20b9 100644 (file)
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(FunctionConstructor);
 
 
-FunctionConstructor::FunctionConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, FunctionPrototype* functionPrototype)
-    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, functionPrototype->classInfo()->className))
+const ClassInfo FunctionConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionConstructor) };
+
+FunctionConstructor::FunctionConstructor(JSGlobalObject* globalObject, Structure* structure)
+    : InternalFunction(globalObject, structure)
+{
+}
+
+void FunctionConstructor::finishCreation(ExecState* exec, FunctionPrototype* functionPrototype)
 {
 {
+    Base::finishCreation(exec->globalData(), Identifier(exec, functionPrototype->classInfo()->className));
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
 
     // Number of arguments for constructor
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
 
     // Number of arguments for constructor
@@ -52,7 +60,7 @@ static EncodedJSValue JSC_HOST_CALL constructWithFunctionConstructor(ExecState*
     return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
     return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
-ConstructType FunctionConstructor::getConstructData(ConstructData& constructData)
+ConstructType FunctionConstructor::getConstructData(JSCell*, ConstructData& constructData)
 {
     constructData.native.function = constructWithFunctionConstructor;
     return ConstructTypeHost;
 {
     constructData.native.function = constructWithFunctionConstructor;
     return ConstructTypeHost;
@@ -65,21 +73,21 @@ static EncodedJSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec)
 }
 
 // ECMA 15.3.1 The Function Constructor Called as a Function
 }
 
 // ECMA 15.3.1 The Function Constructor Called as a Function
-CallType FunctionConstructor::getCallData(CallData& callData)
+CallType FunctionConstructor::getCallData(JSCell*, CallData& callData)
 {
     callData.native.function = callFunctionConstructor;
     return CallTypeHost;
 }
 
 // ECMA 15.3.2 The Function Constructor
 {
     callData.native.function = callFunctionConstructor;
     return CallTypeHost;
 }
 
 // ECMA 15.3.2 The Function Constructor
-JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, 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, const TextPosition& position)
 {
 {
-    if (!globalObject->isEvalEnabled())
+    if (!globalObject->evalEnabled())
         return throwError(exec, createEvalError(exec, "Function constructor is disabled"));
         return throwError(exec, createEvalError(exec, "Function constructor is disabled"));
-    return constructFunctionSkippingEvalEnabledCheck(exec, globalObject, args, functionName, sourceURL, lineNumber);
+    return constructFunctionSkippingEvalEnabledCheck(exec, globalObject, args, functionName, sourceURL, position);
 }
 
 }
 
-JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
+JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const UString& sourceURL, const TextPosition& position)
 {
     // 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
@@ -88,23 +96,23 @@ JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObj
     if (args.isEmpty())
         program = "(function() { \n})";
     else if (args.size() == 1)
     if (args.isEmpty())
         program = "(function() { \n})";
     else if (args.size() == 1)
-        program = makeUString("(function() { ", args.at(0).toString(exec), "\n})");
+        program = makeUString("(function() { ", args.at(0).toString(exec)->value(exec), "\n})");
     else {
         UStringBuilder builder;
         builder.append("(function(");
     else {
         UStringBuilder builder;
         builder.append("(function(");
-        builder.append(args.at(0).toString(exec));
+        builder.append(args.at(0).toString(exec)->value(exec));
         for (size_t i = 1; i < args.size() - 1; i++) {
             builder.append(",");
         for (size_t i = 1; i < args.size() - 1; i++) {
             builder.append(",");
-            builder.append(args.at(i).toString(exec));
+            builder.append(args.at(i).toString(exec)->value(exec));
         }
         builder.append(") { ");
         }
         builder.append(") { ");
-        builder.append(args.at(args.size() - 1).toString(exec));
+        builder.append(args.at(args.size() - 1).toString(exec)->value(exec));
         builder.append("\n})");
         program = builder.toUString();
     }
 
     JSGlobalData& globalData = globalObject->globalData();
         builder.append("\n})");
         program = builder.toUString();
     }
 
     JSGlobalData& globalData = globalObject->globalData();
-    SourceCode source = makeSource(program, sourceURL, lineNumber);
+    SourceCode source = makeSource(program, sourceURL, position);
     JSObject* exception = 0;
     FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception);
     if (!function) {
     JSObject* exception = 0;
     FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception);
     if (!function) {
@@ -112,14 +120,14 @@ JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObj
         return throwError(exec, exception);
     }
 
         return throwError(exec, exception);
     }
 
-    ScopeChainNode* scopeChain = new (exec) ScopeChainNode(0, globalObject, &globalData, globalObject, exec->globalThisValue());
-    return new (exec) JSFunction(exec, function, scopeChain);
+    ScopeChainNode* scopeChain = ScopeChainNode::create(exec, 0, globalObject, &globalData, globalObject, exec->globalThisValue());
+    return JSFunction::create(exec, function, scopeChain);
 }
 
 // ECMA 15.3.2 The Function Constructor
 JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
 {
 }
 
 // ECMA 15.3.2 The Function Constructor
 JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
 {
-    return constructFunction(exec, globalObject, args, Identifier(exec, "anonymous"), UString(), 1);
+    return constructFunction(exec, globalObject, args, Identifier(exec, "anonymous"), UString(), TextPosition::minimumPosition());
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index ba112b9fc7951571ed1cc700a26bbb7c80921e0e..31986b70a73c653d188db26f4b17ee104d052127 100644 (file)
 
 #include "InternalFunction.h"
 
 
 #include "InternalFunction.h"
 
+namespace WTF {
+class TextPosition;
+}
+
 namespace JSC {
 
     class FunctionPrototype;
 
     class FunctionConstructor : public InternalFunction {
     public:
 namespace JSC {
 
     class FunctionPrototype;
 
     class FunctionConstructor : public InternalFunction {
     public:
-        FunctionConstructor(ExecState*, JSGlobalObject*, Structure*, FunctionPrototype*);
+        typedef InternalFunction Base;
+
+        static FunctionConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, FunctionPrototype* functionPrototype)
+        {
+            FunctionConstructor* constructor = new (NotNull, allocateCell<FunctionConstructor>(*exec->heap())) FunctionConstructor(globalObject, structure);
+            constructor->finishCreation(exec, functionPrototype);
+            return constructor;
+        }
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 
+        { 
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); 
+        }
 
     private:
 
     private:
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
+        FunctionConstructor(JSGlobalObject*, Structure*);
+        void finishCreation(ExecState*, FunctionPrototype*);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
     };
 
     };
 
-    JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
+    JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, const Identifier& functionName, const UString& sourceURL, const WTF::TextPosition&);
     JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&);
 
     JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&);
 
-    JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState*, JSGlobalObject*, const ArgList&, const Identifier&, const UString&, int lineNumber);
+    JS_EXPORT_PRIVATE JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState*, JSGlobalObject*, const ArgList&, const Identifier&, const UString&, const WTF::TextPosition&);
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index e2a49416ddee3c4b75f1fa326075583517957f2b..d341b847b98d6113ab4da45e39d67715bef38e4c 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "Arguments.h"
 #include "JSArray.h"
 
 #include "Arguments.h"
 #include "JSArray.h"
+#include "JSBoundFunction.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSStringBuilder.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSStringBuilder.h"
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(FunctionPrototype);
+
+const ClassInfo FunctionPrototype::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionPrototype) };
 
 static EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*);
 
 static EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState*);
+
+FunctionPrototype::FunctionPrototype(JSGlobalObject* globalObject, Structure* structure)
+    : InternalFunction(globalObject, structure)
+{
+}
 
 
-FunctionPrototype::FunctionPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
-    : InternalFunction(&exec->globalData(), globalObject, structure, exec->propertyNames().nullIdentifier)
+void FunctionPrototype::finishCreation(ExecState* exec, const Identifier& name)
 {
 {
+    Base::finishCreation(exec->globalData(), name);
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
 }
 
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
 }
 
-void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction)
+void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, JSFunction** callFunction, JSFunction** applyFunction)
 {
 {
-    putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);
-    *applyFunction = new (exec) JSFunction(exec, globalObject, functionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply);
-    putDirectFunctionWithoutTransition(exec, *applyFunction, DontEnum);
-    *callFunction = new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().call, functionProtoFuncCall);
-    putDirectFunctionWithoutTransition(exec, *callFunction, DontEnum);
+    JSFunction* toStringFunction = JSFunction::create(exec, globalObject, 0, exec->propertyNames().toString, functionProtoFuncToString);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().toString, toStringFunction, DontEnum);
+
+    *applyFunction = JSFunction::create(exec, globalObject, 2, exec->propertyNames().apply, functionProtoFuncApply);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().apply, *applyFunction, DontEnum);
+
+    *callFunction = JSFunction::create(exec, globalObject, 1, exec->propertyNames().call, functionProtoFuncCall);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().call, *callFunction, DontEnum);
+
+    JSFunction* bindFunction = JSFunction::create(exec, globalObject, 1, exec->propertyNames().bind, functionProtoFuncBind);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().bind, bindFunction, DontEnum);
 }
 
 static EncodedJSValue JSC_HOST_CALL callFunctionPrototype(ExecState*)
 }
 
 static EncodedJSValue JSC_HOST_CALL callFunctionPrototype(ExecState*)
@@ -58,7 +74,7 @@ static EncodedJSValue JSC_HOST_CALL callFunctionPrototype(ExecState*)
 }
 
 // ECMA 15.3.4
 }
 
 // ECMA 15.3.4
-CallType FunctionPrototype::getCallData(CallData& callData)
+CallType FunctionPrototype::getCallData(JSCell*, CallData& callData)
 {
     callData.native.function = callFunctionPrototype;
     return CallTypeHost;
 {
     callData.native.function = callFunctionPrototype;
     return CallTypeHost;
@@ -74,7 +90,7 @@ static inline void insertSemicolonIfNeeded(UString& functionBody)
 
     for (size_t i = functionBody.length() - 2; i > 0; --i) {
         UChar ch = functionBody[i];
 
     for (size_t i = functionBody.length() - 2; i > 0; --i) {
         UChar ch = functionBody[i];
-        if (!Lexer::isWhiteSpace(ch) && !Lexer::isLineTerminator(ch)) {
+        if (!Lexer<UChar>::isWhiteSpace(ch) && !Lexer<UChar>::isLineTerminator(ch)) {
             if (ch != ';' && ch != '}')
                 functionBody = makeUString(functionBody.substringSharingImpl(0, i + 1), ";", functionBody.substringSharingImpl(i + 1, functionBody.length() - (i + 1)));
             return;
             if (ch != ';' && ch != '}')
                 functionBody = makeUString(functionBody.substringSharingImpl(0, i + 1), ";", functionBody.substringSharingImpl(i + 1, functionBody.length() - (i + 1)));
             return;
@@ -86,7 +102,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.inherits(&JSFunction::s_info)) {
 {
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.inherits(&JSFunction::s_info)) {
-        JSFunction* function = asFunction(thisValue);
+        JSFunction* function = jsCast<JSFunction*>(thisValue);
         if (function->isHostFunction())
             return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n    [native code]\n}"));
         FunctionExecutable* executable = function->jsExecutable();
         if (function->isHostFunction())
             return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n    [native code]\n}"));
         FunctionExecutable* executable = function->jsExecutable();
@@ -117,18 +133,24 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncApply(ExecState* exec)
     if (!array.isUndefinedOrNull()) {
         if (!array.isObject())
             return throwVMTypeError(exec);
     if (!array.isUndefinedOrNull()) {
         if (!array.isObject())
             return throwVMTypeError(exec);
-        if (asObject(array)->classInfo() == &Arguments::s_info)
+        if (asObject(array)->classInfo() == &Arguments::s_info) {
+            if (asArguments(array)->length(exec) > Arguments::MaxArguments)
+                return JSValue::encode(throwStackOverflowError(exec));
             asArguments(array)->fillArgList(exec, applyArgs);
             asArguments(array)->fillArgList(exec, applyArgs);
-        else if (isJSArray(&exec->globalData(), array))
+        } else if (isJSArray(array)) {
+            if (asArray(array)->length() > Arguments::MaxArguments)
+                return JSValue::encode(throwStackOverflowError(exec));
             asArray(array)->fillArgList(exec, applyArgs);
             asArray(array)->fillArgList(exec, applyArgs);
-        else if (asObject(array)->inherits(&JSArray::s_info)) {
-            unsigned length = asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec);
+        } else {
+            unsigned length = asObject(array)->get(exec, exec->propertyNames().length).toUInt32(exec);
+            if (length > Arguments::MaxArguments)
+                return JSValue::encode(throwStackOverflowError(exec));
+
             for (unsigned i = 0; i < length; ++i)
             for (unsigned i = 0; i < length; ++i)
-                applyArgs.append(asArray(array)->get(exec, i));
-        } else
-            return throwVMTypeError(exec);
+                applyArgs.append(asObject(array)->get(exec, i));
+        }
     }
     }
-
+    
     return JSValue::encode(call(exec, thisValue, callType, callData, exec->argument(0), applyArgs));
 }
 
     return JSValue::encode(call(exec, thisValue, callType, callData, exec->argument(0), applyArgs));
 }
 
@@ -146,4 +168,48 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncCall(ExecState* exec)
     return JSValue::encode(call(exec, thisValue, callType, callData, exec->argument(0), callArgs));
 }
 
     return JSValue::encode(call(exec, thisValue, callType, callData, exec->argument(0), callArgs));
 }
 
+// 15.3.4.5 Function.prototype.bind (thisArg [, arg1 [, arg2, ...]])
+EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec)
+{
+    JSGlobalObject* globalObject = exec->callee()->globalObject();
+
+    // Let Target be the this value.
+    JSValue target = exec->hostThisValue();
+
+    // If IsCallable(Target) is false, throw a TypeError exception.
+    CallData callData;
+    CallType callType = getCallData(target, callData);
+    if (callType == CallTypeNone)
+        return throwVMTypeError(exec);
+    // Primitive values are not callable.
+    ASSERT(target.isObject());
+    JSObject* targetObject = asObject(target);
+
+    // Let A be a new (possibly empty) internal list of all of the argument values provided after thisArg (arg1, arg2 etc), in order.
+    size_t numBoundArgs = exec->argumentCount() > 1 ? exec->argumentCount() - 1 : 0;
+    JSArray* boundArgs = JSArray::tryCreateUninitialized(exec->globalData(), globalObject->arrayStructure(), numBoundArgs);
+    if (!boundArgs)
+        return JSValue::encode(throwOutOfMemoryError(exec));
+
+    for (size_t i = 0; i < numBoundArgs; ++i)
+        boundArgs->initializeIndex(exec->globalData(), i, exec->argument(i + 1));
+    boundArgs->completeInitialization(numBoundArgs);
+
+    // If the [[Class]] internal property of Target is "Function", then ...
+    // Else set the length own property of F to 0.
+    unsigned length = 0;
+    if (targetObject->inherits(&JSFunction::s_info)) {
+        ASSERT(target.get(exec, exec->propertyNames().length).isNumber());
+        // a. Let L be the length property of Target minus the length of A.
+        // b. Set the length own property of F to either 0 or L, whichever is larger.
+        unsigned targetLength = (unsigned)target.get(exec, exec->propertyNames().length).asNumber();
+        if (targetLength > numBoundArgs)
+            length = targetLength - numBoundArgs;
+    }
+
+    Identifier name(exec, target.get(exec, exec->propertyNames().name).toString(exec)->value(exec));
+
+    return JSValue::encode(JSBoundFunction::create(exec, globalObject, targetObject, exec->argument(0), boundArgs, length, name));
+}
+
 } // namespace JSC
 } // namespace JSC
index ab708dd7de33a1900a43b0aa58ec6caa6d5117b5..7dd1c241843ca46dfc622c2b06c6df884126332d 100644 (file)
@@ -27,16 +27,30 @@ namespace JSC {
 
     class FunctionPrototype : public InternalFunction {
     public:
 
     class FunctionPrototype : public InternalFunction {
     public:
-        FunctionPrototype(ExecState*, JSGlobalObject*, Structure*);
-        void addFunctionProperties(ExecState*, JSGlobalObject*, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction);
+        typedef InternalFunction Base;
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
+        static FunctionPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
         {
         {
-            return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            FunctionPrototype* prototype = new (NotNull, allocateCell<FunctionPrototype>(*exec->heap())) FunctionPrototype(globalObject, structure);
+            prototype->finishCreation(exec, exec->propertyNames().nullIdentifier);
+            return prototype;
         }
         }
+        
+        void addFunctionProperties(ExecState*, JSGlobalObject*, JSFunction** callFunction, JSFunction** applyFunction);
+        
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+        {
+            return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info);
+        }
+
+        static const ClassInfo s_info;
+
+    protected:
+        void finishCreation(ExecState*, const Identifier& name);
 
     private:
 
     private:
-        virtual CallType getCallData(CallData&);
+        FunctionPrototype(JSGlobalObject*, Structure*);
+        static CallType getCallData(JSCell*, CallData&);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 308d245a9665d1580fffe52f83f1b4394f2be376..851ffc22352864a3176b70cd7e9157a011083aa1 100644 (file)
@@ -42,7 +42,11 @@ DefaultGCActivityCallback::~DefaultGCActivityCallback()
 {
 }
 
 {
 }
 
-void DefaultGCActivityCallback::operator()()
+void DefaultGCActivityCallback::didAllocate(size_t)
+{
+}
+
+void DefaultGCActivityCallback::willCollect()
 {
 }
 
 {
 }
 
@@ -50,5 +54,17 @@ void DefaultGCActivityCallback::synchronize()
 {
 }
 
 {
 }
 
+void DefaultGCActivityCallback::cancel()
+{
+}
+
+void DefaultGCActivityCallback::didStartVMShutdown()
+{
+}
+
+void DefaultGCActivityCallback::invalidate()
+{
+}
+
 }
 
 }
 
index f40ebee5b8f2551a80dc2d08bbeaac53065f5493..4e0d967e7659f032176c74e8421e75fc7693740d 100644 (file)
@@ -42,9 +42,15 @@ class Heap;
 
 class GCActivityCallback {
 public:
 
 class GCActivityCallback {
 public:
-    virtual ~GCActivityCallback() {}
-    virtual void operator()() {}
-    virtual void synchronize() {}
+    virtual ~GCActivityCallback() { }
+    virtual void didAllocate(size_t) { }
+    virtual void willCollect() { }
+    virtual void synchronize() { }
+    virtual void cancel() { }
+    virtual void didStartVMShutdown() { }
+    virtual void invalidate() { }
+
+    static bool s_shouldCreateGCTimer;
 
 protected:
     GCActivityCallback() {}
 
 protected:
     GCActivityCallback() {}
@@ -54,17 +60,21 @@ struct DefaultGCActivityCallbackPlatformData;
 
 class DefaultGCActivityCallback : public GCActivityCallback {
 public:
 
 class DefaultGCActivityCallback : public GCActivityCallback {
 public:
-    static PassOwnPtr<DefaultGCActivityCallback> create(Heap*);
+    static DefaultGCActivityCallback* create(Heap*);
 
     DefaultGCActivityCallback(Heap*);
 
     DefaultGCActivityCallback(Heap*);
-    ~DefaultGCActivityCallback();
+    JS_EXPORT_PRIVATE virtual ~DefaultGCActivityCallback();
 
 
-    void operator()();
-    void synchronize();
+    JS_EXPORT_PRIVATE virtual void didAllocate(size_t);
+    JS_EXPORT_PRIVATE virtual void willCollect();
+    JS_EXPORT_PRIVATE virtual void synchronize();
+    JS_EXPORT_PRIVATE virtual void cancel();
+    JS_EXPORT_PRIVATE virtual void didStartVMShutdown();
+    JS_EXPORT_PRIVATE virtual void invalidate();
 
 #if USE(CF)
 protected:
 
 #if USE(CF)
 protected:
-    DefaultGCActivityCallback(Heap*, CFRunLoopRef);
+    JS_EXPORT_PRIVATE DefaultGCActivityCallback(Heap*, CFRunLoopRef);
     void commonConstructor(Heap*, CFRunLoopRef);
 #endif
 
     void commonConstructor(Heap*, CFRunLoopRef);
 #endif
 
@@ -72,9 +82,12 @@ private:
     OwnPtr<DefaultGCActivityCallbackPlatformData> d;
 };
 
     OwnPtr<DefaultGCActivityCallbackPlatformData> d;
 };
 
-inline PassOwnPtr<DefaultGCActivityCallback> DefaultGCActivityCallback::create(Heap* heap)
+inline DefaultGCActivityCallback* DefaultGCActivityCallback::create(Heap* heap)
 {
 {
-    return adoptPtr(new DefaultGCActivityCallback(heap));
+    // Big hack.
+    if (GCActivityCallback::s_shouldCreateGCTimer)
+        return new DefaultGCActivityCallback(heap);
+    return 0;
 }
 
 }
 }
 
 }
index 2e878bfe3d6d2464aeacd66bb0824bc1febb6908..cbd5b79d7a0118996448e0282193335bb0f7b74c 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
+bool GCActivityCallback::s_shouldCreateGCTimer = true;
+
 struct DefaultGCActivityCallbackPlatformData {
 struct DefaultGCActivityCallbackPlatformData {
-    static void trigger(CFRunLoopTimerRef, void *info);
+    static void timerDidFire(CFRunLoopTimerRef, void *info);
 
     RetainPtr<CFRunLoopTimerRef> timer;
     RetainPtr<CFRunLoopRef> runLoop;
     CFRunLoopTimerContext context;
 
     RetainPtr<CFRunLoopTimerRef> timer;
     RetainPtr<CFRunLoopRef> runLoop;
     CFRunLoopTimerContext context;
+    double delay;
+    DefaultGCActivityCallback* thisObject;
+    JSGlobalData* globalData;
+    Mutex shutdownMutex;
 };
 
 };
 
+const double gcTimeSlicePerMB = 0.01; // Percentage of CPU time we will spend to reclaim 1 MB
+const double maxGCTimeSlice = 0.05; // The maximum amount of CPU time we want to use for opportunistic timer-triggered collections.
+const double timerSlop = 2.0; // Fudge factor to avoid performance cost of resetting timer.
+const double pagingTimeOut = 0.1; // Time in seconds to allow opportunistic timer to iterate over all blocks to see if the Heap is paged out.
 const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10;
 const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10;
-const CFTimeInterval triggerInterval = 2; // seconds
+const CFTimeInterval hour = 60 * 60;
 
 
-void DefaultGCActivityCallbackPlatformData::trigger(CFRunLoopTimerRef timer, void *info)
+void DefaultGCActivityCallbackPlatformData::timerDidFire(CFRunLoopTimerRef, void *info)
 {
 {
-    Heap* heap = static_cast<Heap*>(info);
-    APIEntryShim shim(heap->globalData());
-    heap->collectAllGarbage();
-    CFRunLoopTimerSetNextFireDate(timer, CFAbsoluteTimeGetCurrent() + decade);
+    DefaultGCActivityCallbackPlatformData* d = static_cast<DefaultGCActivityCallbackPlatformData*>(info);
+    d->shutdownMutex.lock();
+    if (!d->globalData) {
+        d->shutdownMutex.unlock();
+        delete d->thisObject;
+        return;
+    }
+    {
+        // We don't ref here to prevent us from resurrecting the ref count of a "dead" JSGlobalData.
+        APIEntryShim shim(d->globalData, APIEntryShimWithoutLock::DontRefGlobalData);
+
+        Heap* heap = &d->globalData->heap;
+        heap->collectAllGarbage();
+    }
+    d->shutdownMutex.unlock();
 }
 
 DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
 }
 
 DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
@@ -77,9 +98,6 @@ DefaultGCActivityCallback::~DefaultGCActivityCallback()
 {
     CFRunLoopRemoveTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
     CFRunLoopTimerInvalidate(d->timer.get());
 {
     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)
 }
 
 void DefaultGCActivityCallback::commonConstructor(Heap* heap, CFRunLoopRef runLoop)
@@ -87,15 +105,65 @@ void DefaultGCActivityCallback::commonConstructor(Heap* heap, CFRunLoopRef runLo
     d = adoptPtr(new DefaultGCActivityCallbackPlatformData);
 
     memset(&d->context, 0, sizeof(CFRunLoopTimerContext));
     d = adoptPtr(new DefaultGCActivityCallbackPlatformData);
 
     memset(&d->context, 0, sizeof(CFRunLoopTimerContext));
-    d->context.info = heap;
+    d->context.info = d.get();
+    d->thisObject = this;
+    d->globalData = heap->globalData();
     d->runLoop = runLoop;
     d->runLoop = runLoop;
-    d->timer.adoptCF(CFRunLoopTimerCreate(0, decade, decade, 0, 0, DefaultGCActivityCallbackPlatformData::trigger, &d->context));
+    d->timer.adoptCF(CFRunLoopTimerCreate(0, decade, decade, 0, 0, DefaultGCActivityCallbackPlatformData::timerDidFire, &d->context));
+    d->delay = decade;
     CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
 }
 
     CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
 }
 
-void DefaultGCActivityCallback::operator()()
+void DefaultGCActivityCallback::invalidate()
+{
+    d->globalData = 0;
+    // We set the next fire date in the distant past to cause the timer to immediately fire so that
+    // the timer on the remote thread realizes that the VM is shutting down.
+    CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() - decade);
+}
+
+void DefaultGCActivityCallback::didStartVMShutdown()
+{
+    if (CFRunLoopGetCurrent() == d->runLoop.get()) {
+        invalidate();
+        delete this;
+        return;
+    }
+    ASSERT(!d->globalData->apiLock().currentThreadIsHoldingLock());
+    MutexLocker locker(d->shutdownMutex);
+    invalidate();
+}
+
+static void scheduleTimer(DefaultGCActivityCallbackPlatformData* d, double newDelay)
+{
+    if (newDelay * timerSlop > d->delay)
+        return;
+    double delta = d->delay - newDelay;
+    d->delay = newDelay;
+    CFRunLoopTimerSetNextFireDate(d->timer.get(), CFRunLoopTimerGetNextFireDate(d->timer.get()) - delta);
+}
+
+static void cancelTimer(DefaultGCActivityCallbackPlatformData* d)
+{
+    d->delay = decade;
+    CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() + decade);
+}
+
+void DefaultGCActivityCallback::didAllocate(size_t bytes)
 {
 {
-    CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() + triggerInterval);
+    // The first byte allocated in an allocation cycle will report 0 bytes to didAllocate. 
+    // We pretend it's one byte so that we don't ignore this allocation entirely.
+    if (!bytes)
+        bytes = 1;
+    Heap* heap = &static_cast<DefaultGCActivityCallbackPlatformData*>(d->context.info)->globalData->heap;
+    double gcTimeSlice = std::min((static_cast<double>(bytes) / MB) * gcTimeSlicePerMB, maxGCTimeSlice);
+    double newDelay = heap->lastGCLength() / gcTimeSlice;
+    scheduleTimer(d.get(), newDelay);
+}
+
+void DefaultGCActivityCallback::willCollect()
+{
+    cancelTimer(d.get());
 }
 
 void DefaultGCActivityCallback::synchronize()
 }
 
 void DefaultGCActivityCallback::synchronize()
@@ -107,4 +175,9 @@ void DefaultGCActivityCallback::synchronize()
     CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
 }
 
     CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
 }
 
+void DefaultGCActivityCallback::cancel()
+{
+    cancelTimer(d.get());
+}
+
 }
 }
index 04193ea3d5314c2239c152fa607ce5adc0fe4ebd..920399dda3f38bf8771ee505f66d194bdde9c5d9 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo GetterSetter::s_info = { "GetterSetter", 0, 0, 0 };
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(GetterSetter);
 
 
-void GetterSetter::visitChildren(SlotVisitor& visitor)
-{
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
-    JSCell::visitChildren(visitor);
-
-    if (m_getter)
-        visitor.append(&m_getter);
-    if (m_setter)
-        visitor.append(&m_setter);
-}
+const ClassInfo GetterSetter::s_info = { "GetterSetter", 0, 0, 0, CREATE_METHOD_TABLE(GetterSetter) };
 
 
-bool GetterSetter::isGetterSetter() const
+void GetterSetter::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    return true;
+    GetterSetter* thisObject = jsCast<GetterSetter*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    JSCell::visitChildren(thisObject, visitor);
+
+    if (thisObject->m_getter)
+        visitor.append(&thisObject->m_getter);
+    if (thisObject->m_setter)
+        visitor.append(&thisObject->m_setter);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index aca7e3cbb0272f1ff9dea99c60fe5cdbd309a1d2..b8caf01988692d9c49a200bfb330af7472a7b554 100644 (file)
@@ -36,28 +36,37 @@ namespace JSC {
     // for a property.
     class GetterSetter : public JSCell {
         friend class JIT;
     // for a property.
     class GetterSetter : public JSCell {
         friend class JIT;
-    public:
+
+    private:        
         GetterSetter(ExecState* exec)
             : JSCell(exec->globalData(), exec->globalData().getterSetterStructure.get())
         {
         }
 
         GetterSetter(ExecState* exec)
             : JSCell(exec->globalData(), exec->globalData().getterSetterStructure.get())
         {
         }
 
-        virtual void visitChildren(SlotVisitor&);
+    public:
+        typedef JSCell Base;
+
+        static GetterSetter* create(ExecState* exec)
+        {
+            GetterSetter* getterSetter = new (NotNull, allocateCell<GetterSetter>(*exec->heap())) GetterSetter(exec);
+            getterSetter->finishCreation(exec->globalData());
+            return getterSetter;
+        }
+
+        static void visitChildren(JSCell*, SlotVisitor&);
 
         JSObject* getter() const { return m_getter.get(); }
 
         JSObject* getter() const { return m_getter.get(); }
-        void setGetter(JSGlobalData& globalData, JSObject* getter) { m_getter.set(globalData, this, getter); }
+        void setGetter(JSGlobalData& globalData, JSObject* getter) { m_getter.setMayBeNull(globalData, this, getter); }
         JSObject* setter() const { return m_setter.get(); }
         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)
+        void setSetter(JSGlobalData& globalData, JSObject* setter) { m_setter.setMayBeNull(globalData, this, setter); }
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(GetterSetterType, OverridesVisitChildren), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(GetterSetterType, OverridesVisitChildren), &s_info);
         }
         
         static const ClassInfo s_info;
 
     private:
         }
         
         static const ClassInfo s_info;
 
     private:
-        virtual bool isGetterSetter() const;
-
         WriteBarrier<JSObject> m_getter;
         WriteBarrier<JSObject> m_setter;  
     };
         WriteBarrier<JSObject> m_getter;
         WriteBarrier<JSObject> m_setter;  
     };
index b07341c95c8e0e7574bccd9310284b1f1c4fc82f..182bcc462022b4ec2cbac6855c5029f64c711fff 100644 (file)
 #include <wtf/Assertions.h>
 #include <wtf/FastMalloc.h>
 #include <wtf/HashSet.h>
 #include <wtf/Assertions.h>
 #include <wtf/FastMalloc.h>
 #include <wtf/HashSet.h>
-#include <wtf/WTFThreadData.h>
 #include <wtf/text/StringHash.h>
 
 using WTF::ThreadSpecific;
 
 namespace JSC {
 
 #include <wtf/text/StringHash.h>
 
 using WTF::ThreadSpecific;
 
 namespace JSC {
 
-IdentifierTable::~IdentifierTable()
-{
-    HashSet<StringImpl*>::iterator end = m_table.end();
-    for (HashSet<StringImpl*>::iterator iter = m_table.begin(); iter != end; ++iter)
-        (*iter)->setIsIdentifier(false);
-}
-std::pair<HashSet<StringImpl*>::iterator, bool> IdentifierTable::add(StringImpl* value)
-{
-    std::pair<HashSet<StringImpl*>::iterator, bool> result = m_table.add(value);
-    (*result.first)->setIsIdentifier(true);
-    return result;
-}
-template<typename U, typename V>
-std::pair<HashSet<StringImpl*>::iterator, bool> IdentifierTable::add(U value)
-{
-    std::pair<HashSet<StringImpl*>::iterator, bool> result = m_table.add<U, V>(value);
-    (*result.first)->setIsIdentifier(true);
-    return result;
-}
-
 IdentifierTable* createIdentifierTable()
 {
     return new IdentifierTable;
 IdentifierTable* createIdentifierTable()
 {
     return new IdentifierTable;
@@ -67,39 +46,54 @@ void deleteIdentifierTable(IdentifierTable* table)
     delete table;
 }
 
     delete table;
 }
 
-bool Identifier::equal(const StringImpl* r, const char* s)
-{
-    int length = r->length();
-    const UChar* d = r->characters();
-    for (int i = 0; i != length; ++i)
-        if (d[i] != (unsigned char)s[i])
-            return false;
-    return s[length] == 0;
-}
-
 struct IdentifierCStringTranslator {
 struct IdentifierCStringTranslator {
-    static unsigned hash(const char* c)
+    static unsigned hash(const LChar* c)
     {
     {
-        return StringHasher::computeHash<char>(c);
+        return StringHasher::computeHash<LChar>(c);
     }
 
     }
 
-    static bool equal(StringImpl* r, const char* s)
+    static bool equal(StringImpl* r, const LChar* s)
     {
         return Identifier::equal(r, s);
     }
 
     {
         return Identifier::equal(r, s);
     }
 
-    static void translate(StringImpl*& location, const char* c, unsigned hash)
+    static void translate(StringImpl*& location, const LChar* c, unsigned hash)
     {
     {
-        size_t length = strlen(c);
-        UChar* d;
+        size_t length = strlen(reinterpret_cast<const char*>(c));
+        LChar* d;
         StringImpl* r = StringImpl::createUninitialized(length, d).leakRef();
         for (size_t i = 0; i != length; i++)
         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
+            d[i] = c[i];
         r->setHash(hash);
         location = r;
     }
 };
 
         r->setHash(hash);
         location = r;
     }
 };
 
+struct IdentifierLCharFromUCharTranslator {
+    static unsigned hash(const CharBuffer<UChar>& buf)
+    {
+        return StringHasher::computeHash<UChar>(buf.s, buf.length);
+    }
+    
+    static bool equal(StringImpl* str, const CharBuffer<UChar>& buf)
+    {
+        return Identifier::equal(str, buf.s, buf.length);
+    }
+    
+    static void translate(StringImpl*& location, const CharBuffer<UChar>& buf, unsigned hash)
+    {
+        LChar* d;
+        StringImpl* r = StringImpl::createUninitialized(buf.length, d).leakRef();
+        for (unsigned i = 0; i != buf.length; i++) {
+            UChar c = buf.s[i];
+            ASSERT(c <= 0xff);
+            d[i] = c;
+        }
+        r->setHash(hash);
+        location = r; 
+    }
+};
+
 PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const char* c)
 {
     if (!c)
 PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const char* c)
 {
     if (!c)
@@ -107,7 +101,7 @@ PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const char* c)
     if (!c[0])
         return StringImpl::empty();
     if (!c[1])
     if (!c[0])
         return StringImpl::empty();
     if (!c[1])
-        return add(globalData, globalData->smallStrings.singleCharacterStringRep(static_cast<unsigned char>(c[0])));
+        return add(globalData, globalData->smallStrings.singleCharacterStringRep(c[0]));
 
     IdentifierTable& identifierTable = *globalData->identifierTable;
     LiteralIdentifierTable& literalIdentifierTable = identifierTable.literalTable();
 
     IdentifierTable& identifierTable = *globalData->identifierTable;
     LiteralIdentifierTable& literalIdentifierTable = identifierTable.literalTable();
@@ -116,11 +110,11 @@ PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const char* c)
     if (iter != literalIdentifierTable.end())
         return iter->second;
 
     if (iter != literalIdentifierTable.end())
         return iter->second;
 
-    pair<HashSet<StringImpl*>::iterator, bool> addResult = identifierTable.add<const char*, IdentifierCStringTranslator>(c);
+    HashSet<StringImpl*>::AddResult addResult = identifierTable.add<const LChar*, IdentifierCStringTranslator>(reinterpret_cast<const LChar*>(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<StringImpl> addedString = addResult.second ? adoptRef(*addResult.first) : *addResult.first;
+    RefPtr<StringImpl> addedString = addResult.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator;
 
     literalIdentifierTable.add(c, addedString.get());
 
 
     literalIdentifierTable.add(c, addedString.get());
 
@@ -132,96 +126,73 @@ PassRefPtr<StringImpl> Identifier::add(ExecState* exec, const char* c)
     return add(&exec->globalData(), c);
 }
 
     return add(&exec->globalData(), c);
 }
 
-struct UCharBuffer {
-    const UChar* s;
-    unsigned int length;
-};
-
-struct IdentifierUCharBufferTranslator {
-    static unsigned hash(const UCharBuffer& buf)
-    {
-        return StringHasher::computeHash<UChar>(buf.s, buf.length);
-    }
-
-    static bool equal(StringImpl* str, const UCharBuffer& buf)
-    {
-        return Identifier::equal(str, buf.s, buf.length);
-    }
-
-    static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash)
-    {
-        UChar* d;
-        StringImpl* r = StringImpl::createUninitialized(buf.length, d).leakRef();
-        for (unsigned i = 0; i != buf.length; i++)
-            d[i] = buf.s[i];
-        r->setHash(hash);
-        location = r; 
-    }
-};
-
-uint32_t Identifier::toUInt32(const UString& string, bool& ok)
+PassRefPtr<StringImpl> Identifier::add8(JSGlobalData* globalData, const UChar* s, int length)
 {
 {
-    ok = false;
-
-    unsigned length = string.length();
-    const UChar* characters = string.characters();
-
-    // An empty string is not a number.
+    if (length == 1) {
+        UChar c = s[0];
+        ASSERT(c <= 0xff);
+        if (canUseSingleCharacterString(c))
+            return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
+    }
+    
     if (!length)
     if (!length)
-        return 0;
+        return StringImpl::empty();
+    CharBuffer<UChar> buf = {s, length}; 
+    HashSet<StringImpl*>::AddResult addResult = globalData->identifierTable->add<CharBuffer<UChar>, IdentifierLCharFromUCharTranslator >(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.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator;
+}
 
 
+template <typename CharType>
+ALWAYS_INLINE uint32_t Identifier::toUInt32FromCharacters(const CharType* characters, unsigned length, bool& ok)
+{
     // Get the first character, turning it into a digit.
     uint32_t value = characters[0] - '0';
     if (value > 9)
         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;
     // 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;
     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;
         // 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;
     }
         // 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;
 }
 
     ok = true;
     return value;
 }
 
-PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const UChar* s, int length)
+uint32_t Identifier::toUInt32(const UString& string, bool& ok)
 {
 {
-    if (length == 1) {
-        UChar c = s[0];
-        if (c <= maxSingleCharacterString)
-            return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
-    }
-    if (!length)
-        return StringImpl::empty();
-    UCharBuffer buf = {s, length}; 
-    pair<HashSet<StringImpl*>::iterator, bool> addResult = globalData->identifierTable->add<UCharBuffer, IdentifierUCharBufferTranslator>(buf);
+    ok = false;
 
 
-    // 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;
-}
+    unsigned length = string.length();
 
 
-PassRefPtr<StringImpl> Identifier::add(ExecState* exec, const UChar* s, int length)
-{
-    return add(&exec->globalData(), s, length);
+    // An empty string is not a number.
+    if (!length)
+        return 0;
+
+    if (string.is8Bit())
+        return toUInt32FromCharacters(string.characters8(), length, ok);
+    return toUInt32FromCharacters(string.characters16(), length, ok);
 }
 
 PassRefPtr<StringImpl> Identifier::addSlowCase(JSGlobalData* globalData, StringImpl* r)
 }
 
 PassRefPtr<StringImpl> Identifier::addSlowCase(JSGlobalData* globalData, StringImpl* r)
@@ -232,14 +203,14 @@ PassRefPtr<StringImpl> Identifier::addSlowCase(JSGlobalData* globalData, StringI
     ASSERT(r->length());
 
     if (r->length() == 1) {
     ASSERT(r->length());
 
     if (r->length() == 1) {
-        UChar c = r->characters()[0];
+        UChar c = (*r)[0];
         if (c <= maxSingleCharacterString)
             r = globalData->smallStrings.singleCharacterStringRep(c);
             if (r->isIdentifier())
                 return r;
     }
 
         if (c <= maxSingleCharacterString)
             r = globalData->smallStrings.singleCharacterStringRep(c);
             if (r->isIdentifier())
                 return r;
     }
 
-    return *globalData->identifierTable->add(r).first;
+    return *globalData->identifierTable->add(r).iterator;
 }
 
 PassRefPtr<StringImpl> Identifier::addSlowCase(ExecState* exec, StringImpl* r)
 }
 
 PassRefPtr<StringImpl> Identifier::addSlowCase(ExecState* exec, StringImpl* r)
@@ -295,8 +266,8 @@ void Identifier::checkCurrentIdentifierTable(ExecState* exec)
 
 // These only exists so that our exports are the same for debug and release builds.
 // This would be an ASSERT_NOT_REACHED(), but we're in NDEBUG only code here!
 
 // These only exists so that our exports are the same for debug and release builds.
 // This would be an ASSERT_NOT_REACHED(), but we're in NDEBUG only code here!
-void Identifier::checkCurrentIdentifierTable(JSGlobalData*) { CRASH(); }
-void Identifier::checkCurrentIdentifierTable(ExecState*) { CRASH(); }
+NO_RETURN_DUE_TO_CRASH void Identifier::checkCurrentIdentifierTable(JSGlobalData*) { CRASH(); }
+NO_RETURN_DUE_TO_CRASH void Identifier::checkCurrentIdentifierTable(ExecState*) { CRASH(); }
 
 #endif
 
 
 #endif
 
index 36b336ef49241bc9331724facd93ab4da75d6d9a..14960876b6f58d867b9a5e38275ced06c2ace6e5 100644 (file)
@@ -22,8 +22,9 @@
 #define Identifier_h
 
 #include "JSGlobalData.h"
 #define Identifier_h
 
 #include "JSGlobalData.h"
-#include "ThreadSpecific.h"
+#include <wtf/ThreadSpecific.h>
 #include "UString.h"
 #include "UString.h"
+#include <wtf/WTFThreadData.h>
 #include <wtf/text/CString.h>
 
 namespace JSC {
 #include <wtf/text/CString.h>
 
 namespace JSC {
@@ -36,11 +37,11 @@ namespace JSC {
         Identifier() { }
 
         Identifier(ExecState* exec, const char* s) : m_string(add(exec, s)) { } // Only to be used with string literals.
         Identifier() { }
 
         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) : m_string(add(globalData, s)) { } // Only to be used with string literals.
         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) : m_string(add(globalData, s)) { } // Only to be used with string literals.
+        Identifier(JSGlobalData* globalData, const LChar* s, int length) : m_string(add(globalData, s, length)) { }
         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())) { }
         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())) { }
@@ -52,15 +53,17 @@ namespace JSC {
         int length() const { return m_string.length(); }
         
         CString ascii() const { return m_string.ascii(); }
         int length() const { return m_string.length(); }
         
         CString ascii() const { return m_string.ascii(); }
-        
-        static Identifier from(ExecState* exec, unsigned y);
-        static Identifier from(ExecState* exec, int y);
+
+        static Identifier createLCharFromUChar(JSGlobalData* globalData, const UChar* s, int length) { return Identifier(globalData, add8(globalData, s, length)); }
+
+        JS_EXPORT_PRIVATE static Identifier from(ExecState* exec, unsigned y);
+        JS_EXPORT_PRIVATE static Identifier from(ExecState* exec, int y);
         static Identifier from(ExecState* exec, double y);
         static Identifier from(JSGlobalData*, unsigned y);
         static Identifier from(JSGlobalData*, int y);
         static Identifier from(JSGlobalData*, double y);
 
         static Identifier from(ExecState* exec, double y);
         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);
+        JS_EXPORT_PRIVATE static uint32_t toUInt32(const UString&, bool& ok);
         uint32_t toUInt32(bool& ok) const { return toUInt32(m_string, ok); }
         unsigned toArrayIndex(bool& ok) const;
 
         uint32_t toUInt32(bool& ok) const { return toUInt32(m_string, ok); }
         unsigned toArrayIndex(bool& ok) const;
 
@@ -70,24 +73,32 @@ namespace JSC {
         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&);
 
+        friend bool operator==(const Identifier&, const LChar*);
         friend bool operator==(const Identifier&, const char*);
         friend bool operator==(const Identifier&, const char*);
+        friend bool operator!=(const Identifier&, const LChar*);
         friend bool operator!=(const Identifier&, const char*);
     
         friend bool operator!=(const Identifier&, const char*);
     
-        static bool equal(const StringImpl*, const char*);
+        static bool equal(const StringImpl*, const LChar*);
+        static inline bool equal(const StringImpl*a, const char*b) { return Identifier::equal(a, reinterpret_cast<const LChar*>(b)); };
+        static bool equal(const StringImpl*, const LChar*, unsigned length);
         static bool equal(const StringImpl*, const UChar*, unsigned length);
         static bool equal(const StringImpl* a, const StringImpl* b) { return ::equal(a, b); }
 
         static bool equal(const StringImpl*, const UChar*, unsigned length);
         static bool equal(const StringImpl* a, const StringImpl* b) { return ::equal(a, b); }
 
-        static PassRefPtr<StringImpl> add(ExecState*, const char*); // Only to be used with string literals.
+        JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(ExecState*, const char*); // Only to be used with string literals.
         static PassRefPtr<StringImpl> add(JSGlobalData*, const char*); // Only to be used with string literals.
 
     private:
         UString m_string;
         static PassRefPtr<StringImpl> add(JSGlobalData*, const char*); // Only to be used with string literals.
 
     private:
         UString m_string;
-        
+
+        template <typename CharType>
+        ALWAYS_INLINE static uint32_t toUInt32FromCharacters(const CharType* characters, unsigned length, bool& ok);
+
         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 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 bool equal(const Identifier& a, const LChar* b) { return equal(a.m_string.impl(), b); }
 
 
-        static PassRefPtr<StringImpl> add(ExecState*, const UChar*, int length);
-        static PassRefPtr<StringImpl> add(JSGlobalData*, const UChar*, int length);
+        template <typename T> static PassRefPtr<StringImpl> add(JSGlobalData*, const T*, int length);
+        static PassRefPtr<StringImpl> add8(JSGlobalData*, const UChar*, int length);
+        template <typename T> ALWAYS_INLINE static bool canUseSingleCharacterString(T);
 
         static PassRefPtr<StringImpl> add(ExecState* exec, StringImpl* r)
         {
 
         static PassRefPtr<StringImpl> add(ExecState* exec, StringImpl* r)
         {
@@ -108,13 +119,72 @@ namespace JSC {
             return addSlowCase(globalData, r);
         }
 
             return addSlowCase(globalData, r);
         }
 
-        static PassRefPtr<StringImpl> addSlowCase(ExecState*, StringImpl* r);
-        static PassRefPtr<StringImpl> addSlowCase(JSGlobalData*, StringImpl* r);
+        JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> addSlowCase(ExecState*, StringImpl* r);
+        JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> addSlowCase(JSGlobalData*, StringImpl* r);
 
 
-        static void checkCurrentIdentifierTable(ExecState*);
-        static void checkCurrentIdentifierTable(JSGlobalData*);
+        JS_EXPORT_PRIVATE static void checkCurrentIdentifierTable(ExecState*);
+        JS_EXPORT_PRIVATE static void checkCurrentIdentifierTable(JSGlobalData*);
+    };
+
+    template <> ALWAYS_INLINE bool Identifier::canUseSingleCharacterString(LChar)
+    {
+        ASSERT(maxSingleCharacterString == 0xff);
+        return true;
+    }
+
+    template <> ALWAYS_INLINE bool Identifier::canUseSingleCharacterString(UChar c)
+    {
+        return (c <= maxSingleCharacterString);
+    }
+
+    template <typename T>
+    struct CharBuffer {
+        const T* s;
+        unsigned int length;
     };
     
     };
     
+    template <typename T>
+    struct IdentifierCharBufferTranslator {
+        static unsigned hash(const CharBuffer<T>& buf)
+        {
+            return StringHasher::computeHash<T>(buf.s, buf.length);
+        }
+        
+        static bool equal(StringImpl* str, const CharBuffer<T>& buf)
+        {
+            return Identifier::equal(str, buf.s, buf.length);
+        }
+
+        static void translate(StringImpl*& location, const CharBuffer<T>& buf, unsigned hash)
+        {
+            T* d;
+            StringImpl* r = StringImpl::createUninitialized(buf.length, d).leakRef();
+            for (unsigned i = 0; i != buf.length; i++)
+                d[i] = buf.s[i];
+            r->setHash(hash);
+            location = r; 
+        }
+    };
+
+    template <typename T>
+    PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const T* s, int length)
+    {
+        if (length == 1) {
+            T c = s[0];
+            if (canUseSingleCharacterString(c))
+                return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
+        }
+        
+        if (!length)
+            return StringImpl::empty();
+        CharBuffer<T> buf = {s, length}; 
+        HashSet<StringImpl*>::AddResult addResult = globalData->identifierTable->add<CharBuffer<T>, IdentifierCharBufferTranslator<T> >(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.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator;
+    }
+
     inline bool operator==(const Identifier& a, const Identifier& b)
     {
         return Identifier::equal(a, b);
     inline bool operator==(const Identifier& a, const Identifier& b)
     {
         return Identifier::equal(a, b);
@@ -125,25 +195,39 @@ namespace JSC {
         return !Identifier::equal(a, b);
     }
 
         return !Identifier::equal(a, b);
     }
 
-    inline bool operator==(const Identifier& a, const char* b)
+    inline bool operator==(const Identifier& a, const LChar* b)
     {
         return Identifier::equal(a, b);
     }
 
     {
         return Identifier::equal(a, b);
     }
 
-    inline bool operator!=(const Identifier& a, const char* b)
+    inline bool operator==(const Identifier& a, const char* b)
+    {
+        return Identifier::equal(a, reinterpret_cast<const LChar*>(b));
+    }
+    
+    inline bool operator!=(const Identifier& a, const LChar* b)
     {
         return !Identifier::equal(a, b);
     }
 
     {
         return !Identifier::equal(a, b);
     }
 
+    inline bool operator!=(const Identifier& a, const char* b)
+    {
+        return !Identifier::equal(a, reinterpret_cast<const LChar*>(b));
+    }
+    
+    inline bool Identifier::equal(const StringImpl* r, const LChar* s)
+    {
+        return WTF::equal(r, s);
+    }
+
+    inline bool Identifier::equal(const StringImpl* r, const LChar* s, unsigned length)
+    {
+        return WTF::equal(r, s, length);
+    }
+
     inline bool Identifier::equal(const StringImpl* r, const UChar* s, unsigned length)
     {
     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;
+        return WTF::equal(r, s, length);
     }
     
     IdentifierTable* createIdentifierTable();
     }
     
     IdentifierTable* createIdentifierTable();
@@ -154,6 +238,21 @@ namespace JSC {
         static unsigned hash(StringImpl* key) { return key->existingHash(); }
     };
 
         static unsigned hash(StringImpl* key) { return key->existingHash(); }
     };
 
+    struct IdentifierMapIndexHashTraits : HashTraits<int> {
+        static int emptyValue() { return std::numeric_limits<int>::max(); }
+        static const bool emptyValueIsZero = false;
+    };
+
+    typedef HashMap<RefPtr<StringImpl>, int, IdentifierRepHash, HashTraits<RefPtr<StringImpl> >, IdentifierMapIndexHashTraits> IdentifierMap;
+
+    template<typename U, typename V>
+    HashSet<StringImpl*>::AddResult IdentifierTable::add(U value)
+    {
+        HashSet<StringImpl*>::AddResult result = m_table.add<U, V>(value);
+        (*result.iterator)->setIsIdentifier(true);
+        return result;
+    }
+
 } // namespace JSC
 
 #endif // Identifier_h
 } // namespace JSC
 
 #endif // Identifier_h
index 27611b757b34be5c564ce03bb0553ba736e64660..4c0e123a493bf68bcda2d8904a76e0bddde5a9da 100644 (file)
 #include "config.h"
 #include "InitializeThreading.h"
 
 #include "config.h"
 #include "InitializeThreading.h"
 
+#include "ExecutableAllocator.h"
 #include "Heap.h"
 #include "Heap.h"
-#include "dtoa.h"
+#include "Options.h"
 #include "Identifier.h"
 #include "Identifier.h"
+#include "JSDateMath.h"
 #include "JSGlobalObject.h"
 #include "UString.h"
 #include "JSGlobalObject.h"
 #include "UString.h"
-#include <wtf/DateMath.h>
+#include "WriteBarrier.h"
+#include <wtf/dtoa.h>
 #include <wtf/Threading.h>
 #include <wtf/Threading.h>
-#include <wtf/WTFThreadData.h>
+#include <wtf/dtoa/cached-powers.h>
 
 using namespace WTF;
 
 namespace JSC {
 
 
 using namespace WTF;
 
 namespace JSC {
 
-#if OS(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS)
+#if OS(DARWIN)
 static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT;
 #endif
 
 static void initializeThreadingOnce()
 {
 static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT;
 #endif
 
 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::double_conversion::initialize();
     WTF::initializeThreading();
     WTF::initializeThreading();
-    wtfThreadData();
-    JSGlobalData::storeVPtrs();
-#if ENABLE(JSC_MULTIPLE_THREADS)
-    s_dtoaP5Mutex = new Mutex;
-    initializeDates();
-    RegisterFile::initializeThreading();
+    Options::initializeOptions();
+#if ENABLE(WRITE_BARRIER_PROFILING)
+    WriteBarrierCounters::initialize();
 #endif
 #endif
+#if ENABLE(ASSEMBLER)
+    ExecutableAllocator::initializeAllocator();
+#endif
+    RegisterFile::initializeThreading();
 }
 
 void initializeThreading()
 {
 }
 
 void initializeThreading()
 {
-#if OS(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS)
+#if OS(DARWIN)
     pthread_once(&initializeThreadingKeyOnce, initializeThreadingOnce);
 #else
     static bool initializedThreading = false;
     pthread_once(&initializeThreadingKeyOnce, initializeThreadingOnce);
 #else
     static bool initializedThreading = false;
index 1a93ccb9b1a3893319cc0172573c5653dd0672c9..91301a0d8fa66eb71c57454413057851a3d6be15 100644 (file)
@@ -33,7 +33,7 @@ namespace JSC {
 
     // This function must be called from the main thread. It is safe to call it repeatedly.
     // Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly.
 
     // This function must be called from the main thread. It is safe to call it repeatedly.
     // Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly.
-    void initializeThreading();
+    JS_EXPORT_PRIVATE void initializeThreading();
 
 }
 
 
 }
 
index c3b07f8297028e96f2ff503d95178f1ccf98f6ae..50ea504c1a9396d29ee577a37fe5d0a33dd71be9 100644 (file)
 
 namespace JSC {
 
 
 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);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(InternalFunction);
 
 
-const ClassInfo InternalFunction::s_info = { "Function", &JSObjectWithGlobalObject::s_info, 0, 0 };
+const ClassInfo InternalFunction::s_info = { "Function", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(InternalFunction) };
 
 
-InternalFunction::InternalFunction(VPtrStealingHackType)
-    : JSObjectWithGlobalObject(VPtrStealingHack)
+InternalFunction::InternalFunction(JSGlobalObject* globalObject, Structure* structure)
+    : JSNonFinalObject(globalObject->globalData(), structure)
 {
 }
 
 {
 }
 
-InternalFunction::InternalFunction(JSGlobalData* globalData, JSGlobalObject* globalObject, Structure* structure, const Identifier& name)
-    : JSObjectWithGlobalObject(globalObject, structure)
+void InternalFunction::finishCreation(JSGlobalData& globalData, const Identifier& name)
 {
 {
+    Base::finishCreation(globalData);
     ASSERT(inherits(&s_info));
     ASSERT(inherits(&s_info));
-    putDirect(*globalData, globalData->propertyNames->name, jsString(globalData, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
+    ASSERT(methodTable()->getCallData != InternalFunction::s_info.methodTable.getCallData);
+    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)
@@ -57,12 +56,18 @@ const UString InternalFunction::displayName(ExecState* exec)
 {
     JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
     
 {
     JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
     
-    if (displayName && isJSString(&exec->globalData(), displayName))
+    if (displayName && isJSString(displayName))
         return asString(displayName)->tryGetValue();
     
     return UString();
 }
 
         return asString(displayName)->tryGetValue();
     
     return UString();
 }
 
+CallType InternalFunction::getCallData(JSCell*, CallData&)
+{
+    ASSERT_NOT_REACHED();
+    return CallTypeNone;
+}
+
 const UString InternalFunction::calculatedDisplayName(ExecState* exec)
 {
     const UString explicitName = displayName(exec);
 const UString InternalFunction::calculatedDisplayName(ExecState* exec)
 {
     const UString explicitName = displayName(exec);
index 28e260e30130ddd8c0ae796d663337298fe9cfa1..532bd0c8d4b068744c90113272eac83a761a2187 100644 (file)
 #ifndef InternalFunction_h
 #define InternalFunction_h
 
 #ifndef InternalFunction_h
 #define InternalFunction_h
 
-#include "JSObjectWithGlobalObject.h"
+#include "JSObject.h"
 #include "Identifier.h"
 
 namespace JSC {
 
     class FunctionPrototype;
 
 #include "Identifier.h"
 
 namespace JSC {
 
     class FunctionPrototype;
 
-    class InternalFunction : public JSObjectWithGlobalObject {
+    class InternalFunction : public JSNonFinalObject {
     public:
     public:
+        typedef JSNonFinalObject Base;
+
         static JS_EXPORTDATA const ClassInfo s_info;
 
         static JS_EXPORTDATA const ClassInfo s_info;
 
-        const UString& name(ExecState*);
+        JS_EXPORT_PRIVATE const UString& name(ExecState*);
         const UString displayName(ExecState*);
         const UString calculatedDisplayName(ExecState*);
 
         const UString displayName(ExecState*);
         const UString calculatedDisplayName(ExecState*);
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) 
         { 
         { 
-            return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
+            return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info); 
         }
 
     protected:
         static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags;
 
         }
 
     protected:
         static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags;
 
-        // Only used to allow us to determine the JSFunction vptr
-        InternalFunction(VPtrStealingHackType);
-
-        InternalFunction(JSGlobalData*, JSGlobalObject*, Structure*, const Identifier&);
+        JS_EXPORT_PRIVATE InternalFunction(JSGlobalObject*, Structure*);
 
 
-    private:
-        virtual CallType getCallData(CallData&) = 0;
+        JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, const Identifier& name);
 
 
-        virtual void vtableAnchor();
+        static CallType getCallData(JSCell*, CallData&);
     };
 
     InternalFunction* asInternalFunction(JSValue);
     };
 
     InternalFunction* asInternalFunction(JSValue);
diff --git a/runtime/Intrinsic.h b/runtime/Intrinsic.h
new file mode 100644 (file)
index 0000000..73244e7
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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 Intrinsic_h
+#define Intrinsic_h
+
+namespace JSC {
+
+enum Intrinsic {
+    NoIntrinsic,
+    AbsIntrinsic,
+    MinIntrinsic,
+    MaxIntrinsic,
+    SqrtIntrinsic,
+    ArrayPushIntrinsic,
+    ArrayPopIntrinsic,
+    CharCodeAtIntrinsic,
+    CharAtIntrinsic,
+    FromCharCodeIntrinsic,
+    PowIntrinsic,
+    FloorIntrinsic,
+    CeilIntrinsic,
+    RoundIntrinsic,
+    ExpIntrinsic,
+    LogIntrinsic,
+    RegExpExecIntrinsic,
+    RegExpTestIntrinsic,
+};
+
+} // namespace JSC
+
+#endif // Intrinsic_h
index 9a92a9311cea954139a7c0620f89c8c756e7bc57..8517085dfee268f3f4f796b816420d727a24c9f2 100644 (file)
@@ -28,6 +28,8 @@
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo JSAPIValueWrapper::s_info = { "API Wrapper", 0, 0, 0 };
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSAPIValueWrapper);
+
+const ClassInfo JSAPIValueWrapper::s_info = { "API Wrapper", 0, 0, 0, CREATE_METHOD_TABLE(JSAPIValueWrapper) };
 
 } // namespace JSC
 
 } // namespace JSC
index 38cbb569e3691eadd8fe1a3289f5285e8d1b0cce..21d7b215cb493a840854c2d0ef1e3346d3575e28 100644 (file)
@@ -24,6 +24,7 @@
 #define JSAPIValueWrapper_h
 
 #include "JSCell.h"
 #define JSAPIValueWrapper_h
 
 #include "JSCell.h"
+#include "JSValue.h"
 #include "CallFrame.h"
 #include "Structure.h"
 
 #include "CallFrame.h"
 #include "Structure.h"
 
@@ -32,31 +33,44 @@ namespace JSC {
     class JSAPIValueWrapper : public JSCell {
         friend JSValue jsAPIValueWrapper(ExecState*, JSValue);
     public:
     class JSAPIValueWrapper : public JSCell {
         friend JSValue jsAPIValueWrapper(ExecState*, JSValue);
     public:
-        JSValue value() const { return m_value.get(); }
+        typedef JSCell Base;
 
 
-        virtual bool isAPIValueWrapper() const { return true; }
+        JSValue value() const { return m_value.get(); }
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesVisitChildren | OverridesGetPropertyNames), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(APIValueWrapperType, OverridesVisitChildren | OverridesGetPropertyNames), &s_info);
         }
         
         }
         
-        static const ClassInfo s_info;
+        static JS_EXPORTDATA const ClassInfo s_info;
+        
+        static JSAPIValueWrapper* create(ExecState* exec, JSValue value) 
+        {
+            JSAPIValueWrapper* wrapper = new (NotNull, allocateCell<JSAPIValueWrapper>(*exec->heap())) JSAPIValueWrapper(exec);
+            wrapper->finishCreation(exec, value);
+            return wrapper;
+        }
 
 
-    private:
-        JSAPIValueWrapper(ExecState* exec, JSValue value)
-            : JSCell(exec->globalData(), exec->globalData().apiWrapperStructure.get())
+    protected:
+        void finishCreation(ExecState* exec, JSValue value)
         {
         {
+            Base::finishCreation(exec->globalData());
             m_value.set(exec->globalData(), this, value);
             ASSERT(!value.isCell());
         }
 
             m_value.set(exec->globalData(), this, value);
             ASSERT(!value.isCell());
         }
 
+    private:
+        JSAPIValueWrapper(ExecState* exec)
+            : JSCell(exec->globalData(), exec->globalData().apiWrapperStructure.get())
+        {
+        }
+
         WriteBarrier<Unknown> m_value;
     };
 
     inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue value)
     {
         WriteBarrier<Unknown> m_value;
     };
 
     inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue value)
     {
-        return new (exec) JSAPIValueWrapper(exec, value);
+        return JSAPIValueWrapper::create(exec, value);
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
index 09d985afbcfb593d5fbd04599a2a682b5f17f05d..a103610073268b12366807021590b0d4657fa212 100644 (file)
 #include "Interpreter.h"
 #include "JSFunction.h"
 
 #include "Interpreter.h"
 #include "JSFunction.h"
 
+using namespace std;
+
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSActivation);
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSActivation);
 
-const ClassInfo JSActivation::s_info = { "JSActivation", &Base::s_info, 0, 0 };
+const ClassInfo JSActivation::s_info = { "JSActivation", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSActivation) };
 
 JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable)
     : Base(callFrame->globalData(), callFrame->globalData().activationStructure.get(), functionExecutable->symbolTable(), callFrame->registers())
 
 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_numCapturedArgs(max(callFrame->argumentCount(), functionExecutable->parameterCount()))
     , m_numCapturedVars(functionExecutable->capturedVariableCount())
     , m_numCapturedVars(functionExecutable->capturedVariableCount())
-    , m_requiresDynamicChecks(functionExecutable->usesEval())
+    , m_isTornOff(false)
+    , m_requiresDynamicChecks(functionExecutable->usesEval() && !functionExecutable->isStrictMode())
     , m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister())
 {
     , m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister())
 {
+}
+
+void JSActivation::finishCreation(CallFrame* callFrame)
+{
+    Base::finishCreation(callFrame->globalData());
     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();
     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();
+    callFrame->globalData().heap.addFinalizer(this, &finalize);
 }
 
 }
 
-JSActivation::~JSActivation()
+void JSActivation::finalize(JSCell* cell)
 {
 {
-    static_cast<SharedSymbolTable*>(m_symbolTable)->deref();
+    static_cast<SharedSymbolTable*>(jsCast<JSActivation*>(cell)->m_symbolTable)->deref();
 }
 
 }
 
-void JSActivation::visitChildren(SlotVisitor& visitor)
+void JSActivation::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    JSActivation* thisObject = jsCast<JSActivation*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
-    Base::visitChildren(visitor);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    Base::visitChildren(thisObject, visitor);
 
     // No need to mark our registers if they're still in the RegisterFile.
 
     // No need to mark our registers if they're still in the RegisterFile.
-    WriteBarrier<Unknown>* registerArray = m_registerArray.get();
+    WriteBarrier<Unknown>* registerArray = thisObject->m_registerArray.get();
     if (!registerArray)
         return;
     if (!registerArray)
         return;
+    
+    visitor.appendValues(registerArray, thisObject->m_numCapturedArgs);
 
 
-    visitor.appendValues(registerArray, m_numParametersMinusThis);
-
-    // Skip the call frame, which sits between the parameters and vars.
-    visitor.appendValues(registerArray + m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize, m_numCapturedVars, MayContainNullValues);
+    // Skip 'this' and call frame, except for callee and scope chain.
+    int offset = CallFrame::offsetFor(thisObject->m_numCapturedArgs + 1);
+    visitor.append(registerArray + offset + RegisterFile::ScopeChain);
+    visitor.append(registerArray + offset + RegisterFile::Callee);
+    
+    visitor.appendValues(registerArray + offset, thisObject->m_numCapturedVars);
 }
 
 inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
 }
 
 inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
@@ -81,41 +95,46 @@ inline bool JSActivation::symbolTableGet(const Identifier& propertyName, Propert
     SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
     if (entry.isNull())
         return false;
     SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
     if (entry.isNull())
         return false;
-    if (entry.getIndex() >= m_numCapturedVars)
+    if (m_isTornOff && entry.getIndex() >= m_numCapturedVars)
         return false;
 
     slot.setValue(registerAt(entry.getIndex()).get());
     return true;
 }
 
         return false;
 
     slot.setValue(registerAt(entry.getIndex()).get());
     return true;
 }
 
-inline bool JSActivation::symbolTablePut(JSGlobalData& globalData, const Identifier& propertyName, JSValue value)
+inline bool JSActivation::symbolTablePut(ExecState* exec, const Identifier& propertyName, JSValue value, bool shouldThrow)
 {
 {
+    JSGlobalData& globalData = exec->globalData();
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
     
     SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
     if (entry.isNull())
         return false;
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
     
     SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
     if (entry.isNull())
         return false;
-    if (entry.isReadOnly())
+    if (entry.isReadOnly()) {
+        if (shouldThrow)
+            throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
         return true;
         return true;
-    if (entry.getIndex() >= m_numCapturedVars)
+    }
+    if (m_isTornOff && entry.getIndex() >= m_numCapturedVars)
         return false;
 
     registerAt(entry.getIndex()).set(globalData, this, value);
     return true;
 }
 
         return false;
 
     registerAt(entry.getIndex()).set(globalData, this, value);
     return true;
 }
 
-void JSActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void JSActivation::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
-    SymbolTable::const_iterator end = symbolTable().end();
-    for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
+    JSActivation* thisObject = jsCast<JSActivation*>(object);
+    SymbolTable::const_iterator end = thisObject->symbolTable().end();
+    for (SymbolTable::const_iterator it = thisObject->symbolTable().begin(); it != end; ++it) {
         if (it->second.getAttributes() & DontEnum && mode != IncludeDontEnumProperties)
             continue;
         if (it->second.getAttributes() & DontEnum && mode != IncludeDontEnumProperties)
             continue;
-        if (it->second.getIndex() >= m_numCapturedVars)
+        if (it->second.getIndex() >= thisObject->m_numCapturedVars)
             continue;
         propertyNames.add(Identifier(exec, it->first.get()));
     }
     // Skip the JSVariableObject implementation of getOwnPropertyNames
             continue;
         propertyNames.add(Identifier(exec, it->first.get()));
     }
     // Skip the JSVariableObject implementation of getOwnPropertyNames
-    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+    JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
 }
 
 inline bool JSActivation::symbolTablePutWithAttributes(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
 }
 
 inline bool JSActivation::symbolTablePutWithAttributes(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
@@ -135,82 +154,73 @@ inline bool JSActivation::symbolTablePutWithAttributes(JSGlobalData& globalData,
     return true;
 }
 
     return true;
 }
 
-bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+bool JSActivation::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
+    JSActivation* thisObject = jsCast<JSActivation*>(cell);
     if (propertyName == exec->propertyNames().arguments) {
     if (propertyName == exec->propertyNames().arguments) {
-        slot.setCustom(thisgetArgumentsGetter());
+        slot.setCustom(thisObject, thisObject->getArgumentsGetter());
         return true;
     }
 
         return true;
     }
 
-    if (symbolTableGet(propertyName, slot))
+    if (thisObject->symbolTableGet(propertyName, slot))
         return true;
 
         return true;
 
-    if (WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName)) {
+    if (WriteBarrierBase<Unknown>* location = thisObject->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.
         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());
-    ASSERT(prototype().isNull());
+    ASSERT(!thisObject->hasGetterSetterProperties());
+    ASSERT(thisObject->prototype().isNull());
     return false;
 }
 
     return false;
 }
 
-void JSActivation::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void JSActivation::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
-    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+    JSActivation* thisObject = jsCast<JSActivation*>(cell);
+    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
 
 
-    if (symbolTablePut(exec->globalData(), propertyName, value))
+    if (thisObject->symbolTablePut(exec, propertyName, value, slot.isStrictMode()))
         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.
         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(exec->globalData(), propertyName, value, 0, true, slot);
+    ASSERT(!thisObject->hasGetterSetterProperties());
+    thisObject->putOwnDataProperty(exec->globalData(), propertyName, value, slot);
 }
 
 // FIXME: Make this function honor ReadOnly (const) and DontEnum
 }
 
 // FIXME: Make this function honor ReadOnly (const) and DontEnum
-void JSActivation::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
+void JSActivation::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
 {
-    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+    JSActivation* thisObject = jsCast<JSActivation*>(object);
+    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
 
 
-    if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
+    if (thisObject->symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
         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.
         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());
-    PutPropertySlot slot;
-    JSObject::putWithAttributes(exec, propertyName, value, attributes, true, slot);
+    ASSERT(!thisObject->hasGetterSetterProperties());
+    JSObject::putDirectVirtual(thisObject, exec, propertyName, value, attributes);
 }
 
 }
 
-bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName)
+bool JSActivation::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
 {
     if (propertyName == exec->propertyNames().arguments)
         return false;
 
 {
     if (propertyName == exec->propertyNames().arguments)
         return false;
 
-    return Base::deleteProperty(exec, propertyName);
+    return Base::deleteProperty(cell, exec, propertyName);
 }
 
 }
 
-JSObject* JSActivation::toThisObject(ExecState* exec) const
+JSObject* JSActivation::toThisObject(JSCell*, ExecState* exec)
 {
     return exec->globalThisValue();
 }
 
 {
     return exec->globalThisValue();
 }
 
-JSValue JSActivation::toStrictThisObject(ExecState*) const
-{
-    return jsNull();
-}
-    
-bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const
-{
-    requiresDynamicChecks = m_requiresDynamicChecks;
-    return false;
-}
-
 JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identifier&)
 {
     JSActivation* activation = asActivation(slotBase);
 JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identifier&)
 {
     JSActivation* activation = asActivation(slotBase);
@@ -220,7 +230,7 @@ JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identi
         return arguments;
     int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
 
         return arguments;
     int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
 
-    JSValue arguments = JSValue(new (callFrame) Arguments(callFrame));
+    JSValue arguments = JSValue(Arguments::create(callFrame->globalData(), callFrame));
     callFrame->uncheckedR(argumentsRegister) = arguments;
     callFrame->uncheckedR(realArgumentsRegister) = arguments;
     
     callFrame->uncheckedR(argumentsRegister) = arguments;
     callFrame->uncheckedR(realArgumentsRegister) = arguments;
     
index 5f4c9351c5e3dee41ea10ddb6a87a34aa4d2dd8a..fd1b2fd7f314ab7f4366e0ac8a80d3ba58c4b637 100644 (file)
@@ -40,49 +40,60 @@ namespace JSC {
     class Register;
     
     class JSActivation : public JSVariableObject {
     class Register;
     
     class JSActivation : public JSVariableObject {
-        typedef JSVariableObject Base;
-    public:
+    private:
         JSActivation(CallFrame*, FunctionExecutable*);
         JSActivation(CallFrame*, FunctionExecutable*);
-        virtual ~JSActivation();
+    
+    public:
+        typedef JSVariableObject Base;
+
+        static JSActivation* create(JSGlobalData& globalData, CallFrame* callFrame, FunctionExecutable* funcExec)
+        {
+            JSActivation* activation = new (NotNull, allocateCell<JSActivation>(globalData.heap)) JSActivation(callFrame, funcExec);
+            activation->finishCreation(callFrame);
+            return activation;
+        }
 
 
-        virtual void visitChildren(SlotVisitor&);
+        static void finalize(JSCell*);
 
 
-        virtual bool isDynamicScope(bool& requiresDynamicChecks) const;
+        static void visitChildren(JSCell*, SlotVisitor&);
 
 
-        virtual bool isActivationObject() const { return true; }
+        bool isDynamicScope(bool& requiresDynamicChecks) const;
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
 
 
-        virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+        static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
 
 
-        virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes);
-        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+        static void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
+        static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
 
 
-        virtual JSObject* toThisObject(ExecState*) const;
-        virtual JSValue toStrictThisObject(ExecState*) const;
+        static JSObject* toThisObject(JSCell*, ExecState*);
 
 
-        void copyRegisters(JSGlobalData&);
+        void tearOff(JSGlobalData&);
         
         static const ClassInfo s_info;
 
         
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); }
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(ActivationObjectType, StructureFlags), &s_info); }
+
+        bool isValidScopedLookup(int index) { return index < m_numCapturedVars; }
 
     protected:
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
+        void finishCreation(CallFrame*);
+        static const unsigned StructureFlags = IsEnvironmentRecord | OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
 
     private:
         bool symbolTableGet(const Identifier&, PropertySlot&);
         bool symbolTableGet(const Identifier&, PropertyDescriptor&);
         bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
 
     private:
         bool symbolTableGet(const Identifier&, PropertySlot&);
         bool symbolTableGet(const Identifier&, PropertyDescriptor&);
         bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
-        bool symbolTablePut(JSGlobalData&, const Identifier&, JSValue);
+        bool symbolTablePut(ExecState*, const Identifier&, JSValue, bool shouldThrow);
         bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes);
 
         static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
         NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
 
         bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes);
 
         static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
         NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
 
-        int m_numParametersMinusThis;
-        int m_numCapturedVars : 31;
+        int m_numCapturedArgs;
+        int m_numCapturedVars : 30;
+        bool m_isTornOff : 1;
         bool m_requiresDynamicChecks : 1;
         int m_argumentsRegister;
     };
         bool m_requiresDynamicChecks : 1;
         int m_argumentsRegister;
     };
@@ -92,7 +103,7 @@ namespace JSC {
     inline JSActivation* asActivation(JSValue value)
     {
         ASSERT(asObject(value)->inherits(&JSActivation::s_info));
     inline JSActivation* asActivation(JSValue value)
     {
         ASSERT(asObject(value)->inherits(&JSActivation::s_info));
-        return static_cast<JSActivation*>(asObject(value));
+        return jsCast<JSActivation*>(asObject(value));
     }
     
     ALWAYS_INLINE JSActivation* Register::activation() const
     }
     
     ALWAYS_INLINE JSActivation* Register::activation() const
@@ -100,6 +111,32 @@ namespace JSC {
         return asActivation(jsValue());
     }
 
         return asActivation(jsValue());
     }
 
+    inline bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const
+    {
+        requiresDynamicChecks = m_requiresDynamicChecks;
+        return false;
+    }
+
+    inline void JSActivation::tearOff(JSGlobalData& globalData)
+    {
+        ASSERT(!m_registerArray);
+        ASSERT(m_numCapturedVars + m_numCapturedArgs);
+
+        int registerOffset = CallFrame::offsetFor(m_numCapturedArgs + 1);
+        size_t registerArraySize = registerOffset + m_numCapturedVars;
+
+        OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
+        WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset;
+
+        int from = CallFrame::argumentOffset(m_numCapturedArgs - 1);
+        int to = m_numCapturedVars;
+        for (int i = from; i < to; ++i)
+            registers[i].set(globalData, this, m_registers[i].get());
+
+        setRegisters(registers, registerArray.release());
+        m_isTornOff = true;
+    }
+
 } // namespace JSC
 
 #endif // JSActivation_h
 } // namespace JSC
 
 #endif // JSActivation_h
index 473ba1d3eec4973a48a2131dc1c36faf284fe74f..aa1b8b7d981cfc652f6921cd47982848b83f99a0 100644 (file)
 #include "JSArray.h"
 
 #include "ArrayPrototype.h"
 #include "JSArray.h"
 
 #include "ArrayPrototype.h"
+#include "CopiedSpace.h"
+#include "CopiedSpaceInlineMethods.h"
 #include "CachedCall.h"
 #include "Error.h"
 #include "Executable.h"
 #include "CachedCall.h"
 #include "Error.h"
 #include "Executable.h"
+#include "GetterSetter.h"
 #include "PropertyNameArray.h"
 #include <wtf/AVLTree.h>
 #include <wtf/Assertions.h>
 #include "PropertyNameArray.h"
 #include <wtf/AVLTree.h>
 #include <wtf/Assertions.h>
@@ -38,7 +41,9 @@ using namespace WTF;
 
 namespace JSC {
 
 
 namespace JSC {
 
+
 ASSERT_CLASS_FITS_IN_CELL(JSArray);
 ASSERT_CLASS_FITS_IN_CELL(JSArray);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSArray);
 
 // Overview of JSArray
 //
 
 // Overview of JSArray
 //
@@ -57,7 +62,8 @@ ASSERT_CLASS_FITS_IN_CELL(JSArray);
 // storage vector or the sparse map.  An array index i will be handled in the following
 // fashion:
 //
 // storage vector or the sparse map.  An array index i will be handled in the following
 // fashion:
 //
-//   * Where (i < MIN_SPARSE_ARRAY_INDEX) the value will be stored in the storage vector.
+//   * Where (i < MIN_SPARSE_ARRAY_INDEX) the value will be stored in the storage vector,
+//     unless the array is in SparseMode in which case all properties go into the map.
 //   * Where (MIN_SPARSE_ARRAY_INDEX <= i <= MAX_STORAGE_VECTOR_INDEX) the value will either
 //     be stored in the storage vector or in the sparse array, depending on the density of
 //     data that would be stored in the vector (a vector being used where at least
 //   * Where (MIN_SPARSE_ARRAY_INDEX <= i <= MAX_STORAGE_VECTOR_INDEX) the value will either
 //     be stored in the storage vector or in the sparse array, depending on the density of
 //     data that would be stored in the vector (a vector being used where at least
@@ -67,9 +73,9 @@ ASSERT_CLASS_FITS_IN_CELL(JSArray);
 
 // The definition of MAX_STORAGE_VECTOR_LENGTH is dependant on the definition storageSize
 // function below - the MAX_STORAGE_VECTOR_LENGTH limit is defined such that the storage
 
 // The definition of MAX_STORAGE_VECTOR_LENGTH is dependant on the definition storageSize
 // function below - the MAX_STORAGE_VECTOR_LENGTH limit is defined such that the storage
-// size calculation cannot overflow.  (sizeof(ArrayStorage) - sizeof(JSValue)) +
-// (vectorLength * sizeof(JSValue)) must be <= 0xFFFFFFFFU (which is maximum value of size_t).
-#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(JSValue))) / sizeof(JSValue))
+// size calculation cannot overflow.  (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) +
+// (vectorLength * sizeof(WriteBarrier<Unknown>)) must be <= 0xFFFFFFFFU (which is maximum value of size_t).
+#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>))
 
 // These values have to be macros to be used in max() and min() without introducing
 // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
 
 // These values have to be macros to be used in max() and min() without introducing
 // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
@@ -92,31 +98,23 @@ ASSERT_CLASS_FITS_IN_CELL(JSArray);
 // as long as it is 1/8 full. If more sparse than that, we use a map.
 static const unsigned minDensityMultiplier = 8;
 
 // 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::s_info = {"Array", &JSNonFinalObject::s_info, 0, 0};
+const ClassInfo JSArray::s_info = {"Array", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSArray)};
 
 // 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;
 
 
 // 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 bool isDenseEnoughForVector(unsigned length, unsigned numValues)
 {
 {
-    if (vectorLength > MAX_STORAGE_VECTOR_LENGTH)
-        CRASH();
-
-    // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH)
-    // - as asserted above - the following calculation cannot overflow.
-    size_t size = (sizeof(ArrayStorage) - sizeof(JSValue)) + (vectorLength * sizeof(JSValue));
-    // Assertion to detect integer overflow in previous calculation (should not be possible, provided that
-    // MAX_STORAGE_VECTOR_LENGTH is correctly defined).
-    ASSERT(((size - (sizeof(ArrayStorage) - sizeof(JSValue))) / sizeof(JSValue) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(JSValue))));
-
-    return size;
+    return length <= MIN_SPARSE_ARRAY_INDEX || length / minDensityMultiplier <= numValues;
 }
 
 }
 
-static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues)
+static bool reject(ExecState* exec, bool throwException, const char* message)
 {
 {
-    return length / minDensityMultiplier <= numValues;
+    if (throwException)
+        throwTypeError(exec, message);
+    return false;
 }
 
 #if !CHECK_ARRAY_CONSISTENCY
 }
 
 #if !CHECK_ARRAY_CONSISTENCY
@@ -127,433 +125,884 @@ inline void JSArray::checkConsistency(ConsistencyCheckType)
 
 #endif
 
 
 #endif
 
-JSArray::JSArray(VPtrStealingHackType)
-    : JSNonFinalObject(VPtrStealingHack)
-{
-}
-
-JSArray::JSArray(JSGlobalData& globalData, Structure* structure)
-    : JSNonFinalObject(globalData, structure)
+void JSArray::finishCreation(JSGlobalData& globalData, unsigned initialLength)
 {
 {
+    Base::finishCreation(globalData);
     ASSERT(inherits(&s_info));
 
     ASSERT(inherits(&s_info));
 
-    unsigned initialCapacity = 0;
+    unsigned initialVectorLength = BASE_VECTOR_LEN;
+    unsigned initialStorageSize = storageSize(initialVectorLength);
 
 
-    m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
+    void* newStorage = 0;
+    if (!globalData.heap.tryAllocateStorage(initialStorageSize, &newStorage))
+        CRASH();
+    
+    m_storage = static_cast<ArrayStorage*>(newStorage);
     m_storage->m_allocBase = m_storage;
     m_storage->m_allocBase = m_storage;
-    m_indexBias = 0;
-    m_vectorLength = initialCapacity;
+    m_storage->m_length = initialLength;
+    m_vectorLength = initialVectorLength;
+    m_storage->m_numValuesInVector = 0;
+#if CHECK_ARRAY_CONSISTENCY
+    m_storage->m_inCompactInitialization = false;
+#endif
 
     checkConsistency();
 
     checkConsistency();
-
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(0));
 }
 
 }
 
-JSArray::JSArray(JSGlobalData& globalData, Structure* structure, unsigned initialLength, ArrayCreationMode creationMode)
-    : JSNonFinalObject(globalData, structure)
+JSArray* JSArray::tryFinishCreationUninitialized(JSGlobalData& globalData, unsigned initialLength)
 {
 {
+    Base::finishCreation(globalData);
     ASSERT(inherits(&s_info));
 
     ASSERT(inherits(&s_info));
 
-    unsigned initialCapacity;
-    if (creationMode == CreateCompact)
-        initialCapacity = initialLength;
-    else
-        initialCapacity = min(BASE_VECTOR_LEN, MIN_SPARSE_ARRAY_INDEX);
+    // Check for lengths larger than we can handle with a vector.
+    if (initialLength > MAX_STORAGE_VECTOR_LENGTH)
+        return 0;
+
+    unsigned initialVectorLength = max(initialLength, BASE_VECTOR_LEN);
+    unsigned initialStorageSize = storageSize(initialVectorLength);
+
+    void* newStorage = 0;
+    if (!globalData.heap.tryAllocateStorage(initialStorageSize, &newStorage))
+        CRASH();
     
     
-    m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
+    m_storage = static_cast<ArrayStorage*>(newStorage);
     m_storage->m_allocBase = m_storage;
     m_storage->m_length = initialLength;
     m_storage->m_allocBase = m_storage;
     m_storage->m_length = initialLength;
-    m_indexBias = 0;
-    m_vectorLength = initialCapacity;
-    m_storage->m_sparseValueMap = 0;
-    m_storage->subclassData = 0;
-    m_storage->reportedMapCapacity = 0;
+    m_vectorLength = initialVectorLength;
+    m_storage->m_numValuesInVector = initialLength;
 
 
-    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
 #if CHECK_ARRAY_CONSISTENCY
-        storage->m_inCompactInitialization = false;
+    m_storage->m_initializationIndex = 0;
+    m_storage->m_inCompactInitialization = true;
 #endif
 #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();
+
+    return this;
+}
+
+// This function can be called multiple times on the same object.
+void JSArray::finalize(JSCell* cell)
+{
+    JSArray* thisObject = jsCast<JSArray*>(cell);
+    thisObject->checkConsistency(DestructorConsistencyCheck);
+    thisObject->deallocateSparseMap();
+}
+
+inline SparseArrayValueMap::AddResult SparseArrayValueMap::add(JSArray* array, unsigned i)
+{
+    SparseArrayEntry entry;
+    entry.setWithoutWriteBarrier(jsUndefined());
+
+    AddResult result = m_map.add(i, entry);
+    size_t capacity = m_map.capacity();
+    if (capacity != m_reportedCapacity) {
+        Heap::heap(array)->reportExtraMemoryCost((capacity - m_reportedCapacity) * (sizeof(unsigned) + sizeof(WriteBarrier<Unknown>)));
+        m_reportedCapacity = capacity;
     }
     }
+    return result;
+}
 
 
-    checkConsistency();
+inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i, JSValue value, bool shouldThrow)
+{
+    AddResult result = add(array, i);
+    SparseArrayEntry& entry = result.iterator->second;
+
+    // To save a separate find & add, we first always add to the sparse map.
+    // In the uncommon case that this is a new property, and the array is not
+    // extensible, this is not the right thing to have done - so remove again.
+    if (result.isNewEntry && !array->isExtensible()) {
+        remove(result.iterator);
+        if (shouldThrow)
+            throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+        return;
+    }
+
+    if (!(entry.attributes & Accessor)) {
+        if (entry.attributes & ReadOnly) {
+            if (shouldThrow)
+                throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+            return;
+        }
+
+        entry.set(exec->globalData(), array, value);
+        return;
+    }
+
+    JSValue accessor = entry.Base::get();
+    ASSERT(accessor.isGetterSetter());
+    JSObject* setter = asGetterSetter(accessor)->setter();
     
     
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity));
+    if (!setter) {
+        if (shouldThrow)
+            throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+        return;
+    }
+
+    CallData callData;
+    CallType callType = setter->methodTable()->getCallData(setter, callData);
+    MarkedArgumentBuffer args;
+    args.append(value);
+    call(exec, setter, callType, callData, array, args);
 }
 
 }
 
-JSArray::JSArray(JSGlobalData& globalData, Structure* structure, const ArgList& list)
-    : JSNonFinalObject(globalData, structure)
+inline bool SparseArrayValueMap::putDirect(ExecState* exec, JSArray* array, unsigned i, JSValue value, bool shouldThrow)
 {
 {
-    ASSERT(inherits(&s_info));
+    AddResult result = add(array, i);
+    SparseArrayEntry& entry = result.iterator->second;
+
+    // To save a separate find & add, we first always add to the sparse map.
+    // In the uncommon case that this is a new property, and the array is not
+    // extensible, this is not the right thing to have done - so remove again.
+    if (result.isNewEntry && !array->isExtensible()) {
+        remove(result.iterator);
+        return reject(exec, shouldThrow, "Attempting to define property on object that is not extensible.");
+    }
 
 
-    unsigned initialCapacity = list.size();
-    unsigned initialStorage;
-    
-    // If the ArgList is empty, allocate space for 3 entries.  This value empirically
-    // works well for benchmarks.
-    if (!initialCapacity)
-        initialStorage = 3;
-    else
-        initialStorage = initialCapacity;
-    
-    m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialStorage)));
-    m_storage->m_allocBase = m_storage;
-    m_indexBias = 0;
-    m_storage->m_length = initialCapacity;
-    m_vectorLength = initialStorage;
-    m_storage->m_numValuesInVector = initialCapacity;
-    m_storage->m_sparseValueMap = 0;
-    m_storage->subclassData = 0;
-    m_storage->reportedMapCapacity = 0;
-#if CHECK_ARRAY_CONSISTENCY
-    m_storage->m_inCompactInitialization = false;
-#endif
+    entry.attributes = 0;
+    entry.set(exec->globalData(), array, value);
+    return true;
+}
 
 
-    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)
-        vector[i].set(globalData, this, *it);
-    for (; i < initialStorage; i++)
-        vector[i].clear();
+inline void SparseArrayEntry::get(PropertySlot& slot) const
+{
+    JSValue value = Base::get();
+    ASSERT(value);
 
 
-    checkConsistency();
+    if (LIKELY(!value.isGetterSetter())) {
+        slot.setValue(value);
+        return;
+    }
 
 
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(initialStorage));
+    JSObject* getter = asGetterSetter(value)->getter();
+    if (!getter) {
+        slot.setUndefined();
+        return;
+    }
+
+    slot.setGetterSlot(getter);
 }
 
 }
 
-JSArray::~JSArray()
+inline void SparseArrayEntry::get(PropertyDescriptor& descriptor) const
 {
 {
-    ASSERT(vptr() == JSGlobalData::jsArrayVPtr);
-    checkConsistency(DestructorConsistencyCheck);
+    descriptor.setDescriptor(Base::get(), attributes);
+}
+
+inline JSValue SparseArrayEntry::get(ExecState* exec, JSArray* array) const
+{
+    JSValue result = Base::get();
+    ASSERT(result);
+
+    if (LIKELY(!result.isGetterSetter()))
+        return result;
 
 
-    delete m_storage->m_sparseValueMap;
-    fastFree(m_storage->m_allocBase);
+    JSObject* getter = asGetterSetter(result)->getter();
+    if (!getter)
+        return jsUndefined();
+
+    CallData callData;
+    CallType callType = getter->methodTable()->getCallData(getter, callData);
+    return call(exec, getter, callType, callData, array, exec->emptyList());
+}
+
+inline JSValue SparseArrayEntry::getNonSparseMode() const
+{
+    ASSERT(!attributes);
+    return Base::get();
 }
 
 }
 
-bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
+inline void SparseArrayValueMap::visitChildren(SlotVisitor& visitor)
+{
+    iterator end = m_map.end();
+    for (iterator it = m_map.begin(); it != end; ++it)
+        visitor.append(&it->second);
+}
+
+void JSArray::allocateSparseMap(JSGlobalData& globalData)
+{
+    m_sparseValueMap = new SparseArrayValueMap;
+    globalData.heap.addFinalizer(this, finalize);
+}
+
+void JSArray::deallocateSparseMap()
+{
+    delete m_sparseValueMap;
+    m_sparseValueMap = 0;
+}
+
+void JSArray::enterDictionaryMode(JSGlobalData& globalData)
 {
     ArrayStorage* storage = m_storage;
 {
     ArrayStorage* storage = m_storage;
+    SparseArrayValueMap* map = m_sparseValueMap;
+
+    if (!map) {
+        allocateSparseMap(globalData);
+        map = m_sparseValueMap;
+    }
+
+    if (map->sparseMode())
+        return;
+
+    map->setSparseMode();
+
+    unsigned usedVectorLength = min(storage->m_length, m_vectorLength);
+    for (unsigned i = 0; i < usedVectorLength; ++i) {
+        JSValue value = storage->m_vector[i].get();
+        // This will always be a new entry in the map, so no need to check we can write,
+        // and attributes are default so no need to set them.
+        if (value)
+            map->add(this, i).iterator->second.set(globalData, this, value);
+    }
+
+    void* newRawStorage = 0;
+    if (!globalData.heap.tryAllocateStorage(storageSize(0), &newRawStorage))
+        CRASH();
     
     
+    ArrayStorage* newStorage = static_cast<ArrayStorage*>(newRawStorage);
+    memcpy(newStorage, m_storage, storageSize(0));
+    newStorage->m_allocBase = newStorage;
+    m_storage = newStorage;
+    m_indexBias = 0;
+    m_vectorLength = 0;
+}
+
+void JSArray::putDescriptor(ExecState* exec, SparseArrayEntry* entryInMap, PropertyDescriptor& descriptor, PropertyDescriptor& oldDescriptor)
+{
+    if (descriptor.isDataDescriptor()) {
+        if (descriptor.value())
+            entryInMap->set(exec->globalData(), this, descriptor.value());
+        else if (oldDescriptor.isAccessorDescriptor())
+            entryInMap->set(exec->globalData(), this, jsUndefined());
+        entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor) & ~Accessor;
+        return;
+    }
+
+    if (descriptor.isAccessorDescriptor()) {
+        JSObject* getter = 0;
+        if (descriptor.getterPresent())
+            getter = descriptor.getterObject();
+        else if (oldDescriptor.isAccessorDescriptor())
+            getter = oldDescriptor.getterObject();
+        JSObject* setter = 0;
+        if (descriptor.setterPresent())
+            setter = descriptor.setterObject();
+        else if (oldDescriptor.isAccessorDescriptor())
+            setter = oldDescriptor.setterObject();
+
+        GetterSetter* accessor = GetterSetter::create(exec);
+        if (getter)
+            accessor->setGetter(exec->globalData(), getter);
+        if (setter)
+            accessor->setSetter(exec->globalData(), setter);
+
+        entryInMap->set(exec->globalData(), this, accessor);
+        entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor) & ~ReadOnly;
+        return;
+    }
+
+    ASSERT(descriptor.isGenericDescriptor());
+    entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor);
+}
+
+// Defined in ES5.1 8.12.9
+bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, PropertyDescriptor& descriptor, bool throwException)
+{
+    ASSERT(index != 0xFFFFFFFF);
+
+    if (!inSparseMode()) {
+        // Fast case: we're putting a regular property to a regular array
+        // FIXME: this will pessimistically assume that if attributes are missing then they'll default to false
+        // â€“ however if the property currently exists missing attributes will override from their current 'true'
+        // state (i.e. defineOwnProperty could be used to set a value without needing to entering 'SparseMode').
+        if (!descriptor.attributes()) {
+            ASSERT(!descriptor.isAccessorDescriptor());
+            return putDirectIndex(exec, index, descriptor.value(), throwException);
+        }
+
+        enterDictionaryMode(exec->globalData());
+    }
+
+    SparseArrayValueMap* map = m_sparseValueMap;
+    ASSERT(map);
+
+    // 1. Let current be the result of calling the [[GetOwnProperty]] internal method of O with property name P.
+    SparseArrayValueMap::AddResult result = map->add(this, index);
+    SparseArrayEntry* entryInMap = &result.iterator->second;
+
+    // 2. Let extensible be the value of the [[Extensible]] internal property of O.
+    // 3. If current is undefined and extensible is false, then Reject.
+    // 4. If current is undefined and extensible is true, then
+    if (result.isNewEntry) {
+        if (!isExtensible()) {
+            map->remove(result.iterator);
+            return reject(exec, throwException, "Attempting to define property on object that is not extensible.");
+        }
+
+        // 4.a. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then create an own data property
+        // named P of object O whose [[Value]], [[Writable]], [[Enumerable]] and [[Configurable]] attribute values
+        // are described by Desc. If the value of an attribute field of Desc is absent, the attribute of the newly
+        // created property is set to its default value.
+        // 4.b. Else, Desc must be an accessor Property Descriptor so, create an own accessor property named P of
+        // object O whose [[Get]], [[Set]], [[Enumerable]] and [[Configurable]] attribute values are described by
+        // Desc. If the value of an attribute field of Desc is absent, the attribute of the newly created property
+        // is set to its default value.
+        // 4.c. Return true.
+
+        PropertyDescriptor defaults;
+        entryInMap->setWithoutWriteBarrier(jsUndefined());
+        entryInMap->attributes = DontDelete | DontEnum | ReadOnly;
+        entryInMap->get(defaults);
+
+        putDescriptor(exec, entryInMap, descriptor, defaults);
+        if (index >= m_storage->m_length)
+            m_storage->m_length = index + 1;
+        return true;
+    }
+
+    // 5. Return true, if every field in Desc is absent.
+    // 6. Return true, if every field in Desc also occurs in current and the value of every field in Desc is the same value as the corresponding field in current when compared using the SameValue algorithm (9.12).
+    PropertyDescriptor current;
+    entryInMap->get(current);
+    if (descriptor.isEmpty() || descriptor.equalTo(exec, current))
+        return true;
+
+    // 7. If the [[Configurable]] field of current is false then
+    if (!current.configurable()) {
+        // 7.a. Reject, if the [[Configurable]] field of Desc is true.
+        if (descriptor.configurablePresent() && descriptor.configurable())
+            return reject(exec, throwException, "Attempting to change configurable attribute of unconfigurable property.");
+        // 7.b. Reject, if the [[Enumerable]] field of Desc is present and the [[Enumerable]] fields of current and Desc are the Boolean negation of each other.
+        if (descriptor.enumerablePresent() && current.enumerable() != descriptor.enumerable())
+            return reject(exec, throwException, "Attempting to change enumerable attribute of unconfigurable property.");
+    }
+
+    // 8. If IsGenericDescriptor(Desc) is true, then no further validation is required.
+    if (!descriptor.isGenericDescriptor()) {
+        // 9. Else, if IsDataDescriptor(current) and IsDataDescriptor(Desc) have different results, then
+        if (current.isDataDescriptor() != descriptor.isDataDescriptor()) {
+            // 9.a. Reject, if the [[Configurable]] field of current is false.
+            if (!current.configurable())
+                return reject(exec, throwException, "Attempting to change access mechanism for an unconfigurable property.");
+            // 9.b. If IsDataDescriptor(current) is true, then convert the property named P of object O from a
+            // data property to an accessor property. Preserve the existing values of the converted property‘s
+            // [[Configurable]] and [[Enumerable]] attributes and set the rest of the property‘s attributes to
+            // their default values.
+            // 9.c. Else, convert the property named P of object O from an accessor property to a data property.
+            // Preserve the existing values of the converted property‘s [[Configurable]] and [[Enumerable]]
+            // attributes and set the rest of the property‘s attributes to their default values.
+        } else if (current.isDataDescriptor() && descriptor.isDataDescriptor()) {
+            // 10. Else, if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both true, then
+            // 10.a. If the [[Configurable]] field of current is false, then
+            if (!current.configurable() && !current.writable()) {
+                // 10.a.i. Reject, if the [[Writable]] field of current is false and the [[Writable]] field of Desc is true.
+                if (descriptor.writable())
+                    return reject(exec, throwException, "Attempting to change writable attribute of unconfigurable property.");
+                // 10.a.ii. If the [[Writable]] field of current is false, then
+                // 10.a.ii.1. Reject, if the [[Value]] field of Desc is present and SameValue(Desc.[[Value]], current.[[Value]]) is false.
+                if (descriptor.value() && !sameValue(exec, descriptor.value(), current.value()))
+                    return reject(exec, throwException, "Attempting to change value of a readonly property.");
+            }
+            // 10.b. else, the [[Configurable]] field of current is true, so any change is acceptable.
+        } else {
+            ASSERT(current.isAccessorDescriptor() && current.getterPresent() && current.setterPresent());
+            // 11. Else, IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc) are both true so, if the [[Configurable]] field of current is false, then
+            if (!current.configurable()) {
+                // 11.i. Reject, if the [[Set]] field of Desc is present and SameValue(Desc.[[Set]], current.[[Set]]) is false.
+                if (descriptor.setterPresent() && descriptor.setter() != current.setter())
+                    return reject(exec, throwException, "Attempting to change the setter of an unconfigurable property.");
+                // 11.ii. Reject, if the [[Get]] field of Desc is present and SameValue(Desc.[[Get]], current.[[Get]]) is false.
+                if (descriptor.getterPresent() && descriptor.getter() != current.getter())
+                    return reject(exec, throwException, "Attempting to change the getter of an unconfigurable property.");
+            }
+        }
+    }
+
+    // 12. For each attribute field of Desc that is present, set the correspondingly named attribute of the property named P of object O to the value of the field.
+    putDescriptor(exec, entryInMap, descriptor, current);
+    // 13. Return true.
+    return true;
+}
+
+void JSArray::setLengthWritable(ExecState* exec, bool writable)
+{
+    ASSERT(isLengthWritable() || !writable);
+    if (!isLengthWritable() || writable)
+        return;
+
+    enterDictionaryMode(exec->globalData());
+
+    SparseArrayValueMap* map = m_sparseValueMap;
+    ASSERT(map);
+    map->setLengthIsReadOnly();
+}
+
+// Defined in ES5.1 15.4.5.1
+bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
+{
+    JSArray* array = jsCast<JSArray*>(object);
+
+    // 3. If P is "length", then
+    if (propertyName == exec->propertyNames().length) {
+        // All paths through length definition call the default [[DefineOwnProperty]], hence:
+        // from ES5.1 8.12.9 7.a.
+        if (descriptor.configurablePresent() && descriptor.configurable())
+            return reject(exec, throwException, "Attempting to change configurable attribute of unconfigurable property.");
+        // from ES5.1 8.12.9 7.b.
+        if (descriptor.enumerablePresent() && descriptor.enumerable())
+            return reject(exec, throwException, "Attempting to change enumerable attribute of unconfigurable property.");
+
+        // a. If the [[Value]] field of Desc is absent, then
+        // a.i. Return the result of calling the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", Desc, and Throw as arguments.
+        if (descriptor.isAccessorDescriptor())
+            return reject(exec, throwException, "Attempting to change access mechanism for an unconfigurable property.");
+        // from ES5.1 8.12.9 10.a.
+        if (!array->isLengthWritable() && descriptor.writablePresent() && descriptor.writable())
+            return reject(exec, throwException, "Attempting to change writable attribute of unconfigurable property.");
+        // This descriptor is either just making length read-only, or changing nothing!
+        if (!descriptor.value()) {
+            if (descriptor.writablePresent())
+                array->setLengthWritable(exec, descriptor.writable());
+            return true;
+        }
+        
+        // b. Let newLenDesc be a copy of Desc.
+        // c. Let newLen be ToUint32(Desc.[[Value]]).
+        unsigned newLen = descriptor.value().toUInt32(exec);
+        // d. If newLen is not equal to ToNumber( Desc.[[Value]]), throw a RangeError exception.
+        if (newLen != descriptor.value().toNumber(exec)) {
+            throwError(exec, createRangeError(exec, "Invalid array length"));
+            return false;
+        }
+
+        // Based on SameValue check in 8.12.9, this is always okay.
+        if (newLen == array->length()) {
+            if (descriptor.writablePresent())
+                array->setLengthWritable(exec, descriptor.writable());
+            return true;
+        }
+
+        // e. Set newLenDesc.[[Value] to newLen.
+        // f. If newLen >= oldLen, then
+        // f.i. Return the result of calling the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", newLenDesc, and Throw as arguments.
+        // g. Reject if oldLenDesc.[[Writable]] is false.
+        if (!array->isLengthWritable())
+            return reject(exec, throwException, "Attempting to change value of a readonly property.");
+        
+        // h. If newLenDesc.[[Writable]] is absent or has the value true, let newWritable be true.
+        // i. Else,
+        // i.i. Need to defer setting the [[Writable]] attribute to false in case any elements cannot be deleted.
+        // i.ii. Let newWritable be false.
+        // i.iii. Set newLenDesc.[[Writable] to true.
+        // j. Let succeeded be the result of calling the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", newLenDesc, and Throw as arguments.
+        // k. If succeeded is false, return false.
+        // l. While newLen < oldLen repeat,
+        // l.i. Set oldLen to oldLen â€“ 1.
+        // l.ii. Let deleteSucceeded be the result of calling the [[Delete]] internal method of A passing ToString(oldLen) and false as arguments.
+        // l.iii. If deleteSucceeded is false, then
+        if (!array->setLength(exec, newLen, throwException)) {
+            // 1. Set newLenDesc.[[Value] to oldLen+1.
+            // 2. If newWritable is false, set newLenDesc.[[Writable] to false.
+            // 3. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", newLenDesc, and false as arguments.
+            // 4. Reject.
+            if (descriptor.writablePresent())
+                array->setLengthWritable(exec, descriptor.writable());
+            return false;
+        }
+
+        // m. If newWritable is false, then
+        // i. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length",
+        //    Property Descriptor{[[Writable]]: false}, and false as arguments. This call will always
+        //    return true.
+        if (descriptor.writablePresent())
+            array->setLengthWritable(exec, descriptor.writable());
+        // n. Return true.
+        return true;
+    }
+
+    // 4. Else if P is an array index (15.4), then
+    bool isArrayIndex;
+    // a. Let index be ToUint32(P).
+    unsigned index = propertyName.toArrayIndex(isArrayIndex);
+    if (isArrayIndex) {
+        // b. Reject if index >= oldLen and oldLenDesc.[[Writable]] is false.
+        if (index >= array->length() && !array->isLengthWritable())
+            return reject(exec, throwException, "Attempting to define numeric property on array with non-writable length property.");
+        // c. Let succeeded be the result of calling the default [[DefineOwnProperty]] internal method (8.12.9) on A passing P, Desc, and false as arguments.
+        // d. Reject if succeeded is false.
+        // e. If index >= oldLen
+        // e.i. Set oldLenDesc.[[Value]] to index + 1.
+        // e.ii. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", oldLenDesc, and false as arguments. This call will always return true.
+        // f. Return true.
+        return array->defineOwnNumericProperty(exec, index, descriptor, throwException);
+    }
+
+    return JSObject::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+}
+
+bool JSArray::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned i, PropertySlot& slot)
+{
+    JSArray* thisObject = jsCast<JSArray*>(cell);
+    ArrayStorage* storage = thisObject->m_storage;
+
     if (i >= storage->m_length) {
         if (i > MAX_ARRAY_INDEX)
     if (i >= storage->m_length) {
         if (i > MAX_ARRAY_INDEX)
-            return getOwnPropertySlot(exec, Identifier::from(exec, i), slot);
+            return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, Identifier::from(exec, i), slot);
         return false;
     }
 
         return false;
     }
 
-    if (i < m_vectorLength) {
+    if (i < thisObject->m_vectorLength) {
         JSValue value = storage->m_vector[i].get();
         if (value) {
             slot.setValue(value);
             return true;
         }
         JSValue value = storage->m_vector[i].get();
         if (value) {
             slot.setValue(value);
             return true;
         }
-    } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
-        if (i >= MIN_SPARSE_ARRAY_INDEX) {
-            SparseArrayValueMap::iterator it = map->find(i);
-            if (it != map->end()) {
-                slot.setValue(it->second.get());
-                return true;
-            }
+    } else if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) {
+        SparseArrayValueMap::iterator it = map->find(i);
+        if (it != map->notFound()) {
+            it->second.get(slot);
+            return true;
         }
     }
 
         }
     }
 
-    return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, i), slot);
+    return JSObject::getOwnPropertySlot(thisObject, exec, Identifier::from(exec, i), slot);
 }
 
 }
 
-bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+bool JSArray::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
+    JSArray* thisObject = jsCast<JSArray*>(cell);
     if (propertyName == exec->propertyNames().length) {
     if (propertyName == exec->propertyNames().length) {
-        slot.setValue(jsNumber(length()));
+        slot.setValue(jsNumber(thisObject->length()));
         return true;
     }
 
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex)
         return true;
     }
 
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex)
-        return JSArray::getOwnPropertySlot(exec, i, slot);
+        return JSArray::getOwnPropertySlotByIndex(thisObject, exec, i, slot);
 
 
-    return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+    return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
 }
 
 }
 
-bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool JSArray::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
+    JSArray* thisObject = jsCast<JSArray*>(object);
     if (propertyName == exec->propertyNames().length) {
     if (propertyName == exec->propertyNames().length) {
-        descriptor.setDescriptor(jsNumber(length()), DontDelete | DontEnum);
+        descriptor.setDescriptor(jsNumber(thisObject->length()), thisObject->isLengthWritable() ? DontDelete | DontEnum : DontDelete | DontEnum | ReadOnly);
         return true;
     }
 
         return true;
     }
 
-    ArrayStorage* storage = m_storage;
+    ArrayStorage* storage = thisObject->m_storage;
     
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex) {
         if (i >= storage->m_length)
             return false;
     
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex) {
         if (i >= storage->m_length)
             return false;
-        if (i < m_vectorLength) {
+        if (i < thisObject->m_vectorLength) {
             WriteBarrier<Unknown>& value = storage->m_vector[i];
             if (value) {
                 descriptor.setDescriptor(value.get(), 0);
                 return true;
             }
             WriteBarrier<Unknown>& value = storage->m_vector[i];
             if (value) {
                 descriptor.setDescriptor(value.get(), 0);
                 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()) {
-                    descriptor.setDescriptor(it->second.get(), 0);
-                    return true;
-                }
+        } else if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) {
+            SparseArrayValueMap::iterator it = map->find(i);
+            if (it != map->notFound()) {
+                it->second.get(descriptor);
+                return true;
             }
         }
     }
             }
         }
     }
-    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    return JSObject::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
 }
 
 // ECMA 15.4.5.1
 }
 
 // ECMA 15.4.5.1
-void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void JSArray::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
+    JSArray* thisObject = jsCast<JSArray*>(cell);
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex) {
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex) {
-        put(exec, i, value);
+        putByIndex(thisObject, exec, i, value, slot.isStrictMode());
         return;
     }
 
     if (propertyName == exec->propertyNames().length) {
         unsigned newLength = value.toUInt32(exec);
         if (value.toNumber(exec) != static_cast<double>(newLength)) {
         return;
     }
 
     if (propertyName == exec->propertyNames().length) {
         unsigned newLength = value.toUInt32(exec);
         if (value.toNumber(exec) != static_cast<double>(newLength)) {
-            throwError(exec, createRangeError(exec, "Invalid array length."));
+            throwError(exec, createRangeError(exec, "Invalid array length"));
             return;
         }
             return;
         }
-        setLength(newLength);
+        thisObject->setLength(exec, newLength, slot.isStrictMode());
         return;
     }
 
         return;
     }
 
-    JSObject::put(exec, propertyName, value, slot);
+    JSObject::put(thisObject, exec, propertyName, value, slot);
 }
 
 }
 
-void JSArray::put(ExecState* exec, unsigned i, JSValue value)
+void JSArray::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value, bool shouldThrow)
 {
 {
-    checkConsistency();
+    JSArray* thisObject = jsCast<JSArray*>(cell);
+    thisObject->checkConsistency();
 
 
-    ArrayStorage* storage = m_storage;
+    ArrayStorage* storage = thisObject->m_storage;
 
 
-    unsigned length = storage->m_length;
-    if (i >= length && i <= MAX_ARRAY_INDEX) {
-        length = i + 1;
-        storage->m_length = length;
+    // Fast case - store to the vector.
+    if (i < thisObject->m_vectorLength) {
+        WriteBarrier<Unknown>& valueSlot = storage->m_vector[i];
+        unsigned length = storage->m_length;
+
+        // Update m_length & m_numValuesInVector as necessary.
+        if (i >= length) {
+            length = i + 1;
+            storage->m_length = length;
+            ++storage->m_numValuesInVector;
+        } else if (!valueSlot)
+            ++storage->m_numValuesInVector;
+
+        valueSlot.set(exec->globalData(), thisObject, value);
+        thisObject->checkConsistency();
+        return;
     }
 
     }
 
-    if (i < m_vectorLength) {
-        WriteBarrier<Unknown>& valueSlot = storage->m_vector[i];
-        if (valueSlot) {
-            valueSlot.set(exec->globalData(), this, value);
-            checkConsistency();
-            return;
-        }
-        valueSlot.set(exec->globalData(), this, value);
-        ++storage->m_numValuesInVector;
-        checkConsistency();
+    // Handle 2^32-1 - this is not an array index (see ES5.1 15.4), and is treated as a regular property.
+    if (UNLIKELY(i > MAX_ARRAY_INDEX)) {
+        PutPropertySlot slot(shouldThrow);
+        thisObject->methodTable()->put(thisObject, exec, Identifier::from(exec, i), value, slot);
         return;
     }
 
         return;
     }
 
-    putSlowCase(exec, i, value);
+    // For all other cases, call putByIndexBeyondVectorLength.
+    thisObject->putByIndexBeyondVectorLength(exec, i, value, shouldThrow);
+    thisObject->checkConsistency();
 }
 
 }
 
-NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue value)
+void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, bool shouldThrow)
 {
 {
-    ArrayStorage* storage = m_storage;
-    
-    SparseArrayValueMap* map = storage->m_sparseValueMap;
-
-    if (i >= MIN_SPARSE_ARRAY_INDEX) {
-        if (i > MAX_ARRAY_INDEX) {
-            PutPropertySlot slot;
-            put(exec, Identifier::from(exec, i), value, slot);
-            return;
-        }
+    JSGlobalData& globalData = exec->globalData();
 
 
-        // We miss some cases where we could compact the storage, such as a large array that is being filled from the end
-        // (which will only be compacted as we reach indices that are less than MIN_SPARSE_ARRAY_INDEX) - but this makes the check much faster.
-        if ((i > MAX_STORAGE_VECTOR_INDEX) || !isDenseEnoughForVector(i + 1, storage->m_numValuesInVector + 1)) {
-            if (!map) {
-                map = new SparseArrayValueMap;
-                storage->m_sparseValueMap = map;
-            }
+    // i should be a valid array index that is outside of the current vector.
+    ASSERT(i >= m_vectorLength);
+    ASSERT(i <= MAX_ARRAY_INDEX);
 
 
-            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;
+    ArrayStorage* storage = m_storage;
+    SparseArrayValueMap* map = m_sparseValueMap;
 
 
-            size_t capacity = map->capacity();
-            if (capacity != storage->reportedMapCapacity) {
-                Heap::heap(this)->reportExtraMemoryCost((capacity - storage->reportedMapCapacity) * (sizeof(unsigned) + sizeof(JSValue)));
-                storage->reportedMapCapacity = capacity;
-            }
-            return;
-        }
-    }
+    // First, handle cases where we don't currently have a sparse map.
+    if (LIKELY(!map)) {
+        // If the array is not extensible, we should have entered dictionary mode, and created the spare map.
+        ASSERT(isExtensible());
+    
+        // Update m_length if necessary.
+        if (i >= storage->m_length)
+            storage->m_length = i + 1;
 
 
-    // We have decided that we'll put the new item into the vector.
-    // Fast case is when there is no sparse map, so we can increase the vector size without moving values from it.
-    if (!map || map->isEmpty()) {
-        if (increaseVectorLength(i + 1)) {
+        // Check that it is sensible to still be using a vector, and then try to grow the vector.
+        if (LIKELY((isDenseEnoughForVector(i, storage->m_numValuesInVector)) && increaseVectorLength(globalData, i + 1))) {
+            // success! - reread m_storage since it has likely been reallocated, and store to the vector.
             storage = m_storage;
             storage = m_storage;
-            storage->m_vector[i].set(exec->globalData(), this, value);
+            storage->m_vector[i].set(globalData, this, value);
             ++storage->m_numValuesInVector;
             ++storage->m_numValuesInVector;
-            checkConsistency();
-        } else
-            throwOutOfMemoryError(exec);
+            return;
+        }
+        // We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
+        allocateSparseMap(exec->globalData());
+        map = m_sparseValueMap;
+        map->put(exec, this, i, value, shouldThrow);
         return;
     }
 
         return;
     }
 
-    // Decide how many values it would be best to move from the map.
-    unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;
-    unsigned newVectorLength = getNewVectorLength(i + 1);
-    for (unsigned j = max(m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
-        newNumValuesInVector += map->contains(j);
-    if (i >= MIN_SPARSE_ARRAY_INDEX)
-        newNumValuesInVector -= map->contains(i);
-    if (isDenseEnoughForVector(newVectorLength, newNumValuesInVector)) {
-        unsigned needLength = max(i + 1, storage->m_length);
-        unsigned proposedNewNumValuesInVector = newNumValuesInVector;
-        // If newVectorLength is already the maximum - MAX_STORAGE_VECTOR_LENGTH - then do not attempt to grow any further.
-        while ((newVectorLength < 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))
-                break;
-            newVectorLength = proposedNewVectorLength;
-            newNumValuesInVector = proposedNewNumValuesInVector;
+    // Update m_length if necessary.
+    unsigned length = storage->m_length;
+    if (i >= length) {
+        // Prohibit growing the array if length is not writable.
+        if (map->lengthIsReadOnly() || !isExtensible()) {
+            if (shouldThrow)
+                throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+            return;
         }
         }
+        length = i + 1;
+        storage->m_length = length;
     }
 
     }
 
-    void* baseStorage = storage->m_allocBase;
-
-    if ((unsigned)m_indexBias > (MAX_STORAGE_VECTOR_LENGTH - newVectorLength)
-        || !tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage)) {
-        throwOutOfMemoryError(exec);
+    // We are currently using a map - check whether we still want to be doing so.
+    // We will continue  to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails.
+    unsigned numValuesInArray = storage->m_numValuesInVector + map->size();
+    if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->globalData(), length)) {
+        map->put(exec, this, i, value, shouldThrow);
         return;
     }
 
         return;
     }
 
-    m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(baseStorage) + m_indexBias * sizeof(JSValue));
-    m_storage->m_allocBase = baseStorage;
+    // Reread m_storage afterincreaseVectorLength, update m_numValuesInVector.
     storage = m_storage;
     storage = m_storage;
-    
-    unsigned vectorLength = m_vectorLength;
+    storage->m_numValuesInVector = numValuesInArray;
+
+    // Copy all values from the map into the vector, and delete the map.
     WriteBarrier<Unknown>* vector = storage->m_vector;
     WriteBarrier<Unknown>* vector = storage->m_vector;
+    SparseArrayValueMap::const_iterator end = map->end();
+    for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it)
+        vector[it->first].set(globalData, this, it->second.getNonSparseMode());
+    deallocateSparseMap();
+
+    // Store the new property into the vector.
+    WriteBarrier<Unknown>& valueSlot = vector[i];
+    if (!valueSlot)
+        ++storage->m_numValuesInVector;
+    valueSlot.set(globalData, this, value);
+}
 
 
-    if (newNumValuesInVector == storage->m_numValuesInVector + 1) {
-        for (unsigned j = vectorLength; j < newVectorLength; ++j)
-            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)
-            vector[j].clear();
-        JSGlobalData& globalData = exec->globalData();
-        for (unsigned j = max(vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
-            vector[j].set(globalData, this, map->take(j).get());
-    }
+bool JSArray::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, bool shouldThrow)
+{
+    JSGlobalData& globalData = exec->globalData();
 
 
-    ASSERT(i < newVectorLength);
+    // i should be a valid array index that is outside of the current vector.
+    ASSERT(i >= m_vectorLength);
+    ASSERT(i <= MAX_ARRAY_INDEX);
 
 
-    m_vectorLength = newVectorLength;
-    storage->m_numValuesInVector = newNumValuesInVector;
+    ArrayStorage* storage = m_storage;
+    SparseArrayValueMap* map = m_sparseValueMap;
 
 
-    storage->m_vector[i].set(exec->globalData(), this, value);
+    // First, handle cases where we don't currently have a sparse map.
+    if (LIKELY(!map)) {
+        // If the array is not extensible, we should have entered dictionary mode, and created the spare map.
+        ASSERT(isExtensible());
+    
+        // Update m_length if necessary.
+        if (i >= storage->m_length)
+            storage->m_length = i + 1;
 
 
-    checkConsistency();
+        // Check that it is sensible to still be using a vector, and then try to grow the vector.
+        if (LIKELY((isDenseEnoughForVector(i, storage->m_numValuesInVector)) && increaseVectorLength(globalData, i + 1))) {
+            // success! - reread m_storage since it has likely been reallocated, and store to the vector.
+            storage = m_storage;
+            storage->m_vector[i].set(globalData, this, value);
+            ++storage->m_numValuesInVector;
+            return true;
+        }
+        // We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
+        allocateSparseMap(exec->globalData());
+        map = m_sparseValueMap;
+        return map->putDirect(exec, this, i, value, shouldThrow);
+    }
 
 
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
+    // Update m_length if necessary.
+    unsigned length = storage->m_length;
+    if (i >= length) {
+        // Prohibit growing the array if length is not writable.
+        if (map->lengthIsReadOnly())
+            return reject(exec, shouldThrow, StrictModeReadonlyPropertyWriteError);
+        if (!isExtensible())
+            return reject(exec, shouldThrow, "Attempting to define property on object that is not extensible.");
+        length = i + 1;
+        storage->m_length = length;
+    }
+
+    // We are currently using a map - check whether we still want to be doing so.
+    // We will continue  to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails.
+    unsigned numValuesInArray = storage->m_numValuesInVector + map->size();
+    if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->globalData(), length))
+        return map->putDirect(exec, this, i, value, shouldThrow);
+
+    // Reread m_storage afterincreaseVectorLength, update m_numValuesInVector.
+    storage = m_storage;
+    storage->m_numValuesInVector = numValuesInArray;
+
+    // Copy all values from the map into the vector, and delete the map.
+    WriteBarrier<Unknown>* vector = storage->m_vector;
+    SparseArrayValueMap::const_iterator end = map->end();
+    for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it)
+        vector[it->first].set(globalData, this, it->second.getNonSparseMode());
+    deallocateSparseMap();
+
+    // Store the new property into the vector.
+    WriteBarrier<Unknown>& valueSlot = vector[i];
+    if (!valueSlot)
+        ++storage->m_numValuesInVector;
+    valueSlot.set(globalData, this, value);
+    return true;
 }
 
 }
 
-bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName)
+bool JSArray::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
 {
 {
+    JSArray* thisObject = jsCast<JSArray*>(cell);
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex)
     bool isArrayIndex;
     unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex)
-        return deleteProperty(exec, i);
+        return thisObject->methodTable()->deletePropertyByIndex(thisObject, exec, i);
 
     if (propertyName == exec->propertyNames().length)
         return false;
 
 
     if (propertyName == exec->propertyNames().length)
         return false;
 
-    return JSObject::deleteProperty(exec, propertyName);
+    return JSObject::deleteProperty(thisObject, exec, propertyName);
 }
 
 }
 
-bool JSArray::deleteProperty(ExecState* exec, unsigned i)
+bool JSArray::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i)
 {
 {
-    checkConsistency();
+    JSArray* thisObject = jsCast<JSArray*>(cell);
+    thisObject->checkConsistency();
 
 
-    ArrayStorage* storage = m_storage;
+    if (i > MAX_ARRAY_INDEX)
+        return thisObject->methodTable()->deleteProperty(thisObject, exec, Identifier::from(exec, i));
+
+    ArrayStorage* storage = thisObject->m_storage;
     
     
-    if (i < m_vectorLength) {
+    if (i < thisObject->m_vectorLength) {
         WriteBarrier<Unknown>& valueSlot = storage->m_vector[i];
         WriteBarrier<Unknown>& valueSlot = storage->m_vector[i];
-        if (!valueSlot) {
-            checkConsistency();
-            return false;
+        if (valueSlot) {
+            valueSlot.clear();
+            --storage->m_numValuesInVector;
         }
         }
-        valueSlot.clear();
-        --storage->m_numValuesInVector;
-        checkConsistency();
-        return true;
-    }
-
-    if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
-        if (i >= MIN_SPARSE_ARRAY_INDEX) {
-            SparseArrayValueMap::iterator it = map->find(i);
-            if (it != map->end()) {
-                map->remove(it);
-                checkConsistency();
-                return true;
-            }
+    } else if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) {
+        SparseArrayValueMap::iterator it = map->find(i);
+        if (it != map->notFound()) {
+            if (it->second.attributes & DontDelete)
+                return false;
+            map->remove(it);
         }
     }
 
         }
     }
 
-    checkConsistency();
-
-    if (i > MAX_ARRAY_INDEX)
-        return deleteProperty(exec, Identifier::from(exec, i));
+    thisObject->checkConsistency();
+    return true;
+}
 
 
-    return false;
+static int compareKeysForQSort(const void* a, const void* b)
+{
+    unsigned da = *static_cast<const unsigned*>(a);
+    unsigned db = *static_cast<const unsigned*>(b);
+    return (da > db) - (da < db);
 }
 
 }
 
-void JSArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void JSArray::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
+    JSArray* thisObject = jsCast<JSArray*>(object);
     // FIXME: Filling PropertyNameArray with an identifier for every integer
     // is incredibly inefficient for large arrays. We need a different approach,
     // which almost certainly means a different structure for PropertyNameArray.
 
     // FIXME: Filling PropertyNameArray with an identifier for every integer
     // is incredibly inefficient for large arrays. We need a different approach,
     // which almost certainly means a different structure for PropertyNameArray.
 
-    ArrayStorage* storage = m_storage;
+    ArrayStorage* storage = thisObject->m_storage;
     
     
-    unsigned usedVectorLength = min(storage->m_length, m_vectorLength);
+    unsigned usedVectorLength = min(storage->m_length, thisObject->m_vectorLength);
     for (unsigned i = 0; i < usedVectorLength; ++i) {
         if (storage->m_vector[i])
             propertyNames.add(Identifier::from(exec, i));
     }
 
     for (unsigned i = 0; i < usedVectorLength; ++i) {
         if (storage->m_vector[i])
             propertyNames.add(Identifier::from(exec, i));
     }
 
-    if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
-        SparseArrayValueMap::iterator end = map->end();
-        for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
-            propertyNames.add(Identifier::from(exec, it->first));
+    if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) {
+        Vector<unsigned> keys;
+        keys.reserveCapacity(map->size());
+        
+        SparseArrayValueMap::const_iterator end = map->end();
+        for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) {
+            if (mode == IncludeDontEnumProperties || !(it->second.attributes & DontEnum))
+                keys.append(static_cast<unsigned>(it->first));
+        }
+
+        qsort(keys.begin(), keys.size(), sizeof(unsigned), compareKeysForQSort);
+        for (unsigned i = 0; i < keys.size(); ++i)
+            propertyNames.add(Identifier::from(exec, keys[i]));
     }
 
     if (mode == IncludeDontEnumProperties)
         propertyNames.add(exec->propertyNames().length);
 
     }
 
     if (mode == IncludeDontEnumProperties)
         propertyNames.add(exec->propertyNames().length);
 
-    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+    JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
 }
 
 ALWAYS_INLINE unsigned JSArray::getNewVectorLength(unsigned desiredLength)
 }
 
 ALWAYS_INLINE unsigned JSArray::getNewVectorLength(unsigned desiredLength)
@@ -583,90 +1032,190 @@ ALWAYS_INLINE unsigned JSArray::getNewVectorLength(unsigned desiredLength)
     return min(increasedLength, MAX_STORAGE_VECTOR_LENGTH);
 }
 
     return min(increasedLength, MAX_STORAGE_VECTOR_LENGTH);
 }
 
-bool JSArray::increaseVectorLength(unsigned newLength)
+bool JSArray::increaseVectorLength(JSGlobalData& globalData, unsigned newLength)
 {
     // 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.
 {
     // 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.
+    if (newLength > MAX_STORAGE_VECTOR_LENGTH)
+        return false;
 
     ArrayStorage* storage = m_storage;
 
     unsigned vectorLength = m_vectorLength;
     ASSERT(newLength > vectorLength);
 
     ArrayStorage* storage = m_storage;
 
     unsigned vectorLength = m_vectorLength;
     ASSERT(newLength > vectorLength);
-    ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX);
     unsigned newVectorLength = getNewVectorLength(newLength);
     unsigned newVectorLength = getNewVectorLength(newLength);
-    void* baseStorage = storage->m_allocBase;
 
 
-    if ((unsigned)m_indexBias > (MAX_STORAGE_VECTOR_LENGTH - newVectorLength)
-        || !tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage))
-        return false;
+    // Fast case - there is no precapacity. In these cases a realloc makes sense.
+    if (LIKELY(!m_indexBias)) {
+        void* newStorage = storage->m_allocBase;
+        if (!globalData.heap.tryReallocateStorage(&newStorage, storageSize(vectorLength), storageSize(newVectorLength)))
+            return false;
 
 
-    storage = m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(baseStorage) + m_indexBias * sizeof(JSValue));
-    m_storage->m_allocBase = baseStorage;
+        storage = m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(newStorage));
+        m_storage->m_allocBase = newStorage;
+        ASSERT(m_storage->m_allocBase);
 
 
-    WriteBarrier<Unknown>* vector = storage->m_vector;
-    for (unsigned i = vectorLength; i < newVectorLength; ++i)
-        vector[i].clear();
+        m_vectorLength = newVectorLength;
+        
+        return true;
+    }
+
+    // Remove some, but not all of the precapacity. Atomic decay, & capped to not overflow array length.
+    unsigned newIndexBias = min(m_indexBias >> 1, MAX_STORAGE_VECTOR_LENGTH - newVectorLength);
+    // Calculate new stoarge capcity, allowing room for the pre-capacity.
+    unsigned newStorageCapacity = newVectorLength + newIndexBias;
+    void* newAllocBase = 0;
+    if (!globalData.heap.tryAllocateStorage(storageSize(newStorageCapacity), &newAllocBase))    
+        return false;
+    // The sum of m_vectorLength and m_indexBias will never exceed MAX_STORAGE_VECTOR_LENGTH.
+    ASSERT(m_vectorLength <= MAX_STORAGE_VECTOR_LENGTH && (MAX_STORAGE_VECTOR_LENGTH - m_vectorLength) >= m_indexBias);
 
     m_vectorLength = newVectorLength;
 
     m_vectorLength = newVectorLength;
-    
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
+    m_indexBias = newIndexBias;
+    m_storage = reinterpret_cast_ptr<ArrayStorage*>(reinterpret_cast<WriteBarrier<Unknown>*>(newAllocBase) + m_indexBias);
+
+    // Copy the ArrayStorage header & current contents of the vector.
+    memmove(m_storage, storage, storageSize(vectorLength));
+
+    // Free the old allocation, update m_allocBase.
+    m_storage->m_allocBase = newAllocBase;
 
     return true;
 }
 
 
     return true;
 }
 
-bool JSArray::increaseVectorPrefixLength(unsigned newLength)
+// This method makes room in the vector, but leaves the new space uncleared.
+bool JSArray::unshiftCountSlowCase(JSGlobalData& globalData, unsigned count)
 {
 {
-    // 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.
-    
+    // If not, we should have handled this on the fast path.
+    ASSERT(count > m_indexBias);
+
     ArrayStorage* storage = m_storage;
     ArrayStorage* storage = m_storage;
-    
-    unsigned vectorLength = m_vectorLength;
-    ASSERT(newLength > vectorLength);
-    ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX);
-    unsigned newVectorLength = getNewVectorLength(newLength);
 
 
-    if ((unsigned)m_indexBias > (MAX_STORAGE_VECTOR_LENGTH - newVectorLength))
-        return false;
-    void* newBaseStorage = fastMalloc(storageSize(newVectorLength + m_indexBias));
-    if (!newBaseStorage)
+    // Step 1:
+    // Gather 4 key metrics:
+    //  * usedVectorLength - how many entries are currently in the vector (conservative estimate - fewer may be in use in sparse vectors).
+    //  * requiredVectorLength - how many entries are will there be in the vector, after allocating space for 'count' more.
+    //  * currentCapacity - what is the current size of the vector, including any pre-capacity.
+    //  * desiredCapacity - how large should we like to grow the vector to - based on 2x requiredVectorLength.
+
+    unsigned length = storage->m_length;
+    unsigned usedVectorLength = min(m_vectorLength, length);
+    ASSERT(usedVectorLength <= MAX_STORAGE_VECTOR_LENGTH);
+    // Check that required vector length is possible, in an overflow-safe fashion.
+    if (count > MAX_STORAGE_VECTOR_LENGTH - usedVectorLength)
         return false;
         return false;
-    
-    m_indexBias += newVectorLength - newLength;
-    
-    m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(newBaseStorage) + m_indexBias * sizeof(JSValue));
+    unsigned requiredVectorLength = usedVectorLength + count;
+    ASSERT(requiredVectorLength <= MAX_STORAGE_VECTOR_LENGTH);
+    // The sum of m_vectorLength and m_indexBias will never exceed MAX_STORAGE_VECTOR_LENGTH.
+    ASSERT(m_vectorLength <= MAX_STORAGE_VECTOR_LENGTH && (MAX_STORAGE_VECTOR_LENGTH - m_vectorLength) >= m_indexBias);
+    unsigned currentCapacity = m_vectorLength + m_indexBias;
+    // The calculation of desiredCapacity won't overflow, due to the range of MAX_STORAGE_VECTOR_LENGTH.
+    unsigned desiredCapacity = min(MAX_STORAGE_VECTOR_LENGTH, max(BASE_VECTOR_LEN, requiredVectorLength) << 1);
+
+    // Step 2:
+    // We're either going to choose to allocate a new ArrayStorage, or we're going to reuse the existing on.
+
+    void* newAllocBase = 0;
+    unsigned newStorageCapacity;
+    // If the current storage array is sufficiently large (but not too large!) then just keep using it.
+    if (currentCapacity > desiredCapacity && isDenseEnoughForVector(currentCapacity, requiredVectorLength)) {
+        newAllocBase = storage->m_allocBase;
+        newStorageCapacity = currentCapacity;
+    } else {
+        if (!globalData.heap.tryAllocateStorage(storageSize(desiredCapacity), &newAllocBase))
+            return false;
+        newStorageCapacity = desiredCapacity;
+    }
+
+    // Step 3:
+    // Work out where we're going to move things to.
+
+    // Determine how much of the vector to use as pre-capacity, and how much as post-capacity.
+    // If the vector had no free post-capacity (length >= m_vectorLength), don't give it any.
+    // If it did, we calculate the amount that will remain based on an atomic decay - leave the
+    // vector with half the post-capacity it had previously.
+    unsigned postCapacity = 0;
+    if (length < m_vectorLength) {
+        // Atomic decay, + the post-capacity cannot be greater than what is available.
+        postCapacity = min((m_vectorLength - length) >> 1, newStorageCapacity - requiredVectorLength);
+        // If we're moving contents within the same allocation, the post-capacity is being reduced.
+        ASSERT(newAllocBase != storage->m_allocBase || postCapacity < m_vectorLength - length);
+    }
+
+    m_vectorLength = requiredVectorLength + postCapacity;
+    m_indexBias = newStorageCapacity - m_vectorLength;
+    m_storage = reinterpret_cast_ptr<ArrayStorage*>(reinterpret_cast<WriteBarrier<Unknown>*>(newAllocBase) + m_indexBias);
+
+    // Step 4:
+    // Copy array data / header into their new locations, clear post-capacity & free any old allocation.
+
+    // If this is being moved within the existing buffer of memory, we are always shifting data
+    // to the right (since count > m_indexBias). As such this memmove cannot trample the header.
+    memmove(m_storage->m_vector + count, storage->m_vector, sizeof(WriteBarrier<Unknown>) * usedVectorLength);
+    memmove(m_storage, storage, storageSize(0));
+
+    // Are we copying into a new allocation?
+    if (newAllocBase != m_storage->m_allocBase) {
+        // Free the old allocation, update m_allocBase.
+        m_storage->m_allocBase = newAllocBase;
+    }
 
 
-    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;
 }
     return true;
 }
-    
 
 
-void JSArray::setLength(unsigned newLength)
+bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException)
 {
 {
-    ArrayStorage* storage = m_storage;
-    
-#if CHECK_ARRAY_CONSISTENCY
-    if (!storage->m_inCompactInitialization)
-        checkConsistency();
-    else
-        storage->m_inCompactInitialization = false;
-#endif
+    checkConsistency();
 
 
+    ArrayStorage* storage = m_storage;
     unsigned length = storage->m_length;
 
     unsigned length = storage->m_length;
 
+    // If the length is read only then we enter sparse mode, so should enter the following 'if'.
+    ASSERT(isLengthWritable() || m_sparseValueMap);
+
+    if (SparseArrayValueMap* map = m_sparseValueMap) {
+        // Fail if the length is not writable.
+        if (map->lengthIsReadOnly())
+            return reject(exec, throwException, StrictModeReadonlyPropertyWriteError);
+
+        if (newLength < length) {
+            // Copy any keys we might be interested in into a vector.
+            Vector<unsigned> keys;
+            keys.reserveCapacity(min(map->size(), static_cast<size_t>(length - newLength)));
+            SparseArrayValueMap::const_iterator end = map->end();
+            for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) {
+                unsigned index = static_cast<unsigned>(it->first);
+                if (index < length && index >= newLength)
+                    keys.append(index);
+            }
+
+            // Check if the array is in sparse mode. If so there may be non-configurable
+            // properties, so we have to perform deletion with caution, if not we can
+            // delete values in any order.
+            if (map->sparseMode()) {
+                qsort(keys.begin(), keys.size(), sizeof(unsigned), compareKeysForQSort);
+                unsigned i = keys.size();
+                while (i) {
+                    unsigned index = keys[--i];
+                    SparseArrayValueMap::iterator it = map->find(index);
+                    ASSERT(it != map->notFound());
+                    if (it->second.attributes & DontDelete) {
+                        storage->m_length = index + 1;
+                        return reject(exec, throwException, "Unable to delete property.");
+                    }
+                    map->remove(it);
+                }
+            } else {
+                for (unsigned i = 0; i < keys.size(); ++i)
+                    map->remove(keys[i]);
+                if (map->isEmpty())
+                    deallocateSparseMap();
+            }
+        }
+    }
+
     if (newLength < length) {
     if (newLength < length) {
+        // Delete properties from the vector.
         unsigned usedVectorLength = min(length, m_vectorLength);
         for (unsigned i = newLength; i < usedVectorLength; ++i) {
             WriteBarrier<Unknown>& valueSlot = storage->m_vector[i];
         unsigned usedVectorLength = min(length, m_vectorLength);
         for (unsigned i = newLength; i < usedVectorLength; ++i) {
             WriteBarrier<Unknown>& valueSlot = storage->m_vector[i];
@@ -674,105 +1223,87 @@ void JSArray::setLength(unsigned newLength)
             valueSlot.clear();
             storage->m_numValuesInVector -= hadValue;
         }
             valueSlot.clear();
             storage->m_numValuesInVector -= hadValue;
         }
-
-        if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
-            SparseArrayValueMap copy = *map;
-            SparseArrayValueMap::iterator end = copy.end();
-            for (SparseArrayValueMap::iterator it = copy.begin(); it != end; ++it) {
-                if (it->first >= newLength)
-                    map->remove(it->first);
-            }
-            if (map->isEmpty()) {
-                delete map;
-                storage->m_sparseValueMap = 0;
-            }
-        }
     }
 
     storage->m_length = newLength;
 
     checkConsistency();
     }
 
     storage->m_length = newLength;
 
     checkConsistency();
+    return true;
 }
 
 }
 
-JSValue JSArray::pop()
+JSValue JSArray::pop(ExecState* exec)
 {
     checkConsistency();
 {
     checkConsistency();
-
     ArrayStorage* storage = m_storage;
     
     unsigned length = storage->m_length;
     ArrayStorage* storage = m_storage;
     
     unsigned length = storage->m_length;
-    if (!length)
+    if (!length) {
+        if (!isLengthWritable())
+            throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
         return jsUndefined();
         return jsUndefined();
+    }
 
 
-    --length;
-
-    JSValue result;
-
-    if (length < m_vectorLength) {
-        WriteBarrier<Unknown>& valueSlot = storage->m_vector[length];
+    unsigned index = length - 1;
+    if (index < m_vectorLength) {
+        WriteBarrier<Unknown>& valueSlot = storage->m_vector[index];
         if (valueSlot) {
             --storage->m_numValuesInVector;
         if (valueSlot) {
             --storage->m_numValuesInVector;
-            result = valueSlot.get();
+            JSValue element = valueSlot.get();
             valueSlot.clear();
             valueSlot.clear();
-        } else
-            result = jsUndefined();
-    } else {
-        result = jsUndefined();
-        if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
-            SparseArrayValueMap::iterator it = map->find(length);
-            if (it != map->end()) {
-                result = it->second.get();
-                map->remove(it);
-                if (map->isEmpty()) {
-                    delete map;
-                    storage->m_sparseValueMap = 0;
-                }
-            }
+            
+            ASSERT(isLengthWritable());
+            storage->m_length = index;
+            checkConsistency();
+            return element;
         }
     }
 
         }
     }
 
-    storage->m_length = length;
-
+    // Let element be the result of calling the [[Get]] internal method of O with argument indx.
+    JSValue element = get(exec, index);
+    if (exec->hadException())
+        return jsUndefined();
+    // Call the [[Delete]] internal method of O with arguments indx and true.
+    deletePropertyByIndex(this, exec, index);
+    // Call the [[Put]] internal method of O with arguments "length", indx, and true.
+    setLength(exec, index, true);
+    // Return element.
     checkConsistency();
     checkConsistency();
-
-    return result;
+    return element;
 }
 
 }
 
+// Push & putIndex are almost identical, with two small differences.
+//  - we always are writing beyond the current array bounds, so it is always necessary to update m_length & m_numValuesInVector.
+//  - pushing to an array of length 2^32-1 stores the property, but throws a range error.
 void JSArray::push(ExecState* exec, JSValue value)
 {
     checkConsistency();
 void JSArray::push(ExecState* exec, JSValue value)
 {
     checkConsistency();
-    
     ArrayStorage* storage = m_storage;
 
     ArrayStorage* storage = m_storage;
 
-    if (storage->m_length < m_vectorLength) {
-        storage->m_vector[storage->m_length].set(exec->globalData(), this, value);
+    // Fast case - push within vector, always update m_length & m_numValuesInVector.
+    unsigned length = storage->m_length;
+    if (length < m_vectorLength) {
+        storage->m_vector[length].set(exec->globalData(), this, value);
+        storage->m_length = length + 1;
         ++storage->m_numValuesInVector;
         ++storage->m_numValuesInVector;
-        ++storage->m_length;
         checkConsistency();
         return;
     }
 
         checkConsistency();
         return;
     }
 
-    if (storage->m_length < MIN_SPARSE_ARRAY_INDEX) {
-        SparseArrayValueMap* map = storage->m_sparseValueMap;
-        if (!map || map->isEmpty()) {
-            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();
-            throwOutOfMemoryError(exec);
-            return;
-        }
+    // Pushing to an array of length 2^32-1 stores the property, but throws a range error.
+    if (UNLIKELY(storage->m_length == 0xFFFFFFFFu)) {
+        methodTable()->putByIndex(this, exec, storage->m_length, value, true);
+        // Per ES5.1 15.4.4.7 step 6 & 15.4.5.1 step 3.d.
+        if (!exec->hadException())
+            throwError(exec, createRangeError(exec, "Invalid array length"));
+        return;
     }
 
     }
 
-    putSlowCase(exec, storage->m_length++, value);
+    // Handled the same as putIndex.
+    putByIndexBeyondVectorLength(exec, storage->m_length, value, true);
+    checkConsistency();
 }
 
 }
 
-void JSArray::shiftCount(ExecState* exec, int count)
+bool JSArray::shiftCount(ExecState*, unsigned count)
 {
     ASSERT(count > 0);
     
 {
     ASSERT(count > 0);
     
@@ -780,32 +1311,15 @@ void JSArray::shiftCount(ExecState* exec, int count)
     
     unsigned oldLength = storage->m_length;
     
     
     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.
+    // If the array contains holes or is otherwise in an abnormal state,
+    // use the generic algorithm in ArrayPrototype.
+    if (oldLength != storage->m_numValuesInVector || inSparseMode())
+        return false;
 
 
-        // 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;
+    if (!oldLength)
+        return true;
     
     
+    storage->m_numValuesInVector -= count;
     storage->m_length -= count;
     
     if (m_vectorLength) {
     storage->m_length -= count;
     
     if (m_vectorLength) {
@@ -814,70 +1328,74 @@ void JSArray::shiftCount(ExecState* exec, int count)
         m_vectorLength -= count;
         
         if (m_vectorLength) {
         m_vectorLength -= count;
         
         if (m_vectorLength) {
-            char* newBaseStorage = reinterpret_cast<char*>(storage) + count * sizeof(JSValue);
+            char* newBaseStorage = reinterpret_cast<char*>(storage) + count * sizeof(WriteBarrier<Unknown>);
             memmove(newBaseStorage, storage, storageSize(0));
             m_storage = reinterpret_cast_ptr<ArrayStorage*>(newBaseStorage);
 
             m_indexBias += count;
         }
     }
             memmove(newBaseStorage, storage, storageSize(0));
             m_storage = reinterpret_cast_ptr<ArrayStorage*>(newBaseStorage);
 
             m_indexBias += count;
         }
     }
+    return true;
 }
 }
-    
-void JSArray::unshiftCount(ExecState* exec, int count)
+
+// Returns true if the unshift can be handled, false to fallback.    
+bool JSArray::unshiftCount(ExecState* exec, unsigned count)
 {
     ArrayStorage* storage = m_storage;
 {
     ArrayStorage* storage = m_storage;
-
-    ASSERT(m_indexBias >= 0);
-    ASSERT(count >= 0);
-    
     unsigned length = storage->m_length;
     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 the array contains holes or is otherwise in an abnormal state,
+    // use the generic algorithm in ArrayPrototype.
+    if (length != storage->m_numValuesInVector || inSparseMode())
+        return false;
+
     if (m_indexBias >= count) {
         m_indexBias -= count;
     if (m_indexBias >= count) {
         m_indexBias -= count;
-        char* newBaseStorage = reinterpret_cast<char*>(storage) - count * sizeof(JSValue);
+        char* newBaseStorage = reinterpret_cast<char*>(storage) - count * sizeof(WriteBarrier<Unknown>);
         memmove(newBaseStorage, storage, storageSize(0));
         m_storage = reinterpret_cast_ptr<ArrayStorage*>(newBaseStorage);
         m_vectorLength += count;
         memmove(newBaseStorage, storage, storageSize(0));
         m_storage = reinterpret_cast_ptr<ArrayStorage*>(newBaseStorage);
         m_vectorLength += count;
-    } else if ((unsigned)count > (MAX_STORAGE_VECTOR_LENGTH - m_vectorLength)
-        || !increaseVectorPrefixLength(m_vectorLength + count)) {
+    } else if (!unshiftCountSlowCase(exec->globalData(), count)) {
         throwOutOfMemoryError(exec);
         throwOutOfMemoryError(exec);
-        return;
+        return true;
     }
 
     WriteBarrier<Unknown>* vector = m_storage->m_vector;
     }
 
     WriteBarrier<Unknown>* vector = m_storage->m_vector;
-    for (int i = 0; i < count; i++)
+    for (unsigned i = 0; i < count; i++)
         vector[i].clear();
         vector[i].clear();
+    return true;
 }
 
 }
 
-void JSArray::visitChildren(SlotVisitor& visitor)
+void JSArray::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    JSArray* thisObject = jsCast<JSArray*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
-    visitChildrenDirect(visitor);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+
+    JSNonFinalObject::visitChildren(thisObject, visitor);
+
+    if (thisObject->m_storage) {
+        ArrayStorage* storage = thisObject->m_storage;
+        void* baseStorage = storage->m_allocBase;
+
+        visitor.copyAndAppend(reinterpret_cast<void**>(&baseStorage), storageSize(thisObject->m_vectorLength + thisObject->m_indexBias), storage->m_vector->slot(), thisObject->m_vectorLength);
+
+        if (baseStorage != thisObject->m_storage->m_allocBase) {
+            thisObject->m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(baseStorage) + sizeof(JSValue) * thisObject->m_indexBias);
+            thisObject->m_storage->m_allocBase = baseStorage;
+            ASSERT(thisObject->m_storage->m_allocBase);
+        }
+    }
+
+    if (SparseArrayValueMap* map = thisObject->m_sparseValueMap)
+        map->visitChildren(visitor);
 }
 
 static int compareNumbersForQSort(const void* a, const void* b)
 {
 }
 
 static int compareNumbersForQSort(const void* a, const void* b)
 {
-    double da = static_cast<const JSValue*>(a)->uncheckedGetNumber();
-    double db = static_cast<const JSValue*>(b)->uncheckedGetNumber();
+    double da = static_cast<const JSValue*>(a)->asNumber();
+    double db = static_cast<const JSValue*>(b)->asNumber();
     return (da > db) - (da < db);
 }
 
     return (da > db) - (da < db);
 }
 
@@ -890,10 +1408,12 @@ static int compareByStringPairForQSort(const void* a, const void* b)
 
 void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData)
 {
 
 void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData)
 {
+    ASSERT(!inSparseMode());
+
     ArrayStorage* storage = m_storage;
 
     ArrayStorage* storage = m_storage;
 
-    unsigned lengthNotIncludingUndefined = compactForSorting();
-    if (storage->m_sparseValueMap) {
+    unsigned lengthNotIncludingUndefined = compactForSorting(exec->globalData());
+    if (m_sparseValueMap) {
         throwOutOfMemoryError(exec);
         return;
     }
         throwOutOfMemoryError(exec);
         return;
     }
@@ -916,17 +1436,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(storage->m_vector, size, sizeof(JSValue), compareNumbersForQSort);
+    qsort(storage->m_vector, size, sizeof(WriteBarrier<Unknown>), compareNumbersForQSort);
 
     checkConsistency(SortConsistencyCheck);
 }
 
 void JSArray::sort(ExecState* exec)
 {
 
     checkConsistency(SortConsistencyCheck);
 }
 
 void JSArray::sort(ExecState* exec)
 {
-    ArrayStorage* storage = m_storage;
+    ASSERT(!inSparseMode());
 
 
-    unsigned lengthNotIncludingUndefined = compactForSorting();
-    if (storage->m_sparseValueMap) {
+    unsigned lengthNotIncludingUndefined = compactForSorting(exec->globalData());
+    if (m_sparseValueMap) {
         throwOutOfMemoryError(exec);
         return;
     }
         throwOutOfMemoryError(exec);
         return;
     }
@@ -947,17 +1467,19 @@ void JSArray::sort(ExecState* exec)
     
     Heap::heap(this)->pushTempSortVector(&values);
 
     
     Heap::heap(this)->pushTempSortVector(&values);
 
+    bool isSortingPrimitiveValues = true;
     for (size_t i = 0; i < lengthNotIncludingUndefined; i++) {
     for (size_t i = 0; i < lengthNotIncludingUndefined; i++) {
-        JSValue value = storage->m_vector[i].get();
+        JSValue value = m_storage->m_vector[i].get();
         ASSERT(!value.isUndefined());
         values[i].first = value;
         ASSERT(!value.isUndefined());
         values[i].first = value;
+        isSortingPrimitiveValues = isSortingPrimitiveValues && value.isPrimitive();
     }
 
     // FIXME: The following loop continues to call toString on subsequent values even after
     // a toString call raises an exception.
 
     for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
     }
 
     // FIXME: The following loop continues to call toString on subsequent values even after
     // a toString call raises an exception.
 
     for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
-        values[i].second = values[i].first.toString(exec);
+        values[i].second = values[i].first.toUStringInline(exec);
 
     if (exec->hadException()) {
         Heap::heap(this)->popTempSortVector(&values);
 
     if (exec->hadException()) {
         Heap::heap(this)->popTempSortVector(&values);
@@ -968,7 +1490,10 @@ void JSArray::sort(ExecState* exec)
     // than O(N log N).
 
 #if HAVE(MERGESORT)
     // than O(N log N).
 
 #if HAVE(MERGESORT)
-    mergesort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort);
+    if (isSortingPrimitiveValues)
+        qsort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort);
+    else
+        mergesort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort);
 #else
     // FIXME: The qsort library function is likely to not be a stable sort.
     // ECMAScript-262 does not specify a stable sort, but in practice, browsers perform a stable sort.
 #else
     // FIXME: The qsort library function is likely to not be a stable sort.
     // ECMAScript-262 does not specify a stable sort, but in practice, browsers perform a stable sort.
@@ -978,13 +1503,13 @@ void JSArray::sort(ExecState* exec)
     // If the toString function changed the length of the array or vector storage,
     // increase the length to handle the orignal number of actual values.
     if (m_vectorLength < lengthNotIncludingUndefined)
     // If the toString function changed the length of the array or vector storage,
     // increase the length to handle the orignal number of actual values.
     if (m_vectorLength < lengthNotIncludingUndefined)
-        increaseVectorLength(lengthNotIncludingUndefined);
-    if (storage->m_length < lengthNotIncludingUndefined)
-        storage->m_length = lengthNotIncludingUndefined;
+        increaseVectorLength(exec->globalData(), lengthNotIncludingUndefined);
+    if (m_storage->m_length < lengthNotIncludingUndefined)
+        m_storage->m_length = lengthNotIncludingUndefined;
 
     JSGlobalData& globalData = exec->globalData();
     for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
 
     JSGlobalData& globalData = exec->globalData();
     for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
-        storage->m_vector[i].set(globalData, this, values[i].first);
+        m_storage->m_vector[i].set(globalData, this, values[i].first);
 
     Heap::heap(this)->popTempSortVector(&values);
     
 
     Heap::heap(this)->popTempSortVector(&values);
     
@@ -1011,7 +1536,6 @@ struct AVLTreeAbstractorForArrayCompare {
     JSValue m_compareFunction;
     CallType m_compareCallType;
     const CallData* m_compareCallData;
     JSValue m_compareFunction;
     CallType m_compareCallType;
     const CallData* m_compareCallData;
-    JSValue m_globalThisValue;
     OwnPtr<CachedCall> m_cachedCall;
 
     handle get_less(handle h) { return m_nodes[h].lt & 0x7FFFFFFF; }
     OwnPtr<CachedCall> m_cachedCall;
 
     handle get_less(handle h) { return m_nodes[h].lt & 0x7FFFFFFF; }
@@ -1050,7 +1574,7 @@ struct AVLTreeAbstractorForArrayCompare {
 
         double compareResult;
         if (m_cachedCall) {
 
         double compareResult;
         if (m_cachedCall) {
-            m_cachedCall->setThis(m_globalThisValue);
+            m_cachedCall->setThis(jsUndefined());
             m_cachedCall->setArgument(0, va);
             m_cachedCall->setArgument(1, vb);
             compareResult = m_cachedCall->call().toNumber(m_cachedCall->newCallFrame(m_exec));
             m_cachedCall->setArgument(0, va);
             m_cachedCall->setArgument(1, vb);
             compareResult = m_cachedCall->call().toNumber(m_cachedCall->newCallFrame(m_exec));
@@ -1058,7 +1582,7 @@ struct AVLTreeAbstractorForArrayCompare {
             MarkedArgumentBuffer arguments;
             arguments.append(va);
             arguments.append(vb);
             MarkedArgumentBuffer arguments;
             arguments.append(va);
             arguments.append(vb);
-            compareResult = call(m_exec, m_compareFunction, m_compareCallType, *m_compareCallData, m_globalThisValue, arguments).toNumber(m_exec);
+            compareResult = call(m_exec, m_compareFunction, m_compareCallType, *m_compareCallData, jsUndefined(), arguments).toNumber(m_exec);
         }
         return (compareResult < 0) ? -1 : 1; // Not passing equality through, because we need to store all values, even if equivalent.
     }
         }
         return (compareResult < 0) ? -1 : 1; // Not passing equality through, because we need to store all values, even if equivalent.
     }
@@ -1071,20 +1595,20 @@ struct AVLTreeAbstractorForArrayCompare {
 
 void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData)
 {
 
 void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData)
 {
-    checkConsistency();
+    ASSERT(!inSparseMode());
 
 
-    ArrayStorage* storage = m_storage;
+    checkConsistency();
 
     // 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(storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max()));
-    if (storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max()))
+    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()))
         return;
 
         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);
+    unsigned nodeCount = usedVectorLength + (m_sparseValueMap ? m_sparseValueMap->size() : 0);
 
     if (!nodeCount)
         return;
 
     if (!nodeCount)
         return;
@@ -1094,11 +1618,10 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
     tree.abstractor().m_compareFunction = compareFunction;
     tree.abstractor().m_compareCallType = callType;
     tree.abstractor().m_compareCallData = &callData;
     tree.abstractor().m_compareFunction = compareFunction;
     tree.abstractor().m_compareCallType = callType;
     tree.abstractor().m_compareCallData = &callData;
-    tree.abstractor().m_globalThisValue = exec->globalThisValue();
     tree.abstractor().m_nodes.grow(nodeCount);
 
     if (callType == CallTypeJS)
     tree.abstractor().m_nodes.grow(nodeCount);
 
     if (callType == CallTypeJS)
-        tree.abstractor().m_cachedCall = adoptPtr(new CachedCall(exec, asFunction(compareFunction), 2));
+        tree.abstractor().m_cachedCall = adoptPtr(new CachedCall(exec, jsCast<JSFunction*>(compareFunction), 2));
 
     if (!tree.abstractor().m_nodes.begin()) {
         throwOutOfMemoryError(exec);
 
     if (!tree.abstractor().m_nodes.begin()) {
         throwOutOfMemoryError(exec);
@@ -1113,14 +1636,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 = storage->m_vector[numDefined].get();
+        JSValue v = m_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 = storage->m_vector[i].get();
+        JSValue v = m_storage->m_vector[i].get();
         if (v) {
             if (v.isUndefined())
                 ++numUndefined;
         if (v) {
             if (v.isUndefined())
                 ++numUndefined;
@@ -1134,27 +1657,24 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
 
     unsigned newUsedVectorLength = numDefined + numUndefined;
 
 
     unsigned newUsedVectorLength = numDefined + numUndefined;
 
-    if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+    if (SparseArrayValueMap* map = 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.
-            if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) {
+            if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(exec->globalData(), newUsedVectorLength)) {
                 throwOutOfMemoryError(exec);
                 return;
             }
         }
                 throwOutOfMemoryError(exec);
                 return;
             }
         }
-        
-        storage = m_storage;
 
 
-        SparseArrayValueMap::iterator end = map->end();
-        for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
-            tree.abstractor().m_nodes[numDefined].value = it->second.get();
+        SparseArrayValueMap::const_iterator end = map->end();
+        for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) {
+            tree.abstractor().m_nodes[numDefined].value = it->second.getNonSparseMode();
             tree.insert(numDefined);
             ++numDefined;
         }
 
             tree.insert(numDefined);
             ++numDefined;
         }
 
-        delete map;
-        storage->m_sparseValueMap = 0;
+        deallocateSparseMap();
     }
 
     ASSERT(tree.abstractor().m_nodes.size() >= numDefined);
     }
 
     ASSERT(tree.abstractor().m_nodes.size() >= numDefined);
@@ -1167,19 +1687,19 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
     iter.start_iter_least(tree);
     JSGlobalData& globalData = exec->globalData();
     for (unsigned i = 0; i < numDefined; ++i) {
     iter.start_iter_least(tree);
     JSGlobalData& globalData = exec->globalData();
     for (unsigned i = 0; i < numDefined; ++i) {
-        storage->m_vector[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value);
+        m_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)
-        storage->m_vector[i].setUndefined();
+        m_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)
-        storage->m_vector[i].clear();
+        m_storage->m_vector[i].clear();
 
 
-    storage->m_numValuesInVector = newUsedVectorLength;
+    m_storage->m_numValuesInVector = newUsedVectorLength;
 
     checkConsistency(SortConsistencyCheck);
 }
 
     checkConsistency(SortConsistencyCheck);
 }
@@ -1202,26 +1722,28 @@ void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
         args.append(get(exec, i));
 }
 
         args.append(get(exec, i));
 }
 
-void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
+void JSArray::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t length)
 {
 {
-    ASSERT(m_storage->m_length >= maxSize);
-    UNUSED_PARAM(maxSize);
-    WriteBarrier<Unknown>* vector = m_storage->m_vector;
-    unsigned vectorEnd = min(maxSize, m_vectorLength);
+    ASSERT(length == this->length());
+    UNUSED_PARAM(length);
     unsigned i = 0;
     unsigned i = 0;
+    WriteBarrier<Unknown>* vector = m_storage->m_vector;
+    unsigned vectorEnd = min(length, m_vectorLength);
     for (; i < vectorEnd; ++i) {
         WriteBarrier<Unknown>& v = vector[i];
         if (!v)
             break;
     for (; i < vectorEnd; ++i) {
         WriteBarrier<Unknown>& v = vector[i];
         if (!v)
             break;
-        buffer[i] = v.get();
+        callFrame->setArgument(i, v.get());
     }
 
     }
 
-    for (; i < maxSize; ++i)
-        buffer[i] = get(exec, i);
+    for (; i < length; ++i)
+        callFrame->setArgument(i, get(exec, i));
 }
 
 }
 
-unsigned JSArray::compactForSorting()
+unsigned JSArray::compactForSorting(JSGlobalData& globalData)
 {
 {
+    ASSERT(!inSparseMode());
+
     checkConsistency();
 
     ArrayStorage* storage = m_storage;
     checkConsistency();
 
     ArrayStorage* storage = m_storage;
@@ -1249,23 +1771,22 @@ unsigned JSArray::compactForSorting()
 
     unsigned newUsedVectorLength = numDefined + numUndefined;
 
 
     unsigned newUsedVectorLength = numDefined + numUndefined;
 
-    if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+    if (SparseArrayValueMap* map = 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 - if not,
             // exception is thrown by caller.
         newUsedVectorLength += map->size();
         if (newUsedVectorLength > m_vectorLength) {
             // Check that it is possible to allocate an array large enough to hold all the entries - if not,
             // exception is thrown by caller.
-            if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength))
+            if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(globalData, newUsedVectorLength))
                 return 0;
 
             storage = m_storage;
         }
 
                 return 0;
 
             storage = m_storage;
         }
 
-        SparseArrayValueMap::iterator end = map->end();
-        for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
-            storage->m_vector[numDefined++].setWithoutWriteBarrier(it->second.get());
+        SparseArrayValueMap::const_iterator end = map->end();
+        for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it)
+            storage->m_vector[numDefined++].setWithoutWriteBarrier(it->second.getNonSparseMode());
 
 
-        delete map;
-        storage->m_sparseValueMap = 0;
+        deallocateSparseMap();
     }
 
     for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
     }
 
     for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
@@ -1280,29 +1801,21 @@ unsigned JSArray::compactForSorting()
     return numDefined;
 }
 
     return numDefined;
 }
 
-void* JSArray::subclassData() const
-{
-    return m_storage->subclassData;
-}
-
-void JSArray::setSubclassData(void* d)
-{
-    m_storage->subclassData = d;
-}
-
 #if CHECK_ARRAY_CONSISTENCY
 
 void JSArray::checkConsistency(ConsistencyCheckType type)
 {
     ArrayStorage* storage = m_storage;
 
 #if CHECK_ARRAY_CONSISTENCY
 
 void JSArray::checkConsistency(ConsistencyCheckType type)
 {
     ArrayStorage* storage = m_storage;
 
+    ASSERT(!storage->m_inCompactInitialization);
+
     ASSERT(storage);
     if (type == SortConsistencyCheck)
     ASSERT(storage);
     if (type == SortConsistencyCheck)
-        ASSERT(!storage->m_sparseValueMap);
+        ASSERT(!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 = storage->m_vector[i]) {
+        if (JSValue value = storage->m_vector[i].get()) {
             ASSERT(i < storage->m_length);
             if (type != DestructorConsistencyCheck)
                 value.isUndefined(); // Likely to crash if the object was deallocated.
             ASSERT(i < storage->m_length);
             if (type != DestructorConsistencyCheck)
                 value.isUndefined(); // Likely to crash if the object was deallocated.
@@ -1315,16 +1828,16 @@ void JSArray::checkConsistency(ConsistencyCheckType type)
     ASSERT(numValuesInVector == storage->m_numValuesInVector);
     ASSERT(numValuesInVector <= storage->m_length);
 
     ASSERT(numValuesInVector == storage->m_numValuesInVector);
     ASSERT(numValuesInVector <= storage->m_length);
 
-    if (storage->m_sparseValueMap) {
-        SparseArrayValueMap::iterator end = storage->m_sparseValueMap->end();
-        for (SparseArrayValueMap::iterator it = storage->m_sparseValueMap->begin(); it != end; ++it) {
+    if (m_sparseValueMap) {
+        SparseArrayValueMap::const_iterator end = m_sparseValueMap->end();
+        for (SparseArrayValueMap::const_iterator it = m_sparseValueMap->begin(); it != end; ++it) {
             unsigned index = it->first;
             ASSERT(index < storage->m_length);
             unsigned index = it->first;
             ASSERT(index < storage->m_length);
-            ASSERT(index >= storage->m_vectorLength);
+            ASSERT(index >= 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.isUndefined(); // Likely to crash if the object was deallocated.
+                it->second.getNonSparseMode().isUndefined(); // Likely to crash if the object was deallocated.
         }
     }
 }
         }
     }
 }
index 3cb8aadeae342874e7990235e52aba17f3f5d44e..17c7f3ed719ff13d4b6e7bf74beb119d71c01b41 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    typedef HashMap<unsigned, WriteBarrier<Unknown> > SparseArrayValueMap;
+    class JSArray;
+    class LLIntOffsetsExtractor;
+
+    struct SparseArrayEntry : public WriteBarrier<Unknown> {
+        typedef WriteBarrier<Unknown> Base;
+
+        SparseArrayEntry() : attributes(0) {}
+
+        JSValue get(ExecState*, JSArray*) const;
+        void get(PropertySlot&) const;
+        void get(PropertyDescriptor&) const;
+        JSValue getNonSparseMode() const;
+
+        unsigned attributes;
+    };
+
+    class SparseArrayValueMap {
+        typedef HashMap<uint64_t, SparseArrayEntry, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t> > Map;
+
+        enum Flags {
+            Normal = 0,
+            SparseMode = 1,
+            LengthIsReadOnly = 2,
+        };
+
+    public:
+        typedef Map::iterator iterator;
+        typedef Map::const_iterator const_iterator;
+        typedef Map::AddResult AddResult;
+
+        SparseArrayValueMap()
+            : m_flags(Normal)
+            , m_reportedCapacity(0)
+        {
+        }
+
+        void visitChildren(SlotVisitor&);
+
+        bool sparseMode()
+        {
+            return m_flags & SparseMode;
+        }
+
+        void setSparseMode()
+        {
+            m_flags = static_cast<Flags>(m_flags | SparseMode);
+        }
+
+        bool lengthIsReadOnly()
+        {
+            return m_flags & LengthIsReadOnly;
+        }
+
+        void setLengthIsReadOnly()
+        {
+            m_flags = static_cast<Flags>(m_flags | LengthIsReadOnly);
+        }
+
+        // These methods may mutate the contents of the map
+        void put(ExecState*, JSArray*, unsigned, JSValue, bool shouldThrow);
+        bool putDirect(ExecState*, JSArray*, unsigned, JSValue, bool shouldThrow);
+        AddResult add(JSArray*, unsigned);
+        iterator find(unsigned i) { return m_map.find(i); }
+        // This should ASSERT the remove is valid (check the result of the find).
+        void remove(iterator it) { m_map.remove(it); }
+        void remove(unsigned i) { m_map.remove(i); }
+
+        // These methods do not mutate the contents of the map.
+        iterator notFound() { return m_map.end(); }
+        bool isEmpty() const { return m_map.isEmpty(); }
+        bool contains(unsigned i) const { return m_map.contains(i); }
+        size_t size() const { return m_map.size(); }
+        // Only allow const begin/end iteration.
+        const_iterator begin() const { return m_map.begin(); }
+        const_iterator end() const { return m_map.end(); }
+
+    private:
+        Map m_map;
+        Flags m_flags;
+        size_t m_reportedCapacity;
+    };
 
     // 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 
 
     // 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 
@@ -37,56 +117,87 @@ namespace JSC {
     struct ArrayStorage {
         unsigned m_length; // The "length" property on the array
         unsigned m_numValuesInVector;
     struct ArrayStorage {
         unsigned m_length; // The "length" property on the array
         unsigned m_numValuesInVector;
-        SparseArrayValueMap* m_sparseValueMap;
-        void* subclassData; // A JSArray subclass can use this to fill the vector lazily.
         void* m_allocBase; // Pointer to base address returned by malloc().  Keeping this pointer does eliminate false positives from the leak detector.
         void* m_allocBase; // Pointer to base address returned by malloc().  Keeping this pointer does eliminate false positives from the leak detector.
-        size_t reportedMapCapacity;
 #if CHECK_ARRAY_CONSISTENCY
 #if CHECK_ARRAY_CONSISTENCY
-        bool m_inCompactInitialization;
+        // Needs to be a uintptr_t for alignment purposes.
+        uintptr_t m_initializationIndex;
+        uintptr_t m_inCompactInitialization;
+#else
+        uintptr_t m_padding;
 #endif
         WriteBarrier<Unknown> m_vector[1];
 #endif
         WriteBarrier<Unknown> m_vector[1];
-    };
-
-    // 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 };
+        static ptrdiff_t lengthOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_length); }
+        static ptrdiff_t numValuesInVectorOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector); }
+        static ptrdiff_t allocBaseOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_allocBase); }
+        static ptrdiff_t vectorOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_vector); }
+    };
 
     class JSArray : public JSNonFinalObject {
 
     class JSArray : public JSNonFinalObject {
+        friend class LLIntOffsetsExtractor;
         friend class Walker;
         friend class Walker;
+        friend class JIT;
 
 
-    public:
-        JSArray(VPtrStealingHackType);
-
-        explicit JSArray(JSGlobalData&, Structure*);
-        JSArray(JSGlobalData&, Structure*, unsigned initialLength, ArrayCreationMode);
-        JSArray(JSGlobalData&, Structure*, const ArgList& initialValues);
-        virtual ~JSArray();
+    protected:
+        explicit JSArray(JSGlobalData& globalData, Structure* structure)
+            : JSNonFinalObject(globalData, structure)
+            , m_indexBias(0)
+            , m_storage(0)
+            , m_sparseValueMap(0)
+        {
+        }
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
-        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
-        virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem.
+        JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, unsigned initialLength = 0);
+        JS_EXPORT_PRIVATE JSArray* tryFinishCreationUninitialized(JSGlobalData&, unsigned initialLength);
+    
+    public:
+        typedef JSNonFinalObject Base;
+
+        static void finalize(JSCell*);
+
+        static JSArray* create(JSGlobalData&, Structure*, unsigned initialLength = 0);
+
+        // tryCreateUninitialized is used for fast construction of arrays whose size and
+        // contents are known at time of creation. Clients of this interface must:
+        //   - null-check the result (indicating out of memory, or otherwise unable to allocate vector).
+        //   - call 'initializeIndex' for all properties in sequence, for 0 <= i < initialLength.
+        //   - called 'completeInitialization' after all properties have been initialized.
+        static JSArray* tryCreateUninitialized(JSGlobalData&, Structure*, unsigned initialLength);
+
+        JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool throwException);
+
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+        static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
+        // This is similar to the JSObject::putDirect* methods:
+        //  - the prototype chain is not consulted
+        //  - accessors are not called.
+        // This method creates a property with attributes writable, enumerable and configurable all set to true.
+        bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow = true)
+        {
+            if (canSetIndex(propertyName)) {
+                setIndex(exec->globalData(), propertyName, value);
+                return true;
+            }
+            return putDirectIndexBeyondVectorLength(exec, propertyName, value, shouldThrow);
+        }
 
         static JS_EXPORTDATA const ClassInfo s_info;
         
         unsigned length() const { return m_storage->m_length; }
 
         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.
+        // OK to use on new arrays, but not if it might be a RegExpMatchArray.
+        bool setLength(ExecState*, unsigned, bool throwException = false);
 
         void sort(ExecState*);
         void sort(ExecState*, JSValue compareFunction, CallType, const CallData&);
         void sortNumeric(ExecState*, JSValue compareFunction, CallType, const CallData&);
 
         void push(ExecState*, JSValue);
 
         void sort(ExecState*);
         void sort(ExecState*, JSValue compareFunction, CallType, const CallData&);
         void sortNumeric(ExecState*, JSValue compareFunction, CallType, const CallData&);
 
         void push(ExecState*, JSValue);
-        JSValue pop();
+        JSValue pop(ExecState*);
 
 
-        void shiftCount(ExecState*, int count);
-        void unshiftCount(ExecState*, int count);
+        bool shiftCount(ExecState*, unsigned count);
+        bool unshiftCount(ExecState*, unsigned count);
 
         bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; }
         JSValue getIndex(unsigned i)
 
         bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; }
         JSValue getIndex(unsigned i)
@@ -110,26 +221,50 @@ namespace JSC {
             x.set(globalData, this, v);
         }
         
             x.set(globalData, this, v);
         }
         
-        void uncheckedSetIndex(JSGlobalData& globalData, unsigned i, JSValue v)
+        inline void initializeIndex(JSGlobalData& globalData, unsigned i, JSValue v)
         {
             ASSERT(canSetIndex(i));
             ArrayStorage *storage = m_storage;
 #if CHECK_ARRAY_CONSISTENCY
             ASSERT(storage->m_inCompactInitialization);
         {
             ASSERT(canSetIndex(i));
             ArrayStorage *storage = m_storage;
 #if CHECK_ARRAY_CONSISTENCY
             ASSERT(storage->m_inCompactInitialization);
+            // Check that we are initializing the next index in sequence.
+            ASSERT(i == storage->m_initializationIndex);
+            // tryCreateUninitialized set m_numValuesInVector to the initialLength,
+            // check we do not try to initialize more than this number of properties.
+            ASSERT(storage->m_initializationIndex < storage->m_numValuesInVector);
+            storage->m_initializationIndex++;
 #endif
 #endif
+            ASSERT(i < storage->m_length);
+            ASSERT(i < storage->m_numValuesInVector);
             storage->m_vector[i].set(globalData, this, v);
         }
 
             storage->m_vector[i].set(globalData, this, v);
         }
 
+        inline void completeInitialization(unsigned newLength)
+        {
+            // Check that we have initialized as meny properties as we think we have.
+            ASSERT_UNUSED(newLength, newLength == m_storage->m_length);
+#if CHECK_ARRAY_CONSISTENCY
+            // Check that the number of propreties initialized matches the initialLength.
+            ASSERT(m_storage->m_initializationIndex == m_storage->m_numValuesInVector);
+            ASSERT(m_storage->m_inCompactInitialization);
+            m_storage->m_inCompactInitialization = false;
+#endif
+        }
+
+        bool inSparseMode()
+        {
+            SparseArrayValueMap* map = m_sparseValueMap;
+            return map && map->sparseMode();
+        }
+
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
-        void copyToRegisters(ExecState*, Register*, uint32_t);
+        void copyToArguments(ExecState*, CallFrame*, uint32_t length);
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
         
         }
         
-        inline void visitChildrenDirect(SlotVisitor&);
-
         static ptrdiff_t storageOffset()
         {
             return OBJECT_OFFSETOF(JSArray, m_storage);
         static ptrdiff_t storageOffset()
         {
             return OBJECT_OFFSETOF(JSArray, m_storage);
@@ -140,41 +275,78 @@ namespace JSC {
             return OBJECT_OFFSETOF(JSArray, m_vectorLength);
         }
 
             return OBJECT_OFFSETOF(JSArray, m_vectorLength);
         }
 
+        JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
+
+        void enterDictionaryMode(JSGlobalData&);
+
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
     protected:
         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 visitChildren(SlotVisitor&);
+        static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
 
 
-        void* subclassData() const;
-        void setSubclassData(void*);
+        static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
+        static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
+        static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+
+        JS_EXPORT_PRIVATE void* subclassData() const;
+        JS_EXPORT_PRIVATE void setSubclassData(void*);
 
     private:
 
     private:
+        static size_t storageSize(unsigned vectorLength);
+        bool isLengthWritable()
+        {
+            SparseArrayValueMap* map = m_sparseValueMap;
+            return !map || !map->lengthIsReadOnly();
+        }
+
+        void setLengthWritable(ExecState*, bool writable);
+        void putDescriptor(ExecState*, SparseArrayEntry*, PropertyDescriptor&, PropertyDescriptor& old);
+        bool defineOwnNumericProperty(ExecState*, unsigned, PropertyDescriptor&, bool throwException);
+        void allocateSparseMap(JSGlobalData&);
+        void deallocateSparseMap();
+
         bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
         bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
-        void putSlowCase(ExecState*, unsigned propertyName, JSValue);
+        void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
+        JS_EXPORT_PRIVATE bool putDirectIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
 
         unsigned getNewVectorLength(unsigned desiredLength);
 
         unsigned getNewVectorLength(unsigned desiredLength);
-        bool increaseVectorLength(unsigned newLength);
-        bool increaseVectorPrefixLength(unsigned newLength);
+        bool increaseVectorLength(JSGlobalData&, unsigned newLength);
+        bool unshiftCountSlowCase(JSGlobalData&, unsigned count);
         
         
-        unsigned compactForSorting();
+        unsigned compactForSorting(JSGlobalData&);
 
         enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
         void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
 
         unsigned m_vectorLength; // The valid length of m_vector
 
         enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
         void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
 
         unsigned m_vectorLength; // The valid length of m_vector
-        int m_indexBias; // The number of JSValue sized blocks before ArrayStorage.
+        unsigned m_indexBias; // The number of JSValue sized blocks before ArrayStorage.
         ArrayStorage *m_storage;
         ArrayStorage *m_storage;
+
+        // FIXME: Maybe SparseArrayValueMap should be put into its own JSCell?
+        SparseArrayValueMap* m_sparseValueMap;
+
+        static ptrdiff_t sparseValueMapOffset() { return OBJECT_OFFSETOF(JSArray, m_sparseValueMap); }
+        static ptrdiff_t indexBiasOffset() { return OBJECT_OFFSETOF(JSArray, m_indexBias); }
     };
 
     };
 
+    inline JSArray* JSArray::create(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
+    {
+        JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
+        array->finishCreation(globalData, initialLength);
+        return array;
+    }
+
+    inline JSArray* JSArray::tryCreateUninitialized(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
+    {
+        JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
+        return array->tryFinishCreationUninitialized(globalData, initialLength);
+    }
+
     JSArray* asArray(JSValue);
 
     inline JSArray* asArray(JSCell* cell)
     {
         ASSERT(cell->inherits(&JSArray::s_info));
     JSArray* asArray(JSValue);
 
     inline JSArray* asArray(JSCell* cell)
     {
         ASSERT(cell->inherits(&JSArray::s_info));
-        return static_cast<JSArray*>(cell);
+        return jsCast<JSArray*>(cell);
     }
 
     inline JSArray* asArray(JSValue value)
     }
 
     inline JSArray* asArray(JSValue value)
@@ -182,24 +354,8 @@ namespace JSC {
         return asArray(value.asCell());
     }
 
         return asArray(value.asCell());
     }
 
-    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::visitChildrenDirect(SlotVisitor& visitor)
-    {
-        JSObject::visitChildrenDirect(visitor);
-        
-        ArrayStorage* storage = m_storage;
-
-        unsigned usedVectorLength = std::min(storage->m_length, m_vectorLength);
-        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)
-                visitor.append(&it->second);
-        }
-    }
+    inline bool isJSArray(JSCell* cell) { return cell->classInfo() == &JSArray::s_info; }
+    inline bool isJSArray(JSValue v) { return v.isCell() && isJSArray(v.asCell()); }
 
     // 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.
 
     // 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.
@@ -211,6 +367,30 @@ namespace JSC {
         return i;
     }
 
         return i;
     }
 
-} // namespace JSC
+// The definition of MAX_STORAGE_VECTOR_LENGTH is dependant on the definition storageSize
+// function below - the MAX_STORAGE_VECTOR_LENGTH limit is defined such that the storage
+// size calculation cannot overflow.  (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) +
+// (vectorLength * sizeof(WriteBarrier<Unknown>)) must be <= 0xFFFFFFFFU (which is maximum value of size_t).
+#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>))
+
+// These values have to be macros to be used in max() and min() without introducing
+// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
+#define MIN_SPARSE_ARRAY_INDEX 10000U
+#define MAX_STORAGE_VECTOR_INDEX (MAX_STORAGE_VECTOR_LENGTH - 1)
+    inline size_t JSArray::storageSize(unsigned vectorLength)
+    {
+        ASSERT(vectorLength <= MAX_STORAGE_VECTOR_LENGTH);
+    
+        // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH)
+        // - as asserted above - the following calculation cannot overflow.
+        size_t size = (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) + (vectorLength * sizeof(WriteBarrier<Unknown>));
+        // Assertion to detect integer overflow in previous calculation (should not be possible, provided that
+        // MAX_STORAGE_VECTOR_LENGTH is correctly defined).
+        ASSERT(((size - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))));
+    
+        return size;
+    }
+    
+    } // namespace JSC
 
 #endif // JSArray_h
 
 #endif // JSArray_h
diff --git a/runtime/JSBoundFunction.cpp b/runtime/JSBoundFunction.cpp
new file mode 100644 (file)
index 0000000..5fee47c
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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 "JSBoundFunction.h"
+
+#include "GetterSetter.h"
+#include "JSGlobalObject.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSBoundFunction);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSBoundFunction);
+
+const ClassInfo JSBoundFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSBoundFunction) };
+
+EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState* exec)
+{
+    JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee());
+
+    ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true!
+    JSArray* boundArgs = asArray(boundFunction->boundArgs());
+
+    MarkedArgumentBuffer args;
+    for (unsigned i = 0; i < boundArgs->length(); ++i)
+        args.append(boundArgs->getIndex(i));
+    for (unsigned i = 0; i < exec->argumentCount(); ++i)
+        args.append(exec->argument(i));
+
+    JSObject* targetFunction = boundFunction->targetFunction();
+    CallData callData;
+    CallType callType = getCallData(targetFunction, callData);
+    ASSERT(callType != CallTypeNone);
+    return JSValue::encode(call(exec, targetFunction, callType, callData, boundFunction->boundThis(), args));
+}
+
+EncodedJSValue JSC_HOST_CALL boundFunctionConstruct(ExecState* exec)
+{
+    JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee());
+
+    ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true!
+    JSArray* boundArgs = asArray(boundFunction->boundArgs());
+
+    MarkedArgumentBuffer args;
+    for (unsigned i = 0; i < boundArgs->length(); ++i)
+        args.append(boundArgs->getIndex(i));
+    for (unsigned i = 0; i < exec->argumentCount(); ++i)
+        args.append(exec->argument(i));
+
+    JSObject* targetFunction = boundFunction->targetFunction();
+    ConstructData constructData;
+    ConstructType constructType = getConstructData(targetFunction, constructData);
+    ASSERT(constructType != ConstructTypeNone);
+    return JSValue::encode(construct(exec, targetFunction, constructType, constructData, args));
+}
+
+JSBoundFunction* JSBoundFunction::create(ExecState* exec, JSGlobalObject* globalObject, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int length, const Identifier& name)
+{
+    ConstructData constructData;
+    ConstructType constructType = JSC::getConstructData(targetFunction, constructData);
+    bool canConstruct = constructType != ConstructTypeNone;
+
+    NativeExecutable* executable = exec->globalData().getHostFunction(boundFunctionCall, canConstruct ? boundFunctionConstruct : callHostFunctionAsConstructor);
+    JSBoundFunction* function = new (NotNull, allocateCell<JSBoundFunction>(*exec->heap())) JSBoundFunction(exec, globalObject, globalObject->boundFunctionStructure(), targetFunction, boundThis, boundArgs);
+
+    function->finishCreation(exec, executable, length, name);
+    return function;
+}
+
+bool JSBoundFunction::hasInstance(JSObject* object, ExecState* exec, JSValue value, JSValue)
+{
+    JSBoundFunction* thisObject = jsCast<JSBoundFunction*>(object);
+    // FIXME: our instanceof implementation will have already (incorrectly) performed
+    // a [[Get]] of .prototype from the bound function object, which is incorrect!
+    // https://bugs.webkit.org/show_bug.cgi?id=68656
+    JSValue proto = thisObject->m_targetFunction->get(exec, exec->propertyNames().prototype);
+    return thisObject->m_targetFunction->methodTable()->hasInstance(thisObject->m_targetFunction.get(), exec, value, proto);
+}
+
+JSBoundFunction::JSBoundFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs)
+    : Base(exec, globalObject, structure)
+    , m_targetFunction(exec->globalData(), this, targetFunction)
+    , m_boundThis(exec->globalData(), this, boundThis)
+    , m_boundArgs(exec->globalData(), this, boundArgs)
+{
+}
+
+void JSBoundFunction::finishCreation(ExecState* exec, NativeExecutable* executable, int length, const Identifier& name)
+{
+    Base::finishCreation(exec, executable, length, name);
+    ASSERT(inherits(&s_info));
+
+    putDirectAccessor(exec->globalData(), exec->propertyNames().arguments, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+    putDirectAccessor(exec->globalData(), exec->propertyNames().caller, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+}
+
+void JSBoundFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    JSBoundFunction* thisObject = jsCast<JSBoundFunction*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    Base::visitChildren(thisObject, visitor);
+
+    visitor.append(&thisObject->m_targetFunction);
+    visitor.append(&thisObject->m_boundThis);
+    visitor.append(&thisObject->m_boundArgs);
+}
+
+} // namespace JSC
diff --git a/runtime/JSBoundFunction.h b/runtime/JSBoundFunction.h
new file mode 100644 (file)
index 0000000..e54d458
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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 JSBoundFunction_h
+#define JSBoundFunction_h
+
+#include "JSFunction.h"
+
+namespace JSC {
+
+EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState*);
+EncodedJSValue JSC_HOST_CALL boundFunctionConstruct(ExecState*);
+
+class JSBoundFunction : public JSFunction {
+public:
+    typedef JSFunction Base;
+
+    static JSBoundFunction* create(ExecState*, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const Identifier&);
+
+    static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue proto);
+
+    JSObject* targetFunction() { return m_targetFunction.get(); }
+    JSValue boundThis() { return m_boundThis.get(); }
+    JSValue boundArgs() { return m_boundArgs.get(); }
+
+    static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 
+    {
+        ASSERT(globalObject);
+        return Structure::create(globalData, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), &s_info); 
+    }
+
+    static const ClassInfo s_info;
+
+protected:
+    const static unsigned StructureFlags = OverridesHasInstance | OverridesVisitChildren | Base::StructureFlags;
+
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+private:
+    JSBoundFunction(ExecState*, JSGlobalObject*, Structure*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs);
+    
+    void finishCreation(ExecState*, NativeExecutable*, int, const Identifier&);
+
+    WriteBarrier<JSObject> m_targetFunction;
+    WriteBarrier<Unknown> m_boundThis;
+    WriteBarrier<Unknown> m_boundArgs;
+};
+
+} // namespace JSC
+
+#endif // JSFunction_h
diff --git a/runtime/JSByteArray.cpp b/runtime/JSByteArray.cpp
deleted file mode 100644 (file)
index c2abaee..0000000
+++ /dev/null
@@ -1,114 +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 "JSByteArray.h"
-
-#include "JSGlobalObject.h"
-#include "PropertyNameArray.h"
-
-using namespace WTF;
-
-namespace JSC {
-
-const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", &Base::s_info, 0, 0 };
-
-JSByteArray::JSByteArray(ExecState* exec, Structure* structure, ByteArray* storage)
-    : JSNonFinalObject(exec->globalData(), structure)
-    , m_storage(storage)
-{
-    putDirect(exec->globalData(), exec->globalData().propertyNames->length, jsNumber(m_storage->length()), ReadOnly | DontDelete);
-}
-
-#if !ASSERT_DISABLED
-JSByteArray::~JSByteArray()
-{
-    ASSERT(vptr() == JSGlobalData::jsByteArrayVPtr);
-}
-#endif
-
-
-Structure* JSByteArray::createStructure(JSGlobalData& globalData, JSValue prototype, const JSC::ClassInfo* classInfo)
-{
-    return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, classInfo);
-}
-
-bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
-    bool ok;
-    unsigned index = propertyName.toUInt32(ok);
-    if (ok && canAccessIndex(index)) {
-        slot.setValue(getIndex(exec, index));
-        return true;
-    }
-    return JSObject::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-bool JSByteArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
-{
-    bool ok;
-    unsigned index = propertyName.toUInt32(ok);
-    if (ok && canAccessIndex(index)) {
-        descriptor.setDescriptor(getIndex(exec, index), DontDelete);
-        return true;
-    }
-    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
-}
-
-bool JSByteArray::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
-{
-    if (canAccessIndex(propertyName)) {
-        slot.setValue(getIndex(exec, propertyName));
-        return true;
-    }
-    return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
-}
-
-void JSByteArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
-{
-    bool ok;
-    unsigned index = propertyName.toUInt32(ok);
-    if (ok) {
-        setIndex(exec, index, value);
-        return;
-    }
-    JSObject::put(exec, propertyName, value, slot);
-}
-
-void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValue value)
-{
-    setIndex(exec, propertyName, value);
-}
-
-void JSByteArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
-{
-    unsigned length = m_storage->length();
-    for (unsigned i = 0; i < length; ++i)
-        propertyNames.add(Identifier::from(exec, i));
-    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
-}
-
-}
-
diff --git a/runtime/JSByteArray.h b/runtime/JSByteArray.h
deleted file mode 100644 (file)
index c481bb4..0000000
+++ /dev/null
@@ -1,121 +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 JSByteArray_h
-#define JSByteArray_h
-
-#include "JSObject.h"
-
-#include <wtf/ByteArray.h>
-
-namespace JSC {
-
-    class JSByteArray : public JSNonFinalObject {
-        friend class JSGlobalData;
-    public:
-        typedef JSNonFinalObject Base;
-
-        bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
-        JSValue getIndex(ExecState*, unsigned i)
-        {
-            ASSERT(canAccessIndex(i));
-            return jsNumber(m_storage->data()[i]);
-        }
-
-        void setIndex(unsigned i, int value)
-        {
-            ASSERT(canAccessIndex(i));
-            if (value & ~0xFF) {
-                if (value < 0)
-                    value = 0;
-                else
-                    value = 255;
-            }
-            m_storage->data()[i] = static_cast<unsigned char>(value);
-        }
-        
-        void setIndex(unsigned i, double value)
-        {
-            ASSERT(canAccessIndex(i));
-            if (!(value > 0)) // Clamp NaN to 0
-                value = 0;
-            else if (value > 255)
-                value = 255;
-            m_storage->data()[i] = static_cast<unsigned char>(value + 0.5);
-        }
-        
-        void setIndex(ExecState* exec, unsigned i, JSValue value)
-        {
-            double byteValue = value.toNumber(exec);
-            if (exec->hadException())
-                return;
-            if (canAccessIndex(i))
-                setIndex(i, byteValue);
-        }
-
-        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 void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
-        virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);
-
-        virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
-
-        static const ClassInfo s_defaultInfo;
-        
-        size_t length() const { return m_storage->length(); }
-
-        WTF::ByteArray* storage() const { return m_storage.get(); }
-
-#if !ASSERT_DISABLED
-        virtual ~JSByteArray();
-#endif
-
-    protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
-
-    private:
-        JSByteArray(VPtrStealingHackType)
-            : JSNonFinalObject(VPtrStealingHack)
-        {
-        }
-
-        RefPtr<WTF::ByteArray> m_storage;
-    };
-    
-    JSByteArray* asByteArray(JSValue value);
-    inline JSByteArray* asByteArray(JSValue value)
-    {
-        return static_cast<JSByteArray*>(value.asCell());
-    }
-
-    inline bool isJSByteArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsByteArrayVPtr; }
-
-} // namespace JSC
-
-#endif // JSByteArray_h
index 0606cd40886f3376d45cffb4361559c3989a7a55..7f9ba88a2773fbce8bedbcef77194613d1e526eb 100644 (file)
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSObject.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSObject.h"
+#include "NumberObject.h"
 #include <wtf/MathExtras.h>
 
 namespace JSC {
 
 #include <wtf/MathExtras.h>
 
 namespace JSC {
 
-#if defined NAN && defined INFINITY
-
-extern const double NaN = NAN;
-extern const double Inf = INFINITY;
-
-#else // !(defined NAN && defined INFINITY)
-
-// The trick is to define the NaN and Inf globals with a different type than the declaration.
-// This trick works because the mangled name of the globals does not include the type, although
-// I'm not sure that's guaranteed. There could be alignment issues with this, since arrays of
-// characters don't necessarily need the same alignment doubles do, but for now it seems to work.
-// It would be good to figure out a 100% clean way that still avoids code that runs at init time.
-
-// Note, we have to use union to ensure alignment. Otherwise, NaN_Bytes can start anywhere,
-// while NaN_double has to be 4-byte aligned for 32-bits.
-// With -fstrict-aliasing enabled, unions are the only safe way to do type masquerading.
-
-static const union {
-    struct {
-        unsigned char NaN_Bytes[8];
-        unsigned char Inf_Bytes[8];
-    } bytes;
-    
-    struct {
-        double NaN_Double;
-        double Inf_Double;
-    } doubles;
-    
-} NaNInf = { {
-#if CPU(BIG_ENDIAN)
-    { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 },
-    { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
-#elif CPU(MIDDLE_ENDIAN)
-    { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 },
-    { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 }
-#else
-    { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f },
-    { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }
-#endif
-} } ;
-
-extern const double NaN = NaNInf.doubles.NaN_Double;
-extern const double Inf = NaNInf.doubles.Inf_Double;
-#endif // !(defined NAN && defined INFINITY)
-
-const ClassInfo JSCell::s_dummyCellInfo = { "DummyCell", 0, 0, 0 };
-
-bool JSCell::getUInt32(uint32_t&) const
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSCell);
+
+void JSCell::destroy(JSCell* cell)
 {
 {
-    return false;
+    cell->JSCell::~JSCell();
 }
 
 bool JSCell::getString(ExecState* exec, UString&stringValue) const
 }
 
 bool JSCell::getString(ExecState* exec, UString&stringValue) const
@@ -106,124 +61,155 @@ const JSObject* JSCell::getObject() const
     return isObject() ? static_cast<const JSObject*>(this) : 0;
 }
 
     return isObject() ? static_cast<const JSObject*>(this) : 0;
 }
 
-CallType JSCell::getCallData(CallData&)
+CallType JSCell::getCallData(JSCell*, CallData&)
 {
     return CallTypeNone;
 }
 
 {
     return CallTypeNone;
 }
 
-ConstructType JSCell::getConstructData(ConstructData&)
+ConstructType JSCell::getConstructData(JSCell*, ConstructData&)
 {
     return ConstructTypeNone;
 }
 
 {
     return ConstructTypeNone;
 }
 
-bool JSCell::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot)
+bool JSCell::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& identifier, PropertySlot& slot)
 {
     // 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, exec->lexicalGlobalObject());
+    JSObject* object = cell->toObject(exec, exec->lexicalGlobalObject());
     slot.setBase(object);
     if (!object->getPropertySlot(exec, identifier, slot))
         slot.setUndefined();
     return true;
 }
 
     slot.setBase(object);
     if (!object->getPropertySlot(exec, identifier, slot))
         slot.setUndefined();
     return true;
 }
 
-bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySlot& slot)
+bool JSCell::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned identifier, PropertySlot& slot)
 {
     // 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, exec->lexicalGlobalObject());
+    JSObject* object = cell->toObject(exec, exec->lexicalGlobalObject());
     slot.setBase(object);
     if (!object->getPropertySlot(exec, identifier, slot))
         slot.setUndefined();
     return true;
 }
 
     slot.setBase(object);
     if (!object->getPropertySlot(exec, identifier, slot))
         slot.setUndefined();
     return true;
 }
 
-void JSCell::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot)
+void JSCell::put(JSCell* cell, ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot)
 {
 {
-    toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value, slot);
+    if (cell->isString()) {
+        JSValue(cell).putToPrimitive(exec, identifier, value, slot);
+        return;
+    }
+    JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject());
+    thisObject->methodTable()->put(thisObject, exec, identifier, value, slot);
 }
 
 }
 
-void JSCell::put(ExecState* exec, unsigned identifier, JSValue value)
+void JSCell::putByIndex(JSCell* cell, ExecState* exec, unsigned identifier, JSValue value, bool shouldThrow)
 {
 {
-    toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value);
+    if (cell->isString()) {
+        PutPropertySlot slot(shouldThrow);
+        JSValue(cell).putToPrimitive(exec, Identifier::from(exec, identifier), value, slot);
+        return;
+    }
+    JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject());
+    thisObject->methodTable()->putByIndex(thisObject, exec, identifier, value, shouldThrow);
 }
 
 }
 
-bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier)
+bool JSCell::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& identifier)
 {
 {
-    return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier);
+    JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject());
+    return thisObject->methodTable()->deleteProperty(thisObject, exec, identifier);
 }
 
 }
 
-bool JSCell::deleteProperty(ExecState* exec, unsigned identifier)
+bool JSCell::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned identifier)
 {
 {
-    return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier);
+    JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject());
+    return thisObject->methodTable()->deletePropertyByIndex(thisObject, exec, identifier);
 }
 
 }
 
-JSObject* JSCell::toThisObject(ExecState* exec) const
+JSObject* JSCell::toThisObject(JSCell* cell, ExecState* exec)
 {
 {
-    return toObject(exec, exec->lexicalGlobalObject());
+    return cell->toObject(exec, exec->lexicalGlobalObject());
 }
 
 }
 
-JSValue JSCell::getJSNumber()
+JSValue JSCell::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
 {
 {
-    return JSValue();
+    if (isString())
+        return static_cast<const JSString*>(this)->toPrimitive(exec, preferredType);
+    return static_cast<const JSObject*>(this)->toPrimitive(exec, preferredType);
 }
 
 }
 
-bool JSCell::isGetterSetter() const
+bool JSCell::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value) const
 {
 {
-    return false;
+    if (isString())
+        return static_cast<const JSString*>(this)->getPrimitiveNumber(exec, number, value);
+    return static_cast<const JSObject*>(this)->getPrimitiveNumber(exec, number, value);
+}
+
+double JSCell::toNumber(ExecState* exec) const
+{ 
+    if (isString())
+        return static_cast<const JSString*>(this)->toNumber(exec);
+    return static_cast<const JSObject*>(this)->toNumber(exec);
+}
+
+JSObject* JSCell::toObject(ExecState* exec, JSGlobalObject* globalObject) const
+{
+    if (isString())
+        return static_cast<const JSString*>(this)->toObject(exec, globalObject);
+    ASSERT(isObject());
+    return jsCast<JSObject*>(const_cast<JSCell*>(this));
 }
 
 }
 
-JSValue JSCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
+void slowValidateCell(JSCell* cell)
+{
+    ASSERT_GC_OBJECT_LOOKS_VALID(cell);
+}
+
+JSValue JSCell::defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType)
 {
     ASSERT_NOT_REACHED();
 {
     ASSERT_NOT_REACHED();
-    return JSValue();
+    return jsUndefined();
 }
 
 }
 
-bool JSCell::getPrimitiveNumber(ExecState*, double&, JSValue&)
+void JSCell::getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
 {
     ASSERT_NOT_REACHED();
 {
     ASSERT_NOT_REACHED();
-    return false;
 }
 
 }
 
-bool JSCell::toBoolean(ExecState*) const
+UString JSCell::className(const JSObject*)
 {
     ASSERT_NOT_REACHED();
 {
     ASSERT_NOT_REACHED();
-    return false;
+    return UString();
 }
 
 }
 
-double JSCell::toNumber(ExecState*) const
+void JSCell::getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
 {
     ASSERT_NOT_REACHED();
 {
     ASSERT_NOT_REACHED();
-    return 0;
 }
 
 }
 
-UString JSCell::toString(ExecState*) const
+bool JSCell::hasInstance(JSObject*, ExecState*, JSValue, JSValue)
 {
     ASSERT_NOT_REACHED();
 {
     ASSERT_NOT_REACHED();
-    return UString();
+    return false;
 }
 
 }
 
-JSObject* JSCell::toObject(ExecState*, JSGlobalObject*) const
+void JSCell::putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned)
 {
     ASSERT_NOT_REACHED();
 {
     ASSERT_NOT_REACHED();
-    return 0;
 }
 
 }
 
-bool isZombie(const JSCell* cell)
+bool JSCell::defineOwnProperty(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool)
 {
 {
-#if ENABLE(JSC_ZOMBIES)
-    return cell && cell->isZombie();
-#else
-    UNUSED_PARAM(cell);
+    ASSERT_NOT_REACHED();
     return false;
     return false;
-#endif
 }
 
 }
 
-void slowValidateCell(JSCell* cell)
+bool JSCell::getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&)
 {
 {
-    ASSERT_GC_OBJECT_LOOKS_VALID(cell);
+    ASSERT_NOT_REACHED();
+    return false;
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index e30bc183ff69ce2396acef956e15ca566d15777d..431e67145320908d0860d13f97c2a4be70747157 100644 (file)
 #include "Heap.h"
 #include "JSLock.h"
 #include "JSValueInlineMethods.h"
 #include "Heap.h"
 #include "JSLock.h"
 #include "JSValueInlineMethods.h"
-#include "MarkStack.h"
+#include "SlotVisitor.h"
 #include "WriteBarrier.h"
 #include <wtf/Noncopyable.h>
 
 namespace JSC {
 
     class JSGlobalObject;
 #include "WriteBarrier.h"
 #include <wtf/Noncopyable.h>
 
 namespace JSC {
 
     class JSGlobalObject;
+    class LLIntOffsetsExtractor;
+    class PropertyDescriptor;
+    class PropertyNameArray;
     class Structure;
 
     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);
+    enum EnumerationMode {
+        ExcludeDontEnumProperties,
+        IncludeDontEnumProperties
+    };
 
 
-    protected:
-        MSVCBugWorkaround() { }
-        ~MSVCBugWorkaround() { }
+    enum TypedArrayType {
+        TypedArrayNone,
+        TypedArrayInt8,
+        TypedArrayInt16,
+        TypedArrayInt32,
+        TypedArrayUint8,
+        TypedArrayUint8Clamped,
+        TypedArrayUint16,
+        TypedArrayUint32,
+        TypedArrayFloat32,
+        TypedArrayFloat64
     };
 
     };
 
-    class JSCell : MSVCBugWorkaround {
-#else
     class JSCell {
     class JSCell {
-        WTF_MAKE_NONCOPYABLE(JSCell);
-#endif
-
-        friend class ExecutableBase;
-        friend class GetterSetter;
-        friend class Heap;
-        friend class JSObject;
-        friend class JSPropertyNameIterator;
-        friend class JSString;
         friend class JSValue;
         friend class JSValue;
-        friend class JSAPIValueWrapper;
-        friend class JSZombie;
-        friend class JSGlobalData;
-        friend class MarkedSpace;
         friend class MarkedBlock;
         friend class MarkedBlock;
-        friend class ScopeChainNode;
-        friend class Structure;
-        friend class StructureChain;
-        friend class RegExp;
+        template<typename T> friend void* allocateCell(Heap&);
+
+    public:
         enum CreatingEarlyCellTag { CreatingEarlyCell };
         enum CreatingEarlyCellTag { CreatingEarlyCell };
+        JSCell(CreatingEarlyCellTag);
 
     protected:
 
     protected:
-        enum VPtrStealingHackType { VPtrStealingHack };
-
-    private:
-        explicit JSCell(VPtrStealingHackType) { }
         JSCell(JSGlobalData&, Structure*);
         JSCell(JSGlobalData&, Structure*);
-        JSCell(JSGlobalData&, Structure*, CreatingEarlyCellTag);
-        virtual ~JSCell();
-        static const ClassInfo s_dummyCellInfo;
+        JS_EXPORT_PRIVATE static void destroy(JSCell*);
 
     public:
 
     public:
-        static Structure* createDummyStructure(JSGlobalData&);
-
         // Querying the type.
         bool isString() const;
         bool isObject() const;
         // Querying the type.
         bool isString() const;
         bool isObject() const;
-        virtual bool isGetterSetter() const;
+        bool isGetterSetter() const;
         bool inherits(const ClassInfo*) const;
         bool inherits(const ClassInfo*) const;
-        virtual bool isAPIValueWrapper() const { return false; }
-        virtual bool isPropertyNameIterator() const { return false; }
+        bool isAPIValueWrapper() const;
 
         Structure* structure() const;
 
         Structure* structure() const;
+        void setStructure(JSGlobalData&, Structure*);
+        void clearStructure() { m_structure.clear(); }
 
         // Extracting the value.
 
         // Extracting the value.
-        bool getString(ExecState* exec, UString&) const;
-        UString getString(ExecState* exec) const; // null string if not a string
-        JSObject* getObject(); // NULL if not an object
+        JS_EXPORT_PRIVATE bool getString(ExecState* exec, UString&) const;
+        JS_EXPORT_PRIVATE UString getString(ExecState* exec) const; // null string if not a string
+        JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object
         const JSObject* getObject() const; // NULL if not an object
         
         const JSObject* getObject() const; // NULL if not an object
         
-        virtual CallType getCallData(CallData&);
-        virtual ConstructType getConstructData(ConstructData&);
-
-        // Extracting integer values.
-        // FIXME: remove these methods, can check isNumberCell in JSValue && then call asNumberCell::*.
-        virtual bool getUInt32(uint32_t&) const;
+        JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&);
+        JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&);
 
         // Basic conversions.
 
         // Basic conversions.
-        virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
-        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
-        virtual bool toBoolean(ExecState*) const;
-        virtual double toNumber(ExecState*) const;
-        virtual UString toString(ExecState*) const;
-        virtual JSObject* toObject(ExecState*, JSGlobalObject*) const;
-
-        // Garbage collection.
-        void* operator new(size_t, ExecState*);
-        void* operator new(size_t, JSGlobalData*);
-        void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
-
-        virtual void visitChildren(SlotVisitor&);
-#if ENABLE(JSC_ZOMBIES)
-        virtual bool isZombie() const { return false; }
-#endif
+        JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+        bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
+        bool toBoolean(ExecState*) const;
+        JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
+        JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const;
+
+        static void visitChildren(JSCell*, SlotVisitor&);
 
         // Object operations, with the toObject operation included.
         const ClassInfo* classInfo() const;
 
         // Object operations, with the toObject operation included.
         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 bool deleteProperty(ExecState*, unsigned propertyName);
+        const ClassInfo* validatedClassInfo() const;
+        const MethodTable* methodTable() const;
+        static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+        static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
+        
+        static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
+        static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
+
+        static JSObject* toThisObject(JSCell*, ExecState*);
 
 
-        virtual JSObject* toThisObject(ExecState*) const;
-        virtual JSValue getJSNumber();
-        void* vptr() { return *reinterpret_cast<void**>(this); }
-        void setVPtr(void* vptr) { *reinterpret_cast<void**>(this) = vptr; }
+        void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; }
+        bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); }
 
         // FIXME: Rename getOwnPropertySlot to virtualGetOwnPropertySlot, and
         // fastGetOwnPropertySlot to getOwnPropertySlot. Callers should always
         // call this function, not its slower virtual counterpart. (For integer
         // property names, we want a similar interface with appropriate optimizations.)
         bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
 
         // FIXME: Rename getOwnPropertySlot to virtualGetOwnPropertySlot, and
         // fastGetOwnPropertySlot to getOwnPropertySlot. Callers should always
         // call this function, not its slower virtual counterpart. (For integer
         // property names, we want a similar interface with appropriate optimizations.)
         bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+        JSValue fastGetOwnProperty(ExecState*, const UString&);
 
         static ptrdiff_t structureOffset()
         {
             return OBJECT_OFFSETOF(JSCell, m_structure);
         }
 
 
         static ptrdiff_t structureOffset()
         {
             return OBJECT_OFFSETOF(JSCell, m_structure);
         }
 
+        static ptrdiff_t classInfoOffset()
+        {
+            return OBJECT_OFFSETOF(JSCell, m_classInfo);
+        }
+        
+        void* structureAddress()
+        {
+            return &m_structure;
+        }
+
 #if ENABLE(GC_VALIDATION)
         Structure* unvalidatedStructure() { return m_structure.unvalidatedGet(); }
 #endif
         
 #if ENABLE(GC_VALIDATION)
         Structure* unvalidatedStructure() { return m_structure.unvalidatedGet(); }
 #endif
         
+        static const TypedArrayType TypedArrayStorageType = TypedArrayNone;
     protected:
     protected:
-        static const unsigned AnonymousSlotCount = 0;
 
 
-    private:
+        void finishCreation(JSGlobalData&);
+        void finishCreation(JSGlobalData&, Structure*, CreatingEarlyCellTag);
+
         // Base implementation; for non-object classes implements getPropertySlot.
         // Base implementation; for non-object classes implements getPropertySlot.
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
-        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
+        static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+
+        // Dummy implementations of override-able static functions for classes to put in their MethodTable
+        static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
+        static NO_RETURN_DUE_TO_ASSERT void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+        static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+        static UString className(const JSObject*);
+        static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty);
+        static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
+        static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+
+    private:
+        friend class LLIntOffsetsExtractor;
         
         
+        const ClassInfo* m_classInfo;
         WriteBarrier<Structure> m_structure;
     };
 
         WriteBarrier<Structure> m_structure;
     };
 
-    inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure)
-        : m_structure(globalData, this, structure)
+    inline JSCell::JSCell(CreatingEarlyCellTag)
     {
     {
-        ASSERT(m_structure);
     }
 
     }
 
-    inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure, CreatingEarlyCellTag)
+    inline void JSCell::finishCreation(JSGlobalData& globalData)
     {
 #if ENABLE(GC_VALIDATION)
     {
 #if ENABLE(GC_VALIDATION)
-        if (structure)
+        ASSERT(globalData.isInitializingObject());
+        globalData.setInitializingObjectClass(0);
+#else
+        UNUSED_PARAM(globalData);
 #endif
 #endif
-            m_structure.setEarlyValue(globalData, this, structure);
-        // Very first set of allocations won't have a real structure.
-        ASSERT(m_structure || !globalData.dummyMarkableCellStructure);
+        ASSERT(m_structure);
     }
 
     }
 
-    inline JSCell::~JSCell()
+    inline Structure* JSCell::structure() const
     {
     {
-#if ENABLE(GC_VALIDATION)
-        m_structure.clear();
-#endif
+        return m_structure.get();
     }
 
     }
 
-    inline Structure* JSCell::structure() const
+    inline const ClassInfo* JSCell::classInfo() const
     {
     {
-        return m_structure.get();
+        return m_classInfo;
     }
 
     }
 
-    inline void JSCell::visitChildren(SlotVisitor& visitor)
+    inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
     {
     {
-        visitor.append(&m_structure);
+        visitor.append(&cell->m_structure);
     }
 
     // --- JSValue inlines ----------------------------
     }
 
     // --- JSValue inlines ----------------------------
@@ -206,6 +207,11 @@ namespace JSC {
         return isCell() && asCell()->isString();
     }
 
         return isCell() && asCell()->isString();
     }
 
+    inline bool JSValue::isPrimitive() const
+    {
+        return !isCell() || asCell()->isString();
+    }
+
     inline bool JSValue::isGetterSetter() const
     {
         return isCell() && asCell()->isGetterSetter();
     inline bool JSValue::isGetterSetter() const
     {
         return isCell() && asCell()->isGetterSetter();
@@ -236,20 +242,6 @@ namespace JSC {
         return isCell() ? asCell()->getObject() : 0;
     }
 
         return isCell() ? asCell()->getObject() : 0;
     }
 
-    inline CallType getCallData(JSValue value, CallData& callData)
-    {
-        CallType result = value.isCell() ? value.asCell()->getCallData(callData) : CallTypeNone;
-        ASSERT(result == CallTypeNone || value.isValidCallee());
-        return result;
-    }
-
-    inline ConstructType getConstructData(JSValue value, ConstructData& constructData)
-    {
-        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
     {
         if (isInt32()) {
     ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
     {
         if (isInt32()) {
@@ -295,42 +287,18 @@ namespace JSC {
             return true;
         }
         ASSERT(isUndefined());
             return true;
         }
         ASSERT(isUndefined());
-        number = nonInlineNaN();
+        number = std::numeric_limits<double>::quiet_NaN();
         value = *this;
         return true;
     }
 
         value = *this;
         return true;
     }
 
-    inline bool JSValue::toBoolean(ExecState* exec) const
-    {
-        if (isInt32())
-            return asInt32() != 0;
-        if (isDouble())
-            return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN
-        if (isCell())
-            return asCell()->toBoolean(exec);
-        return isTrue(); // false, null, and undefined all convert to false.
-    }
-
     ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
     {
         if (isInt32())
             return asInt32();
         if (isDouble())
             return asDouble();
     ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
     {
         if (isInt32())
             return asInt32();
         if (isDouble())
             return asDouble();
-        if (isCell())
-            return asCell()->toNumber(exec);
-        if (isTrue())
-            return 1.0;
-        return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0.
-    }
-
-    inline JSValue JSValue::getJSNumber()
-    {
-        if (isInt32() || isDouble())
-            return *this;
-        if (isCell())
-            return asCell()->getJSNumber();
-        return JSValue();
+        return toNumberSlowCase(exec);
     }
 
     inline JSObject* JSValue::toObject(ExecState* exec) const
     }
 
     inline JSObject* JSValue::toObject(ExecState* exec) const
@@ -343,88 +311,66 @@ namespace JSC {
         return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
     }
 
         return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
     }
 
-    inline JSObject* JSValue::toThisObject(ExecState* exec) const
-    {
-        return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
-    }
-
-    inline Heap* Heap::heap(JSValue v)
-    {
-        if (!v.isCell())
-            return 0;
-        return heap(v.asCell());
-    }
-
-    inline Heap* Heap::heap(JSCell* c)
-    {
-        return MarkedSpace::heap(c);
-    }
-    
-#if ENABLE(JSC_ZOMBIES)
-    inline bool JSValue::isZombie() const
-    {
-        return isCell() && asCell() > (JSCell*)0x1ffffffffL && asCell()->isZombie();
-    }
+#if COMPILER(CLANG)
+    template<class T>
+    struct NeedsDestructor {
+        static const bool value = !__has_trivial_destructor(T);
+    };
+#else
+    // Write manual specializations for this struct template if you care about non-clang compilers.
+    template<class T>
+    struct NeedsDestructor {
+        static const bool value = true;
+    };
 #endif
 
 #endif
 
-    inline void* MarkedBlock::allocate()
+    template<typename T>
+    void* allocateCell(Heap& heap)
     {
     {
-        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;
+#if ENABLE(GC_VALIDATION)
+        ASSERT(!heap.globalData()->isInitializingObject());
+        heap.globalData()->setInitializingObjectClass(&T::s_info);
+#endif
+        JSCell* result = 0;
+        if (NeedsDestructor<T>::value)
+            result = static_cast<JSCell*>(heap.allocateWithDestructor(sizeof(T)));
+        else {
+            ASSERT(T::s_info.methodTable.destroy == JSCell::destroy);
+            result = static_cast<JSCell*>(heap.allocateWithoutDestructor(sizeof(T)));
         }
         }
-
-        return 0;
+        result->clearStructure();
+        return result;
     }
     
     }
     
-    inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes)
+    inline bool isZapped(const JSCell* cell)
     {
     {
-        ASSERT(bytes && bytes < maxCellSize);
-        if (bytes < preciseCutoff)
-            return m_preciseSizeClasses[(bytes - 1) / preciseStep];
-        return m_impreciseSizeClasses[(bytes - 1) / impreciseStep];
+        return cell->isZapped();
     }
 
     }
 
-    inline void* MarkedSpace::allocate(size_t bytes)
+    template<typename To, typename From>
+    inline To jsCast(From* from)
     {
     {
-        SizeClass& sizeClass = sizeClassFor(bytes);
-        return allocateFromSizeClass(sizeClass);
+        ASSERT(!from || from->JSCell::inherits(&WTF::RemovePointer<To>::Type::s_info));
+        return static_cast<To>(from);
     }
     }
-    
-    inline void* Heap::allocate(size_t bytes)
+
+    template<typename To>
+    inline To jsCast(JSValue from)
     {
     {
-        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);
+        ASSERT(from.isCell() && from.asCell()->JSCell::inherits(&WTF::RemovePointer<To>::Type::s_info));
+        return static_cast<To>(from.asCell());
     }
 
     }
 
-    inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
+    template<typename To, typename From>
+    inline To jsDynamicCast(From* from)
     {
     {
-        JSCell* result = static_cast<JSCell*>(globalData->heap.allocate(size));
-        result->m_structure.clear();
-        return result;
+        return from->inherits(&WTF::RemovePointer<To>::Type::s_info) ? static_cast<To>(from) : 0;
     }
 
     }
 
-    inline void* JSCell::operator new(size_t size, ExecState* exec)
+    template<typename To>
+    inline To jsDynamicCast(JSValue from)
     {
     {
-        JSCell* result = static_cast<JSCell*>(exec->heap()->allocate(size));
-        result->m_structure.clear();
-        return result;
+        return from.isCell() && from.asCell()->inherits(&WTF::RemovePointer<To>::Type::s_info) ? static_cast<To>(from.asCell()) : 0;
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
diff --git a/runtime/JSDateMath.cpp b/runtime/JSDateMath.cpp
new file mode 100644 (file)
index 0000000..dbe7488
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * 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) 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 Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. 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.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.
+
+ * Copyright 2006-2008 the V8 project authors. 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 "JSDateMath.h"
+
+#include "JSObject.h"
+#include "ScopeChain.h"
+
+#include <algorithm>
+#include <limits.h>
+#include <limits>
+#include <stdint.h>
+#include <time.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/Assertions.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/MathExtras.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/StringExtras.h>
+#include <wtf/text/StringBuilder.h>
+
+#if HAVE(ERRNO_H)
+#include <errno.h>
+#endif
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if HAVE(SYS_TIMEB_H)
+#include <sys/timeb.h>
+#endif
+
+using namespace WTF;
+
+namespace JSC {
+
+static inline double timeToMS(double hour, double min, double sec, double ms)
+{
+    return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms);
+}
+
+static inline int msToSeconds(double ms)
+{
+    double result = fmod(floor(ms / msPerSecond), secondsPerMinute);
+    if (result < 0)
+        result += secondsPerMinute;
+    return static_cast<int>(result);
+}
+
+// 0: Sunday, 1: Monday, etc.
+static inline int msToWeekDay(double ms)
+{
+    int wd = (static_cast<int>(msToDays(ms)) + 4) % 7;
+    if (wd < 0)
+        wd += 7;
+    return wd;
+}
+
+// Get the DST offset for the time passed in.
+//
+// NOTE: The implementation relies on the fact that no time zones have
+// more than one daylight savings offset change per month.
+// If this function is called with NaN it returns NaN.
+static double getDSTOffset(ExecState* exec, double ms, double utcOffset)
+{
+    DSTOffsetCache& cache = exec->globalData().dstOffsetCache;
+    double start = cache.start;
+    double end = cache.end;
+
+    if (start <= ms) {
+        // If the time fits in the cached interval, return the cached offset.
+        if (ms <= end) return cache.offset;
+
+        // Compute a possible new interval end.
+        double newEnd = end + cache.increment;
+
+        if (ms <= newEnd) {
+            double endOffset = calculateDSTOffset(newEnd, utcOffset);
+            if (cache.offset == endOffset) {
+                // If the offset at the end of the new interval still matches
+                // the offset in the cache, we grow the cached time interval
+                // and return the offset.
+                cache.end = newEnd;
+                cache.increment = msPerMonth;
+                return endOffset;
+            } else {
+                double offset = calculateDSTOffset(ms, utcOffset);
+                if (offset == endOffset) {
+                    // The offset at the given time is equal to the offset at the
+                    // new end of the interval, so that means that we've just skipped
+                    // the point in time where the DST offset change occurred. Updated
+                    // the interval to reflect this and reset the increment.
+                    cache.start = ms;
+                    cache.end = newEnd;
+                    cache.increment = msPerMonth;
+                } else {
+                    // The interval contains a DST offset change and the given time is
+                    // before it. Adjust the increment to avoid a linear search for
+                    // the offset change point and change the end of the interval.
+                    cache.increment /= 3;
+                    cache.end = ms;
+                }
+                // Update the offset in the cache and return it.
+                cache.offset = offset;
+                return offset;
+            }
+        }
+    }
+
+    // Compute the DST offset for the time and shrink the cache interval
+    // to only contain the time. This allows fast repeated DST offset
+    // computations for the same time.
+    double offset = calculateDSTOffset(ms, utcOffset);
+    cache.offset = offset;
+    cache.start = ms;
+    cache.end = ms;
+    cache.increment = msPerMonth;
+    return offset;
+}
+
+/*
+ * Get the difference in milliseconds between this time zone and UTC (GMT)
+ * NOT including DST.
+ */
+double getUTCOffset(ExecState* exec)
+{
+    double utcOffset = exec->globalData().cachedUTCOffset;
+    if (!isnan(utcOffset))
+        return utcOffset;
+    exec->globalData().cachedUTCOffset = calculateUTCOffset();
+    return exec->globalData().cachedUTCOffset;
+}
+
+double gregorianDateTimeToMS(ExecState* exec, const GregorianDateTime& t, double milliSeconds, bool inputIsUTC)
+{
+    double day = dateToDaysFrom1970(t.year + 1900, t.month, t.monthDay);
+    double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds);
+    double result = (day * WTF::msPerDay) + ms;
+
+    if (!inputIsUTC) { // convert to UTC
+        double utcOffset = getUTCOffset(exec);
+        result -= utcOffset;
+        result -= getDSTOffset(exec, result, utcOffset);
+    }
+
+    return result;
+}
+
+// input is UTC
+void msToGregorianDateTime(ExecState* exec, double ms, bool outputIsUTC, GregorianDateTime& tm)
+{
+    double dstOff = 0.0;
+    double utcOff = 0.0;
+    if (!outputIsUTC) {
+        utcOff = getUTCOffset(exec);
+        dstOff = getDSTOffset(exec, ms, utcOff);
+        ms += dstOff + utcOff;
+    }
+
+    const int year = msToYear(ms);
+    tm.second   =  msToSeconds(ms);
+    tm.minute   =  msToMinutes(ms);
+    tm.hour     =  msToHours(ms);
+    tm.weekDay  =  msToWeekDay(ms);
+    tm.yearDay  =  dayInYear(ms, year);
+    tm.monthDay =  dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year));
+    tm.month    =  monthFromDayInYear(tm.yearDay, isLeapYear(year));
+    tm.year     =  year - 1900;
+    tm.isDST    =  dstOff != 0.0;
+    tm.utcOffset = static_cast<long>((dstOff + utcOff) / WTF::msPerSecond);
+    tm.timeZone = nullptr;
+}
+
+double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateString)
+{
+    ASSERT(exec);
+    bool haveTZ;
+    int offset;
+    double ms = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset);
+    if (isnan(ms))
+        return std::numeric_limits<double>::quiet_NaN();
+
+    // fall back to local timezone
+    if (!haveTZ) {
+        double utcOffset = getUTCOffset(exec);
+        double dstOffset = getDSTOffset(exec, ms, utcOffset);
+        offset = static_cast<int>((utcOffset + dstOffset) / WTF::msPerMinute);
+    }
+    return ms - (offset * WTF::msPerMinute);
+}
+
+} // namespace JSC
diff --git a/runtime/JSDateMath.h b/runtime/JSDateMath.h
new file mode 100644 (file)
index 0000000..f77cf1e
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ */
+
+#ifndef JSDateMath_h
+#define JSDateMath_h
+
+#include <wtf/DateMath.h>
+
+namespace JSC {
+
+class ExecState;
+struct GregorianDateTime;
+
+void msToGregorianDateTime(ExecState*, double, bool outputIsUTC, GregorianDateTime&);
+double gregorianDateTimeToMS(ExecState*, const GregorianDateTime&, double, bool inputIsUTC);
+double getUTCOffset(ExecState*);
+double parseDateFromNullTerminatedCharacters(ExecState*, const char* dateString);
+
+// Intentionally overridding the default tm of the system.
+// The members of tm differ on various operating systems.
+struct GregorianDateTime {
+    WTF_MAKE_NONCOPYABLE(GregorianDateTime);
+public:
+    GregorianDateTime()
+        : second(0)
+        , minute(0)
+        , hour(0)
+        , weekDay(0)
+        , monthDay(0)
+        , yearDay(0)
+        , month(0)
+        , year(0)
+        , isDST(0)
+        , utcOffset(0)
+    {
+    }
+
+    operator tm() const
+    {
+        tm ret;
+        memset(&ret, 0, sizeof(ret));
+
+        ret.tm_sec   =  second;
+        ret.tm_min   =  minute;
+        ret.tm_hour  =  hour;
+        ret.tm_wday  =  weekDay;
+        ret.tm_mday  =  monthDay;
+        ret.tm_yday  =  yearDay;
+        ret.tm_mon   =  month;
+        ret.tm_year  =  year;
+        ret.tm_isdst =  isDST;
+
+#if HAVE(TM_GMTOFF)
+        ret.tm_gmtoff = static_cast<long>(utcOffset);
+#endif
+#if HAVE(TM_ZONE)
+        ret.tm_zone = timeZone.get();
+#endif
+
+        return ret;
+    }
+
+    void copyFrom(const GregorianDateTime& rhs)
+    {
+        second = rhs.second;
+        minute = rhs.minute;
+        hour = rhs.hour;
+        weekDay = rhs.weekDay;
+        monthDay = rhs.monthDay;
+        yearDay = rhs.yearDay;
+        month = rhs.month;
+        year = rhs.year;
+        isDST = rhs.isDST;
+        utcOffset = rhs.utcOffset;
+        if (rhs.timeZone) {
+            int inZoneSize = strlen(rhs.timeZone.get()) + 1;
+            timeZone = adoptArrayPtr(new char[inZoneSize]);
+            strncpy(timeZone.get(), rhs.timeZone.get(), inZoneSize);
+        } else
+            timeZone = nullptr;
+    }
+
+    int second;
+    int minute;
+    int hour;
+    int weekDay;
+    int monthDay;
+    int yearDay;
+    int month;
+    int year;
+    int isDST;
+    int utcOffset;
+    OwnArrayPtr<char> timeZone;
+};
+
+static inline int gmtoffset(const GregorianDateTime& t)
+{
+    return t.utcOffset;
+}
+
+} // namespace JSC
+
+#endif // JSDateMath_h
diff --git a/runtime/JSExportMacros.h b/runtime/JSExportMacros.h
new file mode 100644 (file)
index 0000000..884805f
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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 JSExportMacros_h
+#define JSExportMacros_h
+
+#include <wtf/Platform.h>
+#include <wtf/ExportMacros.h>
+
+// See note in wtf/Platform.h for more info on EXPORT_MACROS.
+#if USE(EXPORT_MACROS)
+
+#if defined(BUILDING_JavaScriptCore)
+#define JS_EXPORT_PRIVATE WTF_EXPORT
+#else
+#define JS_EXPORT_PRIVATE WTF_IMPORT
+#endif
+
+#define JS_EXPORT_HIDDEN WTF_HIDDEN
+#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)
+#define JS_EXPORTDATA __declspec(dllexport)
+#else
+#define JS_EXPORTDATA __declspec(dllimport)
+#endif
+
+#define JS_EXPORTCLASS JS_EXPORTDATA
+
+#else // !PLATFORM...
+
+#define JS_EXPORTDATA
+#define JS_EXPORTCLASS
+
+#endif // !PLATFORM...
+
+#define JS_EXPORT_PRIVATE
+#define JS_EXPORT_HIDDEN
+
+#endif // USE(EXPORT_MACROS)
+
+#endif // JSExportMacros_h
index e33d5d2561bf1f4f0d90d995f83a51c4169cd9bc..243946ba9026f2cb16a2e893bf67bebd95147989 100644 (file)
@@ -30,6 +30,8 @@
 #include "CallFrame.h"
 #include "ExceptionHelpers.h"
 #include "FunctionPrototype.h"
 #include "CallFrame.h"
 #include "ExceptionHelpers.h"
 #include "FunctionPrototype.h"
+#include "GetterSetter.h"
+#include "JSArray.h"
 #include "JSGlobalObject.h"
 #include "JSNotAnObject.h"
 #include "Interpreter.h"
 #include "JSGlobalObject.h"
 #include "JSNotAnObject.h"
 #include "Interpreter.h"
@@ -48,64 +50,66 @@ EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState* exec)
 }
 
 ASSERT_CLASS_FITS_IN_CELL(JSFunction);
 }
 
 ASSERT_CLASS_FITS_IN_CELL(JSFunction);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSFunction);
 
 
-const ClassInfo JSFunction::s_info = { "Function", &Base::s_info, 0, 0 };
+const ClassInfo JSFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSFunction) };
 
 bool JSFunction::isHostFunctionNonInline() const
 {
     return isHostFunction();
 }
 
 
 bool JSFunction::isHostFunctionNonInline() const
 {
     return isHostFunction();
 }
 
-JSFunction::JSFunction(VPtrStealingHackType)
-    : Base(VPtrStealingHack)
+JSFunction* JSFunction::create(ExecState* exec, JSGlobalObject* globalObject, int length, const Identifier& name, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor)
 {
 {
+    NativeExecutable* executable;
+#if !ENABLE(JIT)
+    UNUSED_PARAM(intrinsic);
+#else
+    if (intrinsic != NoIntrinsic && exec->globalData().canUseJIT()) {
+        ASSERT(nativeConstructor == callHostFunctionAsConstructor);
+        executable = exec->globalData().getHostFunction(nativeFunction, intrinsic);
+    } else
+#endif
+        executable = exec->globalData().getHostFunction(nativeFunction, nativeConstructor);
+
+    JSFunction* function = new (NotNull, allocateCell<JSFunction>(*exec->heap())) JSFunction(exec, globalObject, globalObject->functionStructure());
+    // Can't do this during initialization because getHostFunction might do a GC allocation.
+    function->finishCreation(exec, executable, length, name);
+    return function;
 }
 
 }
 
-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())
-{
-    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, JSGlobalObject* globalObject, Structure* structure, int length, const Identifier& name, NativeFunction func)
-    : Base(globalObject, structure)
+JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+    : Base(exec->globalData(), structure)
+    , m_executable()
     , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain())
 {
     , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain())
 {
-    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, FunctionExecutable* executable, ScopeChainNode* scopeChainNode)
 }
 
 JSFunction::JSFunction(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChainNode)
-    : Base(scopeChainNode->globalObject.get(), scopeChainNode->globalObject->functionStructure())
+    : Base(exec->globalData(), scopeChainNode->globalObject->functionStructure())
     , m_executable(exec->globalData(), this, executable)
     , m_scopeChain(exec->globalData(), this, scopeChainNode)
 {
     , m_executable(exec->globalData(), this, executable)
     , m_scopeChain(exec->globalData(), this, 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()
+void JSFunction::finishCreation(ExecState* exec, NativeExecutable* executable, int length, const Identifier& name)
 {
 {
-    ASSERT(vptr() == JSGlobalData::jsFunctionVPtr);
+    Base::finishCreation(exec->globalData());
+    ASSERT(inherits(&s_info));
+    m_executable.set(exec->globalData(), this, executable);
+    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);
 }
 
 }
 
-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)
+void JSFunction::finishCreation(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChainNode)
 {
 {
-    JSValue thrower = createTypeErrorFunction(exec, message);
-    descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
+    Base::finishCreation(exec->globalData());
+    ASSERT(inherits(&s_info));
+
+    // Switching the structure here is only safe if we currently have the function structure!
+    ASSERT(structure() == scopeChainNode->globalObject->functionStructure());
+    setStructure(exec->globalData(), scopeChainNode->globalObject->namedFunctionStructure());
+    putDirectOffset(exec->globalData(), scopeChainNode->globalObject->functionNameOffset(), executable->nameValue());
 }
 
 const UString& JSFunction::name(ExecState* exec)
 }
 
 const UString& JSFunction::name(ExecState* exec)
@@ -117,7 +121,7 @@ const UString JSFunction::displayName(ExecState* exec)
 {
     JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
     
 {
     JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
     
-    if (displayName && isJSString(&exec->globalData(), displayName))
+    if (displayName && isJSString(displayName))
         return asString(displayName)->tryGetValue();
     
     return UString();
         return asString(displayName)->tryGetValue();
     
     return UString();
@@ -130,210 +134,316 @@ const UString JSFunction::calculatedDisplayName(ExecState* exec)
     if (!explicitName.isEmpty())
         return explicitName;
     
     if (!explicitName.isEmpty())
         return explicitName;
     
-    return name(exec);
+    const UString actualName = name(exec);
+    if (!actualName.isEmpty() || isHostFunction())
+        return actualName;
+    
+    return jsExecutable()->inferredName().ustring();
+}
+
+const SourceCode* JSFunction::sourceCode() const
+{
+    if (isHostFunction())
+        return 0;
+    return &jsExecutable()->source();
 }
 
 }
 
-void JSFunction::visitChildren(SlotVisitor& visitor)
+void JSFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    JSFunction* thisObject = jsCast<JSFunction*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
-    Base::visitChildren(visitor);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    Base::visitChildren(thisObject, visitor);
 
 
-    visitor.append(&m_scopeChain);
-    if (m_executable)
-        visitor.append(&m_executable);
+    visitor.append(&thisObject->m_scopeChain);
+    if (thisObject->m_executable)
+        visitor.append(&thisObject->m_executable);
 }
 
 }
 
-CallType JSFunction::getCallData(CallData& callData)
+CallType JSFunction::getCallData(JSCell* cell, CallData& callData)
 {
 {
-    if (isHostFunction()) {
-        callData.native.function = nativeFunction();
+    JSFunction* thisObject = jsCast<JSFunction*>(cell);
+    if (thisObject->isHostFunction()) {
+        callData.native.function = thisObject->nativeFunction();
         return CallTypeHost;
     }
         return CallTypeHost;
     }
-    callData.js.functionExecutable = jsExecutable();
-    callData.js.scopeChain = scope();
+    callData.js.functionExecutable = thisObject->jsExecutable();
+    callData.js.scopeChain = thisObject->scope();
     return CallTypeJS;
 }
 
 JSValue JSFunction::argumentsGetter(ExecState* exec, JSValue slotBase, const Identifier&)
 {
     return CallTypeJS;
 }
 
 JSValue JSFunction::argumentsGetter(ExecState* exec, JSValue slotBase, const Identifier&)
 {
-    JSFunction* thisObj = asFunction(slotBase);
+    JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
     ASSERT(!thisObj->isHostFunction());
     ASSERT(!thisObj->isHostFunction());
-    return exec->interpreter()->retrieveArguments(exec, thisObj);
+    return exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObj);
 }
 
 JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identifier&)
 {
 }
 
 JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identifier&)
 {
-    JSFunction* thisObj = asFunction(slotBase);
+    JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
     ASSERT(!thisObj->isHostFunction());
     ASSERT(!thisObj->isHostFunction());
-    return exec->interpreter()->retrieveCaller(exec, thisObj);
+    JSValue caller = exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj);
+
+    // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller.
+    if (!caller.isObject() || !asObject(caller)->inherits(&JSFunction::s_info))
+        return caller;
+    JSFunction* function = jsCast<JSFunction*>(caller);
+    if (function->isHostFunction() || !function->jsExecutable()->isStrictMode())
+        return caller;
+    return throwTypeError(exec, "Function.caller used to retrieve strict caller");
 }
 
 JSValue JSFunction::lengthGetter(ExecState*, JSValue slotBase, const Identifier&)
 {
 }
 
 JSValue JSFunction::lengthGetter(ExecState*, JSValue slotBase, const Identifier&)
 {
-    JSFunction* thisObj = asFunction(slotBase);
+    JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
     ASSERT(!thisObj->isHostFunction());
     return jsNumber(thisObj->jsExecutable()->parameterCount());
 }
 
     ASSERT(!thisObj->isHostFunction());
     return jsNumber(thisObj->jsExecutable()->parameterCount());
 }
 
-static inline WriteBarrierBase<Unknown>* createPrototypeProperty(JSGlobalData& globalData, JSGlobalObject* globalObject, JSFunction* function)
+bool JSFunction::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
-    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)
-{
-    if (isHostFunction())
-        return Base::getOwnPropertySlot(exec, propertyName, slot);
+    JSFunction* thisObject = jsCast<JSFunction*>(cell);
+    if (thisObject->isHostFunction())
+        return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
 
     if (propertyName == exec->propertyNames().prototype) {
 
     if (propertyName == exec->propertyNames().prototype) {
-        WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName);
+        WriteBarrierBase<Unknown>* location = thisObject->getDirectLocation(exec->globalData(), propertyName);
 
 
-        if (!location)
-            location = createPrototypeProperty(exec->globalData(), scope()->globalObject.get(), this);
+        if (!location) {
+            JSObject* prototype = constructEmptyObject(exec, thisObject->globalObject()->emptyObjectStructure());
+            prototype->putDirect(exec->globalData(), exec->propertyNames().constructor, thisObject, DontEnum);
+            thisObject->putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
+            location = thisObject->getDirectLocation(exec->globalData(), exec->propertyNames().prototype);
+        }
 
 
-        slot.setValue(this, location->get(), offsetForLocation(location));
+        slot.setValue(thisObject, location->get(), thisObject->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;
+        if (thisObject->jsExecutable()->isStrictMode()) {
+            bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+            if (!result) {
+                thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+                result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+                ASSERT(result);
+            }
+            return result;
         }
         }
-   
-        slot.setCacheableCustom(this, argumentsGetter);
+        slot.setCacheableCustom(thisObject, argumentsGetter);
         return true;
     }
 
     if (propertyName == exec->propertyNames().length) {
         return true;
     }
 
     if (propertyName == exec->propertyNames().length) {
-        slot.setCacheableCustom(this, lengthGetter);
+        slot.setCacheableCustom(thisObject, lengthGetter);
         return true;
     }
 
     if (propertyName == exec->propertyNames().caller) {
         return true;
     }
 
     if (propertyName == exec->propertyNames().caller) {
-        if (jsExecutable()->isStrictMode()) {
-            throwTypeError(exec, StrictModeCallerAccessError);
-            slot.setValue(jsNull());
-            return true;
+        if (thisObject->jsExecutable()->isStrictMode()) {
+            bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+            if (!result) {
+                thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+                result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+                ASSERT(result);
+            }
+            return result;
         }
         }
-        slot.setCacheableCustom(this, callerGetter);
+        slot.setCacheableCustom(thisObject, callerGetter);
         return true;
     }
 
         return true;
     }
 
-    return Base::getOwnPropertySlot(exec, propertyName, slot);
+    return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
 }
 
 }
 
-bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool JSFunction::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    if (isHostFunction())
-        return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    JSFunction* thisObject = jsCast<JSFunction*>(object);
+    if (thisObject->isHostFunction())
+        return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
     
     if (propertyName == exec->propertyNames().prototype) {
         PropertySlot slot;
     
     if (propertyName == exec->propertyNames().prototype) {
         PropertySlot slot;
-        getOwnPropertySlot(exec, propertyName, slot);
-        return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+        thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
+        return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
     }
     
     if (propertyName == exec->propertyNames().arguments) {
     }
     
     if (propertyName == exec->propertyNames().arguments) {
-        if (jsExecutable()->isStrictMode())
-            createDescriptorForThrowingProperty(exec, descriptor, StrictModeArgumentsAccessError);
-        else
-            descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete);
+        if (thisObject->jsExecutable()->isStrictMode()) {
+            bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
+            if (!result) {
+                thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+                result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
+                ASSERT(result);
+            }
+            return result;
+        }
+        descriptor.setDescriptor(exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete);
         return true;
     }
     
     if (propertyName == exec->propertyNames().length) {
         return true;
     }
     
     if (propertyName == exec->propertyNames().length) {
-        descriptor.setDescriptor(jsNumber(jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
+        descriptor.setDescriptor(jsNumber(thisObject->jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
         return true;
     }
     
     if (propertyName == exec->propertyNames().caller) {
         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);
+        if (thisObject->jsExecutable()->isStrictMode()) {
+            bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
+            if (!result) {
+                thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+                result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
+                ASSERT(result);
+            }
+            return result;
+        }
+        descriptor.setDescriptor(exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete);
         return true;
     }
     
         return true;
     }
     
-    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
 }
 
 }
 
-void JSFunction::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void JSFunction::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
-    if (!isHostFunction() && (mode == IncludeDontEnumProperties)) {
+    JSFunction* thisObject = jsCast<JSFunction*>(object);
+    if (!thisObject->isHostFunction() && (mode == IncludeDontEnumProperties)) {
         // Make sure prototype has been reified.
         PropertySlot slot;
         // Make sure prototype has been reified.
         PropertySlot slot;
-        getOwnPropertySlot(exec, exec->propertyNames().prototype, slot);
+        thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, exec->propertyNames().prototype, slot);
 
         propertyNames.add(exec->propertyNames().arguments);
 
         propertyNames.add(exec->propertyNames().arguments);
-        propertyNames.add(exec->propertyNames().callee);
         propertyNames.add(exec->propertyNames().caller);
         propertyNames.add(exec->propertyNames().length);
     }
         propertyNames.add(exec->propertyNames().caller);
         propertyNames.add(exec->propertyNames().length);
     }
-    Base::getOwnPropertyNames(exec, propertyNames, mode);
+    Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
 }
 
 }
 
-void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void JSFunction::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
-    if (isHostFunction()) {
-        Base::put(exec, propertyName, value, slot);
+    JSFunction* thisObject = jsCast<JSFunction*>(cell);
+    if (thisObject->isHostFunction()) {
+        Base::put(thisObject, 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;
         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);
+        thisObject->methodTable()->getOwnPropertySlot(thisObject, 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 (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
+        // This will trigger the property to be reified, if this is not already the case!
+        bool okay = thisObject->hasProperty(exec, propertyName);
+        ASSERT_UNUSED(okay, okay);
+        Base::put(thisObject, exec, propertyName, value, slot);
+        return;
     }
     }
-    if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
+    if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length || propertyName == exec->propertyNames().caller) {
+        if (slot.isStrictMode())
+            throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
         return;
         return;
-    Base::put(exec, propertyName, value, slot);
+    }
+    Base::put(thisObject, exec, propertyName, value, slot);
 }
 
 }
 
-bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)
+bool JSFunction::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
 {
 {
-    if (isHostFunction())
-        return Base::deleteProperty(exec, propertyName);
-    if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
+    JSFunction* thisObject = jsCast<JSFunction*>(cell);
+    // For non-host functions, don't let these properties by deleted - except by DefineOwnProperty.
+    if (!thisObject->isHostFunction() && !exec->globalData().isInDefineOwnProperty()
+        && (propertyName == exec->propertyNames().arguments
+            || propertyName == exec->propertyNames().length
+            || propertyName == exec->propertyNames().prototype
+            || propertyName == exec->propertyNames().caller))
+        return false;
+    return Base::deleteProperty(thisObject, exec, propertyName);
+}
+
+bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
+{
+    JSFunction* thisObject = jsCast<JSFunction*>(object);
+    if (thisObject->isHostFunction())
+        return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+
+    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;
+        thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
+        return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+    }
+
+    bool valueCheck;
+    if (propertyName == exec->propertyNames().arguments) {
+        if (thisObject->jsExecutable()->isStrictMode()) {
+            if (!Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor))
+                thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+            return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+        }
+        valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject));
+    } else if (propertyName == exec->propertyNames().caller) {
+        if (thisObject->jsExecutable()->isStrictMode()) {
+            if (!Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor))
+                thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+            return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+        }
+        valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject));
+    } else if (propertyName == exec->propertyNames().length)
+        valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount()));
+    else
+        return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+     
+    if (descriptor.configurablePresent() && descriptor.configurable()) {
+        if (throwException)
+            throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property."));
+        return false;
+    }
+    if (descriptor.enumerablePresent() && descriptor.enumerable()) {
+        if (throwException)
+            throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property."));
+        return false;
+    }
+    if (descriptor.isAccessorDescriptor()) {
+        if (throwException)
+            throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
+        return false;
+    }
+    if (descriptor.writablePresent() && descriptor.writable()) {
+        if (throwException)
+            throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property."));
         return false;
         return false;
-    return Base::deleteProperty(exec, propertyName);
+    }
+    if (!valueCheck) {
+        if (throwException)
+            throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
+        return false;
+    }
+    return true;
 }
 
 // ECMA 13.2.2 [[Construct]]
 }
 
 // ECMA 13.2.2 [[Construct]]
-ConstructType JSFunction::getConstructData(ConstructData& constructData)
+ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& constructData)
 {
 {
-    if (isHostFunction())
-        return ConstructTypeNone;
-    constructData.js.functionExecutable = jsExecutable();
-    constructData.js.scopeChain = scope();
+    JSFunction* thisObject = jsCast<JSFunction*>(cell);
+    if (thisObject->isHostFunction()) {
+        constructData.native.function = thisObject->nativeConstructor();
+        return ConstructTypeHost;
+    }
+    constructData.js.functionExecutable = thisObject->jsExecutable();
+    constructData.js.scopeChain = thisObject->scope();
     return ConstructTypeJS;
 }
     return ConstructTypeJS;
 }
+    
+
+UString getCalculatedDisplayName(CallFrame* callFrame, JSObject* object)
+{
+    if (JSFunction* function = jsDynamicCast<JSFunction*>(object))
+        return function->calculatedDisplayName(callFrame);
+    if (InternalFunction* function = jsDynamicCast<InternalFunction*>(object))
+        return function->calculatedDisplayName(callFrame);
+    return callFrame->globalData().propertyNames->emptyIdentifier.ustring();
+}
 
 } // namespace JSC
 
 } // namespace JSC
index 42fd62a4d16c4b673a7fff64416f6539f2d08b4a..5553115bf12149666251376a043a65b9f59075ab 100644 (file)
@@ -24,7 +24,8 @@
 #ifndef JSFunction_h
 #define JSFunction_h
 
 #ifndef JSFunction_h
 #define JSFunction_h
 
-#include "JSObjectWithGlobalObject.h"
+#include "InternalFunction.h"
+#include "JSObject.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -33,25 +34,39 @@ namespace JSC {
     class FunctionPrototype;
     class JSActivation;
     class JSGlobalObject;
     class FunctionPrototype;
     class JSActivation;
     class JSGlobalObject;
+    class LLIntOffsetsExtractor;
     class NativeExecutable;
     class NativeExecutable;
-    class VPtrHackExecutable;
+    class SourceCode;
+    namespace DFG {
+    class SpeculativeJIT;
+    class JITCompiler;
+    }
 
 
-    EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
+    JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
 
 
-    class JSFunction : public JSObjectWithGlobalObject {
+    JS_EXPORT_PRIVATE UString getCalculatedDisplayName(CallFrame*, JSObject*);
+    
+    class JSFunction : public JSNonFinalObject {
         friend class JIT;
         friend class JIT;
+        friend class DFG::SpeculativeJIT;
+        friend class DFG::JITCompiler;
         friend class JSGlobalData;
 
         friend class JSGlobalData;
 
-        typedef JSObjectWithGlobalObject Base;
-
     public:
     public:
-        JSFunction(ExecState*, JSGlobalObject*, Structure*, int length, const Identifier&, NativeFunction);
-        JSFunction(ExecState*, JSGlobalObject*, Structure*, int length, const Identifier&, NativeExecutable*);
-        JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*);
-        virtual ~JSFunction();
+        typedef JSNonFinalObject Base;
 
 
-        const UString& name(ExecState*);
-        const UString displayName(ExecState*);
+        JS_EXPORT_PRIVATE static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeFunction nativeFunction, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor);
+
+        static JSFunction* create(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChain)
+        {
+            JSFunction* function = new (NotNull, allocateCell<JSFunction>(*exec->heap())) JSFunction(exec, executable, scopeChain);
+            ASSERT(function->structure()->globalObject());
+            function->finishCreation(exec, executable, scopeChain);
+            return function;
+        }
+        
+        JS_EXPORT_PRIVATE const UString& name(ExecState*);
+        JS_EXPORT_PRIVATE const UString displayName(ExecState*);
         const UString calculatedDisplayName(ExecState*);
 
         ScopeChainNode* scope()
         const UString calculatedDisplayName(ExecState*);
 
         ScopeChainNode* scope()
@@ -59,6 +74,15 @@ namespace JSC {
             ASSERT(!isHostFunctionNonInline());
             return m_scopeChain.get();
         }
             ASSERT(!isHostFunctionNonInline());
             return m_scopeChain.get();
         }
+        // This method may be called for host functins, in which case it
+        // will return an arbitrary value. This should only be used for
+        // optimized paths in which the return value does not matter for
+        // host functions, and checking whether the function is a host
+        // function is deemed too expensive.
+        ScopeChainNode* scopeUnchecked()
+        {
+            return m_scopeChain.get();
+        }
         void setScope(JSGlobalData& globalData, ScopeChainNode* scopeChain)
         {
             ASSERT(!isHostFunctionNonInline());
         void setScope(JSGlobalData& globalData, ScopeChainNode* scopeChain)
         {
             ASSERT(!isHostFunctionNonInline());
@@ -71,34 +95,56 @@ namespace JSC {
         inline bool isHostFunction() const;
         FunctionExecutable* jsExecutable() const;
 
         inline bool isHostFunction() const;
         FunctionExecutable* jsExecutable() const;
 
+        JS_EXPORT_PRIVATE const SourceCode* sourceCode() const;
+
         static JS_EXPORTDATA const ClassInfo s_info;
 
         static JS_EXPORTDATA const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) 
-        { 
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 
+        {
+            ASSERT(globalObject);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), &s_info); 
         }
 
         NativeFunction nativeFunction();
         }
 
         NativeFunction nativeFunction();
+        NativeFunction nativeConstructor();
 
 
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
+
+        static inline size_t offsetOfScopeChain()
+        {
+            return OBJECT_OFFSETOF(JSFunction, m_scopeChain);
+        }
+
+        static inline size_t offsetOfExecutable()
+        {
+            return OBJECT_OFFSETOF(JSFunction, m_executable);
+        }
 
     protected:
         const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
 
 
     protected:
         const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
 
-    private:
-        explicit JSFunction(VPtrStealingHackType);
+        JS_EXPORT_PRIVATE JSFunction(ExecState*, JSGlobalObject*, Structure*);
+        JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*);
+        
+        void finishCreation(ExecState*, NativeExecutable*, int length, const Identifier& name);
+        void finishCreation(ExecState*, FunctionExecutable*, ScopeChainNode*);
+
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+        static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode = ExcludeDontEnumProperties);
+        static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
 
 
-        bool isHostFunctionNonInline() const;
+        static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
 
 
-        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);
+        static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
 
 
-        virtual void visitChildren(SlotVisitor&);
+        static void visitChildren(JSCell*, SlotVisitor&);
+
+    private:
+        friend class LLIntOffsetsExtractor;
+        
+        JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
 
         static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
         static JSValue callerGetter(ExecState*, JSValue, const Identifier&);
 
         static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
         static JSValue callerGetter(ExecState*, JSValue, const Identifier&);
@@ -108,12 +154,9 @@ namespace JSC {
         WriteBarrier<ScopeChainNode> m_scopeChain;
     };
 
         WriteBarrier<ScopeChainNode> m_scopeChain;
     };
 
-    JSFunction* asFunction(JSValue);
-
-    inline JSFunction* asFunction(JSValue value)
+    inline bool JSValue::isFunction() const
     {
     {
-        ASSERT(asObject(value)->inherits(&JSFunction::s_info));
-        return static_cast<JSFunction*>(asObject(value));
+        return isCell() && (asCell()->inherits(&JSFunction::s_info) || asCell()->inherits(&InternalFunction::s_info));
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
index 377e849154dce5a33032ae9638b4a6ffd310d25d..31ba6b4915ac744bcf987bac8b4d017df9e7f0be 100644 (file)
 #include "CommonIdentifiers.h"
 #include "DebuggerActivation.h"
 #include "FunctionConstructor.h"
 #include "CommonIdentifiers.h"
 #include "DebuggerActivation.h"
 #include "FunctionConstructor.h"
+#include "GCActivityCallback.h"
 #include "GetterSetter.h"
 #include "GetterSetter.h"
+#include "HostCallReturnValue.h"
 #include "Interpreter.h"
 #include "JSActivation.h"
 #include "JSAPIValueWrapper.h"
 #include "JSArray.h"
 #include "Interpreter.h"
 #include "JSActivation.h"
 #include "JSAPIValueWrapper.h"
 #include "JSArray.h"
-#include "JSByteArray.h"
 #include "JSClassRef.h"
 #include "JSFunction.h"
 #include "JSLock.h"
 #include "JSNotAnObject.h"
 #include "JSPropertyNameIterator.h"
 #include "JSStaticScopeObject.h"
 #include "JSClassRef.h"
 #include "JSFunction.h"
 #include "JSLock.h"
 #include "JSNotAnObject.h"
 #include "JSPropertyNameIterator.h"
 #include "JSStaticScopeObject.h"
-#include "JSZombie.h"
 #include "Lexer.h"
 #include "Lookup.h"
 #include "Nodes.h"
 #include "Lexer.h"
 #include "Lookup.h"
 #include "Nodes.h"
-#include "Parser.h"
+#include "ParserArena.h"
 #include "RegExpCache.h"
 #include "RegExpObject.h"
 #include "StrictEvalActivation.h"
 #include "RegExpCache.h"
 #include "RegExpObject.h"
 #include "StrictEvalActivation.h"
+#include "StrongInlines.h"
+#include <wtf/Threading.h>
 #include <wtf/WTFThreadData.h>
 #include <wtf/WTFThreadData.h>
-#if ENABLE(REGEXP_TRACING)
-#include "RegExp.h"
-#endif
 
 
+#if ENABLE(DFG_JIT)
+#include "ConservativeRoots.h"
+#endif
 
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-#include <wtf/Threading.h>
+#if ENABLE(REGEXP_TRACING)
+#include "RegExp.h"
 #endif
 
 #endif
 
-#if PLATFORM(MAC)
-#include "ProfilerServer.h"
+#if USE(CF)
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
 using namespace WTF;
 
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
 using namespace WTF;
 
-namespace {
-
-using namespace JSC;
-
-class Recompiler {
-public:
-    void operator()(JSCell*);
-};
+namespace JSC {
 
 
-inline void Recompiler::operator()(JSCell* cell)
+extern const HashTable arrayConstructorTable;
+extern const HashTable arrayPrototypeTable;
+extern const HashTable booleanPrototypeTable;
+extern const HashTable jsonTable;
+extern const HashTable dateTable;
+extern const HashTable dateConstructorTable;
+extern const HashTable errorPrototypeTable;
+extern const HashTable globalObjectTable;
+extern const HashTable mathTable;
+extern const HashTable numberConstructorTable;
+extern const HashTable numberPrototypeTable;
+JS_EXPORTDATA extern const HashTable objectConstructorTable;
+extern const HashTable objectPrototypeTable;
+extern const HashTable regExpTable;
+extern const HashTable regExpConstructorTable;
+extern const HashTable regExpPrototypeTable;
+extern const HashTable stringTable;
+extern const HashTable stringConstructorTable;
+
+#if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
+static bool enableAssembler(ExecutableAllocator& executableAllocator)
 {
 {
-    if (!cell->inherits(&JSFunction::s_info))
-        return;
-    JSFunction* function = asFunction(cell);
-    if (function->executable()->isHostFunction())
-        return;
-    function->jsExecutable()->discardCode();
-}
-
-} // namespace
-
-namespace JSC {
+    if (!executableAllocator.isValid() || !Options::useJIT)
+        return false;
+#if USE(CF)
+    CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
+    CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
+    if (canUseJIT) {
+        return kCFBooleanTrue == canUseJIT;
+        CFRelease(canUseJIT);
+    }
+    CFRelease(canUseJITKey);
+#endif
 
 
-extern JSC_CONST_HASHTABLE HashTable arrayConstructorTable;
-extern JSC_CONST_HASHTABLE HashTable arrayPrototypeTable;
-extern JSC_CONST_HASHTABLE HashTable booleanPrototypeTable;
-extern JSC_CONST_HASHTABLE HashTable jsonTable;
-extern JSC_CONST_HASHTABLE HashTable dateTable;
-extern JSC_CONST_HASHTABLE HashTable dateConstructorTable;
-extern JSC_CONST_HASHTABLE HashTable errorPrototypeTable;
-extern JSC_CONST_HASHTABLE HashTable globalObjectTable;
-extern JSC_CONST_HASHTABLE HashTable mathTable;
-extern JSC_CONST_HASHTABLE HashTable numberConstructorTable;
-extern JSC_CONST_HASHTABLE HashTable numberPrototypeTable;
-extern JSC_CONST_HASHTABLE HashTable objectConstructorTable;
-extern JSC_CONST_HASHTABLE HashTable objectPrototypeTable;
-extern JSC_CONST_HASHTABLE HashTable regExpTable;
-extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
-extern JSC_CONST_HASHTABLE HashTable regExpPrototypeTable;
-extern JSC_CONST_HASHTABLE HashTable stringTable;
-extern JSC_CONST_HASHTABLE HashTable stringConstructorTable;
-
-void* JSGlobalData::jsArrayVPtr;
-void* JSGlobalData::jsByteArrayVPtr;
-void* JSGlobalData::jsStringVPtr;
-void* JSGlobalData::jsFunctionVPtr;
-
-#if COMPILER(GCC)
-// Work around for gcc trying to coalesce our reads of the various cell vptrs
-#define CLOBBER_MEMORY() do { \
-    asm volatile ("" : : : "memory"); \
-} while (false)
+#if USE(CF) || OS(UNIX)
+    char* canUseJITString = getenv("JavaScriptCoreUseJIT");
+    return !canUseJITString || atoi(canUseJITString);
 #else
 #else
-#define CLOBBER_MEMORY() do { } while (false)
+    return true;
 #endif
 #endif
-
-void JSGlobalData::storeVPtrs()
-{
-    // 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(storage), sizeof_JSArray_must_be_less_than_storage);
-    JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack);
-    CLOBBER_MEMORY();
-    JSGlobalData::jsArrayVPtr = jsArray->vptr();
-
-    COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(storage), sizeof_JSByteArray_must_be_less_than_storage);
-    JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
-    CLOBBER_MEMORY();
-    JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
-
-    COMPILE_ASSERT(sizeof(JSString) <= sizeof(storage), sizeof_JSString_must_be_less_than_storage);
-    JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
-    CLOBBER_MEMORY();
-    JSGlobalData::jsStringVPtr = jsString->vptr();
-
-    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();
 }
 }
+#endif
 
 
-JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType)
-    : globalDataType(globalDataType)
+JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapSize heapSize)
+    : heap(this, heapSize)
+    , globalDataType(globalDataType)
     , clientData(0)
     , clientData(0)
+    , topCallFrame(CallFrame::noCaller())
     , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable))
     , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable))
     , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable))
     , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable))
     , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable))
     , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable))
@@ -180,15 +145,17 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
     , emptyList(new MarkedArgumentBuffer)
 #if ENABLE(ASSEMBLER)
     , executableAllocator(*this)
     , emptyList(new MarkedArgumentBuffer)
 #if ENABLE(ASSEMBLER)
     , executableAllocator(*this)
-    , regexAllocator(*this)
 #endif
 #endif
-    , lexer(new Lexer(this))
-    , parser(new Parser)
+    , parserArena(adoptPtr(new ParserArena))
+    , keywords(adoptPtr(new Keywords(this)))
     , interpreter(0)
     , interpreter(0)
-    , heap(this)
-    , globalObjectCount(0)
+    , jsArrayClassInfo(&JSArray::s_info)
+    , jsFinalObjectClassInfo(&JSFinalObject::s_info)
+#if ENABLE(DFG_JIT)
+    , sizeOfLastScratchBuffer(0)
+#endif
     , dynamicGlobalObject(0)
     , dynamicGlobalObject(0)
-    , cachedUTCOffset(NaN)
+    , cachedUTCOffset(std::numeric_limits<double>::quiet_NaN())
     , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
     , m_regExpCache(new RegExpCache(this))
 #if ENABLE(REGEXP_TRACING)
     , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
     , m_regExpCache(new RegExpCache(this))
 #if ENABLE(REGEXP_TRACING)
@@ -197,110 +164,68 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
 #ifndef NDEBUG
     , exclusiveThread(0)
 #endif
 #ifndef NDEBUG
     , exclusiveThread(0)
 #endif
+#if CPU(X86) && ENABLE(JIT)
+    , m_timeoutCount(512)
+#endif
+#if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
+    , m_canUseAssembler(enableAssembler(executableAllocator))
+#endif
+#if ENABLE(GC_VALIDATION)
+    , m_initializingObjectClass(0)
+#endif
+    , m_inDefineOwnProperty(false)
 {
 {
-    interpreter = new Interpreter(*this);
-    if (globalDataType == Default)
-        m_stack = wtfThreadData().stack();
+    interpreter = new Interpreter;
 
     // Need to be careful to keep everything consistent here
 
     // Need to be careful to keep everything consistent here
+    JSLockHolder lock(this);
     IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
     IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
-    JSLock lock(SilenceAssertionsOnly);
     structureStructure.set(*this, Structure::createStructure(*this));
     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
+    debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull()));
+    activationStructure.set(*this, JSActivation::createStructure(*this, 0, jsNull()));
+    interruptedExecutionErrorStructure.set(*this, InterruptedExecutionError::createStructure(*this, 0, jsNull()));
+    terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
+    staticScopeStructure.set(*this, JSStaticScopeObject::createStructure(*this, 0, jsNull()));
+    strictEvalActivationStructure.set(*this, StrictEvalActivation::createStructure(*this, 0, jsNull()));
+    stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull()));
+    notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull()));
+    propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull()));
+    getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull()));
+    apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull()));
+    scopeChainNodeStructure.set(*this, ScopeChainNode::createStructure(*this, 0, jsNull()));
+    executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull()));
+    nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull()));
+    evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull()));
+    programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull()));
+    functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull()));
+    regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull()));
+    structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull()));
 
     wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
 
 
     wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
 
-#if PLATFORM(MAC)
-    startProfilerServerIfNeeded();
-#endif
-#if ENABLE(JIT) && ENABLE(INTERPRETER)
-#if USE(CF)
-    CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
-    CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
-    if (canUseJIT) {
-        m_canUseJIT = kCFBooleanTrue == canUseJIT;
-        CFRelease(canUseJIT);
-    } else {
-      char* canUseJITString = getenv("JavaScriptCoreUseJIT");
-      m_canUseJIT = !canUseJITString || atoi(canUseJITString);
-    }
-    CFRelease(canUseJITKey);
-#elif OS(UNIX)
-    char* canUseJITString = getenv("JavaScriptCoreUseJIT");
-    m_canUseJIT = !canUseJITString || atoi(canUseJITString);
-#else
-    m_canUseJIT = true;
-#endif
-#endif
 #if ENABLE(JIT)
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
-    if (m_canUseJIT)
-        m_canUseJIT = executableAllocator.isValid();
-#endif
     jitStubs = adoptPtr(new JITThunks(this));
 #endif
     jitStubs = adoptPtr(new JITThunks(this));
 #endif
-}
+    
+    interpreter->initialize(&llintData, this->canUseJIT());
+    
+    initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support.
 
 
-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
+    heap.notifyIsSafeToCollect();
+    
+    llintData.performAssertions(*this);
 }
 
 JSGlobalData::~JSGlobalData()
 {
 }
 
 JSGlobalData::~JSGlobalData()
 {
-    // By the time this is destroyed, heap.destroy() must already have been called.
+    ASSERT(!m_apiLock.currentThreadIsHoldingLock());
+    if (heap.activityCallback())
+        heap.activityCallback()->didStartVMShutdown();
+    heap.lastChanceToFinalize();
 
     delete interpreter;
 #ifndef NDEBUG
 
     delete interpreter;
 #ifndef NDEBUG
-    // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance.
-    interpreter = 0;
+    interpreter = reinterpret_cast<Interpreter*>(0xbbadbeef);
 #endif
 
     arrayPrototypeTable->deleteTable();
 #endif
 
     arrayPrototypeTable->deleteTable();
@@ -341,10 +266,7 @@ JSGlobalData::~JSGlobalData()
     fastDelete(const_cast<HashTable*>(stringTable));
     fastDelete(const_cast<HashTable*>(stringConstructorTable));
 
     fastDelete(const_cast<HashTable*>(stringTable));
     fastDelete(const_cast<HashTable*>(stringConstructorTable));
 
-    delete parser;
-    delete lexer;
-
-    deleteAllValues(opaqueJSClassData);
+    opaqueJSClassData.clear();
 
     delete emptyList;
 
 
     delete emptyList;
 
@@ -357,21 +279,26 @@ JSGlobalData::~JSGlobalData()
 #if ENABLE(REGEXP_TRACING)
     delete m_rtTraceList;
 #endif
 #if ENABLE(REGEXP_TRACING)
     delete m_rtTraceList;
 #endif
+
+#if ENABLE(DFG_JIT)
+    for (unsigned i = 0; i < scratchBuffers.size(); ++i)
+        fastFree(scratchBuffers[i]);
+#endif
 }
 
 }
 
-PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type)
+PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type, HeapSize heapSize)
 {
 {
-    return adoptRef(new JSGlobalData(APIContextGroup, type));
+    return adoptRef(new JSGlobalData(APIContextGroup, type, heapSize));
 }
 
 }
 
-PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type)
+PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type, HeapSize heapSize)
 {
 {
-    return adoptRef(new JSGlobalData(Default, type));
+    return adoptRef(new JSGlobalData(Default, type, heapSize));
 }
 
 }
 
-PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type)
+PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type, HeapSize heapSize)
 {
 {
-    return create(type);
+    return create(type, heapSize);
 }
 
 bool JSGlobalData::sharedInstanceExists()
 }
 
 bool JSGlobalData::sharedInstanceExists()
@@ -381,36 +308,69 @@ bool JSGlobalData::sharedInstanceExists()
 
 JSGlobalData& JSGlobalData::sharedInstance()
 {
 
 JSGlobalData& JSGlobalData::sharedInstance()
 {
+    GlobalJSLock globalLock;
     JSGlobalData*& instance = sharedInstanceInternal();
     if (!instance) {
     JSGlobalData*& instance = sharedInstanceInternal();
     if (!instance) {
-        instance = adoptRef(new JSGlobalData(APIShared, ThreadStackTypeSmall)).leakRef();
-#if ENABLE(JSC_MULTIPLE_THREADS)
+        instance = adoptRef(new JSGlobalData(APIShared, ThreadStackTypeSmall, SmallHeap)).leakRef();
         instance->makeUsableFromMultipleThreads();
         instance->makeUsableFromMultipleThreads();
-#endif
     }
     return *instance;
 }
 
 JSGlobalData*& JSGlobalData::sharedInstanceInternal()
 {
     }
     return *instance;
 }
 
 JSGlobalData*& JSGlobalData::sharedInstanceInternal()
 {
-    ASSERT(JSLock::currentThreadIsHoldingLock());
     static JSGlobalData* sharedInstance;
     return sharedInstance;
 }
 
 #if ENABLE(JIT)
     static JSGlobalData* sharedInstance;
     return sharedInstance;
 }
 
 #if ENABLE(JIT)
-NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
+static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic)
 {
 {
-    return jitStubs->hostFunctionStub(this, function);
+    switch (intrinsic) {
+    case CharCodeAtIntrinsic:
+        return charCodeAtThunkGenerator;
+    case CharAtIntrinsic:
+        return charAtThunkGenerator;
+    case FromCharCodeIntrinsic:
+        return fromCharCodeThunkGenerator;
+    case SqrtIntrinsic:
+        return sqrtThunkGenerator;
+    case PowIntrinsic:
+        return powThunkGenerator;
+    case AbsIntrinsic:
+        return absThunkGenerator;
+    case FloorIntrinsic:
+        return floorThunkGenerator;
+    case CeilIntrinsic:
+        return ceilThunkGenerator;
+    case RoundIntrinsic:
+        return roundThunkGenerator;
+    case ExpIntrinsic:
+        return expThunkGenerator;
+    case LogIntrinsic:
+        return logThunkGenerator;
+    default:
+        return 0;
+    }
+}
+
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor)
+{
+#if ENABLE(CLASSIC_INTERPRETER)
+    if (!canUseJIT())
+        return NativeExecutable::create(*this, function, constructor);
+#endif
+    return jitStubs->hostFunctionStub(this, function, constructor);
 }
 }
-NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator)
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, Intrinsic intrinsic)
 {
 {
-    return jitStubs->hostFunctionStub(this, function, generator);
+    ASSERT(canUseJIT());
+    return jitStubs->hostFunctionStub(this, function, intrinsic != NoIntrinsic ? thunkGeneratorForIntrinsic(intrinsic) : 0, intrinsic);
 }
 #else
 }
 #else
-NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor)
 {
 {
-    return NativeExecutable::create(*this, function, callHostFunctionAsConstructor);
+    return NativeExecutable::create(*this, function, constructor);
 }
 #endif
 
 }
 #endif
 
@@ -420,10 +380,10 @@ JSGlobalData::ClientData::~ClientData()
 
 void JSGlobalData::resetDateCache()
 {
 
 void JSGlobalData::resetDateCache()
 {
-    cachedUTCOffset = NaN;
+    cachedUTCOffset = std::numeric_limits<double>::quiet_NaN();
     dstOffsetCache.reset();
     cachedDateString = UString();
     dstOffsetCache.reset();
     cachedDateString = UString();
-    cachedDateStringValue = NaN;
+    cachedDateStringValue = std::numeric_limits<double>::quiet_NaN();
     dateInstanceCache.reset();
 }
 
     dateInstanceCache.reset();
 }
 
@@ -440,25 +400,18 @@ void JSGlobalData::stopSampling()
 void JSGlobalData::dumpSampleData(ExecState* exec)
 {
     interpreter->dumpSampleData(exec);
 void JSGlobalData::dumpSampleData(ExecState* exec)
 {
     interpreter->dumpSampleData(exec);
+#if ENABLE(ASSEMBLER)
+    ExecutableAllocator::dumpProfile();
+#endif
 }
 
 }
 
-void JSGlobalData::recompileAllJSFunctions()
-{
-    // If JavaScript is running, it's not safe to recompile, since we'll end
-    // up throwing away code that is live on the stack.
-    ASSERT(!dynamicGlobalObject);
-    
-    Recompiler recompiler;
-    heap.forEach(recompiler);
-}
-
-struct StackPreservingRecompiler {
+struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor {
     HashSet<FunctionExecutable*> currentlyExecutingFunctions;
     void operator()(JSCell* cell)
     {
         if (!cell->inherits(&FunctionExecutable::s_info))
             return;
     HashSet<FunctionExecutable*> currentlyExecutingFunctions;
     void operator()(JSCell* cell)
     {
         if (!cell->inherits(&FunctionExecutable::s_info))
             return;
-        FunctionExecutable* executable = static_cast<FunctionExecutable*>(cell);
+        FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
         if (currentlyExecutingFunctions.contains(executable))
             return;
         executable->discardCode();
         if (currentlyExecutingFunctions.contains(executable))
             return;
         executable->discardCode();
@@ -478,7 +431,7 @@ void JSGlobalData::releaseExecutableMemory()
             if (cell->inherits(&ScriptExecutable::s_info))
                 executable = static_cast<ScriptExecutable*>(*ptr);
             else if (cell->inherits(&JSFunction::s_info)) {
             if (cell->inherits(&ScriptExecutable::s_info))
                 executable = static_cast<ScriptExecutable*>(*ptr);
             else if (cell->inherits(&JSFunction::s_info)) {
-                JSFunction* function = asFunction(*ptr);
+                JSFunction* function = jsCast<JSFunction*>(*ptr);
                 if (function->isHostFunction())
                     continue;
                 executable = function->jsExecutable();
                 if (function->isHostFunction())
                     continue;
                 executable = function->jsExecutable();
@@ -490,10 +443,8 @@ void JSGlobalData::releaseExecutableMemory()
                 recompiler.currentlyExecutingFunctions.add(static_cast<FunctionExecutable*>(executable));
                 
         }
                 recompiler.currentlyExecutingFunctions.add(static_cast<FunctionExecutable*>(executable));
                 
         }
-        heap.forEach(recompiler);
-    } else
-        recompileAllJSFunctions();
-
+        heap.objectSpace().forEachCell<StackPreservingRecompiler>(recompiler);
+    }
     m_regExpCache->invalidateCode();
     heap.collectAllGarbage();
 }
     m_regExpCache->invalidateCode();
     heap.collectAllGarbage();
 }
@@ -505,6 +456,19 @@ void releaseExecutableMemory(JSGlobalData& globalData)
 }
 #endif
 
 }
 #endif
 
+#if ENABLE(DFG_JIT)
+void JSGlobalData::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
+{
+    for (size_t i = 0; i < scratchBuffers.size(); i++) {
+        ScratchBuffer* scratchBuffer = scratchBuffers[i];
+        if (scratchBuffer->activeLength()) {
+            void* bufferStart = scratchBuffer->dataBuffer();
+            conservativeRoots.add(bufferStart, static_cast<void*>(static_cast<char*>(bufferStart) + scratchBuffer->activeLength()));
+        }
+    }
+}
+#endif
+
 #if ENABLE(REGEXP_TRACING)
 void JSGlobalData::addRegExpToTrace(RegExp* regExp)
 {
 #if ENABLE(REGEXP_TRACING)
 void JSGlobalData::addRegExpToTrace(RegExp* regExp)
 {
@@ -517,17 +481,17 @@ void JSGlobalData::dumpRegExpTrace()
     RTTraceList::iterator iter = ++m_rtTraceList->begin();
     
     if (iter != m_rtTraceList->end()) {
     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");
+        dataLog("\nRegExp Tracing\n");
+        dataLog("                                                            match()    matches\n");
+        dataLog("Regular Expression                          JIT Address      calls      found\n");
+        dataLog("----------------------------------------+----------------+----------+----------\n");
     
         unsigned reCount = 0;
     
         for (; iter != m_rtTraceList->end(); ++iter, ++reCount)
             (*iter)->printTraceData();
 
     
         unsigned reCount = 0;
     
         for (; iter != m_rtTraceList->end(); ++iter, ++reCount)
             (*iter)->printTraceData();
 
-        printf("%d Regular Expressions\n", reCount);
+        dataLog("%d Regular Expressions\n", reCount);
     }
     
     m_rtTraceList->clear();
     }
     
     m_rtTraceList->clear();
index fee7818396599a19173d912bc1885ed9adeaf240..613753f55d0e6280b4451a453f93688322cb2b4f 100644 (file)
 #define JSGlobalData_h
 
 #include "CachedTranscendentalFunction.h"
 #define JSGlobalData_h
 
 #include "CachedTranscendentalFunction.h"
-#include "Heap.h"
 #include "DateInstanceCache.h"
 #include "ExecutableAllocator.h"
 #include "DateInstanceCache.h"
 #include "ExecutableAllocator.h"
-#include "Strong.h"
+#include "Heap.h"
+#include "Intrinsic.h"
 #include "JITStubs.h"
 #include "JITStubs.h"
+#include "JSLock.h"
 #include "JSValue.h"
 #include "JSValue.h"
+#include "LLIntData.h"
 #include "NumericStrings.h"
 #include "SmallStrings.h"
 #include "NumericStrings.h"
 #include "SmallStrings.h"
+#include "Strong.h"
 #include "Terminator.h"
 #include "TimeoutChecker.h"
 #include "WeakRandom.h"
 #include <wtf/BumpPointerAllocator.h>
 #include <wtf/Forward.h>
 #include <wtf/HashMap.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/SimpleStats.h>
+#include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/ThreadSpecific.h>
 #include <wtf/WTFThreadData.h>
 #if ENABLE(REGEXP_TRACING)
 #include <wtf/ThreadSpecific.h>
 #include <wtf/WTFThreadData.h>
 #if ENABLE(REGEXP_TRACING)
@@ -63,9 +67,10 @@ namespace JSC {
     class Interpreter;
     class JSGlobalObject;
     class JSObject;
     class Interpreter;
     class JSGlobalObject;
     class JSObject;
-    class Lexer;
+    class Keywords;
+    class LLIntOffsetsExtractor;
     class NativeExecutable;
     class NativeExecutable;
-    class Parser;
+    class ParserArena;
     class RegExpCache;
     class Stringifier;
     class Structure;
     class RegExpCache;
     class Stringifier;
     class Structure;
@@ -102,7 +107,52 @@ namespace JSC {
         ThreadStackTypeSmall
     };
 
         ThreadStackTypeSmall
     };
 
-    class JSGlobalData : public RefCounted<JSGlobalData> {
+    struct TypedArrayDescriptor {
+        TypedArrayDescriptor()
+            : m_classInfo(0)
+            , m_storageOffset(0)
+            , m_lengthOffset(0)
+        {
+        }
+        TypedArrayDescriptor(const ClassInfo* classInfo, size_t storageOffset, size_t lengthOffset)
+            : m_classInfo(classInfo)
+            , m_storageOffset(storageOffset)
+            , m_lengthOffset(lengthOffset)
+        {
+        }
+        const ClassInfo* m_classInfo;
+        size_t m_storageOffset;
+        size_t m_lengthOffset;
+    };
+
+#if ENABLE(DFG_JIT)
+    class ConservativeRoots;
+
+    struct ScratchBuffer {
+        ScratchBuffer()
+            : m_activeLength(0)
+        {
+        }
+
+        static ScratchBuffer* create(size_t size)
+        {
+            ScratchBuffer* result = new (fastMalloc(ScratchBuffer::allocationSize(size))) ScratchBuffer;
+
+            return result;
+        }
+
+        static size_t allocationSize(size_t bufferSize) { return sizeof(size_t) + bufferSize; }
+        void setActiveLength(size_t activeLength) { m_activeLength = activeLength; }
+        size_t activeLength() const { return m_activeLength; };
+        size_t* activeLengthPtr() { return &m_activeLength; };
+        void* dataBuffer() { return m_buffer; }
+
+        size_t m_activeLength;
+        void* m_buffer[0];
+    };
+#endif
+
+    class JSGlobalData : public ThreadSafeRefCounted<JSGlobalData> {
     public:
         // WebCore has a one-to-one mapping of threads to JSGlobalDatas;
         // either create() or createLeaked() should only be called once
     public:
         // WebCore has a one-to-one mapping of threads to JSGlobalDatas;
         // either create() or createLeaked() should only be called once
@@ -113,28 +163,32 @@ namespace JSC {
         // than the old singleton APIShared JSGlobalData created for use by
         // the original API.
         enum GlobalDataType { Default, APIContextGroup, APIShared };
         // than the old singleton APIShared JSGlobalData created for use by
         // the original API.
         enum GlobalDataType { Default, APIContextGroup, APIShared };
-
+        
         struct ClientData {
         struct ClientData {
-            virtual ~ClientData() = 0;
+            JS_EXPORT_PRIVATE virtual ~ClientData() = 0;
         };
 
         bool isSharedInstance() { return globalDataType == APIShared; }
         bool usingAPI() { return globalDataType != Default; }
         };
 
         bool isSharedInstance() { return globalDataType == APIShared; }
         bool usingAPI() { return globalDataType != Default; }
-        static bool sharedInstanceExists();
-        static JSGlobalData& sharedInstance();
+        JS_EXPORT_PRIVATE static bool sharedInstanceExists();
+        JS_EXPORT_PRIVATE static JSGlobalData& sharedInstance();
 
 
-        static PassRefPtr<JSGlobalData> create(ThreadStackType);
-        static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType);
-        static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType);
-        ~JSGlobalData();
+        JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> create(ThreadStackType, HeapSize = SmallHeap);
+        JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType, HeapSize = SmallHeap);
+        static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType, HeapSize = SmallHeap);
+        JS_EXPORT_PRIVATE ~JSGlobalData();
 
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-        // Will start tracking threads that use the heap, which is resource-heavy.
         void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
         void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
-#endif
+
+    private:
+        JSLock m_apiLock;
+
+    public:
+        Heap heap; // The heap is our first data member to ensure that it's destructed after all the objects that reference it.
 
         GlobalDataType globalDataType;
         ClientData* clientData;
 
         GlobalDataType globalDataType;
         ClientData* clientData;
+        CallFrame* topCallFrame;
 
         const HashTable* arrayConstructorTable;
         const HashTable* arrayPrototypeTable;
 
         const HashTable* arrayConstructorTable;
         const HashTable* arrayPrototypeTable;
@@ -173,70 +227,117 @@ namespace JSC {
         Strong<Structure> evalExecutableStructure;
         Strong<Structure> programExecutableStructure;
         Strong<Structure> functionExecutableStructure;
         Strong<Structure> evalExecutableStructure;
         Strong<Structure> programExecutableStructure;
         Strong<Structure> functionExecutableStructure;
-        Strong<Structure> dummyMarkableCellStructure;
         Strong<Structure> regExpStructure;
         Strong<Structure> structureChainStructure;
 
         Strong<Structure> regExpStructure;
         Strong<Structure> structureChainStructure;
 
-#if ENABLE(JSC_ZOMBIES)
-        Strong<Structure> zombieStructure;
-#endif
-
-        static void storeVPtrs();
-        static JS_EXPORTDATA void* jsArrayVPtr;
-        static JS_EXPORTDATA void* jsByteArrayVPtr;
-        static JS_EXPORTDATA void* jsStringVPtr;
-        static JS_EXPORTDATA void* jsFunctionVPtr;
-
         IdentifierTable* identifierTable;
         CommonIdentifiers* propertyNames;
         const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
         SmallStrings smallStrings;
         NumericStrings numericStrings;
         DateInstanceCache dateInstanceCache;
         IdentifierTable* identifierTable;
         CommonIdentifiers* propertyNames;
         const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
         SmallStrings smallStrings;
         NumericStrings numericStrings;
         DateInstanceCache dateInstanceCache;
-        
+        WTF::SimpleStats machineCodeBytesPerBytecodeWordForBaselineJIT;
+        Vector<CodeBlock*> codeBlocksBeingCompiled;
+        void startedCompiling(CodeBlock* codeBlock)
+        {
+            codeBlocksBeingCompiled.append(codeBlock);
+        }
+
+        void finishedCompiling(CodeBlock* codeBlock)
+        {
+            ASSERT_UNUSED(codeBlock, codeBlock == codeBlocksBeingCompiled.last());
+            codeBlocksBeingCompiled.removeLast();
+        }
+
+        void setInDefineOwnProperty(bool inDefineOwnProperty)
+        {
+            m_inDefineOwnProperty = inDefineOwnProperty;
+        }
+
+        bool isInDefineOwnProperty()
+        {
+            return m_inDefineOwnProperty;
+        }
+
 #if ENABLE(ASSEMBLER)
         ExecutableAllocator executableAllocator;
 #if ENABLE(ASSEMBLER)
         ExecutableAllocator executableAllocator;
-        ExecutableAllocator regexAllocator;
 #endif
 
 #if !ENABLE(JIT)
         bool canUseJIT() { return false; } // interpreter only
 #endif
 
 #if !ENABLE(JIT)
         bool canUseJIT() { return false; } // interpreter only
-#elif !ENABLE(INTERPRETER)
+#elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT)
         bool canUseJIT() { return true; } // jit only
 #else
         bool canUseJIT() { return true; } // jit only
 #else
-        bool canUseJIT() { return m_canUseJIT; }
+        bool canUseJIT() { return m_canUseAssembler; }
 #endif
 
 #endif
 
-        const StackBounds& stack()
-        {
-            return wtfThreadData().stack();
-        }
+#if !ENABLE(YARR_JIT)
+        bool canUseRegExpJIT() { return false; } // interpreter only
+#elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT)
+        bool canUseRegExpJIT() { return true; } // jit only
+#else
+        bool canUseRegExpJIT() { return m_canUseAssembler; }
+#endif
 
 
-        Lexer* lexer;
-        Parser* parser;
+        OwnPtr<ParserArena> parserArena;
+        OwnPtr<Keywords> keywords;
         Interpreter* interpreter;
 #if ENABLE(JIT)
         OwnPtr<JITThunks> jitStubs;
         Interpreter* interpreter;
 #if ENABLE(JIT)
         OwnPtr<JITThunks> jitStubs;
-        MacroAssemblerCodePtr getCTIStub(ThunkGenerator generator)
+        MacroAssemblerCodeRef getCTIStub(ThunkGenerator generator)
         {
             return jitStubs->ctiStub(this, generator);
         }
         {
             return jitStubs->ctiStub(this, generator);
         }
-        NativeExecutable* getHostFunction(NativeFunction, ThunkGenerator);
+        NativeExecutable* getHostFunction(NativeFunction, Intrinsic);
 #endif
 #endif
-        NativeExecutable* getHostFunction(NativeFunction);
+        NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor);
 
         TimeoutChecker timeoutChecker;
         Terminator terminator;
 
         TimeoutChecker timeoutChecker;
         Terminator terminator;
-        Heap heap;
 
         JSValue exception;
 
         JSValue exception;
-#if ENABLE(JIT)
+
+        const ClassInfo* const jsArrayClassInfo;
+        const ClassInfo* const jsFinalObjectClassInfo;
+
+        LLInt::Data llintData;
+
         ReturnAddressPtr exceptionLocation;
         ReturnAddressPtr exceptionLocation;
+        JSValue hostCallReturnValue;
+        CallFrame* callFrameForThrow;
+        void* targetMachinePCForThrow;
+        Instruction* targetInterpreterPCForThrow;
+#if ENABLE(DFG_JIT)
+        uint32_t osrExitIndex;
+        void* osrExitJumpDestination;
+        Vector<ScratchBuffer*> scratchBuffers;
+        size_t sizeOfLastScratchBuffer;
+        
+        ScratchBuffer* scratchBufferForSize(size_t size)
+        {
+            if (!size)
+                return 0;
+            
+            if (size > sizeOfLastScratchBuffer) {
+                // Protect against a N^2 memory usage pathology by ensuring
+                // that at worst, we get a geometric series, meaning that the
+                // total memory usage is somewhere around
+                // max(scratch buffer size) * 4.
+                sizeOfLastScratchBuffer = size * 2;
+
+                scratchBuffers.append(ScratchBuffer::create(sizeOfLastScratchBuffer));
+            }
+
+            ScratchBuffer* result = scratchBuffers.last();
+            result->setActiveLength(0);
+            return result;
+        }
+
+        void gatherConservativeRoots(ConservativeRoots&);
 #endif
 
 #endif
 
-        HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData;
+        HashMap<OpaqueJSClass*, OwnPtr<OpaqueJSClassContextData> > opaqueJSClassData;
 
 
-        unsigned globalObjectCount;
         JSGlobalObject* dynamicGlobalObject;
 
         HashSet<JSObject*> stringRecursionCheckVisitedObjects;
         JSGlobalObject* dynamicGlobalObject;
 
         HashSet<JSObject*> stringRecursionCheckVisitedObjects;
@@ -263,39 +364,87 @@ namespace JSC {
 
         CachedTranscendentalFunction<sin> cachedSin;
 
 
         CachedTranscendentalFunction<sin> cachedSin;
 
-        void resetDateCache();
+        JS_EXPORT_PRIVATE void resetDateCache();
 
 
-        void startSampling();
-        void stopSampling();
-        void dumpSampleData(ExecState* exec);
-        void recompileAllJSFunctions();
+        JS_EXPORT_PRIVATE void startSampling();
+        JS_EXPORT_PRIVATE void stopSampling();
+        JS_EXPORT_PRIVATE void dumpSampleData(ExecState* exec);
         RegExpCache* regExpCache() { return m_regExpCache; }
 #if ENABLE(REGEXP_TRACING)
         void addRegExpToTrace(PassRefPtr<RegExp> regExp);
 #endif
         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();
+        JS_EXPORT_PRIVATE void dumpRegExpTrace();
 
         bool isCollectorBusy() { return heap.isBusy(); }
 
         bool isCollectorBusy() { return heap.isBusy(); }
-        void releaseExecutableMemory();
+        JS_EXPORT_PRIVATE void releaseExecutableMemory();
+
+#if ENABLE(GC_VALIDATION)
+        bool isInitializingObject() const; 
+        void setInitializingObjectClass(const ClassInfo*);
+#endif
+
+#if CPU(X86) && ENABLE(JIT)
+        unsigned m_timeoutCount;
+#endif
+
+#define registerTypedArrayFunction(type, capitalizedType) \
+        void registerTypedArrayDescriptor(const capitalizedType##Array*, const TypedArrayDescriptor& descriptor) \
+        { \
+            ASSERT(!m_##type##ArrayDescriptor.m_classInfo || m_##type##ArrayDescriptor.m_classInfo == descriptor.m_classInfo); \
+            m_##type##ArrayDescriptor = descriptor; \
+        } \
+        const TypedArrayDescriptor& type##ArrayDescriptor() const { ASSERT(m_##type##ArrayDescriptor.m_classInfo); return m_##type##ArrayDescriptor; }
+
+        registerTypedArrayFunction(int8, Int8);
+        registerTypedArrayFunction(int16, Int16);
+        registerTypedArrayFunction(int32, Int32);
+        registerTypedArrayFunction(uint8, Uint8);
+        registerTypedArrayFunction(uint8Clamped, Uint8Clamped);
+        registerTypedArrayFunction(uint16, Uint16);
+        registerTypedArrayFunction(uint32, Uint32);
+        registerTypedArrayFunction(float32, Float32);
+        registerTypedArrayFunction(float64, Float64);
+#undef registerTypedArrayFunction
+
+        JSLock& apiLock() { return m_apiLock; }
 
     private:
 
     private:
-        JSGlobalData(GlobalDataType, ThreadStackType);
+        friend class LLIntOffsetsExtractor;
+        
+        JSGlobalData(GlobalDataType, ThreadStackType, HeapSize);
         static JSGlobalData*& sharedInstanceInternal();
         void createNativeThunk();
         static JSGlobalData*& sharedInstanceInternal();
         void createNativeThunk();
-#if ENABLE(JIT) && ENABLE(INTERPRETER)
-        bool m_canUseJIT;
+#if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
+        bool m_canUseAssembler;
+#endif
+#if ENABLE(GC_VALIDATION)
+        const ClassInfo* m_initializingObjectClass;
 #endif
 #endif
-        StackBounds m_stack;
+        bool m_inDefineOwnProperty;
+
+        TypedArrayDescriptor m_int8ArrayDescriptor;
+        TypedArrayDescriptor m_int16ArrayDescriptor;
+        TypedArrayDescriptor m_int32ArrayDescriptor;
+        TypedArrayDescriptor m_uint8ArrayDescriptor;
+        TypedArrayDescriptor m_uint8ClampedArrayDescriptor;
+        TypedArrayDescriptor m_uint16ArrayDescriptor;
+        TypedArrayDescriptor m_uint32ArrayDescriptor;
+        TypedArrayDescriptor m_float32ArrayDescriptor;
+        TypedArrayDescriptor m_float64ArrayDescriptor;
     };
 
     };
 
-    inline HandleSlot allocateGlobalHandle(JSGlobalData& globalData)
+#if ENABLE(GC_VALIDATION)
+    inline bool JSGlobalData::isInitializingObject() const
     {
     {
-        return globalData.allocateGlobalHandle();
+        return !!m_initializingObjectClass;
     }
 
     }
 
+    inline void JSGlobalData::setInitializingObjectClass(const ClassInfo* initializingObjectClass)
+    {
+        m_initializingObjectClass = initializingObjectClass;
+    }
+#endif
+
 } // namespace JSC
 
 #endif // JSGlobalData_h
 } // namespace JSC
 
 #endif // JSGlobalData_h
index a71624f33c468a2c2e5c0d1864085aa1069ffe77..dc68bdec7b2b769c6856fb69be13a05a62aea220 100644 (file)
 #include "CodeBlock.h"
 #include "DateConstructor.h"
 #include "DatePrototype.h"
 #include "CodeBlock.h"
 #include "DateConstructor.h"
 #include "DatePrototype.h"
+#include "Error.h"
 #include "ErrorConstructor.h"
 #include "ErrorPrototype.h"
 #include "FunctionConstructor.h"
 #include "FunctionPrototype.h"
 #include "ErrorConstructor.h"
 #include "ErrorPrototype.h"
 #include "FunctionConstructor.h"
 #include "FunctionPrototype.h"
+#include "GetterSetter.h"
+#include "JSBoundFunction.h"
 #include "JSFunction.h"
 #include "JSGlobalObjectFunctions.h"
 #include "JSLock.h"
 #include "JSFunction.h"
 #include "JSGlobalObjectFunctions.h"
 #include "JSLock.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &JSVariableObject::s_info, 0, ExecState::globalObjectTable };
+const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &JSVariableObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(JSGlobalObject) };
+
+const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript
+    , &shouldInterruptScriptBeforeTimeout
+};
 
 /* Source for JSGlobalObject.lut.h
 @begin globalObjectTable
 
 /* Source for JSGlobalObject.lut.h
 @begin globalObjectTable
@@ -106,8 +113,6 @@ template <typename T> static inline void visitIfNeeded(SlotVisitor& visitor, Wri
 
 JSGlobalObject::~JSGlobalObject()
 {
 
 JSGlobalObject::~JSGlobalObject()
 {
-    ASSERT(JSLock::currentThreadIsHoldingLock());
-
     if (m_debugger)
         m_debugger->detach(this);
 
     if (m_debugger)
         m_debugger->detach(this);
 
@@ -117,63 +122,64 @@ JSGlobalObject::~JSGlobalObject()
     }
 }
 
     }
 }
 
+void JSGlobalObject::destroy(JSCell* cell)
+{
+    jsCast<JSGlobalObject*>(cell)->JSGlobalObject::~JSGlobalObject();
+}
+
 void JSGlobalObject::init(JSObject* thisValue)
 {
 void JSGlobalObject::init(JSObject* thisValue)
 {
-    ASSERT(JSLock::currentThreadIsHoldingLock());
+    ASSERT(globalData().apiLock().currentThreadIsHoldingLock());
     
     structure()->disableSpecificFunctionTracking();
 
     
     structure()->disableSpecificFunctionTracking();
 
-    m_globalData = Heap::heap(this)->globalData();
-    m_globalScopeChain.set(*m_globalData, this, new (m_globalData.get()) ScopeChainNode(0, this, m_globalData.get(), this, thisValue));
+    m_globalScopeChain.set(globalData(), this, ScopeChainNode::create(0, this, &globalData(), this, thisValue));
 
     JSGlobalObject::globalExec()->init(0, 0, m_globalScopeChain.get(), CallFrame::noCaller(), 0, 0);
 
     m_debugger = 0;
 
 
     JSGlobalObject::globalExec()->init(0, 0, m_globalScopeChain.get(), CallFrame::noCaller(), 0, 0);
 
     m_debugger = 0;
 
-    m_profileGroup = 0;
-
     reset(prototype());
 }
 
     reset(prototype());
 }
 
-void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void JSGlobalObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
-    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell);
+    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
 
 
-    if (symbolTablePut(exec->globalData(), propertyName, value))
+    if (thisObject->symbolTablePut(exec, propertyName, value, slot.isStrictMode()))
         return;
         return;
-    JSVariableObject::put(exec, propertyName, value, slot);
+    JSVariableObject::put(thisObject, exec, propertyName, value, slot);
 }
 
 }
 
-void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
+void JSGlobalObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
 {
-    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
+    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
 
 
-    if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
+    if (thisObject->symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
         return;
 
         return;
 
-    JSValue valueBefore = getDirect(exec->globalData(), propertyName);
+    JSValue valueBefore = thisObject->getDirect(exec->globalData(), propertyName);
     PutPropertySlot slot;
     PutPropertySlot slot;
-    JSVariableObject::put(exec, propertyName, value, slot);
+    JSVariableObject::put(thisObject, exec, propertyName, value, slot);
     if (!valueBefore) {
     if (!valueBefore) {
-        JSValue valueAfter = getDirect(exec->globalData(), propertyName);
+        JSValue valueAfter = thisObject->getDirect(exec->globalData(), propertyName);
         if (valueAfter)
         if (valueAfter)
-            JSObject::putWithAttributes(exec, propertyName, valueAfter, attributes);
+            JSObject::putDirectVirtual(thisObject, exec, propertyName, valueAfter, attributes);
     }
 }
 
     }
 }
 
-void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes)
+bool JSGlobalObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
 {
 {
+    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
     PropertySlot slot;
     PropertySlot slot;
-    if (!symbolTableGet(propertyName, slot))
-        JSVariableObject::defineGetter(exec, propertyName, getterFunc, attributes);
+    // silently ignore attempts to add accessors aliasing vars.
+    if (descriptor.isAccessorDescriptor() && thisObject->symbolTableGet(propertyName, slot))
+        return false;
+    return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
 }
 
 }
 
-void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes)
-{
-    PropertySlot slot;
-    if (!symbolTableGet(propertyName, slot))
-        JSVariableObject::defineSetter(exec, propertyName, setterFunc, attributes);
-}
 
 static inline JSObject* lastInPrototypeChain(JSObject* object)
 {
 
 static inline JSObject* lastInPrototypeChain(JSObject* object)
 {
@@ -187,115 +193,131 @@ void JSGlobalObject::reset(JSValue prototype)
 {
     ExecState* exec = JSGlobalObject::globalExec();
 
 {
     ExecState* exec = JSGlobalObject::globalExec();
 
-    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()));
+    m_functionPrototype.set(exec->globalData(), this, FunctionPrototype::create(exec, this, FunctionPrototype::createStructure(exec->globalData(), this, jsNull()))); // The real prototype will be set once ObjectPrototype is created.
+    m_functionStructure.set(exec->globalData(), this, JSFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
+    m_boundFunctionStructure.set(exec->globalData(), this, JSBoundFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
+    m_namedFunctionStructure.set(exec->globalData(), this, Structure::addPropertyTransition(exec->globalData(), m_functionStructure.get(), exec->globalData().propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset));
+    m_internalFunctionStructure.set(exec->globalData(), this, InternalFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
     JSFunction* callFunction = 0;
     JSFunction* applyFunction = 0;
     JSFunction* callFunction = 0;
     JSFunction* applyFunction = 0;
-    m_functionPrototype->addFunctionProperties(exec, this, m_functionStructure.get(), &callFunction, &applyFunction);
+    m_functionPrototype->addFunctionProperties(exec, this, &callFunction, &applyFunction);
     m_callFunction.set(exec->globalData(), this, callFunction);
     m_applyFunction.set(exec->globalData(), this, 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_objectPrototype.set(exec->globalData(), this, ObjectPrototype::create(exec, this, ObjectPrototype::createStructure(exec->globalData(), this, jsNull())));
+    GetterSetter* protoAccessor = GetterSetter::create(exec);
+    protoAccessor->setGetter(exec->globalData(), JSFunction::create(exec, this, 0, Identifier(), globalFuncProtoGetter));
+    protoAccessor->setSetter(exec->globalData(), JSFunction::create(exec, this, 0, Identifier(), globalFuncProtoSetter));
+    m_objectPrototype->putDirectAccessor(exec->globalData(), exec->propertyNames().underscoreProto, protoAccessor, Accessor | DontEnum);
     m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->globalData(), m_objectPrototype.get());
 
     m_emptyObjectStructure.set(exec->globalData(), this, m_objectPrototype->inheritorID(exec->globalData()));
     m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->globalData(), m_objectPrototype.get());
 
     m_emptyObjectStructure.set(exec->globalData(), this, m_objectPrototype->inheritorID(exec->globalData()));
-    m_nullPrototypeObjectStructure.set(exec->globalData(), this, createEmptyObjectStructure(exec->globalData(), jsNull()));
+    m_nullPrototypeObjectStructure.set(exec->globalData(), this, createEmptyObjectStructure(exec->globalData(), this, jsNull()));
 
 
-    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()));
+    m_callbackFunctionStructure.set(exec->globalData(), this, JSCallbackFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
+    m_argumentsStructure.set(exec->globalData(), this, Arguments::createStructure(exec->globalData(), this, m_objectPrototype.get()));
+    m_callbackConstructorStructure.set(exec->globalData(), this, JSCallbackConstructor::createStructure(exec->globalData(), this, m_objectPrototype.get()));
+    m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSNonFinalObject>::createStructure(exec->globalData(), this, m_objectPrototype.get()));
 
 
-    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()));
+    m_arrayPrototype.set(exec->globalData(), this, ArrayPrototype::create(exec, this, ArrayPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
+    m_arrayStructure.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get()));
+    m_regExpMatchesArrayStructure.set(exec->globalData(), this, RegExpMatchesArray::createStructure(exec->globalData(), this, m_arrayPrototype.get()));
 
 
-    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()));
+    m_stringPrototype.set(exec->globalData(), this, StringPrototype::create(exec, this, StringPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
+    m_stringObjectStructure.set(exec->globalData(), this, StringObject::createStructure(exec->globalData(), this, m_stringPrototype.get()));
 
 
-    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()));
+    m_booleanPrototype.set(exec->globalData(), this, BooleanPrototype::create(exec, this, BooleanPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
+    m_booleanObjectStructure.set(exec->globalData(), this, BooleanObject::createStructure(exec->globalData(), this, m_booleanPrototype.get()));
 
 
-    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()));
+    m_numberPrototype.set(exec->globalData(), this, NumberPrototype::create(exec, this, NumberPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
+    m_numberObjectStructure.set(exec->globalData(), this, NumberObject::createStructure(exec->globalData(), this, m_numberPrototype.get()));
 
 
-    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()));
+    m_datePrototype.set(exec->globalData(), this, DatePrototype::create(exec, this, DatePrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
+    m_dateStructure.set(exec->globalData(), this, DateInstance::createStructure(exec->globalData(), this, m_datePrototype.get()));
 
 
-    RegExp* emptyRegex = RegExp::create(&exec->globalData(), "", NoFlags);
+    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()));
+    m_regExpPrototype.set(exec->globalData(), this, RegExpPrototype::create(exec, this, RegExpPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()), emptyRegex));
+    m_regExpStructure.set(exec->globalData(), this, RegExpObject::createStructure(exec->globalData(), this, m_regExpPrototype.get()));
 
     m_methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec));
 
 
     m_methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec));
 
-    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));
+    ErrorPrototype* errorPrototype = ErrorPrototype::create(exec, this, ErrorPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()));
+    m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), this, errorPrototype));
 
     // Constructors
 
 
     // Constructors
 
-    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);
+    JSCell* objectConstructor = ObjectConstructor::create(exec, this, ObjectConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_objectPrototype.get());
+    JSCell* functionConstructor = FunctionConstructor::create(exec, this, FunctionConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_functionPrototype.get());
+    JSCell* arrayConstructor = ArrayConstructor::create(exec, this, ArrayConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_arrayPrototype.get());
+    JSCell* stringConstructor = StringConstructor::create(exec, this, StringConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_stringPrototype.get());
+    JSCell* booleanConstructor = BooleanConstructor::create(exec, this, BooleanConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_booleanPrototype.get());
+    JSCell* numberConstructor = NumberConstructor::create(exec, this, NumberConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_numberPrototype.get());
+    JSCell* dateConstructor = DateConstructor::create(exec, this, DateConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_datePrototype.get());
+
+    m_regExpConstructor.set(exec->globalData(), this, RegExpConstructor::create(exec, this, RegExpConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_regExpPrototype.get()));
+
+    m_errorConstructor.set(exec->globalData(), this, ErrorConstructor::create(exec, this, ErrorConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), errorPrototype));
+
+    Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->globalData(), this, errorPrototype);
+    Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get());
+    m_evalErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError"));
+    m_rangeErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError"));
+    m_referenceErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError"));
+    m_syntaxErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError"));
+    m_typeErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError"));
+    m_URIErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError"));
+
+    m_objectPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum);
+    m_functionPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum);
+    m_arrayPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum);
+    m_booleanPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum);
+    m_stringPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum);
+    m_numberPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum);
+    m_datePrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum);
+    m_regExpPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum);
+    errorPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum);
+
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Object"), objectConstructor, DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Function"), functionConstructor, DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Array"), arrayConstructor, DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "String"), stringConstructor, DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Number"), numberConstructor, DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Date"), dateConstructor, DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), m_regExpConstructor.get(), DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Error"), m_errorConstructor.get(), DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), m_evalErrorConstructor.get(), DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), m_rangeErrorConstructor.get(), DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), m_referenceErrorConstructor.get(), DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), m_syntaxErrorConstructor.get(), DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), m_typeErrorConstructor.get(), DontEnum);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), m_URIErrorConstructor.get(), DontEnum);
+
+    m_evalFunction.set(exec->globalData(), this, JSFunction::create(exec, this, 1, exec->propertyNames().eval, globalFuncEval));
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().eval, m_evalFunction.get(), DontEnum);
+
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "JSON"), JSONObject::create(exec, this, JSONObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum);
 
     GlobalPropertyInfo staticGlobals[] = {
 
     GlobalPropertyInfo staticGlobals[] = {
-        GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, this, MathObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete),
+        GlobalPropertyInfo(Identifier(exec, "Math"), MathObject::create(exec, this, MathObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum | DontDelete),
         GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly),
-        GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(Inf), DontEnum | DontDelete | ReadOnly),
-        GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly),
-        GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(this, JSONObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete)
+        GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(std::numeric_limits<double>::infinity()), DontEnum | DontDelete | ReadOnly),
+        GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly)
     };
     addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
 
     resetPrototype(exec->globalData(), prototype);
 }
 
     };
     addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
 
     resetPrototype(exec->globalData(), prototype);
 }
 
+void JSGlobalObject::createThrowTypeError(ExecState* exec)
+{
+    JSFunction* thrower = JSFunction::create(exec, this, 0, Identifier(), globalFuncThrowTypeError);
+    GetterSetter* getterSetter = GetterSetter::create(exec);
+    getterSetter->setGetter(exec->globalData(), thrower);
+    getterSetter->setSetter(exec->globalData(), thrower);
+    m_throwTypeErrorGetterSetter.set(exec->globalData(), this, getterSetter);
+}
+
 // Set prototype, and also insert the object prototype at the end of the chain.
 void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype)
 {
 // Set prototype, and also insert the object prototype at the end of the chain.
 void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype)
 {
@@ -307,64 +329,68 @@ void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype)
         oldLastInPrototypeChain->setPrototype(globalData, objectPrototype);
 }
 
         oldLastInPrototypeChain->setPrototype(globalData, objectPrototype);
 }
 
-void JSGlobalObject::visitChildren(SlotVisitor& visitor)
-{
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{ 
+    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     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) {
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    JSVariableObject::visitChildren(thisObject, visitor);
+
+    visitIfNeeded(visitor, &thisObject->m_globalScopeChain);
+    visitIfNeeded(visitor, &thisObject->m_methodCallDummy);
+
+    visitIfNeeded(visitor, &thisObject->m_regExpConstructor);
+    visitIfNeeded(visitor, &thisObject->m_errorConstructor);
+    visitIfNeeded(visitor, &thisObject->m_evalErrorConstructor);
+    visitIfNeeded(visitor, &thisObject->m_rangeErrorConstructor);
+    visitIfNeeded(visitor, &thisObject->m_referenceErrorConstructor);
+    visitIfNeeded(visitor, &thisObject->m_syntaxErrorConstructor);
+    visitIfNeeded(visitor, &thisObject->m_typeErrorConstructor);
+    visitIfNeeded(visitor, &thisObject->m_URIErrorConstructor);
+
+    visitIfNeeded(visitor, &thisObject->m_evalFunction);
+    visitIfNeeded(visitor, &thisObject->m_callFunction);
+    visitIfNeeded(visitor, &thisObject->m_applyFunction);
+    visitIfNeeded(visitor, &thisObject->m_throwTypeErrorGetterSetter);
+
+    visitIfNeeded(visitor, &thisObject->m_objectPrototype);
+    visitIfNeeded(visitor, &thisObject->m_functionPrototype);
+    visitIfNeeded(visitor, &thisObject->m_arrayPrototype);
+    visitIfNeeded(visitor, &thisObject->m_booleanPrototype);
+    visitIfNeeded(visitor, &thisObject->m_stringPrototype);
+    visitIfNeeded(visitor, &thisObject->m_numberPrototype);
+    visitIfNeeded(visitor, &thisObject->m_datePrototype);
+    visitIfNeeded(visitor, &thisObject->m_regExpPrototype);
+
+    visitIfNeeded(visitor, &thisObject->m_argumentsStructure);
+    visitIfNeeded(visitor, &thisObject->m_arrayStructure);
+    visitIfNeeded(visitor, &thisObject->m_booleanObjectStructure);
+    visitIfNeeded(visitor, &thisObject->m_callbackConstructorStructure);
+    visitIfNeeded(visitor, &thisObject->m_callbackFunctionStructure);
+    visitIfNeeded(visitor, &thisObject->m_callbackObjectStructure);
+    visitIfNeeded(visitor, &thisObject->m_dateStructure);
+    visitIfNeeded(visitor, &thisObject->m_emptyObjectStructure);
+    visitIfNeeded(visitor, &thisObject->m_nullPrototypeObjectStructure);
+    visitIfNeeded(visitor, &thisObject->m_errorStructure);
+    visitIfNeeded(visitor, &thisObject->m_functionStructure);
+    visitIfNeeded(visitor, &thisObject->m_boundFunctionStructure);
+    visitIfNeeded(visitor, &thisObject->m_namedFunctionStructure);
+    visitIfNeeded(visitor, &thisObject->m_numberObjectStructure);
+    visitIfNeeded(visitor, &thisObject->m_regExpMatchesArrayStructure);
+    visitIfNeeded(visitor, &thisObject->m_regExpStructure);
+    visitIfNeeded(visitor, &thisObject->m_stringObjectStructure);
+    visitIfNeeded(visitor, &thisObject->m_internalFunctionStructure);
+
+    if (thisObject->m_registerArray) {
         // Outside the execution of global code, when our variables are torn off,
         // we can mark the torn-off array.
         // 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) {
+        visitor.appendValues(thisObject->m_registerArray.get(), thisObject->m_registerArraySize);
+    } else if (thisObject->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.
         // 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());
+        visitor.appendValues(thisObject->m_registers - thisObject->symbolTable().size(), thisObject->symbolTable().size());
     }
 }
 
     }
 }
 
@@ -373,122 +399,57 @@ ExecState* JSGlobalObject::globalExec()
     return CallFrame::create(m_globalCallFrame + RegisterFile::CallFrameHeaderSize);
 }
 
     return CallFrame::create(m_globalCallFrame + RegisterFile::CallFrameHeaderSize);
 }
 
-bool JSGlobalObject::isDynamicScope(bool&) const
-{
-    return true;
-}
-
-void JSGlobalObject::disableEval()
-{
-    ASSERT(m_isEvalEnabled);
-    m_isEvalEnabled = false;
-}
-
-void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile)
-{
-    ASSERT(!m_registerArray);
-    ASSERT(!m_registerArraySize);
-
-    int numGlobals = registerFile.numGlobals();
-    if (!numGlobals) {
-        m_registers = 0;
-        return;
-    }
-
-    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)
-{
-    JSGlobalObject* lastGlobalObject = registerFile.globalObject();
-    if (lastGlobalObject && lastGlobalObject != this)
-        lastGlobalObject->copyGlobalsFrom(registerFile);
-
-    registerFile.setGlobalObject(this);
-    registerFile.setNumGlobals(symbolTable().size());
-
-    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)
+void JSGlobalObject::resizeRegisters(size_t newSize)
 {
 {
-    ASSERT(oldSize <= newSize);
-    if (newSize == oldSize)
+    // Previous duplicate symbols may have created spare capacity in m_registerArray.
+    if (newSize <= m_registerArraySize)
         return;
         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();
-}
+    size_t oldSize = m_registerArraySize;
+    OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]);
+    for (size_t i = 0; i < oldSize; ++i)
+        registerArray[i].set(globalData(), this, m_registerArray[i].get());
+    for (size_t i = oldSize; i < newSize; ++i)
+        registerArray[i].setUndefined();
 
 
-void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
-{
-    return globalData->heap.allocate(size);
+    WriteBarrier<Unknown>* registers = registerArray.get();
+    setRegisters(registers, registerArray.release(), newSize);
 }
 
 void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
 {
 }
 
 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));
-    }
+    resizeRegisters(symbolTable().size() + count);
 
 
-    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) {
+    for (int i = 0; i < count; ++i) {
         GlobalPropertyInfo& global = globals[i];
         ASSERT(global.attributes & DontDelete);
         GlobalPropertyInfo& global = globals[i];
         ASSERT(global.attributes & DontDelete);
+        
+        int index = symbolTable().size();
         SymbolTableEntry newEntry(index, global.attributes);
         symbolTable().add(global.identifier.impl(), newEntry);
         registerAt(index).set(globalData(), this, global.value);
     }
 }
 
         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)
+bool JSGlobalObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
-    if (getStaticFunctionSlot<JSVariableObject>(exec, ExecState::globalObjectTable(exec), this, propertyName, slot))
+    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell);
+    if (getStaticFunctionSlot<JSVariableObject>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, slot))
         return true;
         return true;
-    return symbolTableGet(propertyName, slot);
+    return thisObject->symbolTableGet(propertyName, slot);
 }
 
 }
 
-bool JSGlobalObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool JSGlobalObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    if (getStaticFunctionDescriptor<JSVariableObject>(exec, ExecState::globalObjectTable(exec), this, propertyName, descriptor))
+    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
+    if (getStaticFunctionDescriptor<JSVariableObject>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, descriptor))
         return true;
         return true;
-    return symbolTableGet(propertyName, descriptor);
-}
-
-void JSGlobalObject::WeakMapsFinalizer::finalize(Handle<Unknown> handle, void*)
-{
-    JSGlobalObject* globalObject = asGlobalObject(handle.get());
-    globalObject->m_weakMaps.clear();
+    return thisObject->symbolTableGet(propertyName, descriptor);
 }
 
 }
 
-JSGlobalObject::WeakMapsFinalizer* JSGlobalObject::weakMapsFinalizer()
+void JSGlobalObject::clearRareData(JSCell* cell)
 {
 {
-    static WeakMapsFinalizer* finalizer = new WeakMapsFinalizer();
-    return finalizer;
+    jsCast<JSGlobalObject*>(cell)->m_rareData.clear();
 }
 
 DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSGlobalObject* dynamicGlobalObject)
 }
 
 DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSGlobalObject* dynamicGlobalObject)
@@ -498,7 +459,7 @@ DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSG
     if (!m_dynamicGlobalObjectSlot) {
 #if ENABLE(ASSEMBLER)
         if (ExecutableAllocator::underMemoryPressure())
     if (!m_dynamicGlobalObjectSlot) {
 #if ENABLE(ASSEMBLER)
         if (ExecutableAllocator::underMemoryPressure())
-            globalData.recompileAllJSFunctions();
+            globalData.heap.discardAllCompiledCode();
 #endif
 
         m_dynamicGlobalObjectSlot = dynamicGlobalObject;
 #endif
 
         m_dynamicGlobalObjectSlot = dynamicGlobalObject;
index 9f05d49123aa43f9ed33bdd423bc01d32b4da7e9..435c2be2c024a4930d90491153f14b64e8e54a09 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "JSArray.h"
 #include "JSGlobalData.h"
 
 #include "JSArray.h"
 #include "JSGlobalData.h"
+#include "JSGlobalThis.h"
 #include "JSVariableObject.h"
 #include "JSWeakObjectMapRefInternal.h"
 #include "NumberPrototype.h"
 #include "JSVariableObject.h"
 #include "JSWeakObjectMapRefInternal.h"
 #include "NumberPrototype.h"
@@ -41,7 +42,9 @@ namespace JSC {
     class Debugger;
     class ErrorConstructor;
     class FunctionPrototype;
     class Debugger;
     class ErrorConstructor;
     class FunctionPrototype;
+    class GetterSetter;
     class GlobalCodeBlock;
     class GlobalCodeBlock;
+    class LLIntOffsetsExtractor;
     class NativeErrorConstructor;
     class ProgramCodeBlock;
     class RegExpConstructor;
     class NativeErrorConstructor;
     class ProgramCodeBlock;
     class RegExpConstructor;
@@ -53,11 +56,38 @@ namespace JSC {
 
     typedef Vector<ExecState*, 16> ExecStateStack;
     
 
     typedef Vector<ExecState*, 16> ExecStateStack;
     
+    struct GlobalObjectMethodTable {
+        typedef bool (*AllowsAccessFromFunctionPtr)(const JSGlobalObject*, ExecState*);
+        AllowsAccessFromFunctionPtr allowsAccessFrom;
+
+        typedef bool (*SupportsProfilingFunctionPtr)(const JSGlobalObject*); 
+        SupportsProfilingFunctionPtr supportsProfiling;
+
+        typedef bool (*SupportsRichSourceInfoFunctionPtr)(const JSGlobalObject*);
+        SupportsRichSourceInfoFunctionPtr supportsRichSourceInfo;
+
+        typedef bool (*ShouldInterruptScriptFunctionPtr)(const JSGlobalObject*);
+        ShouldInterruptScriptFunctionPtr shouldInterruptScript;
+
+        typedef bool (*ShouldInterruptScriptBeforeTimeoutPtr)(const JSGlobalObject*);
+        ShouldInterruptScriptBeforeTimeoutPtr shouldInterruptScriptBeforeTimeout;
+    };
+
     class JSGlobalObject : public JSVariableObject {
     class JSGlobalObject : public JSVariableObject {
-    protected:
+    private:
         typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet;
 
         typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet;
 
-        RefPtr<JSGlobalData> m_globalData;
+        struct JSGlobalObjectRareData {
+            JSGlobalObjectRareData()
+                : profileGroup(0)
+            {
+            }
+
+            WeakMapSet weakMaps;
+            unsigned profileGroup;
+        };
+
+    protected:
 
         size_t m_registerArraySize;
         Register m_globalCallFrame[RegisterFile::CallFrameHeaderSize];
 
         size_t m_registerArraySize;
         Register m_globalCallFrame[RegisterFile::CallFrameHeaderSize];
@@ -77,6 +107,7 @@ namespace JSC {
         WriteBarrier<JSFunction> m_evalFunction;
         WriteBarrier<JSFunction> m_callFunction;
         WriteBarrier<JSFunction> m_applyFunction;
         WriteBarrier<JSFunction> m_evalFunction;
         WriteBarrier<JSFunction> m_callFunction;
         WriteBarrier<JSFunction> m_applyFunction;
+        WriteBarrier<GetterSetter> m_throwTypeErrorGetterSetter;
 
         WriteBarrier<ObjectPrototype> m_objectPrototype;
         WriteBarrier<FunctionPrototype> m_functionPrototype;
 
         WriteBarrier<ObjectPrototype> m_objectPrototype;
         WriteBarrier<FunctionPrototype> m_functionPrototype;
@@ -98,72 +129,89 @@ namespace JSC {
         WriteBarrier<Structure> m_nullPrototypeObjectStructure;
         WriteBarrier<Structure> m_errorStructure;
         WriteBarrier<Structure> m_functionStructure;
         WriteBarrier<Structure> m_nullPrototypeObjectStructure;
         WriteBarrier<Structure> m_errorStructure;
         WriteBarrier<Structure> m_functionStructure;
+        WriteBarrier<Structure> m_boundFunctionStructure;
+        WriteBarrier<Structure> m_namedFunctionStructure;
+        size_t m_functionNameOffset;
         WriteBarrier<Structure> m_numberObjectStructure;
         WriteBarrier<Structure> m_regExpMatchesArrayStructure;
         WriteBarrier<Structure> m_regExpStructure;
         WriteBarrier<Structure> m_stringObjectStructure;
         WriteBarrier<Structure> m_internalFunctionStructure;
 
         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;
 
         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();
+        OwnPtr<JSGlobalObjectRareData> m_rareData;
 
         WeakRandom m_weakRandom;
 
         SymbolTable m_symbolTable;
 
 
         WeakRandom m_weakRandom;
 
         SymbolTable m_symbolTable;
 
-        bool m_isEvalEnabled;
+        bool m_evalEnabled;
+
+        static JS_EXPORTDATA const GlobalObjectMethodTable s_globalObjectMethodTable;
+        const GlobalObjectMethodTable* m_globalObjectMethodTable;
 
 
+        void createRareDataIfNeeded()
+        {
+            if (m_rareData)
+                return;
+            m_rareData = adoptPtr(new JSGlobalObjectRareData);
+            Heap::heap(this)->addFinalizer(this, clearRareData);
+        }
+        
     public:
     public:
-        void* operator new(size_t, JSGlobalData*);
+        typedef JSVariableObject Base;
 
 
-        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)
+        static JSGlobalObject* create(JSGlobalData& globalData, Structure* structure)
         {
         {
-            COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot);
-            putThisToAnonymousValue(0);
-            init(this);
+            JSGlobalObject* globalObject = new (NotNull, allocateCell<JSGlobalObject>(globalData.heap)) JSGlobalObject(globalData, structure);
+            globalObject->finishCreation(globalData);
+            return globalObject;
         }
 
         static JS_EXPORTDATA const ClassInfo s_info;
 
     protected:
         }
 
         static JS_EXPORTDATA const ClassInfo s_info;
 
     protected:
-        JSGlobalObject(JSGlobalData& globalData, Structure* structure, JSObject* thisValue)
+        explicit JSGlobalObject(JSGlobalData& globalData, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable = 0)
             : JSVariableObject(globalData, structure, &m_symbolTable, 0)
             , m_registerArraySize(0)
             , m_globalScopeChain()
             , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
             : 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)
+            , m_evalEnabled(true)
+            , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable)
+        {
+        }
+
+        void finishCreation(JSGlobalData& globalData)
+        {
+            Base::finishCreation(globalData);
+            structure()->setGlobalObject(globalData, this);
+            init(this);
+        }
+
+        void finishCreation(JSGlobalData& globalData, JSGlobalThis* thisValue)
         {
         {
-            COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot);
-            putThisToAnonymousValue(0);
+            Base::finishCreation(globalData);
+            structure()->setGlobalObject(globalData, this);
             init(thisValue);
         }
 
     public:
             init(thisValue);
         }
 
     public:
-        virtual ~JSGlobalObject();
+        JS_EXPORT_PRIVATE ~JSGlobalObject();
+        JS_EXPORT_PRIVATE static void destroy(JSCell*);
+
+        JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
 
 
-        virtual void visitChildren(SlotVisitor&);
+        JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+        bool hasOwnPropertyForWrite(ExecState*, const Identifier&);
+        JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
-        virtual bool hasOwnPropertyForWrite(ExecState*, const Identifier&);
-        virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
-        virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
+        JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
 
 
-        virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
-        virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
+        JS_EXPORT_PRIVATE static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
+        JS_EXPORT_PRIVATE static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
+        JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
 
         // We use this in the code generator as we perform symbol table
         // lookups prior to initializing the properties
 
         // We use this in the code generator as we perform symbol table
         // lookups prior to initializing the properties
@@ -185,6 +233,12 @@ namespace JSC {
         JSFunction* evalFunction() const { return m_evalFunction.get(); }
         JSFunction* callFunction() const { return m_callFunction.get(); }
         JSFunction* applyFunction() const { return m_applyFunction.get(); }
         JSFunction* evalFunction() const { return m_evalFunction.get(); }
         JSFunction* callFunction() const { return m_callFunction.get(); }
         JSFunction* applyFunction() const { return m_applyFunction.get(); }
+        GetterSetter* throwTypeErrorGetterSetter(ExecState* exec)
+        {
+            if (!m_throwTypeErrorGetterSetter)
+                createThrowTypeError(exec);
+            return m_throwTypeErrorGetterSetter.get();
+        }
 
         ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); }
         FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); }
 
         ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); }
         FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); }
@@ -208,66 +262,70 @@ namespace JSC {
         Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); }
         Structure* errorStructure() const { return m_errorStructure.get(); }
         Structure* functionStructure() const { return m_functionStructure.get(); }
         Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); }
         Structure* errorStructure() const { return m_errorStructure.get(); }
         Structure* functionStructure() const { return m_functionStructure.get(); }
+        Structure* boundFunctionStructure() const { return m_boundFunctionStructure.get(); }
+        Structure* namedFunctionStructure() const { return m_namedFunctionStructure.get(); }
+        size_t functionNameOffset() const { return m_functionNameOffset; }
         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(); }
 
         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; }
+        void setProfileGroup(unsigned value) { createRareDataIfNeeded(); m_rareData->profileGroup = value; }
+        unsigned profileGroup() const
+        { 
+            if (!m_rareData)
+                return 0;
+            return m_rareData->profileGroup;
+        }
 
         Debugger* debugger() const { return m_debugger; }
         void setDebugger(Debugger* debugger) { m_debugger = debugger; }
 
 
         Debugger* debugger() const { return m_debugger; }
         void setDebugger(Debugger* debugger) { m_debugger = debugger; }
 
-        virtual bool supportsProfiling() const { return false; }
-        virtual bool supportsRichSourceInfo() const { return true; }
+        const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; }
 
 
-        ScopeChainNode* globalScopeChain() { return m_globalScopeChain.get(); }
-
-        virtual bool isGlobalObject() const { return true; }
+        static bool allowsAccessFrom(const JSGlobalObject*, ExecState*) { return true; }
+        static bool supportsProfiling(const JSGlobalObject*) { return false; }
+        static bool supportsRichSourceInfo(const JSGlobalObject*) { return true; }
 
 
-        virtual ExecState* globalExec();
+        ScopeChainNode* globalScopeChain() { return m_globalScopeChain.get(); }
 
 
-        virtual bool shouldInterruptScriptBeforeTimeout() const { return false; }
-        virtual bool shouldInterruptScript() const { return true; }
+        JS_EXPORT_PRIVATE ExecState* globalExec();
 
 
-        virtual bool allowsAccessFrom(const JSGlobalObject*) const { return true; }
+        static bool shouldInterruptScriptBeforeTimeout(const JSGlobalObject*) { return false; }
+        static bool shouldInterruptScript(const JSGlobalObject*) { return true; }
 
 
-        virtual bool isDynamicScope(bool& requiresDynamicChecks) const;
+        bool isDynamicScope(bool& requiresDynamicChecks) const;
 
 
-        void disableEval();
-        bool isEvalEnabled() { return m_isEvalEnabled; }
+        void setEvalEnabled(bool enabled) { m_evalEnabled = enabled; }
+        bool evalEnabled() { return m_evalEnabled; }
 
 
-        void copyGlobalsFrom(RegisterFile&);
-        void copyGlobalsTo(RegisterFile&);
-        void resizeRegisters(int oldSize, int newSize);
+        void resizeRegisters(size_t newSize);
 
         void resetPrototype(JSGlobalData&, JSValue prototype);
 
 
         void resetPrototype(JSGlobalData&, JSValue prototype);
 
-        JSGlobalData& globalData() const { return *m_globalData.get(); }
+        JSGlobalData& globalData() const { return *Heap::heap(this)->globalData(); }
 
         static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
 
         static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
         }
 
         void registerWeakMap(OpaqueJSWeakObjectMap* map)
         {
         }
 
         void registerWeakMap(OpaqueJSWeakObjectMap* map)
         {
-            if (!m_weakMapsFinalizer)
-                m_weakMapsFinalizer.set(globalData(), this, weakMapsFinalizer());
-            m_weakMaps.add(map);
+            createRareDataIfNeeded();
+            m_rareData->weakMaps.add(map);
         }
 
         }
 
-        void deregisterWeakMap(OpaqueJSWeakObjectMap* map)
+        void unregisterWeakMap(OpaqueJSWeakObjectMap* map)
         {
         {
-            m_weakMaps.remove(map);
+            if (m_rareData)
+                m_rareData->weakMaps.remove(map);
         }
 
         double weakRandomNumber() { return m_weakRandom.get(); }
     protected:
 
         }
 
         double weakRandomNumber() { return m_weakRandom.get(); }
     protected:
 
-        static const unsigned AnonymousSlotCount = JSVariableObject::AnonymousSlotCount + 1;
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
 
         struct GlobalPropertyInfo {
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
 
         struct GlobalPropertyInfo {
@@ -282,16 +340,19 @@ namespace JSC {
             JSValue value;
             unsigned attributes;
         };
             JSValue value;
             unsigned attributes;
         };
-        void addStaticGlobals(GlobalPropertyInfo*, int count);
+        JS_EXPORT_PRIVATE void addStaticGlobals(GlobalPropertyInfo*, int count);
 
     private:
 
     private:
+        friend class LLIntOffsetsExtractor;
+        
         // FIXME: Fold reset into init.
         // FIXME: Fold reset into init.
-        void init(JSObject* thisValue);
+        JS_EXPORT_PRIVATE void init(JSObject* thisValue);
         void reset(JSValue prototype);
 
         void reset(JSValue prototype);
 
-        void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count);
+        void createThrowTypeError(ExecState*);
 
 
-        void* operator new(size_t); // can only be allocated with JSGlobalData
+        void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count);
+        JS_EXPORT_PRIVATE static void clearRareData(JSCell*);
     };
 
     JSGlobalObject* asGlobalObject(JSValue);
     };
 
     JSGlobalObject* asGlobalObject(JSValue);
@@ -299,7 +360,7 @@ namespace JSC {
     inline JSGlobalObject* asGlobalObject(JSValue value)
     {
         ASSERT(asObject(value)->isGlobalObject());
     inline JSGlobalObject* asGlobalObject(JSValue value)
     {
         ASSERT(asObject(value)->isGlobalObject());
-        return static_cast<JSGlobalObject*>(asObject(value));
+        return jsCast<JSGlobalObject*>(asObject(value));
     }
 
     inline void JSGlobalObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count)
     }
 
     inline void JSGlobalObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count)
@@ -311,7 +372,7 @@ namespace JSC {
     inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
     {
         PropertySlot slot;
     inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
     {
         PropertySlot slot;
-        if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
+        if (JSVariableObject::getOwnPropertySlot(this, exec, propertyName, slot))
             return true;
         bool slotIsWriteable;
         return symbolTableGet(propertyName, slot, slotIsWriteable);
             return true;
         bool slotIsWriteable;
         return symbolTableGet(propertyName, slot, slotIsWriteable);
@@ -325,7 +386,7 @@ namespace JSC {
 
     inline JSValue Structure::prototypeForLookup(ExecState* exec) const
     {
 
     inline JSValue Structure::prototypeForLookup(ExecState* exec) const
     {
-        if (typeInfo().type() == ObjectType)
+        if (isObject())
             return m_prototype.get();
 
         ASSERT(typeInfo().type() == StringType);
             return m_prototype.get();
 
         ASSERT(typeInfo().type() == StringType);
@@ -379,52 +440,65 @@ namespace JSC {
         return constructEmptyObject(exec, exec->lexicalGlobalObject());
     }
 
         return constructEmptyObject(exec, exec->lexicalGlobalObject());
     }
 
-    inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject)
+    inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject, unsigned initialLength = 0)
     {
     {
-        return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure());
-    }
-    
-    inline JSArray* constructEmptyArray(ExecState* exec)
-    {
-        return constructEmptyArray(exec, exec->lexicalGlobalObject());
-    }
-
-    inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject, unsigned initialLength)
-    {
-        return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), initialLength, CreateInitialized);
+        return JSArray::create(exec->globalData(), globalObject->arrayStructure(), initialLength);
     }
 
     }
 
-    inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength)
+    inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength = 0)
     {
         return constructEmptyArray(exec, exec->lexicalGlobalObject(), initialLength);
     }
 
     {
         return constructEmptyArray(exec, exec->lexicalGlobalObject(), initialLength);
     }
 
-    inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, JSValue singleItemValue)
+    inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const ArgList& values)
     {
     {
-        MarkedArgumentBuffer values;
-        values.append(singleItemValue);
-        return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), values);
+        JSGlobalData& globalData = exec->globalData();
+        unsigned length = values.size();
+        JSArray* array = JSArray::tryCreateUninitialized(globalData, globalObject->arrayStructure(), length);
+
+        // FIXME: we should probably throw an out of memory error here, but
+        // when making this change we should check that all clients of this
+        // function will correctly handle an exception being thrown from here.
+        if (!array)
+            CRASH();
+
+        for (unsigned i = 0; i < length; ++i)
+            array->initializeIndex(globalData, i, values.at(i));
+        array->completeInitialization(length);
+        return array;
     }
 
     }
 
-    inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue)
+    inline JSArray* constructArray(ExecState* exec, const ArgList& values)
     {
     {
-        return constructArray(exec, exec->lexicalGlobalObject(), singleItemValue);
+        return constructArray(exec, exec->lexicalGlobalObject(), values);
     }
 
     }
 
-    inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const ArgList& values)
+    inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const JSValue* values, unsigned length)
     {
     {
-        return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), values);
+        JSGlobalData& globalData = exec->globalData();
+        JSArray* array = JSArray::tryCreateUninitialized(globalData, globalObject->arrayStructure(), length);
+
+        // FIXME: we should probably throw an out of memory error here, but
+        // when making this change we should check that all clients of this
+        // function will correctly handle an exception being thrown from here.
+        if (!array)
+            CRASH();
+
+        for (unsigned i = 0; i < length; ++i)
+            array->initializeIndex(globalData, i, values[i]);
+        array->completeInitialization(length);
+        return array;
     }
 
     }
 
-    inline JSArray* constructArray(ExecState* exec, const ArgList& values)
+    inline JSArray* constructArray(ExecState* exec, const JSValue* values, unsigned length)
     {
     {
-        return constructArray(exec, exec->lexicalGlobalObject(), values);
+        return constructArray(exec, exec->lexicalGlobalObject(), values, length);
     }
 
     class DynamicGlobalObjectScope {
         WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope);
     public:
     }
 
     class DynamicGlobalObjectScope {
         WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope);
     public:
-        DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*);
+        JS_EXPORT_PRIVATE DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*);
 
         ~DynamicGlobalObjectScope()
         {
 
         ~DynamicGlobalObjectScope()
         {
@@ -436,6 +510,11 @@ namespace JSC {
         JSGlobalObject* m_savedDynamicGlobalObject;
     };
 
         JSGlobalObject* m_savedDynamicGlobalObject;
     };
 
+    inline bool JSGlobalObject::isDynamicScope(bool&) const
+    {
+        return true;
+    }
+
 } // namespace JSC
 
 #endif // JSGlobalObject_h
 } // namespace JSC
 
 #endif // JSGlobalObject_h
index 35507e872042e5812ae85f7f0dd9ba930be97a84..e8017b9043befc733162437c636adbae3c1d1467 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 /*
  *  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) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 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
  *
@@ -35,7 +35,7 @@
 #include "Nodes.h"
 #include "Parser.h"
 #include "UStringBuilder.h"
 #include "Nodes.h"
 #include "Parser.h"
 #include "UStringBuilder.h"
-#include "dtoa.h"
+#include <wtf/dtoa.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <wtf/ASCIICType.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <wtf/ASCIICType.h>
@@ -51,8 +51,7 @@ namespace JSC {
 
 static JSValue encode(ExecState* exec, const char* doNotEscape)
 {
 
 static JSValue encode(ExecState* exec, const char* doNotEscape)
 {
-    UString str = exec->argument(0).toString(exec);
-    CString cstr = str.utf8(true);
+    CString cstr = exec->argument(0).toString(exec)->value(exec).utf8(true);
     if (!cstr.data())
         return throwError(exec, createURIError(exec, "String contained an illegal UTF-16 sequence."));
 
     if (!cstr.data())
         return throwError(exec, createURIError(exec, "String contained an illegal UTF-16 sequence."));
 
@@ -71,30 +70,29 @@ static JSValue encode(ExecState* exec, const char* doNotEscape)
     return builder.build(exec);
 }
 
     return builder.build(exec);
 }
 
-static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
+template <typename CharType>
+ALWAYS_INLINE
+static JSValue decode(ExecState* exec, const CharType* characters, int length, const char* doNotUnescape, bool strict)
 {
     JSStringBuilder builder;
 {
     JSStringBuilder builder;
-    UString str = exec->argument(0).toString(exec);
     int k = 0;
     int k = 0;
-    int len = str.length();
-    const UChar* d = str.characters();
     UChar u = 0;
     UChar u = 0;
-    while (k < len) {
-        const UChar* p = d + k;
-        UChar c = *p;
+    while (k < length) {
+        const CharType* p = characters + k;
+        CharType c = *p;
         if (c == '%') {
             int charLen = 0;
         if (c == '%') {
             int charLen = 0;
-            if (k <= len - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {
-                const char b0 = Lexer::convertHex(p[1], p[2]);
+            if (k <= length - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {
+                const char b0 = Lexer<CharType>::convertHex(p[1], p[2]);
                 const int sequenceLen = UTF8SequenceLength(b0);
                 const int sequenceLen = UTF8SequenceLength(b0);
-                if (sequenceLen != 0 && k <= len - sequenceLen * 3) {
+                if (sequenceLen && k <= length - sequenceLen * 3) {
                     charLen = sequenceLen * 3;
                     char sequence[5];
                     sequence[0] = b0;
                     for (int i = 1; i < sequenceLen; ++i) {
                     charLen = sequenceLen * 3;
                     char sequence[5];
                     sequence[0] = b0;
                     for (int i = 1; i < sequenceLen; ++i) {
-                        const UChar* q = p + i * 3;
+                        const CharType* q = p + i * 3;
                         if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))
                         if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))
-                            sequence[i] = Lexer::convertHex(q[1], q[2]);
+                            sequence[i] = Lexer<CharType>::convertHex(q[1], q[2]);
                         else {
                             charLen = 0;
                             break;
                         else {
                             charLen = 0;
                             break;
@@ -119,16 +117,20 @@ static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
                     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.
                     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'
+                if (k <= length - 6 && p[1] == 'u'
                         && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])
                         && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {
                     charLen = 6;
                         && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])
                         && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {
                     charLen = 6;
-                    u = Lexer::convertUnicode(p[2], p[3], p[4], p[5]);
+                    u = Lexer<UChar>::convertUnicode(p[2], p[3], p[4], p[5]);
                 }
             }
             if (charLen && (u == 0 || u >= 128 || !strchr(doNotUnescape, u))) {
                 }
             }
             if (charLen && (u == 0 || u >= 128 || !strchr(doNotUnescape, u))) {
-                c = u;
-                k += charLen - 1;
+                if (u < 256)
+                    builder.append(static_cast<LChar>(u));
+                else
+                    builder.append(u);
+                k += charLen;
+                continue;
             }
         }
         k++;
             }
         }
         k++;
@@ -137,6 +139,16 @@ static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
     return builder.build(exec);
 }
 
     return builder.build(exec);
 }
 
+static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
+{
+    JSStringBuilder builder;
+    UString str = exec->argument(0).toString(exec)->value(exec);
+    
+    if (str.is8Bit())
+        return decode(exec, str.characters8(), str.length(), doNotUnescape, strict);
+    return decode(exec, str.characters16(), str.length(), doNotUnescape, strict);
+}
+
 bool isStrWhiteSpace(UChar c)
 {
     switch (c) {
 bool isStrWhiteSpace(UChar c)
 {
     switch (c) {
@@ -173,15 +185,15 @@ static int parseDigit(unsigned short c, int radix)
     return digit;
 }
 
     return digit;
 }
 
-double parseIntOverflow(const char* s, int length, int radix)
+double parseIntOverflow(const LChar* s, int length, int radix)
 {
     double number = 0.0;
     double radixMultiplier = 1.0;
 
 {
     double number = 0.0;
     double radixMultiplier = 1.0;
 
-    for (const char* p = s + length - 1; p >= s; p--) {
-        if (radixMultiplier == Inf) {
+    for (const LChar* p = s + length - 1; p >= s; p--) {
+        if (radixMultiplier == std::numeric_limits<double>::infinity()) {
             if (*p != '0') {
             if (*p != '0') {
-                number = Inf;
+                number = std::numeric_limits<double>::infinity();
                 break;
             }
         } else {
                 break;
             }
         } else {
@@ -201,9 +213,9 @@ double parseIntOverflow(const UChar* s, int length, int radix)
     double radixMultiplier = 1.0;
 
     for (const UChar* p = s + length - 1; p >= s; p--) {
     double radixMultiplier = 1.0;
 
     for (const UChar* p = s + length - 1; p >= s; p--) {
-        if (radixMultiplier == Inf) {
+        if (radixMultiplier == std::numeric_limits<double>::infinity()) {
             if (*p != '0') {
             if (*p != '0') {
-                number = Inf;
+                number = std::numeric_limits<double>::infinity();
                 break;
             }
         } else {
                 break;
             }
         } else {
@@ -217,15 +229,23 @@ double parseIntOverflow(const UChar* s, int length, int radix)
     return number;
 }
 
     return number;
 }
 
-static double parseInt(const UString& s, int radix)
+// ES5.1 15.1.2.2
+template <typename CharType>
+ALWAYS_INLINE
+static double parseInt(const UString& s, const CharType* data, int radix)
 {
 {
+    // 1. Let inputString be ToString(string).
+    // 2. Let S be a newly created substring of inputString consisting of the first character that is not a
+    //    StrWhiteSpaceChar and all characters following that character. (In other words, remove leading white
+    //    space.) If inputString does not contain any such characters, let S be the empty string.
     int length = s.length();
     int length = s.length();
-    const UChar* data = s.characters();
     int p = 0;
     int p = 0;
-
     while (p < length && isStrWhiteSpace(data[p]))
         ++p;
 
     while (p < length && isStrWhiteSpace(data[p]))
         ++p;
 
+    // 3. Let sign be 1.
+    // 4. If S is not empty and the first character of S is a minus sign -, let sign be -1.
+    // 5. If S is not empty and the first character of S is a plus sign + or a minus sign -, then remove the first character from S.
     double sign = 1;
     if (p < length) {
         if (data[p] == '+')
     double sign = 1;
     if (p < length) {
         if (data[p] == '+')
@@ -236,19 +256,33 @@ static double parseInt(const UString& s, int radix)
         }
     }
 
         }
     }
 
+    // 6. Let R = ToInt32(radix).
+    // 7. Let stripPrefix be true.
+    // 8. If R != 0,then
+    //   b. If R != 16, let stripPrefix be false.
+    // 9. Else, R == 0
+    //   a. LetR = 10.
+    // 10. If stripPrefix is true, then
+    //   a. If the length of S is at least 2 and the first two characters of S are either â€•0x or â€•0X,
+    //      then remove the first two characters from S and let R = 16.
+    // 11. If S contains any character that is not a radix-R digit, then let Z be the substring of S
+    //     consisting of all characters before the first such character; otherwise, let Z be S.
     if ((radix == 0 || radix == 16) && length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X')) {
         radix = 16;
         p += 2;
     if ((radix == 0 || radix == 16) && length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X')) {
         radix = 16;
         p += 2;
-    } else if (radix == 0) {
-        if (p < length && data[p] == '0')
-            radix = 8;
-        else
-            radix = 10;
-    }
+    } else if (radix == 0)
+        radix = 10;
 
 
+    // 8.a If R < 2 or R > 36, then return NaN.
     if (radix < 2 || radix > 36)
     if (radix < 2 || radix > 36)
-        return NaN;
-
+        return std::numeric_limits<double>::quiet_NaN();
+
+    // 13. Let mathInt be the mathematical integer value that is represented by Z in radix-R notation, using the letters
+    //     A-Z and a-z for digits with values 10 through 35. (However, if R is 10 and Z contains more than 20 significant
+    //     digits, every significant digit after the 20th may be replaced by a 0 digit, at the option of the implementation;
+    //     and if R is not 2, 4, 8, 10, 16, or 32, then mathInt may be an implementation-dependent approximation to the
+    //     mathematical integer value that is represented by Z in radix-R notation.)
+    // 14. Let number be the Number value for mathInt.
     int firstDigitPosition = p;
     bool sawDigit = false;
     double number = 0;
     int firstDigitPosition = p;
     bool sawDigit = false;
     double number = 0;
@@ -262,22 +296,34 @@ static double parseInt(const UString& s, int radix)
         ++p;
     }
 
         ++p;
     }
 
+    // 12. If Z is empty, return NaN.
+    if (!sawDigit)
+        return std::numeric_limits<double>::quiet_NaN();
+
+    // Alternate code path for certain large numbers.
     if (number >= mantissaOverflowLowerBound) {
     if (number >= mantissaOverflowLowerBound) {
-        if (radix == 10)
-            number = WTF::strtod(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), 0);
-        else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)
+        if (radix == 10) {
+            size_t parsedLength;
+            number = parseDouble(s.characters() + firstDigitPosition, p - firstDigitPosition, parsedLength);
+        } else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)
             number = parseIntOverflow(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), p - firstDigitPosition, radix);
     }
 
             number = parseIntOverflow(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), p - firstDigitPosition, radix);
     }
 
-    if (!sawDigit)
-        return NaN;
-
+    // 15. Return sign x number.
     return sign * number;
 }
 
     return sign * number;
 }
 
+static double parseInt(const UString& s, int radix)
+{
+    if (s.is8Bit())
+        return parseInt(s, s.characters8(), radix);
+    return parseInt(s, s.characters16(), radix);
+}
+
 static const int SizeOfInfinity = 8;
 
 static const int SizeOfInfinity = 8;
 
-static bool isInfinity(const UChar* data, const UChar* end)
+template <typename CharType>
+static bool isInfinity(const CharType* data, const CharType* end)
 {
     return (end - data) >= SizeOfInfinity
         && data[0] == 'I'
 {
     return (end - data) >= SizeOfInfinity
         && data[0] == 'I'
@@ -291,11 +337,12 @@ static bool isInfinity(const UChar* data, const UChar* end)
 }
 
 // See ecma-262 9.3.1
 }
 
 // See ecma-262 9.3.1
-static double jsHexIntegerLiteral(const UChar*& data, const UChar* end)
+template <typename CharType>
+static double jsHexIntegerLiteral(const CharType*& data, const CharType* end)
 {
     // Hex number.
     data += 2;
 {
     // Hex number.
     data += 2;
-    const UChar* firstDigitPosition = data;
+    const CharType* firstDigitPosition = data;
     double number = 0;
     while (true) {
         number = number * 16 + toASCIIHexValue(*data);
     double number = 0;
     while (true) {
         number = number * 16 + toASCIIHexValue(*data);
@@ -312,24 +359,15 @@ static double jsHexIntegerLiteral(const UChar*& data, const UChar* end)
 }
 
 // See ecma-262 9.3.1
 }
 
 // See ecma-262 9.3.1
-static double jsStrDecimalLiteral(const UChar*& data, const UChar* end)
+template <typename CharType>
+static double jsStrDecimalLiteral(const CharType*& data, const CharType* end)
 {
     ASSERT(data < 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;
+    size_t parsedLength;
+    double number = parseDouble(data, end - data, parsedLength);
+    if (parsedLength) {
+        data += parsedLength;
         return number;
     }
 
         return number;
     }
 
@@ -338,85 +376,109 @@ static double jsStrDecimalLiteral(const UChar*& data, const UChar* end)
     case 'I':
         if (isInfinity(data, end)) {
             data += SizeOfInfinity;
     case 'I':
         if (isInfinity(data, end)) {
             data += SizeOfInfinity;
-            return Inf;
+            return std::numeric_limits<double>::infinity();
         }
         break;
 
     case '+':
         if (isInfinity(data + 1, end)) {
             data += SizeOfInfinity + 1;
         }
         break;
 
     case '+':
         if (isInfinity(data + 1, end)) {
             data += SizeOfInfinity + 1;
-            return Inf;
+            return std::numeric_limits<double>::infinity();
         }
         break;
 
     case '-':
         if (isInfinity(data + 1, end)) {
             data += SizeOfInfinity + 1;
         }
         break;
 
     case '-':
         if (isInfinity(data + 1, end)) {
             data += SizeOfInfinity + 1;
-            return -Inf;
+            return -std::numeric_limits<double>::infinity();
         }
         break;
     }
 
     // Not a number.
         }
         break;
     }
 
     // Not a number.
-    return NaN;
+    return std::numeric_limits<double>::quiet_NaN();
 }
 
 }
 
-// See ecma-262 9.3.1
-double jsToNumber(const UString& s)
+template <typename CharType>
+static double toDouble(const CharType* characters, unsigned size)
 {
 {
-    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;
+    const CharType* endCharacters = characters + size;
 
     // Skip leading white space.
 
     // Skip leading white space.
-    for (; data < end; ++data) {
-        if (!isStrWhiteSpace(*data))
+    for (; characters < endCharacters; ++characters) {
+        if (!isStrWhiteSpace(*characters))
             break;
     }
             break;
     }
-
+    
     // Empty string.
     // Empty string.
-    if (data == end)
+    if (characters == endCharacters)
         return 0.0;
         return 0.0;
-
+    
     double number;
     double number;
-    if (data[0] == '0' && data + 2 < end && (data[1] | 0x20) == 'x' && isASCIIHexDigit(data[2]))
-        number = jsHexIntegerLiteral(data, end);
+    if (characters[0] == '0' && characters + 2 < endCharacters && (characters[1] | 0x20) == 'x' && isASCIIHexDigit(characters[2]))
+        number = jsHexIntegerLiteral(characters, endCharacters);
     else
     else
-        number = jsStrDecimalLiteral(data, end);
-
+        number = jsStrDecimalLiteral(characters, endCharacters);
+    
     // Allow trailing white space.
     // Allow trailing white space.
-    for (; data < end; ++data) {
-        if (!isStrWhiteSpace(*data))
+    for (; characters < endCharacters; ++characters) {
+        if (!isStrWhiteSpace(*characters))
             break;
     }
             break;
     }
-    if (data != end)
-        return NaN;
-
+    if (characters != endCharacters)
+        return std::numeric_limits<double>::quiet_NaN();
+    
     return number;
 }
 
     return number;
 }
 
+// See ecma-262 9.3.1
+double jsToNumber(const UString& s)
+{
+    unsigned size = s.length();
+
+    if (size == 1) {
+        UChar c = s[0];
+        if (isASCIIDigit(c))
+            return c - '0';
+        if (isStrWhiteSpace(c))
+            return 0;
+        return std::numeric_limits<double>::quiet_NaN();
+    }
+
+    if (s.is8Bit())
+        return toDouble(s.characters8(), size);
+    return toDouble(s.characters16(), size);
+}
+
 static double parseFloat(const UString& s)
 {
     unsigned size = s.length();
 
     if (size == 1) {
 static double parseFloat(const UString& s)
 {
     unsigned size = s.length();
 
     if (size == 1) {
-        UChar c = s.characters()[0];
+        UChar c = s[0];
         if (isASCIIDigit(c))
             return c - '0';
         if (isASCIIDigit(c))
             return c - '0';
-        return NaN;
+        return std::numeric_limits<double>::quiet_NaN();
+    }
+
+    if (s.is8Bit()) {
+        const LChar* data = s.characters8();
+        const LChar* end = data + size;
+
+        // Skip leading white space.
+        for (; data < end; ++data) {
+            if (!isStrWhiteSpace(*data))
+                break;
+        }
+
+        // Empty string.
+        if (data == end)
+            return std::numeric_limits<double>::quiet_NaN();
+
+        return jsStrDecimalLiteral(data, end);
     }
 
     }
 
-    const UChar* data = s.characters();
+    const UChar* data = s.characters16();
     const UChar* end = data + size;
 
     // Skip leading white space.
     const UChar* end = data + size;
 
     // Skip leading white space.
@@ -427,7 +489,7 @@ static double parseFloat(const UString& s)
 
     // Empty string.
     if (data == end)
 
     // Empty string.
     if (data == end)
-        return NaN;
+        return std::numeric_limits<double>::quiet_NaN();
 
     return jsStrDecimalLiteral(data, end);
 }
 
     return jsStrDecimalLiteral(data, end);
 }
@@ -436,53 +498,66 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
 {
     JSObject* thisObject = exec->hostThisValue().toThisObject(exec);
     JSObject* unwrappedObject = thisObject->unwrappedObject();
 {
     JSObject* thisObject = exec->hostThisValue().toThisObject(exec);
     JSObject* unwrappedObject = thisObject->unwrappedObject();
-    if (!unwrappedObject->isGlobalObject() || static_cast<JSGlobalObject*>(unwrappedObject)->evalFunction() != exec->callee())
+    if (!unwrappedObject->isGlobalObject() || jsCast<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 = exec->argument(0);
     if (!x.isString())
         return JSValue::encode(x);
 
         return throwVMError(exec, createEvalError(exec, "The \"this\" value passed to eval must be the global object from which eval originated"));
 
     JSValue x = exec->argument(0);
     if (!x.isString())
         return JSValue::encode(x);
 
-    UString s = x.toString(exec);
+    UString s = x.toString(exec)->value(exec);
 
 
-    LiteralParser preparser(exec, s.characters(), s.length(), LiteralParser::NonStrictJSON);
-    if (JSValue parsedObject = preparser.tryLiteralParse())
-        return JSValue::encode(parsedObject);
+    if (s.is8Bit()) {
+        LiteralParser<LChar> preparser(exec, s.characters8(), s.length(), NonStrictJSON);
+        if (JSValue parsedObject = preparser.tryLiteralParse())
+            return JSValue::encode(parsedObject);
+    } else {
+        LiteralParser<UChar> preparser(exec, s.characters16(), s.length(), NonStrictJSON);
+        if (JSValue parsedObject = preparser.tryLiteralParse())
+            return JSValue::encode(parsedObject);        
+    }
 
     EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false);
 
     EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false);
-    JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain());
+    JSObject* error = eval->compile(exec, jsCast<JSGlobalObject*>(unwrappedObject)->globalScopeChain());
     if (error)
         return throwVMError(exec, error);
 
     if (error)
         return throwVMError(exec, error);
 
-    return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain()));
+    return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, jsCast<JSGlobalObject*>(unwrappedObject)->globalScopeChain()));
 }
 
 EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
 {
     JSValue value = exec->argument(0);
 }
 
 EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
 {
     JSValue value = exec->argument(0);
-    int32_t radix = exec->argument(1).toInt32(exec);
-
-    if (radix != 0 && radix != 10)
-        return JSValue::encode(jsNumber(parseInt(value.toString(exec), radix)));
-
-    if (value.isInt32())
-        return JSValue::encode(value);
-
-    if (value.isDouble()) {
-        double d = value.asDouble();
-        if (isfinite(d))
-            return JSValue::encode(jsNumber((d > 0) ? floor(d) : ceil(d)));
-        if (isnan(d) || isinf(d))
-            return JSValue::encode(jsNaN());
-        return JSValue::encode(jsNumber(0));
+    JSValue radixValue = exec->argument(1);
+
+    // Optimized handling for numbers:
+    // If the argument is 0 or a number in range 10^-6 <= n < INT_MAX+1, then parseInt
+    // results in a truncation to integer. In the case of -0, this is converted to 0.
+    //
+    // This is also a truncation for values in the range INT_MAX+1 <= n < 10^21,
+    // however these values cannot be trivially truncated to int since 10^21 exceeds
+    // even the int64_t range. Negative numbers are a little trickier, the case for
+    // values in the range -10^21 < n <= -1 are similar to those for integer, but
+    // values in the range -1 < n <= -10^-6 need to truncate to -0, not 0.
+    static const double tenToTheMinus6 = 0.000001;
+    static const double intMaxPlusOne = 2147483648.0;
+    if (value.isNumber()) {
+        double n = value.asNumber();
+        if (((n < intMaxPlusOne && n >= tenToTheMinus6) || !n) && radixValue.isUndefinedOrNull())
+            return JSValue::encode(jsNumber(static_cast<int32_t>(n)));
     }
 
     }
 
-    return JSValue::encode(jsNumber(parseInt(value.toString(exec), radix)));
+    // If ToString throws, we shouldn't call ToInt32.
+    UString s = value.toString(exec)->value(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    return JSValue::encode(jsNumber(parseInt(s, radixValue.toInt32(exec))));
 }
 
 EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec)
 {
 }
 
 EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec)
 {
-    return JSValue::encode(jsNumber(parseFloat(exec->argument(0).toString(exec))));
+    return JSValue::encode(jsNumber(parseFloat(exec->argument(0).toString(exec)->value(exec))));
 }
 
 EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec)
@@ -493,7 +568,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL globalFuncIsFinite(ExecState* exec)
 {
     double n = exec->argument(0).toNumber(exec);
 EncodedJSValue JSC_HOST_CALL globalFuncIsFinite(ExecState* exec)
 {
     double n = exec->argument(0).toNumber(exec);
-    return JSValue::encode(jsBoolean(!isnan(n) && !isinf(n)));
+    return JSValue::encode(jsBoolean(isfinite(n)));
 }
 
 EncodedJSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState* exec)
@@ -540,8 +615,24 @@ EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec)
         "*+-./@_";
 
     JSStringBuilder builder;
         "*+-./@_";
 
     JSStringBuilder builder;
-    UString str = exec->argument(0).toString(exec);
-    const UChar* c = str.characters();
+    UString str = exec->argument(0).toString(exec)->value(exec);
+    if (str.is8Bit()) {
+        const LChar* c = str.characters8();
+        for (unsigned k = 0; k < str.length(); k++, c++) {
+            int u = c[0];
+            if (u && strchr(do_not_escape, static_cast<char>(u)))
+                builder.append(c, 1);
+            else {
+                char tmp[4];
+                snprintf(tmp, sizeof(tmp), "%%%02X", u);
+                builder.append(tmp);
+            }
+        }
+
+        return JSValue::encode(builder.build(exec));        
+    }
+
+    const UChar* c = str.characters16();
     for (unsigned k = 0; k < str.length(); k++, c++) {
         int u = c[0];
         if (u > 255) {
     for (unsigned k = 0; k < str.length(); k++, c++) {
         int u = c[0];
         if (u > 255) {
@@ -563,28 +654,93 @@ EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec)
 {
     UStringBuilder builder;
 EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec)
 {
     UStringBuilder builder;
-    UString str = exec->argument(0).toString(exec);
+    UString str = exec->argument(0).toString(exec)->value(exec);
     int k = 0;
     int len = str.length();
     int k = 0;
     int len = str.length();
-    while (k < len) {
-        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])) {
-                u = Lexer::convertUnicode(c[2], c[3], c[4], c[5]);
-                c = &u;
-                k += 5;
+    
+    if (str.is8Bit()) {
+        const LChar* characters = str.characters8();
+        LChar convertedLChar;
+        while (k < len) {
+            const LChar* c = characters + k;
+            if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {
+                if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(c[5])) {
+                    builder.append(Lexer<UChar>::convertUnicode(c[2], c[3], c[4], c[5]));
+                    k += 6;
+                    continue;
+                }
+            } else if (c[0] == '%' && k <= len - 3 && isASCIIHexDigit(c[1]) && isASCIIHexDigit(c[2])) {
+                convertedLChar = LChar(Lexer<LChar>::convertHex(c[1], c[2]));
+                c = &convertedLChar;
+                k += 2;
             }
             }
-        } else if (c[0] == '%' && k <= len - 3 && isASCIIHexDigit(c[1]) && isASCIIHexDigit(c[2])) {
-            u = UChar(Lexer::convertHex(c[1], c[2]));
-            c = &u;
-            k += 2;
+            builder.append(*c);
+            k++;
+        }        
+    } else {
+        const UChar* characters = str.characters16();
+
+        while (k < len) {
+            const UChar* c = characters + k;
+            UChar convertedUChar;
+            if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {
+                if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(c[5])) {
+                    convertedUChar = Lexer<UChar>::convertUnicode(c[2], c[3], c[4], c[5]);
+                    c = &convertedUChar;
+                    k += 5;
+                }
+            } else if (c[0] == '%' && k <= len - 3 && isASCIIHexDigit(c[1]) && isASCIIHexDigit(c[2])) {
+                convertedUChar = UChar(Lexer<UChar>::convertHex(c[1], c[2]));
+                c = &convertedUChar;
+                k += 2;
+            }
+            k++;
+            builder.append(*c);
         }
         }
-        k++;
-        builder.append(*c);
     }
 
     return JSValue::encode(jsString(exec, builder.toUString()));
 }
 
     }
 
     return JSValue::encode(jsString(exec, builder.toUString()));
 }
 
+EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState* exec)
+{
+    return throwVMTypeError(exec);
+}
+
+EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState* exec)
+{
+    if (!exec->thisValue().isObject())
+        return JSValue::encode(exec->thisValue().synthesizePrototype(exec));
+
+    JSObject* thisObject = asObject(exec->thisValue());
+    if (!thisObject->allowsAccessFrom(exec->trueCallerFrame()))
+        return JSValue::encode(jsUndefined());
+
+    return JSValue::encode(thisObject->prototype());
+}
+
+EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec)
+{
+    JSValue value = exec->argument(0);
+
+    // Setting __proto__ of a primitive should have no effect.
+    if (!exec->thisValue().isObject())
+        return JSValue::encode(jsUndefined());
+
+    JSObject* thisObject = asObject(exec->thisValue());
+    if (!thisObject->allowsAccessFrom(exec->trueCallerFrame()))
+        return JSValue::encode(jsUndefined());
+
+    // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
+    if (!value.isObject() && !value.isNull())
+        return JSValue::encode(jsUndefined());
+
+    if (!thisObject->isExtensible())
+        return throwVMError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
+
+    if (!thisObject->setPrototypeWithCycleCheck(exec->globalData(), value))
+        throwError(exec, createError(exec, "cyclic __proto__ value"));
+    return JSValue::encode(jsUndefined());
+}
+
 } // namespace JSC
 } // namespace JSC
index 36e9ac4cf90d103e54c10dd6ff333e69ca3a343e..8833bf6d0cf0336c41ee42b65b4beef76f7d6cda 100644 (file)
@@ -47,9 +47,13 @@ namespace JSC {
     EncodedJSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState*);
     EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState*);
     EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState*);
     EncodedJSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState*);
     EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState*);
     EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*);
 
     static const double mantissaOverflowLowerBound = 9007199254740992.0;
 
     static const double mantissaOverflowLowerBound = 9007199254740992.0;
-    double parseIntOverflow(const char*, int length, int radix);
+    double parseIntOverflow(const LChar*, int length, int radix);
+    ALWAYS_INLINE double parseIntOverflow(const char* s, int length, int radix) { return parseIntOverflow(reinterpret_cast<const LChar*>(s), length, radix); }
     double parseIntOverflow(const UChar*, int length, int radix);
     bool isStrWhiteSpace(UChar);
     double jsToNumber(const UString& s);
     double parseIntOverflow(const UChar*, int length, int radix);
     bool isStrWhiteSpace(UChar);
     double jsToNumber(const UString& s);
diff --git a/runtime/JSGlobalThis.cpp b/runtime/JSGlobalThis.cpp
new file mode 100644 (file)
index 0000000..abd31ac
--- /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. 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 "JSGlobalThis.h"
+
+#include "JSGlobalObject.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(JSGlobalThis);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSGlobalThis);
+
+const ClassInfo JSGlobalThis::s_info = { "JSGlobalThis", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSGlobalThis) };
+
+void JSGlobalThis::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    JSGlobalThis* thisObject = jsCast<JSGlobalThis*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+
+    Base::visitChildren(thisObject, visitor);
+    if (thisObject->m_unwrappedObject)
+        visitor.append(&thisObject->m_unwrappedObject);
+}
+
+void JSGlobalThis::setUnwrappedObject(JSGlobalData& globalData, JSGlobalObject* globalObject)
+{
+    ASSERT_ARG(globalObject, globalObject);
+    m_unwrappedObject.set(globalData, this, globalObject);
+    setPrototype(globalData, globalObject->prototype());
+    resetInheritorID();
+}
+
+} // namespace JSC
diff --git a/runtime/JSGlobalThis.h b/runtime/JSGlobalThis.h
new file mode 100644 (file)
index 0000000..0ca9941
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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 JSGlobalThis_h
+#define JSGlobalThis_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+class JSGlobalThis : public JSNonFinalObject {
+public:
+    typedef JSNonFinalObject Base;
+
+    static JSGlobalThis* create(JSGlobalData& globalData, Structure* structure)
+    {
+        JSGlobalThis* globalThis = new (NotNull, allocateCell<JSGlobalThis>(globalData.heap)) JSGlobalThis(globalData, structure);
+        globalThis->finishCreation(globalData);
+        return globalThis;
+    }
+
+    static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) 
+    {
+        return Structure::create(globalData, 0, prototype, TypeInfo(GlobalThisType, StructureFlags), &s_info); 
+    }
+
+    static JS_EXPORTDATA const JSC::ClassInfo s_info;
+
+    JSGlobalObject* unwrappedObject() const { return m_unwrappedObject.get(); }
+
+protected:
+    JSGlobalThis(JSGlobalData& globalData, Structure* structure)
+        : JSNonFinalObject(globalData, structure)
+    {
+    }
+
+    void finishCreation(JSGlobalData& globalData)
+    {
+        Base::finishCreation(globalData);
+    }
+
+    static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
+
+    JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
+
+    JS_EXPORT_PRIVATE void setUnwrappedObject(JSGlobalData&, JSGlobalObject*);
+    
+private:
+    WriteBarrier<JSGlobalObject> m_unwrappedObject;
+};
+
+} // namespace JSC
+
+#endif // JSGlobalThis_h
index fc543f0e82f72f768b8c75645885bcc1f163ace0..087c81dc59b042c47e8a0bd80cdaf127b7a79874 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "Heap.h"
 #include "CallFrame.h"
 
 #include "Heap.h"
 #include "CallFrame.h"
+#include "JSGlobalObject.h"
 #include "JSObject.h"
 #include "ScopeChain.h"
 
 #include "JSObject.h"
 #include "ScopeChain.h"
 
@@ -35,99 +36,98 @@ namespace JSC {
 // JSLock is only needed to support an obsolete execution model where JavaScriptCore
 // automatically protected against concurrent access from multiple threads.
 // So it's safe to disable it on non-mac platforms where we don't have native pthreads.
 // 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))
+#if (OS(DARWIN) || USE(PTHREADS))
 
 
-// Acquire this mutex before accessing lock-related data.
-static pthread_mutex_t JSMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t sharedInstanceLock = PTHREAD_MUTEX_INITIALIZER;
 
 
-// Thread-specific key that tells whether a thread holds the JSMutex, and how many times it was taken recursively.
-pthread_key_t JSLockCount;
+GlobalJSLock::GlobalJSLock()
+{
+    pthread_mutex_lock(&sharedInstanceLock);
+}
 
 
-static void createJSLockCount()
+GlobalJSLock::~GlobalJSLock()
 {
 {
-    pthread_key_create(&JSLockCount, 0);
+    pthread_mutex_unlock(&sharedInstanceLock);
 }
 
 }
 
-pthread_once_t createJSLockCountOnce = PTHREAD_ONCE_INIT;
+JSLockHolder::JSLockHolder(ExecState* exec)
+    : m_globalData(&exec->globalData())
+{
+    m_globalData->apiLock().lock();
+}
 
 
-// Lock nesting count.
-intptr_t JSLock::lockCount()
+JSLockHolder::JSLockHolder(JSGlobalData* globalData)
+    : m_globalData(globalData)
 {
 {
-    pthread_once(&createJSLockCountOnce, createJSLockCount);
+    m_globalData->apiLock().lock();
+}
 
 
-    return reinterpret_cast<intptr_t>(pthread_getspecific(JSLockCount));
+JSLockHolder::JSLockHolder(JSGlobalData& globalData)
+    : m_globalData(&globalData)
+{
+    m_globalData->apiLock().lock();
 }
 
 }
 
-static void setLockCount(intptr_t count)
+JSLockHolder::~JSLockHolder()
 {
 {
-    ASSERT(count >= 0);
-    pthread_setspecific(JSLockCount, reinterpret_cast<void*>(count));
+    m_globalData->apiLock().unlock();
 }
 
 }
 
-JSLock::JSLock(ExecState* exec)
-    : m_lockBehavior(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly)
+JSLock::JSLock()
+    : m_lockCount(0)
 {
 {
-    lock(m_lockBehavior);
+    m_spinLock.Init();
 }
 
 }
 
-JSLock::JSLock(JSGlobalData* globalData)
-    : m_lockBehavior(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly)
+JSLock::~JSLock()
 {
 {
-    lock(m_lockBehavior);
 }
 
 }
 
-void JSLock::lock(JSLockBehavior lockBehavior)
+void JSLock::lock()
 {
 {
-#ifdef NDEBUG
-    // Locking "not for real" is a debug-only feature.
-    if (lockBehavior == SilenceAssertionsOnly)
-        return;
-#endif
+    ThreadIdentifier currentThread = WTF::currentThread();
+    {
+        SpinLockHolder holder(&m_spinLock);
+        if (m_ownerThread == currentThread && m_lockCount) {
+            m_lockCount++;
+            return;
+        }
+    }
 
 
-    pthread_once(&createJSLockCountOnce, createJSLockCount);
+    m_lock.lock();
 
 
-    intptr_t currentLockCount = lockCount();
-    if (!currentLockCount && lockBehavior == LockForReal) {
-        int result;
-        result = pthread_mutex_lock(&JSMutex);
-        ASSERT(!result);
+    {
+        SpinLockHolder holder(&m_spinLock);
+        m_ownerThread = currentThread;
+        ASSERT(!m_lockCount);
+        m_lockCount = 1;
     }
     }
-    setLockCount(currentLockCount + 1);
 }
 
 }
 
-void JSLock::unlock(JSLockBehavior lockBehavior)
+void JSLock::unlock()
 {
 {
-    ASSERT(lockCount());
+    ASSERT(currentThreadIsHoldingLock());
 
 
-#ifdef NDEBUG
-    // Locking "not for real" is a debug-only feature.
-    if (lockBehavior == SilenceAssertionsOnly)
-        return;
-#endif
+    SpinLockHolder holder(&m_spinLock);
+    m_lockCount--;
 
 
-    intptr_t newLockCount = lockCount() - 1;
-    setLockCount(newLockCount);
-    if (!newLockCount && lockBehavior == LockForReal) {
-        int result;
-        result = pthread_mutex_unlock(&JSMutex);
-        ASSERT(!result);
-    }
+    if (!m_lockCount)
+        m_lock.unlock();
 }
 
 void JSLock::lock(ExecState* exec)
 {
 }
 
 void JSLock::lock(ExecState* exec)
 {
-    lock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly);
+    exec->globalData().apiLock().lock();
 }
 
 void JSLock::unlock(ExecState* exec)
 {
 }
 
 void JSLock::unlock(ExecState* exec)
 {
-    unlock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly);
+    exec->globalData().apiLock().unlock();
 }
 
 bool JSLock::currentThreadIsHoldingLock()
 {
 }
 
 bool JSLock::currentThreadIsHoldingLock()
 {
-    pthread_once(&createJSLockCountOnce, createJSLockCount);
-    return !!pthread_getspecific(JSLockCount);
+    return m_lockCount && m_ownerThread == WTF::currentThread();
 }
 
 // This is fairly nasty.  We allow multiple threads to run on the same
 }
 
 // This is fairly nasty.  We allow multiple threads to run on the same
@@ -151,7 +151,7 @@ bool JSLock::currentThreadIsHoldingLock()
 // this to happen, and were its stack to grow further, then it may potentially
 // write over the second thread's call frames.
 //
 // this to happen, and were its stack to grow further, then it may potentially
 // write over the second thread's call frames.
 //
-// In avoid JS stack corruption we enforce a policy of only ever allowing two
+// To avoid JS stack corruption we enforce a policy of only ever allowing two
 // threads to use a JS context concurrently, and only allowing the second of
 // these threads to execute until it has completed and fully returned from its
 // outermost call into JSC.  We enforce this policy using 'lockDropDepth'.  The
 // threads to use a JS context concurrently, and only allowing the second of
 // these threads to execute until it has completed and fully returned from its
 // outermost call into JSC.  We enforce this policy using 'lockDropDepth'.  The
@@ -160,7 +160,7 @@ bool JSLock::currentThreadIsHoldingLock()
 // same thread again, enter JSC (through evaluate script or call function), and exit
 // again through a callback, then the locks will not be dropped when DropAllLocks
 // is called (since lockDropDepth is non-zero).  Since this thread is still holding
 // same thread again, enter JSC (through evaluate script or call function), and exit
 // again through a callback, then the locks will not be dropped when DropAllLocks
 // is called (since lockDropDepth is non-zero).  Since this thread is still holding
-// the locks, only it will re able to re-enter JSC (either be returning from the
+// the locks, only it will be able to re-enter JSC (either be returning from the
 // callback, or by re-entering through another call to evaulate script or call
 // function).
 //
 // callback, or by re-entering through another call to evaulate script or call
 // function).
 //
@@ -170,61 +170,138 @@ bool JSLock::currentThreadIsHoldingLock()
 // order in which they were made - though implementing the less restrictive policy
 // would likely increase complexity and overhead.
 //
 // order in which they were made - though implementing the less restrictive policy
 // would likely increase complexity and overhead.
 //
-static unsigned lockDropDepth = 0;
 
 
-JSLock::DropAllLocks::DropAllLocks(ExecState* exec)
-    : m_lockBehavior(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly)
+// This function returns the number of locks that were dropped.
+unsigned JSLock::dropAllLocks()
 {
 {
-    pthread_once(&createJSLockCountOnce, createJSLockCount);
-
-    if (lockDropDepth++) {
-        m_lockCount = 0;
-        return;
+    unsigned lockCount;
+    {
+        // Check if this thread is currently holding the lock.
+        // FIXME: Maybe we want to require this, guard with an ASSERT?
+        SpinLockHolder holder(&m_spinLock);
+        lockCount = m_lockCount;
+        if (!lockCount || m_ownerThread != WTF::currentThread())
+            return 0;
     }
 
     }
 
-    m_lockCount = JSLock::lockCount();
-    for (intptr_t i = 0; i < m_lockCount; i++)
-        JSLock::unlock(m_lockBehavior);
+    // Don't drop the locks if they've already been dropped once.
+    // (If the prior drop came from another thread, and it resumed first,
+    // it could trash our register file).
+    if (m_lockDropDepth)
+        return 0;
+
+    // m_lockDropDepth is only incremented if any locks were dropped.
+    m_lockDropDepth++;
+    m_lockCount = 0;
+    m_lock.unlock();
+    return lockCount;
 }
 
 }
 
-JSLock::DropAllLocks::DropAllLocks(JSLockBehavior JSLockBehavior)
-    : m_lockBehavior(JSLockBehavior)
+unsigned JSLock::dropAllLocksUnconditionally()
 {
 {
-    pthread_once(&createJSLockCountOnce, createJSLockCount);
+    unsigned lockCount;
+    {
+        // Check if this thread is currently holding the lock.
+        // FIXME: Maybe we want to require this, guard with an ASSERT?
+        SpinLockHolder holder(&m_spinLock);
+        lockCount = m_lockCount;
+        if (!lockCount || m_ownerThread != WTF::currentThread())
+            return 0;
+    }
 
 
-    if (lockDropDepth++) {
-        m_lockCount = 0;
+    // m_lockDropDepth is only incremented if any locks were dropped.
+    m_lockDropDepth++;
+    m_lockCount = 0;
+    m_lock.unlock();
+    return lockCount;
+}
+
+void JSLock::grabAllLocks(unsigned lockCount)
+{
+    // If no locks were dropped, nothing to do!
+    if (!lockCount)
         return;
         return;
+
+    ThreadIdentifier currentThread = WTF::currentThread();
+    {
+        // Check if this thread is currently holding the lock.
+        // FIXME: Maybe we want to prohibit this, guard against with an ASSERT?
+        SpinLockHolder holder(&m_spinLock);
+        if (m_ownerThread == currentThread && m_lockCount) {
+            m_lockCount += lockCount;
+            m_lockDropDepth--;
+            return;
+        }
+    }
+
+    m_lock.lock();
+
+    {
+        SpinLockHolder holder(&m_spinLock);
+        m_ownerThread = currentThread;
+        ASSERT(!m_lockCount);
+        m_lockCount = lockCount;
+        m_lockDropDepth--;
     }
     }
+}
 
 
-    // It is necessary to drop even "unreal" locks, because having a non-zero lock count
-    // will prevent a real lock from being taken.
+JSLock::DropAllLocks::DropAllLocks(ExecState* exec, AlwaysDropLocksTag alwaysDropLocks)
+    : m_lockCount(0)
+    , m_globalData(&exec->globalData())
+{
+    if (alwaysDropLocks)
+        m_lockCount = m_globalData->apiLock().dropAllLocksUnconditionally();
+    else
+        m_lockCount = m_globalData->apiLock().dropAllLocks();
+}
 
 
-    m_lockCount = JSLock::lockCount();
-    for (intptr_t i = 0; i < m_lockCount; i++)
-        JSLock::unlock(m_lockBehavior);
+JSLock::DropAllLocks::DropAllLocks(JSGlobalData* globalData, AlwaysDropLocksTag alwaysDropLocks)
+    : m_lockCount(0)
+    , m_globalData(globalData)
+{
+    if (alwaysDropLocks)
+        m_lockCount = m_globalData->apiLock().dropAllLocksUnconditionally();
+    else
+        m_lockCount = m_globalData->apiLock().dropAllLocks();
 }
 
 JSLock::DropAllLocks::~DropAllLocks()
 {
 }
 
 JSLock::DropAllLocks::~DropAllLocks()
 {
-    for (intptr_t i = 0; i < m_lockCount; i++)
-        JSLock::lock(m_lockBehavior);
+    m_globalData->apiLock().grabAllLocks(m_lockCount);
+}
+
+#else // (OS(DARWIN) || USE(PTHREADS))
+
+GlobalJSLock::GlobalJSLock()
+{
+}
+
+GlobalJSLock::~GlobalJSLock()
+{
+}
 
 
-    --lockDropDepth;
+JSLockHolder::JSLockHolder(JSGlobalData*)
+{
 }
 
 }
 
-#else // ENABLE(JSC_MULTIPLE_THREADS) && (OS(DARWIN) || USE(PTHREADS))
+JSLockHolder::JSLockHolder(JSGlobalData&)
+{
+}
 
 
-JSLock::JSLock(ExecState*)
-    : m_lockBehavior(SilenceAssertionsOnly)
+JSLockHolder::JSLockHolder(ExecState*)
 {
 }
 
 {
 }
 
-// If threading support is off, set the lock count to a constant value of 1 so ssertions
-// that the lock is held don't fail
-intptr_t JSLock::lockCount()
+JSLockHolder::~JSLockHolder()
+{
+}
+
+JSLock::JSLock()
+{
+}
+
+JSLock::~JSLock()
 {
 {
-    return 1;
 }
 
 bool JSLock::currentThreadIsHoldingLock()
 }
 
 bool JSLock::currentThreadIsHoldingLock()
@@ -232,11 +309,11 @@ bool JSLock::currentThreadIsHoldingLock()
     return true;
 }
 
     return true;
 }
 
-void JSLock::lock(JSLockBehavior)
+void JSLock::lock()
 {
 }
 
 {
 }
 
-void JSLock::unlock(JSLockBehavior)
+void JSLock::unlock()
 {
 }
 
 {
 }
 
@@ -248,11 +325,33 @@ void JSLock::unlock(ExecState*)
 {
 }
 
 {
 }
 
+void JSLock::lock(JSGlobalData&)
+{
+}
+
+void JSLock::unlock(JSGlobalData&)
+{
+}
+
+unsigned JSLock::dropAllLocks()
+{
+    return 0;
+}
+
+unsigned JSLock::dropAllLocksUnconditionally()
+{
+    return 0;
+}
+
+void JSLock::grabAllLocks(unsigned)
+{
+}
+
 JSLock::DropAllLocks::DropAllLocks(ExecState*)
 {
 }
 
 JSLock::DropAllLocks::DropAllLocks(ExecState*)
 {
 }
 
-JSLock::DropAllLocks::DropAllLocks(JSLockBehavior)
+JSLock::DropAllLocks::DropAllLocks(JSGlobalData*)
 {
 }
 
 {
 }
 
@@ -260,6 +359,6 @@ JSLock::DropAllLocks::~DropAllLocks()
 {
 }
 
 {
 }
 
-#endif // ENABLE(JSC_MULTIPLE_THREADS) && (OS(DARWIN) || USE(PTHREADS))
+#endif // (OS(DARWIN) || USE(PTHREADS))
 
 } // namespace JSC
 
 } // namespace JSC
index 7b07b4fb3da5e4e82e005c5244565c9a670bf87f..8336a3a77be9147efa4bf73614aefa4c1b7182f9 100644 (file)
@@ -23,6 +23,9 @@
 
 #include <wtf/Assertions.h>
 #include <wtf/Noncopyable.h>
 
 #include <wtf/Assertions.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/RefPtr.h>
+#include <wtf/TCSpinLock.h>
+#include <wtf/Threading.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -30,8 +33,9 @@ namespace JSC {
     // important to lock before doing anything that allocates a
     // JavaScript data structure or that interacts with shared state
     // such as the protect count hash table. The simplest way to lock
     // important to lock before doing anything that allocates a
     // JavaScript data structure or that interacts with shared state
     // such as the protect count hash table. The simplest way to lock
-    // is to create a local JSLock object in the scope where the lock 
-    // must be held. The lock is recursive so nesting is ok. The JSLock 
+    // is to create a local JSLockHolder object in the scope where the lock 
+    // must be held and pass it the context that requires protection. 
+    // The lock is recursive so nesting is ok. The JSLock 
     // object also acts as a convenience short-hand for running important
     // initialization routines.
 
     // object also acts as a convenience short-hand for running important
     // initialization routines.
 
@@ -44,62 +48,69 @@ namespace JSC {
     // DropAllLocks object takes care to release the JSLock only if your
     // thread acquired it to begin with.
 
     // DropAllLocks object takes care to release the JSLock only if your
     // thread acquired it to begin with.
 
-    // For contexts other than the single shared one, implicit locking is not done,
-    // but we still need to perform all the counting in order to keep debug
-    // assertions working, so that clients that use the shared context don't break.
-
     class ExecState;
     class JSGlobalData;
 
     class ExecState;
     class JSGlobalData;
 
-    enum JSLockBehavior { SilenceAssertionsOnly, LockForReal };
+    // This class is used to protect the initialization of the legacy single 
+    // shared JSGlobalData.
+    class GlobalJSLock {
+        WTF_MAKE_NONCOPYABLE(GlobalJSLock);
+    public:
+        JS_EXPORT_PRIVATE GlobalJSLock();
+        JS_EXPORT_PRIVATE ~GlobalJSLock();
+    };
+
+    class JSLockHolder {
+    public:
+        JS_EXPORT_PRIVATE JSLockHolder(JSGlobalData*);
+        JS_EXPORT_PRIVATE JSLockHolder(JSGlobalData&);
+        JS_EXPORT_PRIVATE JSLockHolder(ExecState*);
+
+        JS_EXPORT_PRIVATE ~JSLockHolder();
+    private:
+        RefPtr<JSGlobalData> m_globalData;
+    };
 
     class JSLock {
         WTF_MAKE_NONCOPYABLE(JSLock);
     public:
 
     class JSLock {
         WTF_MAKE_NONCOPYABLE(JSLock);
     public:
-        JSLock(ExecState*);
-        JSLock(JSGlobalData*);
-
-        JSLock(JSLockBehavior lockBehavior)
-            : m_lockBehavior(lockBehavior)
-        {
-#ifdef NDEBUG
-            // Locking "not for real" is a debug-only feature.
-            if (lockBehavior == SilenceAssertionsOnly)
-                return;
-#endif
-            lock(lockBehavior);
-        }
-
-        ~JSLock()
-        { 
-#ifdef NDEBUG
-            // Locking "not for real" is a debug-only feature.
-            if (m_lockBehavior == SilenceAssertionsOnly)
-                return;
-#endif
-            unlock(m_lockBehavior); 
-        }
-        
-        static void lock(JSLockBehavior);
-        static void unlock(JSLockBehavior);
+        JSLock();
+        JS_EXPORT_PRIVATE ~JSLock();
+
+        JS_EXPORT_PRIVATE void lock();
+        JS_EXPORT_PRIVATE void unlock();
+
         static void lock(ExecState*);
         static void unlock(ExecState*);
         static void lock(ExecState*);
         static void unlock(ExecState*);
+        static void lock(JSGlobalData&);
+        static void unlock(JSGlobalData&);
+
+        JS_EXPORT_PRIVATE bool currentThreadIsHoldingLock();
 
 
-        static intptr_t lockCount();
-        static bool currentThreadIsHoldingLock();
+        unsigned dropAllLocks();
+        unsigned dropAllLocksUnconditionally();
+        void grabAllLocks(unsigned lockCount);
 
 
-        JSLockBehavior m_lockBehavior;
+        SpinLock m_spinLock;
+        Mutex m_lock;
+        ThreadIdentifier m_ownerThread;
+        intptr_t m_lockCount;
+        unsigned m_lockDropDepth;
 
         class DropAllLocks {
             WTF_MAKE_NONCOPYABLE(DropAllLocks);
         public:
 
         class DropAllLocks {
             WTF_MAKE_NONCOPYABLE(DropAllLocks);
         public:
-            DropAllLocks(ExecState* exec);
-            DropAllLocks(JSLockBehavior);
-            ~DropAllLocks();
+            // This is a hack to allow Mobile Safari to always release the locks since 
+            // hey depend on the behavior that DropAllLocks does indeed always drop all 
+            // locks, which isn't always the case with the default behavior.
+            enum AlwaysDropLocksTag { DontAlwaysDropLocks = 0, AlwaysDropLocks };
+            JS_EXPORT_PRIVATE DropAllLocks(ExecState* exec, AlwaysDropLocksTag alwaysDropLocks = DontAlwaysDropLocks);
+            JS_EXPORT_PRIVATE DropAllLocks(JSGlobalData*, AlwaysDropLocksTag alwaysDropLocks = DontAlwaysDropLocks);
+            JS_EXPORT_PRIVATE ~DropAllLocks();
             
         private:
             intptr_t m_lockCount;
             
         private:
             intptr_t m_lockCount;
-            JSLockBehavior m_lockBehavior;
+            RefPtr<JSGlobalData> m_globalData;
         };
     };
 
         };
     };
 
index 1115dc070b74444e265e48e44e38b3736ee3f014..337e3a70c6d054a39a4c0b46f0713f4d5cd096c8 100644 (file)
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSNotAnObject);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSNotAnObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSNotAnObject);
+
+const ClassInfo JSNotAnObject::s_info = { "Object", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSNotAnObject) };
 
 // JSValue methods
 
 // JSValue methods
-JSValue JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const
+JSValue JSNotAnObject::defaultValue(const JSObject*, ExecState* exec, PreferredPrimitiveType)
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return jsNumber(0);
 }
 
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return jsNumber(0);
 }
 
-bool JSNotAnObject::getPrimitiveNumber(ExecState* exec, double&, JSValue&)
-{
-    ASSERT_UNUSED(exec, exec->hadException());
-    return false;
-}
-
-bool JSNotAnObject::toBoolean(ExecState* exec) const
-{
-    ASSERT_UNUSED(exec, exec->hadException());
-    return false;
-}
-
-double JSNotAnObject::toNumber(ExecState* exec) const
-{
-    ASSERT_UNUSED(exec, exec->hadException());
-    return NaN;
-}
-
-UString JSNotAnObject::toString(ExecState* exec) const
-{
-    ASSERT_UNUSED(exec, exec->hadException());
-    return "";
-}
-
-JSObject* JSNotAnObject::toObject(ExecState* exec, JSGlobalObject*) const
-{
-    ASSERT_UNUSED(exec, exec->hadException());
-    return const_cast<JSNotAnObject*>(this);
-}
-
 // JSObject methods
 // JSObject methods
-bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, const Identifier&, PropertySlot&)
+bool JSNotAnObject::getOwnPropertySlot(JSCell*, ExecState* exec, const Identifier&, PropertySlot&)
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
-bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, unsigned, PropertySlot&)
+bool JSNotAnObject::getOwnPropertySlotByIndex(JSCell*, ExecState* exec, unsigned, PropertySlot&)
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
-bool JSNotAnObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier&, PropertyDescriptor&)
+bool JSNotAnObject::getOwnPropertyDescriptor(JSObject*, ExecState* exec, const Identifier&, PropertyDescriptor&)
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
-void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue, PutPropertySlot&)
+void JSNotAnObject::put(JSCell*, ExecState* exec, const Identifier& , JSValue, PutPropertySlot&)
 {
     ASSERT_UNUSED(exec, exec->hadException());
 }
 
 {
     ASSERT_UNUSED(exec, exec->hadException());
 }
 
-void JSNotAnObject::put(ExecState* exec, unsigned, JSValue)
+void JSNotAnObject::putByIndex(JSCell*, ExecState* exec, unsigned, JSValue, bool)
 {
     ASSERT_UNUSED(exec, exec->hadException());
 }
 
 {
     ASSERT_UNUSED(exec, exec->hadException());
 }
 
-bool JSNotAnObject::deleteProperty(ExecState* exec, const Identifier&)
+bool JSNotAnObject::deleteProperty(JSCell*, ExecState* exec, const Identifier&)
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
-bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned)
+bool JSNotAnObject::deletePropertyByIndex(JSCell*, ExecState* exec, unsigned)
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 {
     ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
-void JSNotAnObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray&, EnumerationMode)
+void JSNotAnObject::getOwnPropertyNames(JSObject*, ExecState* exec, PropertyNameArray&, EnumerationMode)
 {
     ASSERT_UNUSED(exec, exec->hadException());
 }
 {
     ASSERT_UNUSED(exec, exec->hadException());
 }
index 4c6806a5f1250eb22c30742c30524a94f87ffb46..5f80688b05f5fed225d7dcbda244aebc5532b844 100644 (file)
@@ -37,41 +37,48 @@ namespace JSC {
     // in certain SquirrelFish bytecodes -- effectively it just silently consumes
     // any operations performed on the result of a failed toObject call.
     class JSNotAnObject : public JSNonFinalObject {
     // in certain SquirrelFish bytecodes -- effectively it just silently consumes
     // any operations performed on the result of a failed toObject call.
     class JSNotAnObject : public JSNonFinalObject {
-    public:
+    private:
         JSNotAnObject(ExecState* exec)
             : JSNonFinalObject(exec->globalData(), exec->globalData().notAnObjectStructure.get())
         {
         }
         JSNotAnObject(ExecState* exec)
             : JSNonFinalObject(exec->globalData(), exec->globalData().notAnObjectStructure.get())
         {
         }
+        
+    public:
+        typedef JSNonFinalObject Base;
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static JSNotAnObject* create(ExecState* exec)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            JSNotAnObject* object = new (NotNull, allocateCell<JSNotAnObject>(*exec->heap())) JSNotAnObject(exec);
+            object->finishCreation(exec->globalData());
+            return object;
         }
 
         }
 
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+        {
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
+        }
+
+        static const ClassInfo s_info;
+
      private:
         
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
 
         // JSValue methods
      private:
         
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
 
         // JSValue methods
-        virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
-        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
-        virtual bool toBoolean(ExecState*) const;
-        virtual double toNumber(ExecState*) const;
-        virtual UString toString(ExecState*) const;
-        virtual JSObject* toObject(ExecState*, JSGlobalObject*) const;
+        static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
 
         // JSObject methods
 
         // JSObject methods
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
-        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
+        static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
 
-        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
-        virtual void put(ExecState*, unsigned propertyName, JSValue);
+        static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+        static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
 
 
-        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
-        virtual bool deleteProperty(ExecState*, unsigned propertyName);
+        static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
+        static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
 
 
-        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+        static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 8d261a20b1d60fe8fa77b24f4a600350e91a04e9..436e78353b170a07506157053c704b56e3f23b39 100644 (file)
@@ -43,6 +43,7 @@
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSONObject);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSONObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSONObject);
 
 static EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState*);
 static EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*);
 
 static EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState*);
 static EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*);
@@ -54,8 +55,13 @@ static EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*);
 namespace JSC {
 
 JSONObject::JSONObject(JSGlobalObject* globalObject, Structure* structure)
 namespace JSC {
 
 JSONObject::JSONObject(JSGlobalObject* globalObject, Structure* structure)
-    : JSObjectWithGlobalObject(globalObject, structure)
+    : JSNonFinalObject(globalObject->globalData(), structure)
 {
 {
+}
+
+void JSONObject::finishCreation(JSGlobalObject* globalObject)
+{
+    Base::finishCreation(globalObject->globalData());
     ASSERT(inherits(&s_info));
 }
 
     ASSERT(inherits(&s_info));
 }
 
@@ -136,7 +142,7 @@ static inline JSValue unwrapBoxedPrimitive(ExecState* exec, JSValue value)
     if (object->inherits(&NumberObject::s_info))
         return jsNumber(object->toNumber(exec));
     if (object->inherits(&StringObject::s_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 object->toString(exec);
     if (object->inherits(&BooleanObject::s_info))
         return object->toPrimitive(exec);
     return value;
     if (object->inherits(&BooleanObject::s_info))
         return object->toPrimitive(exec);
     return value;
@@ -148,8 +154,8 @@ static inline UString gap(ExecState* exec, JSValue space)
     space = unwrapBoxedPrimitive(exec, space);
 
     // If the space value is a number, create a gap string with that number of spaces.
     space = unwrapBoxedPrimitive(exec, space);
 
     // If the space value is a number, create a gap string with that number of spaces.
-    double spaceCount;
-    if (space.getNumber(spaceCount)) {
+    if (space.isNumber()) {
+        double spaceCount = space.asNumber();
         int count;
         if (spaceCount > maxGapLength)
             count = maxGapLength;
         int count;
         if (spaceCount > maxGapLength)
             count = maxGapLength;
@@ -217,31 +223,17 @@ Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const
             if (exec->hadException())
                 break;
 
             if (exec->hadException())
                 break;
 
-            UString propertyName;
-            if (name.getString(exec, propertyName)) {
-                m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
-                continue;
-            }
-
-            double value = 0;
-            if (name.getNumber(value)) {
-                m_arrayReplacerPropertyNames.add(Identifier::from(exec, value));
-                continue;
-            }
-
             if (name.isObject()) {
                 if (!asObject(name)->inherits(&NumberObject::s_info) && !asObject(name)->inherits(&StringObject::s_info))
                     continue;
             if (name.isObject()) {
                 if (!asObject(name)->inherits(&NumberObject::s_info) && !asObject(name)->inherits(&StringObject::s_info))
                     continue;
-                propertyName = name.toString(exec);
-                if (exec->hadException())
-                    break;
-                m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
             }
             }
+
+            m_arrayReplacerPropertyNames.add(Identifier(exec, name.toString(exec)->value(exec)));
         }
         return;
     }
 
         }
         return;
     }
 
-    m_replacerCallType = m_replacer.asObject()->getCallData(m_replacerCallData);
+    m_replacerCallType = m_replacer.asObject()->methodTable()->getCallData(m_replacer.asObject().get(), m_replacerCallData);
 }
 
 Local<Unknown> Stringifier::stringify(Handle<Unknown> value)
 }
 
 Local<Unknown> Stringifier::stringify(Handle<Unknown> value)
@@ -262,13 +254,9 @@ Local<Unknown> Stringifier::stringify(Handle<Unknown> value)
     return Local<Unknown>(m_exec->globalData(), jsString(m_exec, result.toUString()));
 }
 
     return Local<Unknown>(m_exec->globalData(), jsString(m_exec, result.toUString()));
 }
 
-void Stringifier::appendQuotedString(UStringBuilder& builder, const UString& value)
+template <typename CharType>
+static void appendStringToUStringBuilder(UStringBuilder& builder, const CharType* data, int length)
 {
 {
-    int length = value.length();
-
-    builder.append('"');
-
-    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] != '\\'))
@@ -277,42 +265,54 @@ void Stringifier::appendQuotedString(UStringBuilder& builder, const UString& val
         if (i >= length)
             break;
         switch (data[i]) {
         if (i >= length)
             break;
         switch (data[i]) {
-            case '\t':
-                builder.append('\\');
-                builder.append('t');
-                break;
-            case '\r':
-                builder.append('\\');
-                builder.append('r');
-                break;
-            case '\n':
-                builder.append('\\');
-                builder.append('n');
-                break;
-            case '\f':
-                builder.append('\\');
-                builder.append('f');
-                break;
-            case '\b':
-                builder.append('\\');
-                builder.append('b');
-                break;
-            case '"':
-                builder.append('\\');
-                builder.append('"');
-                break;
-            case '\\':
-                builder.append('\\');
-                builder.append('\\');
-                break;
-            default:
-                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, WTF_ARRAY_LENGTH(hex));
-                break;
+        case '\t':
+            builder.append('\\');
+            builder.append('t');
+            break;
+        case '\r':
+            builder.append('\\');
+            builder.append('r');
+            break;
+        case '\n':
+            builder.append('\\');
+            builder.append('n');
+            break;
+        case '\f':
+            builder.append('\\');
+            builder.append('f');
+            break;
+        case '\b':
+            builder.append('\\');
+            builder.append('b');
+            break;
+        case '"':
+            builder.append('\\');
+            builder.append('"');
+            break;
+        case '\\':
+            builder.append('\\');
+            builder.append('\\');
+            break;
+        default:
+            static const char hexDigits[] = "0123456789abcdef";
+            UChar ch = data[i];
+            LChar hex[] = { '\\', 'u', hexDigits[(ch >> 12) & 0xF], hexDigits[(ch >> 8) & 0xF], hexDigits[(ch >> 4) & 0xF], hexDigits[ch & 0xF] };
+            builder.append(hex, WTF_ARRAY_LENGTH(hex));
+            break;
         }
     }
         }
     }
+}
+    
+void Stringifier::appendQuotedString(UStringBuilder& builder, const UString& value)
+{
+    int length = value.length();
+
+    builder.append('"');
+
+    if (value.is8Bit())
+        appendStringToUStringBuilder<LChar>(builder, value.characters8(), length);
+    else
+        appendStringToUStringBuilder<UChar>(builder, value.characters16(), length);
 
     builder.append('"');
 }
 
     builder.append('"');
 }
@@ -332,12 +332,12 @@ inline JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFunctionC
 
     JSObject* object = asObject(toJSONFunction);
     CallData callData;
 
     JSObject* object = asObject(toJSONFunction);
     CallData callData;
-    CallType callType = object->getCallData(callData);
+    CallType callType = object->methodTable()->getCallData(object, callData);
     if (callType == CallTypeNone)
         return value;
 
     if (callType == CallTypeNone)
         return value;
 
-    JSValue list[] = { propertyName.value(m_exec) };
-    ArgList args(list, WTF_ARRAY_LENGTH(list));
+    MarkedArgumentBuffer args;
+    args.append(propertyName.value(m_exec));
     return call(m_exec, object, callType, callData, value, args);
 }
 
     return call(m_exec, object, callType, callData, value, args);
 }
 
@@ -350,8 +350,9 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder&
 
     // Call the replacer function.
     if (m_replacerCallType != CallTypeNone) {
 
     // Call the replacer function.
     if (m_replacerCallType != CallTypeNone) {
-        JSValue list[] = { propertyName.value(m_exec), value };
-        ArgList args(list, WTF_ARRAY_LENGTH(list));
+        MarkedArgumentBuffer args;
+        args.append(propertyName.value(m_exec));
+        args.append(value);
         value = call(m_exec, m_replacer.get(), m_replacerCallType, m_replacerCallData, holder, args);
         if (m_exec->hadException())
             return StringifyFailed;
         value = call(m_exec, m_replacer.get(), m_replacerCallType, m_replacerCallData, holder, args);
         if (m_exec->hadException())
             return StringifyFailed;
@@ -371,7 +372,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder&
         return StringifyFailed;
 
     if (value.isBoolean()) {
         return StringifyFailed;
 
     if (value.isBoolean()) {
-        builder.append(value.getBoolean() ? "true" : "false");
+        builder.append(value.isTrue() ? "true" : "false");
         return StringifySucceeded;
     }
 
         return StringifySucceeded;
     }
 
@@ -381,12 +382,12 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder&
         return StringifySucceeded;
     }
 
         return StringifySucceeded;
     }
 
-    double numericValue;
-    if (value.getNumber(numericValue)) {
-        if (!isfinite(numericValue))
+    if (value.isNumber()) {
+        double number = value.asNumber();
+        if (!isfinite(number))
             builder.append("null");
         else
             builder.append("null");
         else
-            builder.append(UString::number(numericValue));
+            builder.append(UString::number(number));
         return StringifySucceeded;
     }
 
         return StringifySucceeded;
     }
 
@@ -396,7 +397,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder&
     JSObject* object = asObject(value);
 
     CallData callData;
     JSObject* object = asObject(value);
 
     CallData callData;
-    if (object->getCallData(callData) != CallTypeNone) {
+    if (object->methodTable()->getCallData(object, callData) != CallTypeNone) {
         if (holder->inherits(&JSArray::s_info)) {
             builder.append("null");
             return StringifySucceeded;
         if (holder->inherits(&JSArray::s_info)) {
             builder.append("null");
             return StringifySucceeded;
@@ -482,7 +483,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBu
     // 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.get());
+            m_isJSArray = isJSArray(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 {
@@ -490,7 +491,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBu
                 m_propertyNames = stringifier.m_arrayReplacerPropertyNames.data();
             else {
                 PropertyNameArray objectPropertyNames(exec);
                 m_propertyNames = stringifier.m_arrayReplacerPropertyNames.data();
             else {
                 PropertyNameArray objectPropertyNames(exec);
-                m_object->getOwnPropertyNames(exec, objectPropertyNames);
+                m_object->methodTable()->getOwnPropertyNames(m_object.get(), exec, objectPropertyNames, ExcludeDontEnumProperties);
                 m_propertyNames = objectPropertyNames.releaseData();
             }
             m_size = m_propertyNames->propertyNameVector().size();
                 m_propertyNames = objectPropertyNames.releaseData();
             }
             m_size = m_propertyNames->propertyNameVector().size();
@@ -519,7 +520,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBu
             value = asArray(m_object.get())->getIndex(index);
         else {
             PropertySlot slot(m_object.get());
             value = asArray(m_object.get())->getIndex(index);
         else {
             PropertySlot slot(m_object.get());
-            if (!m_object->getOwnPropertySlot(exec, index, slot))
+            if (!m_object->methodTable()->getOwnPropertySlotByIndex(m_object.get(), exec, index, slot))
                 slot.setUndefined();
             if (exec->hadException())
                 return false;
                 slot.setUndefined();
             if (exec->hadException())
                 return false;
@@ -537,7 +538,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBu
         // Get the value.
         PropertySlot slot(m_object.get());
         Identifier& propertyName = m_propertyNames->propertyNameVector()[index];
         // Get the value.
         PropertySlot slot(m_object.get());
         Identifier& propertyName = m_propertyNames->propertyNameVector()[index];
-        if (!m_object->getOwnPropertySlot(exec, propertyName, slot))
+        if (!m_object->methodTable()->getOwnPropertySlot(m_object.get(), exec, propertyName, slot))
             return true;
         JSValue value = slot.getValue(exec, propertyName);
         if (exec->hadException())
             return true;
         JSValue value = slot.getValue(exec, propertyName);
         if (exec->hadException())
@@ -583,7 +584,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBu
 
 // ------------------------------ JSONObject --------------------------------
 
 
 // ------------------------------ JSONObject --------------------------------
 
-const ClassInfo JSONObject::s_info = { "JSON", &JSObjectWithGlobalObject::s_info, 0, ExecState::jsonTable };
+const ClassInfo JSONObject::s_info = { "JSON", &JSNonFinalObject::s_info, 0, ExecState::jsonTable, CREATE_METHOD_TABLE(JSONObject) };
 
 /* Source for JSONObject.lut.h
 @begin jsonTable
 
 /* Source for JSONObject.lut.h
 @begin jsonTable
@@ -594,14 +595,14 @@ const ClassInfo JSONObject::s_info = { "JSON", &JSObjectWithGlobalObject::s_info
 
 // ECMA 15.8
 
 
 // ECMA 15.8
 
-bool JSONObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+bool JSONObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
-    return getStaticFunctionSlot<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<JSObject>(exec, ExecState::jsonTable(exec), jsCast<JSONObject*>(cell), propertyName, slot);
 }
 
 }
 
-bool JSONObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool JSONObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), jsCast<JSONObject*>(object), propertyName, descriptor);
 }
 
 class Walker {
 }
 
 class Walker {
@@ -617,9 +618,10 @@ public:
 private:
     JSValue callReviver(JSObject* thisObj, JSValue property, JSValue unfiltered)
     {
 private:
     JSValue callReviver(JSObject* thisObj, JSValue property, JSValue unfiltered)
     {
-        JSValue args[] = { property, unfiltered };
-        ArgList argList(args, 2);
-        return call(m_exec, m_function.get(), m_callType, m_callData, thisObj, argList);
+        MarkedArgumentBuffer args;
+        args.append(property);
+        args.append(unfiltered);
+        return call(m_exec, m_function.get(), m_callType, m_callData, thisObj, args);
     }
 
     friend class Holder;
     }
 
     friend class Holder;
@@ -655,7 +657,7 @@ 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::s_info));
+                ASSERT(isJSArray(asObject(inValue)) || asObject(inValue)->inherits(&JSArray::s_info));
                 if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
                     return throwError(m_exec, createStackOverflowError(m_exec));
 
                 if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
                     return throwError(m_exec, createStackOverflowError(m_exec));
 
@@ -680,11 +682,11 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                     indexStack.removeLast();
                     break;
                 }
                     indexStack.removeLast();
                     break;
                 }
-                if (isJSArray(&m_exec->globalData(), array) && array->canGetIndex(index))
+                if (isJSArray(array) && array->canGetIndex(index))
                     inValue = array->getIndex(index);
                 else {
                     PropertySlot slot;
                     inValue = array->getIndex(index);
                 else {
                     PropertySlot slot;
-                    if (array->getOwnPropertySlot(m_exec, index, slot))
+                    if (array->methodTable()->getOwnPropertySlotByIndex(array, m_exec, index, slot))
                         inValue = slot.getValue(m_exec, index);
                     else
                         inValue = jsUndefined();
                         inValue = slot.getValue(m_exec, index);
                     else
                         inValue = jsUndefined();
@@ -701,13 +703,9 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                 JSArray* array = arrayStack.peek();
                 JSValue filteredValue = callReviver(array, jsString(m_exec, UString::number(indexStack.last())), outValue);
                 if (filteredValue.isUndefined())
                 JSArray* array = arrayStack.peek();
                 JSValue filteredValue = callReviver(array, jsString(m_exec, UString::number(indexStack.last())), outValue);
                 if (filteredValue.isUndefined())
-                    array->deleteProperty(m_exec, indexStack.last());
-                else {
-                    if (isJSArray(&m_exec->globalData(), array) && array->canSetIndex(indexStack.last()))
-                        array->setIndex(m_exec->globalData(), indexStack.last(), filteredValue);
-                    else
-                        array->put(m_exec, indexStack.last(), filteredValue);
-                }
+                    array->methodTable()->deletePropertyByIndex(array, m_exec, indexStack.last());
+                else
+                    array->putDirectIndex(m_exec, indexStack.last(), filteredValue, false);
                 if (m_exec->hadException())
                     return jsNull();
                 indexStack.last()++;
                 if (m_exec->hadException())
                     return jsNull();
                 indexStack.last()++;
@@ -716,7 +714,7 @@ 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::s_info));
+                ASSERT(!isJSArray(asObject(inValue)) && !asObject(inValue)->inherits(&JSArray::s_info));
                 if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
                     return throwError(m_exec, createStackOverflowError(m_exec));
 
                 if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
                     return throwError(m_exec, createStackOverflowError(m_exec));
 
@@ -724,7 +722,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                 objectStack.push(object);
                 indexStack.append(0);
                 propertyStack.append(PropertyNameArray(m_exec));
                 objectStack.push(object);
                 indexStack.append(0);
                 propertyStack.append(PropertyNameArray(m_exec));
-                object->getOwnPropertyNames(m_exec, propertyStack.last());
+                object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
                 // fallthrough
             }
             objectStartVisitMember:
                 // fallthrough
             }
             objectStartVisitMember:
@@ -746,7 +744,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                     break;
                 }
                 PropertySlot slot;
                     break;
                 }
                 PropertySlot slot;
-                if (object->getOwnPropertySlot(m_exec, properties[index], slot))
+                if (object->methodTable()->getOwnPropertySlot(object, m_exec, properties[index], slot))
                     inValue = slot.getValue(m_exec, properties[index]);
                 else
                     inValue = jsUndefined();
                     inValue = slot.getValue(m_exec, properties[index]);
                 else
                     inValue = jsUndefined();
@@ -768,9 +766,9 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                 PutPropertySlot slot;
                 JSValue filteredValue = callReviver(object, jsString(m_exec, prop.ustring()), outValue);
                 if (filteredValue.isUndefined())
                 PutPropertySlot slot;
                 JSValue filteredValue = callReviver(object, jsString(m_exec, prop.ustring()), outValue);
                 if (filteredValue.isUndefined())
-                    object->deleteProperty(m_exec, prop);
+                    object->methodTable()->deleteProperty(object, m_exec, prop);
                 else
                 else
-                    object->put(m_exec, prop, filteredValue, slot);
+                    object->methodTable()->put(object, m_exec, prop, filteredValue, slot);
                 if (m_exec->hadException())
                     return jsNull();
                 indexStack.last()++;
                 if (m_exec->hadException())
                     return jsNull();
                 indexStack.last()++;
@@ -783,7 +781,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::s_info))
+                if (isJSArray(object) || object->inherits(&JSArray::s_info))
                     goto arrayStartState;
                 goto objectStartState;
         }
                     goto arrayStartState;
                 goto objectStartState;
         }
@@ -801,7 +799,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
     }
     JSObject* finalHolder = constructEmptyObject(m_exec);
     PutPropertySlot slot;
     }
     JSObject* finalHolder = constructEmptyObject(m_exec);
     PutPropertySlot slot;
-    finalHolder->put(m_exec, m_exec->globalData().propertyNames->emptyIdentifier, outValue, slot);
+    finalHolder->methodTable()->put(finalHolder, m_exec, m_exec->globalData().propertyNames->emptyIdentifier, outValue, slot);
     return callReviver(finalHolder, jsEmptyString(m_exec), outValue);
 }
 
     return callReviver(finalHolder, jsEmptyString(m_exec), outValue);
 }
 
@@ -810,16 +808,23 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec)
 {
     if (!exec->argumentCount())
         return throwVMError(exec, createError(exec, "JSON.parse requires at least one parameter"));
 {
     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);
+    UString source = exec->argument(0).toString(exec)->value(exec);
     if (exec->hadException())
         return JSValue::encode(jsNull());
 
     if (exec->hadException())
         return JSValue::encode(jsNull());
 
+    JSValue unfiltered;
     LocalScope scope(exec->globalData());
     LocalScope scope(exec->globalData());
-    LiteralParser jsonParser(exec, source.characters(), source.length(), LiteralParser::StrictJSON);
-    JSValue unfiltered = jsonParser.tryLiteralParse();
-    if (!unfiltered)
-        return throwVMError(exec, createSyntaxError(exec, "Unable to parse JSON string"));
+    if (source.is8Bit()) {
+        LiteralParser<LChar> jsonParser(exec, source.characters8(), source.length(), StrictJSON);
+        unfiltered = jsonParser.tryLiteralParse();
+        if (!unfiltered)
+            return throwVMError(exec, createSyntaxError(exec, jsonParser.getErrorMessage()));
+    } else {
+        LiteralParser<UChar> jsonParser(exec, source.characters16(), source.length(), StrictJSON);
+        unfiltered = jsonParser.tryLiteralParse();
+        if (!unfiltered)
+            return throwVMError(exec, createSyntaxError(exec, jsonParser.getErrorMessage()));        
+    }
     
     if (exec->argumentCount() < 2)
         return JSValue::encode(unfiltered);
     
     if (exec->argumentCount() < 2)
         return JSValue::encode(unfiltered);
index b7733205c808be2d783fd7c7e82e891f4dceb1fb..29535f6d02fbc4bfa0cd08698873b2abb8036ba0 100644 (file)
 #ifndef JSONObject_h
 #define JSONObject_h
 
 #ifndef JSONObject_h
 #define JSONObject_h
 
-#include "JSObjectWithGlobalObject.h"
+#include "JSObject.h"
 
 namespace JSC {
 
     class Stringifier;
 
 
 namespace JSC {
 
     class Stringifier;
 
-    class JSONObject : public JSObjectWithGlobalObject {
+    class JSONObject : public JSNonFinalObject {
     public:
     public:
-        JSONObject(JSGlobalObject*, Structure*);
+        typedef JSNonFinalObject Base;
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static JSONObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            JSONObject* object = new (NotNull, allocateCell<JSONObject>(*exec->heap())) JSONObject(globalObject, structure);
+            object->finishCreation(globalObject);
+            return object;
+        }
+        
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+        {
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
         
         static const ClassInfo s_info;
 
     protected:
         }
         
         static const ClassInfo s_info;
 
     protected:
+        void finishCreation(JSGlobalObject*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
 
     private:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
 
     private:
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        JSONObject(JSGlobalObject*, Structure*);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
     };
 
 
     };
 
index dbf9ccfbce9fe6dc27d514d18a0e7e196bfc202e..500f3891ae30a1bce59a6f28facfd2134d4b7506 100644 (file)
 #include "config.h"
 #include "JSObject.h"
 
 #include "config.h"
 #include "JSObject.h"
 
+#include "CopiedSpaceInlineMethods.h"
 #include "DatePrototype.h"
 #include "ErrorConstructor.h"
 #include "GetterSetter.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "DatePrototype.h"
 #include "ErrorConstructor.h"
 #include "GetterSetter.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
+#include "JSGlobalThis.h"
+#include "Lookup.h"
 #include "NativeErrorConstructor.h"
 #include "NativeErrorConstructor.h"
+#include "Nodes.h"
 #include "ObjectPrototype.h"
 #include "ObjectPrototype.h"
+#include "Operations.h"
 #include "PropertyDescriptor.h"
 #include "PropertyNameArray.h"
 #include "PropertyDescriptor.h"
 #include "PropertyNameArray.h"
-#include "Lookup.h"
-#include "Nodes.h"
-#include "Operations.h"
 #include <math.h>
 #include <wtf/Assertions.h>
 
 #include <math.h>
 #include <wtf/Assertions.h>
 
@@ -45,9 +47,14 @@ ASSERT_CLASS_FITS_IN_CELL(JSObject);
 ASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject);
 ASSERT_CLASS_FITS_IN_CELL(JSFinalObject);
 
 ASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject);
 ASSERT_CLASS_FITS_IN_CELL(JSFinalObject);
 
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSFinalObject);
+
 const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
 
 const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
 
-const ClassInfo JSObject::s_info = { "Object", 0, 0, 0 };
+const ClassInfo JSObject::s_info = { "Object", 0, 0, 0, CREATE_METHOD_TABLE(JSObject) };
+
+const ClassInfo JSFinalObject::s_info = { "Object", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSFinalObject) };
 
 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)
 {
@@ -68,86 +75,98 @@ static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* class
     }
 }
 
     }
 }
 
-void JSObject::visitChildren(SlotVisitor& visitor)
+void JSObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
-#ifndef NDEBUG
+    JSObject* thisObject = jsCast<JSObject*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+#if !ASSERT_DISABLED
     bool wasCheckingForDefaultMarkViolation = visitor.m_isCheckingForDefaultMarkViolation;
     visitor.m_isCheckingForDefaultMarkViolation = false;
 #endif
 
     bool wasCheckingForDefaultMarkViolation = visitor.m_isCheckingForDefaultMarkViolation;
     visitor.m_isCheckingForDefaultMarkViolation = false;
 #endif
 
-    visitChildrenDirect(visitor);
+    JSCell::visitChildren(thisObject, visitor);
+
+    PropertyStorage storage = thisObject->propertyStorage();
+    size_t storageSize = thisObject->structure()->propertyStorageSize();
+    if (thisObject->isUsingInlineStorage())
+        visitor.appendValues(storage, storageSize);
+    else {
+        // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers.
+        void* temp = storage;
+        visitor.copyAndAppend(&temp, thisObject->structure()->propertyStorageCapacity() * sizeof(WriteBarrierBase<Unknown>), storage->slot(), storageSize);
+        storage = static_cast<PropertyStorage>(temp);
+        thisObject->m_propertyStorage.set(storage, StorageBarrier::Unchecked);
+    }
+
+    if (thisObject->m_inheritorID)
+        visitor.append(&thisObject->m_inheritorID);
 
 
-#ifndef NDEBUG
+#if !ASSERT_DISABLED
     visitor.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
 #endif
 }
 
     visitor.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
 #endif
 }
 
-UString JSObject::className() const
+UString JSObject::className(const JSObject* object)
 {
 {
-    const ClassInfo* info = classInfo();
+    const ClassInfo* info = object->classInfo();
     ASSERT(info);
     return info->className;
 }
 
     ASSERT(info);
     return info->className;
 }
 
-bool JSObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+bool JSObject::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)
 {
 {
-    return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
-}
-
-static void throwSetterError(ExecState* exec)
-{
-    throwError(exec, createTypeError(exec, "setting a property that has only a getter"));
+    JSObject* thisObject = jsCast<JSObject*>(cell);
+    return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot);
 }
 
 // ECMA 8.6.2.2
 }
 
 // ECMA 8.6.2.2
-void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
+    JSObject* thisObject = jsCast<JSObject*>(cell);
     ASSERT(value);
     ASSERT(value);
-    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
-
-    if (propertyName == exec->propertyNames().underscoreProto) {
-        // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
-        if (!value.isObject() && !value.isNull())
-            return;
-        if (!setPrototypeWithCycleCheck(exec->globalData(), value))
-            throwError(exec, createError(exec, "cyclic __proto__ value"));
-        return;
-    }
+    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
+    JSGlobalData& globalData = exec->globalData();
 
     // Check if there are any setters or getters in the prototype chain
     JSValue prototype;
 
     // Check if there are any setters or getters in the prototype chain
     JSValue prototype;
-    for (JSObject* obj = this; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) {
-        prototype = obj->prototype();
-        if (prototype.isNull()) {
-            if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode())
-                throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
-            return;
+    if (propertyName != exec->propertyNames().underscoreProto) {
+        for (JSObject* obj = thisObject; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {
+            prototype = obj->prototype();
+            if (prototype.isNull()) {
+                if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode())
+                    throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+                return;
+            }
         }
     }
         }
     }
-    
-    unsigned attributes;
-    JSCell* specificValue;
-    if ((m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) {
-        if (slot.isStrictMode())
-            throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
-        return;
-    }
 
 
-    for (JSObject* obj = this; ; obj = asObject(prototype)) {
-        if (JSValue gs = obj->getDirect(exec->globalData(), propertyName)) {
+    for (JSObject* obj = thisObject; ; obj = asObject(prototype)) {
+        unsigned attributes;
+        JSCell* specificValue;
+        size_t offset = obj->structure()->get(globalData, propertyName, attributes, specificValue);
+        if (offset != WTF::notFound) {
+            if (attributes & ReadOnly) {
+                if (slot.isStrictMode())
+                    throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
+                return;
+            }
+
+            JSValue gs = obj->getDirectOffset(offset);
             if (gs.isGetterSetter()) {
                 JSObject* setterFunc = asGetterSetter(gs)->setter();        
                 if (!setterFunc) {
             if (gs.isGetterSetter()) {
                 JSObject* setterFunc = asGetterSetter(gs)->setter();        
                 if (!setterFunc) {
-                    throwSetterError(exec);
+                    if (slot.isStrictMode())
+                        throwError(exec, createTypeError(exec, "setting a property that has only a getter"));
                     return;
                 }
                 
                 CallData callData;
                     return;
                 }
                 
                 CallData callData;
-                CallType callType = setterFunc->getCallData(callData);
+                CallType callType = setterFunc->methodTable()->getCallData(setterFunc, callData);
                 MarkedArgumentBuffer args;
                 args.append(value);
                 MarkedArgumentBuffer args;
                 args.append(value);
-                call(exec, setterFunc, callType, callData, this, args);
+
+                // If this is WebCore's global object then we need to substitute the shell.
+                call(exec, setterFunc, callType, callData, thisObject->methodTable()->toThisObject(thisObject, exec), args);
                 return;
             }
 
                 return;
             }
 
@@ -160,46 +179,65 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu
         if (prototype.isNull())
             break;
     }
         if (prototype.isNull())
             break;
     }
-
-    if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode())
+    
+    if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode())
         throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
     return;
 }
 
         throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
     return;
 }
 
-void JSObject::put(ExecState* exec, unsigned propertyName, JSValue value)
+void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
 {
 {
-    PutPropertySlot slot;
-    put(exec, Identifier::from(exec, propertyName), value, slot);
+    PutPropertySlot slot(shouldThrow);
+    JSObject* thisObject = jsCast<JSObject*>(cell);
+    thisObject->methodTable()->put(thisObject, exec, Identifier::from(exec, propertyName), value, slot);
 }
 
 }
 
-void JSObject::putWithAttributes(JSGlobalData* globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+void JSObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
 {
-    putDirectInternal(*globalData, propertyName, value, attributes, checkReadOnly, slot);
+    ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
+    PutPropertySlot slot;
+    object->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, value, attributes, slot, getJSFunction(value));
 }
 
 }
 
-void JSObject::putWithAttributes(JSGlobalData* globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
+bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prototype)
 {
 {
-    putDirectInternal(*globalData, propertyName, value, attributes);
-}
+    JSValue checkFor = this;
+    if (this->isGlobalObject())
+        checkFor = jsCast<JSGlobalObject*>(this)->globalExec()->thisValue();
 
 
-void JSObject::putWithAttributes(JSGlobalData* globalData, unsigned propertyName, JSValue value, unsigned attributes)
-{
-    putWithAttributes(globalData, Identifier::from(globalData, propertyName), value, attributes);
+    JSValue nextPrototype = prototype;
+    while (nextPrototype && nextPrototype.isObject()) {
+        if (nextPrototype == checkFor)
+            return false;
+        nextPrototype = asObject(nextPrototype)->prototype();
+    }
+    setPrototype(globalData, prototype);
+    return true;
 }
 
 }
 
-void JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+bool JSObject::allowsAccessFrom(ExecState* exec)
 {
 {
-    putDirectInternal(exec->globalData(), propertyName, value, attributes, checkReadOnly, slot);
+    JSGlobalObject* globalObject = isGlobalThis() ? jsCast<JSGlobalThis*>(this)->unwrappedObject() : this->globalObject();
+    return globalObject->globalObjectMethodTable()->allowsAccessFrom(globalObject, exec);
 }
 
 }
 
-void JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
+void JSObject::putDirectAccessor(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
 {
-    putDirectInternal(exec->globalData(), propertyName, value, attributes);
-}
+    ASSERT(value.isGetterSetter() && (attributes & Accessor));
 
 
-void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValue value, unsigned attributes)
-{
-    putWithAttributes(exec, Identifier::from(exec, propertyName), value, attributes);
+    PutPropertySlot slot;
+    putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value));
+
+    // 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)
+        setStructure(globalData, Structure::attributeChangeTransition(globalData, structure(), propertyName, attributes));
+
+    if (attributes & ReadOnly)
+        structure()->setContainsReadOnlyProperties();
+
+    structure()->setHasGetterSetterProperties(propertyName == globalData.propertyNames->underscoreProto);
 }
 
 bool JSObject::hasProperty(ExecState* exec, const Identifier& propertyName) const
 }
 
 bool JSObject::hasProperty(ExecState* exec, const Identifier& propertyName) const
@@ -215,20 +253,25 @@ bool JSObject::hasProperty(ExecState* exec, unsigned propertyName) const
 }
 
 // ECMA 8.6.2.5
 }
 
 // ECMA 8.6.2.5
-bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
+bool JSObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
 {
 {
+    JSObject* thisObject = jsCast<JSObject*>(cell);
+
+    if (!thisObject->staticFunctionsReified())
+        thisObject->reifyStaticFunctionsForDelete(exec);
+
     unsigned attributes;
     JSCell* specificValue;
     unsigned attributes;
     JSCell* specificValue;
-    if (m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) {
-        if ((attributes & DontDelete))
+    if (thisObject->structure()->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) {
+        if (attributes & DontDelete && !exec->globalData().isInDefineOwnProperty())
             return false;
             return false;
-        removeDirect(exec->globalData(), propertyName);
+        thisObject->removeDirect(exec->globalData(), propertyName);
         return true;
     }
 
     // Look in the static hashtable of properties
         return true;
     }
 
     // Look in the static hashtable of properties
-    const HashEntry* entry = findPropertyHashEntry(exec, propertyName);
-    if (entry && entry->attributes() & DontDelete)
+    const HashEntry* entry = thisObject->findPropertyHashEntry(exec, propertyName);
+    if (entry && entry->attributes() & DontDelete && !exec->globalData().isInDefineOwnProperty())
         return false; // this builtin property can't be deleted
 
     // FIXME: Should the code here actually do some deletion?
         return false; // this builtin property can't be deleted
 
     // FIXME: Should the code here actually do some deletion?
@@ -238,12 +281,13 @@ bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
 bool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) const
 {
     PropertySlot slot;
 bool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) const
 {
     PropertySlot slot;
-    return const_cast<JSObject*>(this)->getOwnPropertySlot(exec, propertyName, slot);
+    return const_cast<JSObject*>(this)->methodTable()->getOwnPropertySlot(const_cast<JSObject*>(this), exec, propertyName, slot);
 }
 
 }
 
-bool JSObject::deleteProperty(ExecState* exec, unsigned propertyName)
+bool JSObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName)
 {
 {
-    return deleteProperty(exec, Identifier::from(exec, propertyName));
+    JSObject* thisObject = jsCast<JSObject*>(cell);
+    return thisObject->methodTable()->deleteProperty(thisObject, exec, Identifier::from(exec, propertyName));
 }
 
 static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName)
 }
 
 static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName)
@@ -268,29 +312,29 @@ static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSO
     return result;
 }
 
     return result;
 }
 
-bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result)
+bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result) const
 {
 {
-    result = defaultValue(exec, PreferNumber);
+    result = methodTable()->defaultValue(this, exec, PreferNumber);
     number = result.toNumber(exec);
     return !result.isString();
 }
 
 // ECMA 8.6.2.6
     number = result.toNumber(exec);
     return !result.isString();
 }
 
 // ECMA 8.6.2.6
-JSValue JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
+JSValue JSObject::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint)
 {
     // Must call toString first for Date objects.
 {
     // Must call toString first for Date objects.
-    if ((hint == PreferString) || (hint != PreferNumber && prototype() == exec->lexicalGlobalObject()->datePrototype())) {
-        JSValue value = callDefaultValueFunction(exec, this, exec->propertyNames().toString);
+    if ((hint == PreferString) || (hint != PreferNumber && object->prototype() == exec->lexicalGlobalObject()->datePrototype())) {
+        JSValue value = callDefaultValueFunction(exec, object, exec->propertyNames().toString);
         if (value)
             return value;
         if (value)
             return value;
-        value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf);
+        value = callDefaultValueFunction(exec, object, exec->propertyNames().valueOf);
         if (value)
             return value;
     } else {
         if (value)
             return value;
     } else {
-        JSValue value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf);
+        JSValue value = callDefaultValueFunction(exec, object, exec->propertyNames().valueOf);
         if (value)
             return value;
         if (value)
             return value;
-        value = callDefaultValueFunction(exec, this, exec->propertyNames().toString);
+        value = callDefaultValueFunction(exec, object, exec->propertyNames().toString);
         if (value)
             return value;
     }
         if (value)
             return value;
     }
@@ -311,106 +355,7 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifi
     return 0;
 }
 
     return 0;
 }
 
-void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
-{
-    if (propertyName == exec->propertyNames().underscoreProto) {
-        // Defining a getter for __proto__ is silently ignored.
-        return;
-    }
-
-    JSValue object = getDirect(exec->globalData(), propertyName);
-    if (object && object.isGetterSetter()) {
-        ASSERT(m_structure->hasGetterSetterProperties());
-        asGetterSetter(object)->setGetter(exec->globalData(), getterFunction);
-        return;
-    }
-
-    JSGlobalData& globalData = exec->globalData();
-    PutPropertySlot slot;
-    GetterSetter* getterSetter = new (exec) GetterSetter(exec);
-    putDirectInternal(globalData, propertyName, getterSetter, attributes | Getter, true, slot);
-
-    // putDirect will change our Structure if we add a new property. For
-    // getters and setters, though, we also need to change our Structure
-    // if we override an existing non-getter or non-setter.
-    if (slot.type() != PutPropertySlot::NewProperty) {
-        if (!m_structure->isDictionary())
-            setStructure(exec->globalData(), Structure::getterSetterTransition(globalData, m_structure.get()));
-    }
-
-    m_structure->setHasGetterSetterProperties(true);
-    getterSetter->setGetter(globalData, getterFunction);
-}
-
-void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
-{
-    if (propertyName == exec->propertyNames().underscoreProto) {
-        // Defining a setter for __proto__ is silently ignored.
-        return;
-    }
-
-    JSValue object = getDirect(exec->globalData(), propertyName);
-    if (object && object.isGetterSetter()) {
-        ASSERT(m_structure->hasGetterSetterProperties());
-        asGetterSetter(object)->setSetter(exec->globalData(), setterFunction);
-        return;
-    }
-
-    PutPropertySlot slot;
-    GetterSetter* getterSetter = new (exec) GetterSetter(exec);
-    putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Setter, true, slot);
-
-    // putDirect will change our Structure if we add a new property. For
-    // getters and setters, though, we also need to change our Structure
-    // if we override an existing non-getter or non-setter.
-    if (slot.type() != PutPropertySlot::NewProperty) {
-        if (!m_structure->isDictionary())
-            setStructure(exec->globalData(), Structure::getterSetterTransition(exec->globalData(), m_structure.get()));
-    }
-
-    m_structure->setHasGetterSetterProperties(true);
-    getterSetter->setSetter(exec->globalData(), setterFunction);
-}
-
-JSValue JSObject::lookupGetter(ExecState* exec, const Identifier& propertyName)
-{
-    JSObject* object = this;
-    while (true) {
-        if (JSValue value = object->getDirect(exec->globalData(), propertyName)) {
-            if (!value.isGetterSetter())
-                return jsUndefined();
-            JSObject* functionObject = asGetterSetter(value)->getter();
-            if (!functionObject)
-                return jsUndefined();
-            return functionObject;
-        }
-
-        if (!object->prototype() || !object->prototype().isObject())
-            return jsUndefined();
-        object = asObject(object->prototype());
-    }
-}
-
-JSValue JSObject::lookupSetter(ExecState* exec, const Identifier& propertyName)
-{
-    JSObject* object = this;
-    while (true) {
-        if (JSValue value = object->getDirect(exec->globalData(), propertyName)) {
-            if (!value.isGetterSetter())
-                return jsUndefined();
-            JSObject* functionObject = asGetterSetter(value)->setter();
-            if (!functionObject)
-                return jsUndefined();
-            return functionObject;
-        }
-
-        if (!object->prototype() || !object->prototype().isObject())
-            return jsUndefined();
-        object = asObject(object->prototype());
-    }
-}
-
-bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue proto)
+bool JSObject::hasInstance(JSObject*, ExecState* exec, JSValue value, JSValue proto)
 {
     if (!value.isObject())
         return false;
 {
     if (!value.isObject())
         return false;
@@ -431,7 +376,7 @@ bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue proto)
 bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const
 {
     PropertyDescriptor descriptor;
 bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const
 {
     PropertyDescriptor descriptor;
-    if (!const_cast<JSObject*>(this)->getOwnPropertyDescriptor(exec, propertyName, descriptor))
+    if (!const_cast<JSObject*>(this)->methodTable()->getOwnPropertyDescriptor(const_cast<JSObject*>(this), exec, propertyName, descriptor))
         return false;
     return descriptor.enumerable();
 }
         return false;
     return descriptor.enumerable();
 }
@@ -439,7 +384,7 @@ bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyN
 bool JSObject::getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificValue) const
 {
     unsigned attributes;
 bool JSObject::getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificValue) const
 {
     unsigned attributes;
-    if (m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound)
+    if (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
@@ -449,20 +394,20 @@ bool JSObject::getPropertySpecificValue(ExecState* exec, const Identifier& prope
     return false;
 }
 
     return false;
 }
 
-void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void JSObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
-    getOwnPropertyNames(exec, propertyNames, mode);
+    object->methodTable()->getOwnPropertyNames(object, exec, propertyNames, mode);
 
 
-    if (prototype().isNull())
+    if (object->prototype().isNull())
         return;
 
         return;
 
-    JSObject* prototype = asObject(this->prototype());
+    JSObject* prototype = asObject(object->prototype());
     while(1) {
         if (prototype->structure()->typeInfo().overridesGetPropertyNames()) {
     while(1) {
         if (prototype->structure()->typeInfo().overridesGetPropertyNames()) {
-            prototype->getPropertyNames(exec, propertyNames, mode);
+            prototype->methodTable()->getPropertyNames(prototype, exec, propertyNames, mode);
             break;
         }
             break;
         }
-        prototype->getOwnPropertyNames(exec, propertyNames, mode);
+        prototype->methodTable()->getOwnPropertyNames(prototype, exec, propertyNames, mode);
         JSValue nextProto = prototype->prototype();
         if (nextProto.isNull())
             break;
         JSValue nextProto = prototype->prototype();
         if (nextProto.isNull())
             break;
@@ -470,10 +415,11 @@ void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyName
     }
 }
 
     }
 }
 
-void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
-    m_structure->getPropertyNames(exec->globalData(), propertyNames, mode);
-    getClassPropertyNames(exec, classInfo(), propertyNames, mode);
+    object->structure()->getPropertyNamesFromStructure(exec->globalData(), propertyNames, mode);
+    if (!object->staticFunctionsReified())
+        getClassPropertyNames(exec, object->classInfo(), propertyNames, mode);
 }
 
 bool JSObject::toBoolean(ExecState*) const
 }
 
 bool JSObject::toBoolean(ExecState*) const
@@ -489,31 +435,23 @@ double JSObject::toNumber(ExecState* exec) const
     return primitive.toNumber(exec);
 }
 
     return primitive.toNumber(exec);
 }
 
-UString JSObject::toString(ExecState* exec) const
+JSString* JSObject::toString(ExecState* exec) const
 {
     JSValue primitive = toPrimitive(exec, PreferString);
     if (exec->hadException())
 {
     JSValue primitive = toPrimitive(exec, PreferString);
     if (exec->hadException())
-        return "";
+        return jsEmptyString(exec);
     return primitive.toString(exec);
 }
 
     return primitive.toString(exec);
 }
 
-JSObject* JSObject::toObject(ExecState*, JSGlobalObject*) const
-{
-    return const_cast<JSObject*>(this);
-}
-
-JSObject* JSObject::toThisObject(ExecState*) const
-{
-    return const_cast<JSObject*>(this);
-}
-
-JSValue JSObject::toStrictThisObject(ExecState*) const
+JSObject* JSObject::toThisObject(JSCell* cell, ExecState*)
 {
 {
-    return const_cast<JSObject*>(this);
+    return jsCast<JSObject*>(cell);
 }
 
 JSObject* JSObject::unwrappedObject()
 {
 }
 
 JSObject* JSObject::unwrappedObject()
 {
+    if (isGlobalThis())
+        return jsCast<JSGlobalThis*>(this)->unwrappedObject();
     return this;
 }
 
     return this;
 }
 
@@ -522,7 +460,7 @@ void JSObject::seal(JSGlobalData& globalData)
     if (isSealed(globalData))
         return;
     preventExtensions(globalData);
     if (isSealed(globalData))
         return;
     preventExtensions(globalData);
-    setStructure(globalData, Structure::sealTransition(globalData, m_structure.get()));
+    setStructure(globalData, Structure::sealTransition(globalData, structure()));
 }
 
 void JSObject::freeze(JSGlobalData& globalData)
 }
 
 void JSObject::freeze(JSGlobalData& globalData)
@@ -530,53 +468,66 @@ void JSObject::freeze(JSGlobalData& globalData)
     if (isFrozen(globalData))
         return;
     preventExtensions(globalData);
     if (isFrozen(globalData))
         return;
     preventExtensions(globalData);
-    setStructure(globalData, Structure::freezeTransition(globalData, m_structure.get()));
+    setStructure(globalData, Structure::freezeTransition(globalData, structure()));
 }
 
 void JSObject::preventExtensions(JSGlobalData& globalData)
 {
 }
 
 void JSObject::preventExtensions(JSGlobalData& globalData)
 {
+    if (isJSArray(this))
+        asArray(this)->enterDictionaryMode(globalData);
     if (isExtensible())
     if (isExtensible())
-        setStructure(globalData, Structure::preventExtensionsTransition(globalData, m_structure.get()));
+        setStructure(globalData, Structure::preventExtensionsTransition(globalData, structure()));
+}
+
+// This presently will flatten to an uncachable dictionary; this is suitable
+// for use in delete, we may want to do something different elsewhere.
+void JSObject::reifyStaticFunctionsForDelete(ExecState* exec)
+{
+    ASSERT(!staticFunctionsReified());
+    JSGlobalData& globalData = exec->globalData();
+
+    // If this object's ClassInfo has no static properties, then nothing to reify!
+    // We can safely set the flag to avoid the expensive check again in the future.
+    if (!classInfo()->hasStaticProperties()) {
+        structure()->setStaticFunctionsReified();
+        return;
+    }
+
+    if (!structure()->isUncacheableDictionary())
+        setStructure(globalData, Structure::toUncacheableDictionaryTransition(globalData, structure()));
+
+    for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {
+        const HashTable* hashTable = info->propHashTable(globalObject()->globalExec());
+        if (!hashTable)
+            continue;
+        PropertySlot slot;
+        for (HashTable::ConstIterator iter = hashTable->begin(globalData); iter != hashTable->end(globalData); ++iter) {
+            if (iter->attributes() & Function)
+                setUpStaticFunctionSlot(globalObject()->globalExec(), *iter, this, Identifier(&globalData, iter->key()), slot);
+        }
+    }
+
+    structure()->setStaticFunctionsReified();
 }
 
 void JSObject::removeDirect(JSGlobalData& globalData, const Identifier& propertyName)
 {
 }
 
 void JSObject::removeDirect(JSGlobalData& globalData, const Identifier& propertyName)
 {
-    if (m_structure->get(globalData, propertyName) == WTF::notFound)
+    if (structure()->get(globalData, propertyName) == WTF::notFound)
         return;
 
     size_t offset;
         return;
 
     size_t offset;
-    if (m_structure->isUncacheableDictionary()) {
-        offset = m_structure->removePropertyWithoutTransition(globalData, propertyName);
+    if (structure()->isUncacheableDictionary()) {
+        offset = structure()->removePropertyWithoutTransition(globalData, propertyName);
         if (offset != WTF::notFound)
             putUndefinedAtDirectOffset(offset);
         return;
     }
 
         if (offset != WTF::notFound)
             putUndefinedAtDirectOffset(offset);
         return;
     }
 
-    setStructure(globalData, Structure::removePropertyTransition(globalData, m_structure.get(), propertyName, offset));
+    setStructure(globalData, Structure::removePropertyTransition(globalData, structure(), propertyName, offset));
     if (offset != WTF::notFound)
         putUndefinedAtDirectOffset(offset);
 }
 
     if (offset != WTF::notFound)
         putUndefinedAtDirectOffset(offset);
 }
 
-void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr)
-{
-    putDirectFunction(exec->globalData(), Identifier(exec, function->name(exec)), function, attr);
-}
-
-void JSObject::putDirectFunction(ExecState* exec, JSFunction* function, unsigned attr)
-{
-    putDirectFunction(exec->globalData(), Identifier(exec, function->name(exec)), function, attr);
-}
-
-void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr)
-{
-    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, function->name(exec)), function, attr);
-}
-
-void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, JSFunction* function, unsigned attr)
-{
-    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()) {
 NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarrierBase<Unknown>* location)
 {
     if (JSObject* getterFunction = asGetterSetter(location->get())->getter()) {
@@ -590,39 +541,56 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarr
 
 Structure* JSObject::createInheritorID(JSGlobalData& globalData)
 {
 
 Structure* JSObject::createInheritorID(JSGlobalData& globalData)
 {
-    m_inheritorID.set(globalData, this, createEmptyObjectStructure(globalData, this));
+    JSGlobalObject* globalObject;
+    if (isGlobalThis())
+        globalObject = static_cast<JSGlobalThis*>(this)->unwrappedObject();
+    else
+        globalObject = structure()->globalObject();
+    ASSERT(globalObject);
+    m_inheritorID.set(globalData, this, createEmptyObjectStructure(globalData, globalObject, this));
     ASSERT(m_inheritorID->isEmpty());
     return m_inheritorID.get();
 }
 
     ASSERT(m_inheritorID->isEmpty());
     return m_inheritorID.get();
 }
 
-void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
+PropertyStorage JSObject::growPropertyStorage(JSGlobalData& globalData, size_t oldSize, size_t newSize)
 {
     ASSERT(newSize > oldSize);
 
 {
     ASSERT(newSize > oldSize);
 
-    // It's important that this function not rely on m_structure, since
+    // It's important that this function not rely on structure(), since
     // we might be in the middle of a transition.
     // we might be in the middle of a transition.
-    bool wasInline = (oldSize < JSObject::baseExternalStorageCapacity);
 
 
-    PropertyStorage oldPropertyStorage = m_propertyStorage;
-    PropertyStorage newPropertyStorage = new WriteBarrierBase<Unknown>[newSize];
+    PropertyStorage oldPropertyStorage = m_propertyStorage.get();
+    PropertyStorage newPropertyStorage = 0;
 
 
-    for (unsigned i = 0; i < oldSize; ++i)
-       newPropertyStorage[i] = oldPropertyStorage[i];
+    if (isUsingInlineStorage()) {
+        // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers.
+        void* temp = newPropertyStorage;
+        if (!globalData.heap.tryAllocateStorage(sizeof(WriteBarrierBase<Unknown>) * newSize, &temp))
+            CRASH();
+        newPropertyStorage = static_cast<PropertyStorage>(temp);
 
 
-    if (!wasInline)
-        delete [] oldPropertyStorage;
+        for (unsigned i = 0; i < oldSize; ++i)
+            newPropertyStorage[i] = oldPropertyStorage[i];
+    } else {
+        // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers.
+        void* temp = oldPropertyStorage;
+        if (!globalData.heap.tryReallocateStorage(&temp, sizeof(WriteBarrierBase<Unknown>) * oldSize, sizeof(WriteBarrierBase<Unknown>) * newSize))
+            CRASH();
+        newPropertyStorage = static_cast<PropertyStorage>(temp);
+    }
 
 
-    m_propertyStorage = newPropertyStorage;
+    ASSERT(newPropertyStorage);
+    return newPropertyStorage;
 }
 
 }
 
-bool JSObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool JSObject::getOwnPropertyDescriptor(JSObject* object, 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(exec->globalData(), propertyName, attributes, cell);
+    size_t offset = object->structure()->get(exec->globalData(), propertyName, attributes, cell);
     if (offset == WTF::notFound)
         return false;
     if (offset == WTF::notFound)
         return false;
-    descriptor.setDescriptor(getDirectOffset(offset), attributes);
+    descriptor.setDescriptor(object->getDirectOffset(offset), attributes);
     return true;
 }
 
     return true;
 }
 
@@ -630,7 +598,7 @@ bool JSObject::getPropertyDescriptor(ExecState* exec, const Identifier& property
 {
     JSObject* object = this;
     while (true) {
 {
     JSObject* object = this;
     while (true) {
-        if (object->getOwnPropertyDescriptor(exec, propertyName, descriptor))
+        if (object->methodTable()->getOwnPropertyDescriptor(object, exec, propertyName, descriptor))
             return true;
         JSValue prototype = object->prototype();
         if (!prototype.isObject())
             return true;
         JSValue prototype = object->prototype();
         if (!prototype.isObject())
@@ -643,16 +611,12 @@ static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& p
 {
     if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) {
         if (descriptor.isGenericDescriptor() && oldDescriptor.isAccessorDescriptor()) {
 {
     if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) {
         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);
+            GetterSetter* accessor = GetterSetter::create(exec);
+            if (oldDescriptor.getterPresent())
+                accessor->setGetter(exec->globalData(), oldDescriptor.getterObject());
+            if (oldDescriptor.setterPresent())
+                accessor->setSetter(exec->globalData(), oldDescriptor.setterObject());
+            target->putDirectAccessor(exec->globalData(), propertyName, accessor, attributes | Accessor);
             return true;
         }
         JSValue newValue = jsUndefined();
             return true;
         }
         JSValue newValue = jsUndefined();
@@ -660,33 +624,64 @@ static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& p
             newValue = descriptor.value();
         else if (oldDescriptor.value())
             newValue = oldDescriptor.value();
             newValue = descriptor.value();
         else if (oldDescriptor.value())
             newValue = oldDescriptor.value();
-        target->putWithAttributes(exec, propertyName, newValue, attributes & ~(Getter | Setter));
+        target->putDirect(exec->globalData(), propertyName, newValue, attributes & ~Accessor);
+        if (attributes & ReadOnly)
+            target->structure()->setContainsReadOnlyProperties();
         return true;
     }
     attributes &= ~ReadOnly;
         return true;
     }
     attributes &= ~ReadOnly;
-    if (descriptor.getter() && descriptor.getter().isObject())
-        target->defineGetter(exec, propertyName, asObject(descriptor.getter()), attributes);
-    if (exec->hadException())
-        return false;
-    if (descriptor.setter() && descriptor.setter().isObject())
-        target->defineSetter(exec, propertyName, asObject(descriptor.setter()), attributes);
-    return !exec->hadException();
+    GetterSetter* accessor = GetterSetter::create(exec);
+
+    if (descriptor.getterPresent())
+        accessor->setGetter(exec->globalData(), descriptor.getterObject());
+    else if (oldDescriptor.getterPresent())
+        accessor->setGetter(exec->globalData(), oldDescriptor.getterObject());
+    if (descriptor.setterPresent())
+        accessor->setSetter(exec->globalData(), descriptor.setterObject());
+    else if (oldDescriptor.setterPresent())
+        accessor->setSetter(exec->globalData(), oldDescriptor.setterObject());
+
+    target->putDirectAccessor(exec->globalData(), propertyName, accessor, attributes | Accessor);
+    return true;
 }
 
 }
 
-bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
+class DefineOwnPropertyScope {
+public:
+    DefineOwnPropertyScope(ExecState* exec)
+        : m_globalData(exec->globalData())
+    {
+        m_globalData.setInDefineOwnProperty(true);
+    }
+
+    ~DefineOwnPropertyScope()
+    {
+        m_globalData.setInDefineOwnProperty(false);
+    }
+
+private:
+    JSGlobalData& m_globalData;
+};
+
+bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
 {
 {
+    // Track on the globaldata that we're in define property.
+    // Currently DefineOwnProperty uses delete to remove properties when they are being replaced
+    // (particularly when changing attributes), however delete won't allow non-configurable (i.e.
+    // DontDelete) properties to be deleted. For now, we can use this flag to make this work.
+    DefineOwnPropertyScope scope(exec);
+
     // 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)) {
+    if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, propertyName, current)) {
         // unless extensions are prevented!
         // unless extensions are prevented!
-        if (!isExtensible()) {
+        if (!object->isExtensible()) {
             if (throwException)
                 throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible."));
             return false;
         }
         PropertyDescriptor oldDescriptor;
         oldDescriptor.setValue(jsUndefined());
             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);
+        return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributes(), oldDescriptor);
     }
 
     if (descriptor.isEmpty())
     }
 
     if (descriptor.isEmpty())
@@ -712,8 +707,8 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
     // A generic descriptor is simply changing the attributes of an existing property
     if (descriptor.isGenericDescriptor()) {
         if (!current.attributesEqual(descriptor)) {
     // A generic descriptor is simply changing the attributes of an existing property
     if (descriptor.isGenericDescriptor()) {
         if (!current.attributesEqual(descriptor)) {
-            deleteProperty(exec, propertyName);
-            putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
+            object->methodTable()->deleteProperty(object, exec, propertyName);
+            return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
         }
         return true;
     }
         }
         return true;
     }
@@ -725,8 +720,8 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
                 throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
             return false;
         }
                 throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
             return false;
         }
-        deleteProperty(exec, propertyName);
-        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
+        object->methodTable()->deleteProperty(object, exec, propertyName);
+        return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
     }
 
     // Changing the value and attributes of an existing property
     }
 
     // Changing the value and attributes of an existing property
@@ -738,23 +733,17 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
                 return false;
             }
             if (!current.writable()) {
                 return false;
             }
             if (!current.writable()) {
-                if (descriptor.value() || !JSValue::strictEqual(exec, current.value(), descriptor.value())) {
+                if (descriptor.value() && !sameValue(exec, current.value(), descriptor.value())) {
                     if (throwException)
                         throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
                     return false;
                 }
             }
                     if (throwException)
                         throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
                     return false;
                 }
             }
-        } else if (current.attributesEqual(descriptor)) {
-            if (!descriptor.value())
-                return true;
-            PutPropertySlot slot;
-            put(exec, propertyName, descriptor.value(), slot);
-            if (exec->hadException())
-                return false;
-            return true;
         }
         }
-        deleteProperty(exec, propertyName);
-        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
+        if (current.attributesEqual(descriptor) && !descriptor.value())
+            return true;
+        object->methodTable()->deleteProperty(object, exec, propertyName);
+        return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
     }
 
     // Changing the accessor functions of an existing accessor property
     }
 
     // Changing the accessor functions of an existing accessor property
@@ -771,24 +760,19 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
             return false;
         }
     }
             return false;
         }
     }
-    JSValue accessor = getDirect(exec->globalData(), propertyName);
+    JSValue accessor = object->getDirect(exec->globalData(), propertyName);
     if (!accessor)
         return false;
     GetterSetter* getterSetter = asGetterSetter(accessor);
     if (!accessor)
         return false;
     GetterSetter* getterSetter = asGetterSetter(accessor);
-    if (current.attributesEqual(descriptor)) {
-        if (descriptor.setter())
-            getterSetter->setSetter(exec->globalData(), asObject(descriptor.setter()));
-        if (descriptor.getter())
-            getterSetter->setGetter(exec->globalData(), asObject(descriptor.getter()));
+    if (descriptor.setterPresent())
+        getterSetter->setSetter(exec->globalData(), descriptor.setterObject());
+    if (descriptor.getterPresent())
+        getterSetter->setGetter(exec->globalData(), descriptor.getterObject());
+    if (current.attributesEqual(descriptor))
         return true;
         return true;
-    }
-    deleteProperty(exec, propertyName);
-    unsigned attrs = current.attributesWithOverride(descriptor);
-    if (descriptor.setter())
-        attrs |= Setter;
-    if (descriptor.getter())
-        attrs |= Getter;
-    putDirect(exec->globalData(), propertyName, getterSetter, attrs);
+    object->methodTable()->deleteProperty(object, exec, propertyName);
+    unsigned attrs = descriptor.attributesOverridingCurrent(current);
+    object->putDirectAccessor(exec->globalData(), propertyName, getterSetter, attrs | Accessor);
     return true;
 }
 
     return true;
 }
 
index 60def6e9cea26a06dac76a6f50a645474aed69ca..d95860d6214a79df30221daf916851a4b83c0313 100644 (file)
 #include "ArgList.h"
 #include "ClassInfo.h"
 #include "CommonIdentifiers.h"
 #include "ArgList.h"
 #include "ClassInfo.h"
 #include "CommonIdentifiers.h"
-#include "Completion.h"
 #include "CallFrame.h"
 #include "JSCell.h"
 #include "CallFrame.h"
 #include "JSCell.h"
-#include "MarkStack.h"
 #include "PropertySlot.h"
 #include "PutPropertySlot.h"
 #include "ScopeChain.h"
 #include "PropertySlot.h"
 #include "PutPropertySlot.h"
 #include "ScopeChain.h"
+#include "StorageBarrier.h"
 #include "Structure.h"
 #include "JSGlobalData.h"
 #include "JSString.h"
 #include "Structure.h"
 #include "JSGlobalData.h"
 #include "JSString.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
-    inline JSCell* getJSFunction(JSGlobalData& globalData, JSValue value)
+    inline JSCell* getJSFunction(JSValue value)
     {
     {
-        if (value.isCell() && (value.asCell()->vptr() == globalData.jsFunctionVPtr))
+        if (value.isCell() && (value.asCell()->structure()->typeInfo().type() == JSFunctionType))
             return value.asCell();
         return 0;
     }
             return value.asCell();
         return 0;
     }
-    
+
+    class GetterSetter;
     class HashEntry;
     class InternalFunction;
     class HashEntry;
     class InternalFunction;
+    class LLIntOffsetsExtractor;
+    class MarkedBlock;
     class PropertyDescriptor;
     class PropertyNameArray;
     class Structure;
     struct HashTable;
 
     class PropertyDescriptor;
     class PropertyNameArray;
     class Structure;
     struct HashTable;
 
-    JSObject* throwTypeError(ExecState*, const UString&);
-    extern const char* StrictModeReadonlyPropertyWriteError;
+    JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*, const UString&);
+    extern JS_EXPORTDATA const char* StrictModeReadonlyPropertyWriteError;
 
     // ECMA 262-3 8.6.1
     // Property attributes
 
     // ECMA 262-3 8.6.1
     // Property attributes
@@ -65,103 +67,106 @@ namespace JSC {
         DontEnum     = 1 << 2,  // property doesn't appear in (for .. in ..)
         DontDelete   = 1 << 3,  // property can't be deleted
         Function     = 1 << 4,  // property is a function - only used by static hashtables
         DontEnum     = 1 << 2,  // property doesn't appear in (for .. in ..)
         DontDelete   = 1 << 3,  // property can't be deleted
         Function     = 1 << 4,  // property is a function - only used by static hashtables
-        Getter       = 1 << 5,  // property is a getter
-        Setter       = 1 << 6   // property is a setter
+        Accessor     = 1 << 5,  // property is a getter/setter
     };
 
     };
 
-    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);
+        friend class MarkedBlock;
+        JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot);
+
+        enum PutMode {
+            PutModePut,
+            PutModeDefineOwnProperty,
+        };
 
     public:
 
     public:
-        virtual void visitChildren(SlotVisitor&);
-        ALWAYS_INLINE void visitChildrenDirect(SlotVisitor&);
+        typedef JSCell Base;
+
+        JS_EXPORT_PRIVATE static void visitChildren(JSCell*, 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();
+        JS_EXPORT_PRIVATE static UString className(const JSObject*);
 
         JSValue prototype() const;
         void setPrototype(JSGlobalData&, JSValue prototype);
         bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype);
         
 
         JSValue prototype() const;
         void setPrototype(JSGlobalData&, JSValue prototype);
         bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype);
         
-        void setStructure(JSGlobalData&, Structure*);
         Structure* inheritorID(JSGlobalData&);
 
         Structure* inheritorID(JSGlobalData&);
 
-        virtual UString className() const;
-
         JSValue get(ExecState*, const Identifier& propertyName) const;
         JSValue get(ExecState*, unsigned propertyName) const;
 
         bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
         JSValue get(ExecState*, const Identifier& propertyName) const;
         JSValue get(ExecState*, unsigned propertyName) const;
 
         bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
-        bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
+        JS_EXPORT_PRIVATE bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
+
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
+        JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+        JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
-        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        bool allowsAccessFrom(ExecState*);
 
 
-        virtual void put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&);
-        virtual void put(ExecState*, unsigned propertyName, JSValue value);
+        JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+        JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
 
 
-        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);
+        // putDirect is effectively an unchecked vesion of 'defineOwnProperty':
+        //  - the prototype chain is not consulted
+        //  - accessors are not called.
+        //  - attributes will be respected (after the call the property will exist with the given attributes)
+        JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
+        void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0);
+        void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&);
+        void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0);
+        void putDirectAccessor(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes);
 
         bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const;
 
 
         bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const;
 
-        bool hasProperty(ExecState*, const Identifier& propertyName) const;
-        bool hasProperty(ExecState*, unsigned propertyName) const;
+        JS_EXPORT_PRIVATE bool hasProperty(ExecState*, const Identifier& propertyName) const;
+        JS_EXPORT_PRIVATE bool hasProperty(ExecState*, unsigned propertyName) const;
         bool hasOwnProperty(ExecState*, const Identifier& propertyName) const;
 
         bool hasOwnProperty(ExecState*, const Identifier& propertyName) const;
 
-        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
-        virtual bool deleteProperty(ExecState*, unsigned propertyName);
+        JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
+        JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
 
 
-        virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
+        JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
 
 
-        virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty);
+        JS_EXPORT_PRIVATE static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty);
 
 
-        virtual void getPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
-        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+        JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+        JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
 
 
-        virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) 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*, JSGlobalObject*) const;
+        JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
+        JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const;
+        bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
+        JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
+        JS_EXPORT_PRIVATE JSString* toString(ExecState*) const;
 
 
-        virtual JSObject* toThisObject(ExecState*) const;
-        virtual JSValue toStrictThisObject(ExecState*) const;
-        virtual JSObject* unwrappedObject();
+        // NOTE: JSObject and its subclasses must be able to gracefully handle ExecState* = 0,
+        // because this call may come from inside the compiler.
+        JS_EXPORT_PRIVATE static JSObject* toThisObject(JSCell*, ExecState*);
+        JSObject* unwrappedObject();
 
         bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const;
 
         // This get function only looks at the property map.
         JSValue getDirect(JSGlobalData& globalData, const Identifier& propertyName) const
         {
 
         bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const;
 
         // This get function only looks at the property map.
         JSValue getDirect(JSGlobalData& globalData, const Identifier& propertyName) const
         {
-            size_t offset = m_structure->get(globalData, propertyName);
+            size_t offset = structure()->get(globalData, propertyName);
             return offset != WTF::notFound ? getDirectOffset(offset) : JSValue();
         }
 
         WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName)
         {
             return offset != WTF::notFound ? getDirectOffset(offset) : JSValue();
         }
 
         WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName)
         {
-            size_t offset = m_structure->get(globalData, propertyName);
+            size_t offset = structure()->get(globalData, propertyName);
             return offset != WTF::notFound ? locationForOffset(offset) : 0;
         }
 
         WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes)
         {
             JSCell* specificFunction;
             return offset != WTF::notFound ? locationForOffset(offset) : 0;
         }
 
         WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes)
         {
             JSCell* specificFunction;
-            size_t offset = m_structure->get(globalData, propertyName, attributes, specificFunction);
+            size_t offset = structure()->get(globalData, propertyName, attributes, specificFunction);
             return offset != WTF::notFound ? locationForOffset(offset) : 0;
         }
 
             return offset != WTF::notFound ? locationForOffset(offset) : 0;
         }
 
@@ -173,115 +178,111 @@ namespace JSC {
         void transitionTo(JSGlobalData&, Structure*);
 
         void removeDirect(JSGlobalData&, const Identifier& propertyName);
         void transitionTo(JSGlobalData&, Structure*);
 
         void removeDirect(JSGlobalData&, const Identifier& propertyName);
-        bool hasCustomProperties() { return m_structure->didTransition(); }
-        bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); }
-
-        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&);
+        bool hasCustomProperties() { return structure()->didTransition(); }
+        bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); }
 
 
-        void putDirectFunction(JSGlobalData&, const Identifier& propertyName, JSCell*, unsigned attr = 0);
-        void putDirectFunction(JSGlobalData&, const Identifier& propertyName, JSCell*, unsigned attr, bool checkReadOnly, PutPropertySlot&);
-        void putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr = 0);
-        void putDirectFunction(ExecState* exec, JSFunction* function, unsigned attr = 0);
-
-        void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr = 0);
-        void putDirectFunctionWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSCell* value, unsigned attr = 0);
-        void putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr = 0);
-        void putDirectFunctionWithoutTransition(ExecState* exec, JSFunction* function, unsigned attr = 0);
+        // putOwnDataProperty has 'put' like semantics, however this method:
+        //  - assumes the object contains no own getter/setter properties.
+        //  - provides no special handling for __proto__
+        //  - does not walk the prototype chain (to check for accessors or non-writable properties).
+        // This is used by JSActivation.
+        bool putOwnDataProperty(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&);
 
         // Fast access to known property offsets.
         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(); }
 
 
         // Fast access to known property offsets.
         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&, 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 JSValue lookupGetter(ExecState*, const Identifier& propertyName);
-        virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
-        virtual bool defineOwnProperty(ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
+        JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
 
 
-        virtual bool isGlobalObject() const { return false; }
-        virtual bool isVariableObject() const { return false; }
-        virtual bool isActivationObject() const { return false; }
-        virtual bool isStrictModeFunction() const { return false; }
-        virtual bool isErrorInstance() const { return false; }
+        bool isGlobalObject() const;
+        bool isVariableObject() const;
+        bool isStaticScopeObject() const;
+        bool isActivationObject() const;
+        bool isErrorInstance() const;
+        bool isGlobalThis() const;
 
         void seal(JSGlobalData&);
         void freeze(JSGlobalData&);
 
         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(); }
+        JS_EXPORT_PRIVATE void preventExtensions(JSGlobalData&);
+        bool isSealed(JSGlobalData& globalData) { return structure()->isSealed(globalData); }
+        bool isFrozen(JSGlobalData& globalData) { return structure()->isFrozen(globalData); }
+        bool isExtensible() { return structure()->isExtensible(); }
 
 
-        virtual ComplType exceptionType() const { return Throw; }
+        bool staticFunctionsReified() { return structure()->staticFunctionsReified(); }
+        void reifyStaticFunctionsForDelete(ExecState* exec);
 
 
-        void allocatePropertyStorage(size_t oldSize, size_t newSize);
-        bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage) == static_cast<const void*>(this + 1); }
+        JS_EXPORT_PRIVATE PropertyStorage growPropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize);
+        bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage.get()) == static_cast<const void*>(this + 1); }
+        void setPropertyStorage(JSGlobalData&, PropertyStorage, Structure*);
+
+        void* addressOfPropertyStorage()
+        {
+            return &m_propertyStorage;
+        }
 
         static const unsigned baseExternalStorageCapacity = 16;
 
         void flattenDictionaryObject(JSGlobalData& globalData)
         {
 
         static const unsigned baseExternalStorageCapacity = 16;
 
         void flattenDictionaryObject(JSGlobalData& globalData)
         {
-            m_structure->flattenDictionaryStructure(globalData, this);
+            structure()->flattenDictionaryStructure(globalData, this);
         }
 
         }
 
-        void putAnonymousValue(JSGlobalData& globalData, unsigned index, JSValue value)
-        {
-            ASSERT(index < m_structure->anonymousSlotCount());
-            locationForOffset(index)->set(globalData, this, value);
-        }
-        void clearAnonymousValue(unsigned index)
+        JSGlobalObject* globalObject() const
         {
         {
-            ASSERT(index < m_structure->anonymousSlotCount());
-            locationForOffset(index)->clear();
+            ASSERT(structure()->globalObject());
+            ASSERT(!isGlobalObject() || ((JSObject*)structure()->globalObject()) == this);
+            return structure()->globalObject();
         }
         }
-        JSValue getAnonymousValue(unsigned index) const
-        {
-            ASSERT(index < m_structure->anonymousSlotCount());
-            return locationForOffset(index)->get();
-        }
-
-        static size_t offsetOfInlineStorage();
         
         
+        static size_t offsetOfInlineStorage();
+        static size_t offsetOfPropertyStorage();
+        static size_t offsetOfInheritorID();
+
         static JS_EXPORTDATA const ClassInfo s_info;
 
     protected:
         static JS_EXPORTDATA const ClassInfo s_info;
 
     protected:
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        void finishCreation(JSGlobalData& globalData, PropertyStorage inlineStorage)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            Base::finishCreation(globalData);
+            ASSERT(inherits(&s_info));
+            ASSERT(structure()->propertyStorageCapacity() < baseExternalStorageCapacity);
+            ASSERT(structure()->isEmpty());
+            ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
+            ASSERT_UNUSED(inlineStorage, static_cast<void*>(inlineStorage) == static_cast<void*>(this + 1));
+            ASSERT(structure()->isObject());
+            ASSERT(classInfo());
         }
 
         }
 
-        static const unsigned StructureFlags = 0;
-
-        void putThisToAnonymousValue(unsigned index)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            locationForOffset(index)->setWithoutWriteBarrier(this);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
         }
 
+        static const unsigned StructureFlags = 0;
+
         // To instantiate objects you likely want JSFinalObject, below.
         // To create derived types you likely want JSNonFinalObject, below.
         JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage);
         // 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)
+        
+        void resetInheritorID()
         {
         {
+            m_inheritorID.clear();
         }
 
     private:
         }
 
     private:
+        friend class LLIntOffsetsExtractor;
+        
         // Nobody should ever ask any of these questions on something already known to be a JSObject.
         using JSCell::isAPIValueWrapper;
         using JSCell::isGetterSetter;
         // Nobody should ever ask any of these questions on something already known to be a JSObject.
         using JSCell::isAPIValueWrapper;
         using JSCell::isGetterSetter;
-        using JSCell::toObject;
         void getObject();
         void getString(ExecState* exec);
         void isObject();
         void isString();
         
         void getObject();
         void getString(ExecState* exec);
         void isObject();
         void isString();
         
-        ConstPropertyStorage propertyStorage() const { return m_propertyStorage; }
-        PropertyStorage propertyStorage() { return m_propertyStorage; }
+        ConstPropertyStorage propertyStorage() const { return m_propertyStorage.get(); }
+        PropertyStorage propertyStorage() { return m_propertyStorage.get(); }
 
         const WriteBarrierBase<Unknown>* locationForOffset(size_t offset) const
         {
 
         const WriteBarrierBase<Unknown>* locationForOffset(size_t offset) const
         {
@@ -293,16 +294,16 @@ namespace JSC {
             return &propertyStorage()[offset];
         }
 
             return &propertyStorage()[offset];
         }
 
-        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);
+        template<PutMode>
+        bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*);
 
         bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
 
         bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+        JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase<Unknown>* location);
 
         const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
         Structure* createInheritorID(JSGlobalData&);
 
 
         const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
         Structure* createInheritorID(JSGlobalData&);
 
-        PropertyStorage m_propertyStorage;
+        StorageBarrier m_propertyStorage;
         WriteBarrier<Structure> m_inheritorID;
     };
 
         WriteBarrier<Structure> m_inheritorID;
     };
 
@@ -324,77 +325,170 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt
         friend class JSObject;
 
     public:
         friend class JSObject;
 
     public:
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        typedef JSObject Base;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
-        explicit JSNonFinalObject(VPtrStealingHackType)
-            : JSObject(VPtrStealingHack, m_inlineStorage)
-        {
-        }
-    
         explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure)
             : JSObject(globalData, structure, m_inlineStorage)
         {
         explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure)
             : JSObject(globalData, structure, m_inlineStorage)
         {
+        }
+
+        void finishCreation(JSGlobalData& globalData)
+        {
+            Base::finishCreation(globalData, m_inlineStorage);
             ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double)));
             ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity);
             ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double)));
             ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity);
+            ASSERT(classInfo());
         }
 
     private:
         WriteBarrier<Unknown> m_inlineStorage[JSNonFinalObject_inlineStorageCapacity];
     };
 
         }
 
     private:
         WriteBarrier<Unknown> m_inlineStorage[JSNonFinalObject_inlineStorageCapacity];
     };
 
+    class JSFinalObject;
+
     // 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:
     // 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)
+        typedef JSObject Base;
+
+        static JSFinalObject* create(ExecState*, Structure*);
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return new (exec) JSFinalObject(exec->globalData(), structure);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(FinalObjectType, StructureFlags), &s_info);
         }
 
         }
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static JS_EXPORTDATA const ClassInfo s_info;
+
+    protected:
+        void finishCreation(JSGlobalData& globalData)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            Base::finishCreation(globalData, m_inlineStorage);
+            ASSERT(!(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) % sizeof(double)));
+            ASSERT(this->structure()->propertyStorageCapacity() == JSFinalObject_inlineStorageCapacity);
+            ASSERT(classInfo());
         }
 
     private:
         }
 
     private:
+        friend class LLIntOffsetsExtractor;
+        
         explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
             : JSObject(globalData, structure, m_inlineStorage)
         {
         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;
+        static const unsigned StructureFlags = JSObject::StructureFlags;
 
         WriteBarrierBase<Unknown> m_inlineStorage[JSFinalObject_inlineStorageCapacity];
     };
 
 
         WriteBarrierBase<Unknown> m_inlineStorage[JSFinalObject_inlineStorageCapacity];
     };
 
+inline JSFinalObject* JSFinalObject::create(ExecState* exec, Structure* structure)
+{
+    JSFinalObject* finalObject = new (NotNull, allocateCell<JSFinalObject>(*exec->heap())) JSFinalObject(exec->globalData(), structure);
+    finalObject->finishCreation(exec->globalData());
+    return finalObject;
+}
+
+inline bool isJSFinalObject(JSCell* cell)
+{
+    return cell->classInfo() == &JSFinalObject::s_info;
+}
+
+inline bool isJSFinalObject(JSValue value)
+{
+    return value.isCell() && isJSFinalObject(value.asCell());
+}
+
 inline size_t JSObject::offsetOfInlineStorage()
 {
     ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) == OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage));
     return OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage);
 }
 
 inline size_t JSObject::offsetOfInlineStorage()
 {
     ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) == OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage));
     return OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage);
 }
 
+inline size_t JSObject::offsetOfPropertyStorage()
+{
+    return OBJECT_OFFSETOF(JSObject, m_propertyStorage);
+}
+
+inline size_t JSObject::offsetOfInheritorID()
+{
+    return OBJECT_OFFSETOF(JSObject, m_inheritorID);
+}
+
+inline bool JSObject::isGlobalObject() const
+{
+    return structure()->typeInfo().type() == GlobalObjectType;
+}
+
+inline bool JSObject::isVariableObject() const
+{
+    return structure()->typeInfo().type() >= VariableObjectType;
+}
+
+inline bool JSObject::isStaticScopeObject() const
+{
+    return structure()->typeInfo().type() == StaticScopeObjectType;
+}
+
+inline bool JSObject::isActivationObject() const
+{
+    return structure()->typeInfo().type() == ActivationObjectType;
+}
+
+inline bool JSObject::isErrorInstance() const
+{
+    return structure()->typeInfo().type() == ErrorInstanceType;
+}
+
+inline bool JSObject::isGlobalThis() const
+{
+    return structure()->typeInfo().type() == GlobalThisType;
+}
+
+inline void JSObject::setPropertyStorage(JSGlobalData& globalData, PropertyStorage storage, Structure* structure)
+{
+    ASSERT(storage);
+    ASSERT(structure);
+    setStructure(globalData, structure);
+    m_propertyStorage.set(globalData, this, storage);
+}
+
 inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure)
 {
     return JSFinalObject::create(exec, structure);
 }
 
 inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure)
 {
     return JSFinalObject::create(exec, structure);
 }
 
-inline Structure* createEmptyObjectStructure(JSGlobalData& globalData, JSValue prototype)
+inline CallType getCallData(JSValue value, CallData& callData)
+{
+    CallType result = value.isCell() ? value.asCell()->methodTable()->getCallData(value.asCell(), callData) : CallTypeNone;
+    ASSERT(result == CallTypeNone || value.isValidCallee());
+    return result;
+}
+
+inline ConstructType getConstructData(JSValue value, ConstructData& constructData)
 {
 {
-    return JSFinalObject::createStructure(globalData, prototype);
+    ConstructType result = value.isCell() ? value.asCell()->methodTable()->getConstructData(value.asCell(), constructData) : ConstructTypeNone;
+    ASSERT(result == ConstructTypeNone || value.isValidCallee());
+    return result;
+}
+
+inline Structure* createEmptyObjectStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return JSFinalObject::createStructure(globalData, globalObject, prototype);
 }
 
 inline JSObject* asObject(JSCell* cell)
 {
     ASSERT(cell->isObject());
 }
 
 inline JSObject* asObject(JSCell* cell)
 {
     ASSERT(cell->isObject());
-    return static_cast<JSObject*>(cell);
+    return jsCast<JSObject*>(cell);
 }
 
 inline JSObject* asObject(JSValue value)
 }
 
 inline JSObject* asObject(JSValue value)
@@ -404,50 +498,19 @@ inline JSObject* asObject(JSValue value)
 
 inline JSObject::JSObject(JSGlobalData& globalData, Structure* structure, PropertyStorage inlineStorage)
     : JSCell(globalData, structure)
 
 inline JSObject::JSObject(JSGlobalData& globalData, Structure* structure, PropertyStorage inlineStorage)
     : JSCell(globalData, structure)
-    , m_propertyStorage(inlineStorage)
+    , m_propertyStorage(globalData, this, inlineStorage)
 {
 {
-    ASSERT(inherits(&s_info));
-    ASSERT(m_structure->propertyStorageCapacity() < baseExternalStorageCapacity);
-    ASSERT(m_structure->isEmpty());
-    ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
-    ASSERT(static_cast<void*>(inlineStorage) == static_cast<void*>(this + 1));
-    ASSERT(m_structure->typeInfo().type() == ObjectType);
-}
-
-inline JSObject::~JSObject()
-{
-    if (!isUsingInlineStorage())
-        delete [] m_propertyStorage;
 }
 
 inline JSValue JSObject::prototype() const
 {
 }
 
 inline JSValue JSObject::prototype() const
 {
-    return m_structure->storedPrototype();
-}
-
-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;
+    return structure()->storedPrototype();
 }
 
 inline void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype)
 {
     ASSERT(prototype);
 }
 
 inline void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype)
 {
     ASSERT(prototype);
-    setStructure(globalData, Structure::changePrototypeTransition(globalData, m_structure.get(), prototype));
-}
-
-inline void JSObject::setStructure(JSGlobalData& globalData, Structure* structure)
-{
-    ASSERT(structure->typeInfo().overridesVisitChildren() == m_structure->typeInfo().overridesVisitChildren());
-    m_structure.set(globalData, this, structure);
+    setStructure(globalData, Structure::changePrototypeTransition(globalData, structure(), prototype));
 }
 
 inline Structure* JSObject::inheritorID(JSGlobalData& globalData)
 }
 
 inline Structure* JSObject::inheritorID(JSGlobalData& globalData)
@@ -466,11 +529,12 @@ inline bool Structure::isUsingInlineStorage() const
 
 inline bool JSCell::inherits(const ClassInfo* info) const
 {
 
 inline bool JSCell::inherits(const ClassInfo* info) const
 {
-    for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) {
-        if (ci == info)
-            return true;
-    }
-    return false;
+    return classInfo()->isSubClassOf(info);
+}
+
+inline const MethodTable* JSCell::methodTable() const
+{
+    return &classInfo()->methodTable;
 }
 
 // this method is here to be after the inline declaration of JSCell::inherits
 }
 
 // this method is here to be after the inline declaration of JSCell::inherits
@@ -479,38 +543,53 @@ inline bool JSValue::inherits(const ClassInfo* classInfo) const
     return isCell() && asCell()->inherits(classInfo);
 }
 
     return isCell() && asCell()->inherits(classInfo);
 }
 
+inline JSObject* JSValue::toThisObject(ExecState* exec) const
+{
+    return isCell() ? asCell()->methodTable()->toThisObject(asCell(), exec) : toThisObjectSlowCase(exec);
+}
+
 ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
     if (WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName)) {
 ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
     if (WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName)) {
-        if (m_structure->hasGetterSetterProperties() && location->isGetterSetter())
+        if (structure()->hasGetterSetterProperties() && location->isGetterSetter())
             fillGetterPropertySlot(slot, location);
         else
             slot.setValue(this, location->get(), offsetForLocation(location));
         return true;
     }
 
             fillGetterPropertySlot(slot, location);
         else
             slot.setValue(this, location->get(), offsetForLocation(location));
         return true;
     }
 
-    // non-standard Netscape extension
-    if (propertyName == exec->propertyNames().underscoreProto) {
-        slot.setValue(prototype());
-        return true;
-    }
-
     return false;
 }
 
 // It may seem crazy to inline a function this large, especially a virtual function,
 // but it makes a big difference to property lookup that derived classes can inline their
 // base class call to this.
     return false;
 }
 
 // It may seem crazy to inline a function this large, especially a virtual function,
 // but it makes a big difference to property lookup that derived classes can inline their
 // base class call to this.
-ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+ALWAYS_INLINE bool JSObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
-    return inlineGetOwnPropertySlot(exec, propertyName, slot);
+    return jsCast<JSObject*>(cell)->inlineGetOwnPropertySlot(exec, propertyName, slot);
 }
 
 ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
     if (!structure()->typeInfo().overridesGetOwnPropertySlot())
         return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot);
 }
 
 ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
     if (!structure()->typeInfo().overridesGetOwnPropertySlot())
         return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot);
-    return getOwnPropertySlot(exec, propertyName, slot);
+    return methodTable()->getOwnPropertySlot(this, exec, propertyName, slot);
+}
+
+// Fast call to get a property where we may not yet have converted the string to an
+// identifier. The first time we perform a property access with a given string, try
+// performing the property map lookup without forming an identifier. We detect this
+// case by checking whether the hash has yet been set for this string.
+ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(ExecState* exec, const UString& name)
+{
+    if (!structure()->typeInfo().overridesGetOwnPropertySlot() && !structure()->hasGetterSetterProperties()) {
+        size_t offset = name.impl()->hasHash()
+            ? structure()->get(exec->globalData(), Identifier(exec, name))
+            : structure()->get(exec->globalData(), name);
+        if (offset != WTF::notFound)
+            return asObject(this)->locationForOffset(offset)->get();
+    }
+    return JSValue();
 }
 
 // It may seem crazy to inline a function this large but it makes a big difference
 }
 
 // It may seem crazy to inline a function this large but it makes a big difference
@@ -532,7 +611,7 @@ ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyN
 {
     JSObject* object = this;
     while (true) {
 {
     JSObject* object = this;
     while (true) {
-        if (object->getOwnPropertySlot(exec, propertyName, slot))
+        if (object->methodTable()->getOwnPropertySlotByIndex(object, exec, propertyName, slot))
             return true;
         JSValue prototype = object->prototype();
         if (!prototype.isObject())
             return true;
         JSValue prototype = object->prototype();
         if (!prototype.isObject())
@@ -559,21 +638,23 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const
     return jsUndefined();
 }
 
     return jsUndefined();
 }
 
-inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction)
+template<JSObject::PutMode mode>
+inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction)
 {
     ASSERT(value);
 {
     ASSERT(value);
+    ASSERT(value.isGetterSetter() == !!(attributes & Accessor));
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-    if (m_structure->isDictionary()) {
+    if (structure()->isDictionary()) {
         unsigned currentAttributes;
         JSCell* currentSpecificFunction;
         unsigned currentAttributes;
         JSCell* currentSpecificFunction;
-        size_t offset = m_structure->get(globalData, propertyName, currentAttributes, currentSpecificFunction);
+        size_t offset = 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(globalData, propertyName);
-            if (checkReadOnly && currentAttributes & ReadOnly)
+                structure()->despecifyDictionaryFunction(globalData, propertyName);
+            if ((mode == PutModePut) && currentAttributes & ReadOnly)
                 return false;
 
             putDirectOffset(globalData, offset, value);
                 return false;
 
             putDirectOffset(globalData, offset, value);
@@ -588,15 +669,16 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
             return true;
         }
 
             return true;
         }
 
-        if (checkReadOnly && !isExtensible())
+        if ((mode == PutModePut) && !isExtensible())
             return false;
 
             return false;
 
-        size_t currentCapacity = m_structure->propertyStorageCapacity();
-        offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction);
-        if (currentCapacity != m_structure->propertyStorageCapacity())
-            allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
+        PropertyStorage newStorage = propertyStorage();
+        if (structure()->shouldGrowPropertyStorage())
+            newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
+        offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction);
+        setPropertyStorage(globalData, newStorage, structure());
 
 
-        ASSERT(offset < m_structure->propertyStorageCapacity());
+        ASSERT(offset < structure()->propertyStorageCapacity());
         putDirectOffset(globalData, offset, value);
         // See comment on setNewProperty call below.
         if (!specificFunction)
         putDirectOffset(globalData, offset, value);
         // See comment on setNewProperty call below.
         if (!specificFunction)
@@ -605,13 +687,14 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
     }
 
     size_t offset;
     }
 
     size_t offset;
-    size_t currentCapacity = m_structure->propertyStorageCapacity();
-    if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(m_structure.get(), propertyName, attributes, specificFunction, offset)) {    
+    size_t currentCapacity = structure()->propertyStorageCapacity();
+    if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) {
+        PropertyStorage newStorage = propertyStorage(); 
         if (currentCapacity != structure->propertyStorageCapacity())
         if (currentCapacity != structure->propertyStorageCapacity())
-            allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
+            newStorage = growPropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity());
 
         ASSERT(offset < structure->propertyStorageCapacity());
 
         ASSERT(offset < structure->propertyStorageCapacity());
-        setStructure(globalData, structure);
+        setPropertyStorage(globalData, newStorage, 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.
         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.
@@ -622,9 +705,9 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
 
     unsigned currentAttributes;
     JSCell* currentSpecificFunction;
 
     unsigned currentAttributes;
     JSCell* currentSpecificFunction;
-    offset = m_structure->get(globalData, propertyName, currentAttributes, currentSpecificFunction);
+    offset = structure()->get(globalData, propertyName, currentAttributes, currentSpecificFunction);
     if (offset != WTF::notFound) {
     if (offset != WTF::notFound) {
-        if (checkReadOnly && currentAttributes & ReadOnly)
+        if ((mode == PutModePut) && currentAttributes & ReadOnly)
             return false;
 
         // There are three possibilities here:
             return false;
 
         // There are three possibilities here:
@@ -643,7 +726,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
                 return true;
             }
             // case (2) Despecify, fall through to (3).
                 return true;
             }
             // case (2) Despecify, fall through to (3).
-            setStructure(globalData, Structure::despecifyFunctionTransition(globalData, m_structure.get(), propertyName));
+            setStructure(globalData, Structure::despecifyFunctionTransition(globalData, structure(), propertyName));
         }
 
         // case (3) set the slot, do the put, return.
         }
 
         // case (3) set the slot, do the put, return.
@@ -652,16 +735,17 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
         return true;
     }
 
         return true;
     }
 
-    if (checkReadOnly && !isExtensible())
+    if ((mode == PutModePut) && !isExtensible())
         return false;
 
         return false;
 
-    Structure* structure = Structure::addPropertyTransition(globalData, m_structure.get(), propertyName, attributes, specificFunction, offset);
+    PropertyStorage newStorage = propertyStorage();
+    if (structure()->shouldGrowPropertyStorage())
+        newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
 
 
-    if (currentCapacity != structure->propertyStorageCapacity())
-        allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
+    Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset);
 
     ASSERT(offset < structure->propertyStorageCapacity());
 
     ASSERT(offset < structure->propertyStorageCapacity());
-    setStructure(globalData, structure);
+    setPropertyStorage(globalData, newStorage, 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.
     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.
@@ -670,78 +754,50 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
     return true;
 }
 
     return true;
 }
 
-inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, 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));
+    ASSERT(!structure()->hasGetterSetterProperties());
 
 
-    return putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value));
-}
-
-inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
-{
-    PutPropertySlot slot;
-    putDirectInternal(globalData, propertyName, value, attributes, false, slot, getJSFunction(globalData, value));
-}
-
-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));
-
-    return putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, 0);
+    return putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value));
 }
 
 inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
 }
 
 inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
+    ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
     PutPropertySlot slot;
     PutPropertySlot slot;
-    putDirectInternal(globalData, propertyName, value, attributes, false, slot, 0);
+    putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value));
 }
 
 }
 
-inline bool JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
-    return putDirectInternal(globalData, propertyName, value, 0, false, slot, 0);
-}
-
-inline void JSObject::putDirectFunction(JSGlobalData& globalData, const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
-{
-    putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, value);
-}
-
-inline void JSObject::putDirectFunction(JSGlobalData& globalData, const Identifier& propertyName, JSCell* value, unsigned attr)
-{
-    PutPropertySlot slot;
-    putDirectInternal(globalData, propertyName, value, attr, false, slot, value);
+    ASSERT(!value.isGetterSetter());
+    putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, 0, slot, getJSFunction(value));
 }
 
 inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
 }
 
 inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
-    size_t currentCapacity = m_structure->propertyStorageCapacity();
-    size_t offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, 0);
-    if (currentCapacity != m_structure->propertyStorageCapacity())
-        allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
-    putDirectOffset(globalData, offset, value);
-}
-
-inline void JSObject::putDirectFunctionWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSCell* value, unsigned attributes)
-{
-    size_t currentCapacity = m_structure->propertyStorageCapacity();
-    size_t offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, value);
-    if (currentCapacity != m_structure->propertyStorageCapacity())
-        allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
+    ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
+    PropertyStorage newStorage = propertyStorage();
+    if (structure()->shouldGrowPropertyStorage())
+        newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
+    size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getJSFunction(value));
+    setPropertyStorage(globalData, newStorage, structure());
     putDirectOffset(globalData, offset, value);
 }
 
 inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure)
 {
     putDirectOffset(globalData, offset, value);
 }
 
 inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure)
 {
-    if (m_structure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
-        allocatePropertyStorage(m_structure->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
-    setStructure(globalData, newStructure);
+    PropertyStorage newStorage = propertyStorage();
+    if (structure()->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
+        newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
+    setPropertyStorage(globalData, newStorage, newStructure);
 }
 
 inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
 {
 }
 
 inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
 {
-    return defaultValue(exec, preferredType);
+    return methodTable()->defaultValue(this, exec, preferredType);
 }
 
 inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName) const
 }
 
 inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName) const
@@ -754,8 +810,6 @@ inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, Pro
 {
     if (UNLIKELY(!isCell())) {
         JSObject* prototype = synthesizePrototype(exec);
 {
     if (UNLIKELY(!isCell())) {
         JSObject* prototype = synthesizePrototype(exec);
-        if (propertyName == exec->propertyNames().underscoreProto)
-            return prototype;
         if (!prototype->getPropertySlot(exec, propertyName, slot))
             return jsUndefined();
         return slot.getValue(exec, propertyName);
         if (!prototype->getPropertySlot(exec, propertyName, slot))
             return jsUndefined();
         return slot.getValue(exec, propertyName);
@@ -787,7 +841,7 @@ inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot
     }
     JSCell* cell = const_cast<JSCell*>(asCell());
     while (true) {
     }
     JSCell* cell = const_cast<JSCell*>(asCell());
     while (true) {
-        if (cell->getOwnPropertySlot(exec, propertyName, slot))
+        if (cell->methodTable()->getOwnPropertySlotByIndex(cell, exec, propertyName, slot))
             return slot.getValue(exec, propertyName);
         JSValue prototype = asObject(cell)->prototype();
         if (!prototype.isObject())
             return slot.getValue(exec, propertyName);
         JSValue prototype = asObject(cell)->prototype();
         if (!prototype.isObject())
@@ -799,58 +853,24 @@ inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot
 inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     if (UNLIKELY(!isCell())) {
 inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     if (UNLIKELY(!isCell())) {
-        synthesizeObject(exec)->put(exec, propertyName, value, slot);
+        putToPrimitive(exec, propertyName, value, slot);
         return;
     }
         return;
     }
-    asCell()->put(exec, propertyName, value, slot);
-}
-
-inline void JSValue::putDirect(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
-{
-    ASSERT(isCell() && isObject());
-    if (!asObject(asCell())->putDirect(exec->globalData(), propertyName, value, slot) && slot.isStrictMode())
-        throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+    asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot);
 }
 
 }
 
-inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
+inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
 {
     if (UNLIKELY(!isCell())) {
 {
     if (UNLIKELY(!isCell())) {
-        synthesizeObject(exec)->put(exec, propertyName, value);
+        PutPropertySlot slot(shouldThrow);
+        putToPrimitive(exec, Identifier::from(exec, propertyName), value, slot);
         return;
     }
         return;
     }
-    asCell()->put(exec, propertyName, value);
-}
-
-ALWAYS_INLINE void JSObject::visitChildrenDirect(SlotVisitor& visitor)
-{
-    JSCell::visitChildren(visitor);
-
-    PropertyStorage storage = propertyStorage();
-    size_t storageSize = m_structure->propertyStorageSize();
-    visitor.appendValues(storage, storageSize);
-    if (m_inheritorID)
-        visitor.append(&m_inheritorID);
+    asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value, shouldThrow);
 }
 
 // --- JSValue inlines ----------------------------
 
 }
 
 // --- JSValue inlines ----------------------------
 
-ALWAYS_INLINE UString JSValue::toThisString(ExecState* exec) const
-{
-    return isString() ? static_cast<JSString*>(asCell())->value(exec) : toThisObject(exec)->toString(exec);
-}
-
-inline JSString* JSValue::toThisJSString(ExecState* exec) const
-{
-    return isString() ? static_cast<JSString*>(asCell()) : jsString(exec, toThisObject(exec)->toString(exec));
-}
-
-inline JSValue JSValue::toStrictThisObject(ExecState* exec) const
-{
-    if (!isObject())
-        return *this;
-    return asObject(asCell())->toStrictThisObject(exec);
-}
-
 ALWAYS_INLINE JSObject* Register::function() const
 {
     if (!jsValue())
 ALWAYS_INLINE JSObject* Register::function() const
 {
     if (!jsValue())
diff --git a/runtime/JSObjectWithGlobalObject.cpp b/runtime/JSObjectWithGlobalObject.cpp
deleted file mode 100644 (file)
index 2b489a2..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 844bcd8..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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 e05bb3f44d5a01657b5edeb95d74c897a5261bc3..6fd8b770b75ee363520418fb9d51fcaeb0644380 100644 (file)
@@ -35,7 +35,7 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
 
 
 ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
 
-const ClassInfo JSPropertyNameIterator::s_info = { "JSPropertyNameIterator", 0, 0, 0 };
+const ClassInfo JSPropertyNameIterator::s_info = { "JSPropertyNameIterator", 0, 0, 0, CREATE_METHOD_TABLE(JSPropertyNameIterator) };
 
 inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
     : JSCell(exec->globalData(), exec->globalData().propertyNameIteratorStructure.get())
 
 inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
     : JSCell(exec->globalData(), exec->globalData().propertyNameIteratorStructure.get())
@@ -43,9 +43,6 @@ inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyN
     , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
     , m_jsStrings(adoptArrayPtr(new WriteBarrier<Unknown>[m_jsStringsSize]))
 {
     , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
     , m_jsStrings(adoptArrayPtr(new WriteBarrier<Unknown>[m_jsStringsSize]))
 {
-    PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector();
-    for (size_t i = 0; i < m_jsStringsSize; ++i)
-        m_jsStrings[i].set(exec->globalData(), this, jsOwnedString(exec, propertyNameVector[i].ustring()));
 }
 
 JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o)
 }
 
 JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o)
@@ -55,14 +52,14 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject
             o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec));
 
     PropertyNameArray propertyNames(exec);
             o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec));
 
     PropertyNameArray propertyNames(exec);
-    o->getPropertyNames(exec, propertyNames);
+    o->methodTable()->getPropertyNames(o, exec, propertyNames, ExcludeDontEnumProperties);
     size_t numCacheableSlots = 0;
     size_t numCacheableSlots = 0;
-    if (!o->structure()->hasNonEnumerableProperties() && !o->structure()->hasAnonymousSlots() &&
-        !o->structure()->hasGetterSetterProperties() && !o->structure()->isUncacheableDictionary() &&
-        !o->structure()->typeInfo().overridesGetPropertyNames())
+    if (!o->structure()->hasNonEnumerableProperties() && !o->structure()->hasGetterSetterProperties()
+        && !o->structure()->isUncacheableDictionary() && !o->structure()->typeInfo().overridesGetPropertyNames())
         numCacheableSlots = o->structure()->propertyStorageSize();
         numCacheableSlots = o->structure()->propertyStorageSize();
-
-    JSPropertyNameIterator* jsPropertyNameIterator = new (exec) JSPropertyNameIterator(exec, propertyNames.data(), numCacheableSlots);
+    
+    JSPropertyNameIterator* jsPropertyNameIterator = new (NotNull, allocateCell<JSPropertyNameIterator>(*exec->heap())) JSPropertyNameIterator(exec, propertyNames.data(), numCacheableSlots);
+    jsPropertyNameIterator->finishCreation(exec, propertyNames.data());
 
     if (o->structure()->isDictionary())
         return jsPropertyNameIterator;
 
     if (o->structure()->isDictionary())
         return jsPropertyNameIterator;
@@ -84,6 +81,11 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject
     return jsPropertyNameIterator;
 }
 
     return jsPropertyNameIterator;
 }
 
+void JSPropertyNameIterator::destroy(JSCell* cell)
+{
+    jsCast<JSPropertyNameIterator*>(cell)->JSPropertyNameIterator::~JSPropertyNameIterator();
+}
+
 JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
 {
     JSValue identifier = m_jsStrings[i].get();
 JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
 {
     JSValue identifier = m_jsStrings[i].get();
@@ -95,13 +97,14 @@ JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
     return identifier;
 }
 
     return identifier;
 }
 
-void JSPropertyNameIterator::visitChildren(SlotVisitor& visitor)
+void JSPropertyNameIterator::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    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);
+    JSPropertyNameIterator* thisObject = jsCast<JSPropertyNameIterator*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    visitor.appendValues(thisObject->m_jsStrings.get(), thisObject->m_jsStringsSize);
+    if (thisObject->m_cachedPrototypeChain)
+        visitor.append(&thisObject->m_cachedPrototypeChain);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index ff129f0549a1324b9a48080874680b347adf6d27..5b65e59f25c7222f541d8bdf6a960ab50430f057 100644 (file)
@@ -38,21 +38,30 @@ namespace JSC {
 
     class Identifier;
     class JSObject;
 
     class Identifier;
     class JSObject;
+    class LLIntOffsetsExtractor;
 
     class JSPropertyNameIterator : public JSCell {
         friend class JIT;
 
     public:
 
     class JSPropertyNameIterator : public JSCell {
         friend class JIT;
 
     public:
+        typedef JSCell Base;
+
         static JSPropertyNameIterator* create(ExecState*, JSObject*);
         static JSPropertyNameIterator* create(ExecState*, JSObject*);
-        
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static JSPropertyNameIterator* create(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesVisitChildren), AnonymousSlotCount, &s_info);
+            JSPropertyNameIterator* iterator = new (NotNull, allocateCell<JSPropertyNameIterator>(*exec->heap())) JSPropertyNameIterator(exec, propertyNameArrayData, numCacheableSlot);
+            iterator->finishCreation(exec, propertyNameArrayData);
+            return iterator;
         }
 
         }
 
-        virtual bool isPropertyNameIterator() const { return true; }
+        static void destroy(JSCell*);
+       
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+        {
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(CompoundType, OverridesVisitChildren), &s_info);
+        }
 
 
-        virtual void visitChildren(SlotVisitor&);
+        static void visitChildren(JSCell*, SlotVisitor&);
 
         bool getOffset(size_t i, int& offset)
         {
 
         bool getOffset(size_t i, int& offset)
         {
@@ -78,7 +87,18 @@ namespace JSC {
         
         static const ClassInfo s_info;
 
         
         static const ClassInfo s_info;
 
+    protected:
+        void finishCreation(ExecState* exec, PropertyNameArrayData* propertyNameArrayData)
+        {
+            Base::finishCreation(exec->globalData());
+            PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector();
+            for (size_t i = 0; i < m_jsStringsSize; ++i)
+                m_jsStrings[i].set(exec->globalData(), this, jsOwnedString(exec, propertyNameVector[i].ustring()));
+        }
+
     private:
     private:
+        friend class LLIntOffsetsExtractor;
+        
         JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
 
         WriteBarrier<Structure> m_cachedStructure;
         JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
 
         WriteBarrier<Structure> m_cachedStructure;
@@ -101,7 +121,7 @@ namespace JSC {
 
     ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const
     {
 
     ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const
     {
-        return static_cast<JSPropertyNameIterator*>(jsValue().asCell());
+        return jsCast<JSPropertyNameIterator*>(jsValue().asCell());
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
index 5206510d6cd2a7724a73b5bed12a1f2d6d8cc716..f8942b5f865db59e1542dc4e3b5c7cf279c17163 100644 (file)
 namespace JSC {
 ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
 
 namespace JSC {
 ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
 
-void JSStaticScopeObject::visitChildren(SlotVisitor& visitor)
+const ClassInfo JSStaticScopeObject::s_info = { "Object", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSStaticScopeObject) };
+
+void JSStaticScopeObject::destroy(JSCell* cell)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
-    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
-    JSVariableObject::visitChildren(visitor);
-    visitor.append(&m_registerStore);
+    jsCast<JSStaticScopeObject*>(cell)->JSStaticScopeObject::~JSStaticScopeObject();
 }
 
 }
 
-JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
+void JSStaticScopeObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    return exec->globalThisValue();
+    JSStaticScopeObject* thisObject = jsCast<JSStaticScopeObject*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    JSVariableObject::visitChildren(thisObject, visitor);
+    visitor.append(&thisObject->m_registerStore);
 }
 
 }
 
-JSValue JSStaticScopeObject::toStrictThisObject(ExecState*) const
+JSObject* JSStaticScopeObject::toThisObject(JSCell*, ExecState* exec)
 {
 {
-    return jsNull();
+    return exec->globalThisValue();
 }
 
 }
 
-void JSStaticScopeObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void JSStaticScopeObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
+    JSStaticScopeObject* thisObject = jsCast<JSStaticScopeObject*>(cell);
     if (slot.isStrictMode()) {
         // Double lookup in strict mode, but this only occurs when
         // a) indirectly writing to an exception slot
     if (slot.isStrictMode()) {
         // Double lookup in strict mode, but this only occurs when
         // a) indirectly writing to an exception slot
@@ -62,34 +66,30 @@ void JSStaticScopeObject::put(ExecState* exec, const Identifier& propertyName, J
         // a pointer compare.
         PropertySlot slot;
         bool isWritable = true;
         // a pointer compare.
         PropertySlot slot;
         bool isWritable = true;
-        symbolTableGet(propertyName, slot, isWritable);
+        thisObject->symbolTableGet(propertyName, slot, isWritable);
         if (!isWritable) {
             throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
             return;
         }
     }
         if (!isWritable) {
             throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
             return;
         }
     }
-    if (symbolTablePut(exec->globalData(), propertyName, value))
+    if (thisObject->symbolTablePut(exec, propertyName, value, slot.isStrictMode()))
         return;
     
     ASSERT_NOT_REACHED();
 }
 
         return;
     
     ASSERT_NOT_REACHED();
 }
 
-void JSStaticScopeObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
+void JSStaticScopeObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
 {
-    if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
+    JSStaticScopeObject* thisObject = jsCast<JSStaticScopeObject*>(object);
+    if (thisObject->symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
         return;
     
     ASSERT_NOT_REACHED();
 }
 
         return;
     
     ASSERT_NOT_REACHED();
 }
 
-bool JSStaticScopeObject::isDynamicScope(bool&) const
-{
-    return false;
-}
-
-bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot)
+bool JSStaticScopeObject::getOwnPropertySlot(JSCell* cell, ExecState*, const Identifier& propertyName, PropertySlot& slot)
 {
 {
-    return symbolTableGet(propertyName, slot);
+    return jsCast<JSStaticScopeObject*>(cell)->symbolTableGet(propertyName, slot);
 }
 
 }
 }
 
 }
index b201fe05676b2f17171a74caea418a99af31c928..bbf03a3473a25769d2b4259b750f6bf7ffd40f89 100644 (file)
@@ -32,31 +32,53 @@ namespace JSC{
     
     class JSStaticScopeObject : public JSVariableObject {
     public:
     
     class JSStaticScopeObject : public JSVariableObject {
     public:
-        JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue value, unsigned attributes)
-            : JSVariableObject(exec->globalData(), exec->globalData().staticScopeStructure.get(), &m_symbolTable, reinterpret_cast<Register*>(&m_registerStore + 1))
+        typedef JSVariableObject Base;
+
+        static JSStaticScopeObject* create(ExecState* exec, const Identifier& identifier, JSValue value, unsigned attributes)
         {
         {
-            m_registerStore.set(exec->globalData(), this, value);
-            symbolTable().add(ident.impl(), SymbolTableEntry(-1, attributes));
+            JSStaticScopeObject* scopeObject = new (NotNull, allocateCell<JSStaticScopeObject>(*exec->heap())) JSStaticScopeObject(exec);
+            scopeObject->finishCreation(exec, identifier, value, attributes);
+            return scopeObject;
         }
 
         }
 
-        virtual void visitChildren(SlotVisitor&);
+        static void visitChildren(JSCell*, SlotVisitor&);
         bool isDynamicScope(bool& requiresDynamicChecks) 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);
+        static JSObject* toThisObject(JSCell*, ExecState*);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+
+        static void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); }
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(StaticScopeObjectType, StructureFlags), &s_info); }
+
+        static const ClassInfo s_info;
 
     protected:
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
+        void finishCreation(ExecState* exec, const Identifier& identifier, JSValue value, unsigned attributes)
+        {
+            Base::finishCreation(exec->globalData());
+            m_registerStore.set(exec->globalData(), this, value);
+            symbolTable().add(identifier.impl(), SymbolTableEntry(-1, attributes));
+        }
+        static const unsigned StructureFlags = IsEnvironmentRecord | OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
 
     private:
 
     private:
+        JSStaticScopeObject(ExecState* exec)
+            : JSVariableObject(exec->globalData(), exec->globalData().staticScopeStructure.get(), &m_symbolTable, reinterpret_cast<Register*>(&m_registerStore + 1))
+        {
+        }
+
+        static void destroy(JSCell*);
+
         SymbolTable m_symbolTable;
         WriteBarrier<Unknown> m_registerStore;
     };
 
         SymbolTable m_symbolTable;
         WriteBarrier<Unknown> m_registerStore;
     };
 
+    inline bool JSStaticScopeObject::isDynamicScope(bool&) const
+    {
+        return false;
+    }
+
 }
 
 #endif // JSStaticScopeObject_h
 }
 
 #endif // JSStaticScopeObject_h
index da15997d32db78aed7b57f07f0cc4b529331f010..904cc4d3e51fa4d91f5681a8d02de042b78d1d73 100644 (file)
@@ -34,53 +34,98 @@ namespace JSC {
     
 static const unsigned substringFromRopeCutoff = 4;
 
     
 static const unsigned substringFromRopeCutoff = 4;
 
-const ClassInfo JSString::s_info = { "string", 0, 0, 0 };
+const ClassInfo JSString::s_info = { "string", 0, 0, 0, CREATE_METHOD_TABLE(JSString) };
 
 
-void JSString::resolveRope(ExecState* exec) const
+void JSRopeString::RopeBuilder::expand()
+{
+    ASSERT(m_index == JSRopeString::s_maxInternalRopeLength);
+    JSString* jsString = m_jsString;
+    m_jsString = jsStringBuilder(&m_globalData);
+    m_index = 0;
+    append(jsString);
+}
+
+void JSString::destroy(JSCell* cell)
+{
+    JSString* thisObject = jsCast<JSString*>(cell);
+    thisObject->JSString::~JSString();
+}
+
+void JSString::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    JSString* thisObject = jsCast<JSString*>(cell);
+    Base::visitChildren(thisObject, visitor);
+    
+    if (thisObject->isRope())
+        static_cast<JSRopeString*>(thisObject)->visitFibers(visitor);
+}
+
+void JSRopeString::visitFibers(SlotVisitor& visitor)
+{
+    for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i)
+        visitor.append(&m_fibers[i]);
+}
+
+void JSRopeString::resolveRope(ExecState* exec) const
 {
     ASSERT(isRope());
 
 {
     ASSERT(isRope());
 
+    if (is8Bit()) {
+        LChar* buffer;
+        if (RefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) {
+            Heap::heap(this)->reportExtraMemoryCost(newImpl->cost());
+            m_value = newImpl.release();
+        } else {
+            outOfMemory(exec);
+            return;
+        }
+
+        for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
+            if (m_fibers[i]->isRope())
+                return resolveRopeSlowCase8(buffer);
+        }
+
+        LChar* position = buffer;
+        for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
+            StringImpl* string = m_fibers[i]->m_value.impl();
+            unsigned length = string->length();
+            StringImpl::copyChars(position, string->characters8(), length);
+            position += length;
+            m_fibers[i].clear();
+        }
+        ASSERT((buffer + m_length) == position);
+        ASSERT(!isRope());
+
+        return;
+    }
+
     UChar* buffer;
     UChar* buffer;
-    if (PassRefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer))
-        m_value = newImpl;
-    else {
+    if (RefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) {
+        Heap::heap(this)->reportExtraMemoryCost(newImpl->cost());
+        m_value = newImpl.release();
+    } else {
         outOfMemory(exec);
         return;
     }
 
         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;
+    for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
+        if (m_fibers[i]->isRope())
+            return resolveRopeSlowCase(buffer);
     }
 
     UChar* position = buffer;
     }
 
     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();
+    for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
+        StringImpl* string = m_fibers[i]->m_value.impl();
+        unsigned length = string->length();
         StringImpl::copyChars(position, string->characters(), length);
         position += length;
         StringImpl::copyChars(position, string->characters(), length);
         position += length;
+        m_fibers[i].clear();
     }
     }
-
     ASSERT((buffer + m_length) == position);
     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());
 }
 
     ASSERT(!isRope());
 }
 
-// Overview: this methods converts a JSString from holding a string in rope form
+// Overview: These functions convert a JSString from holding a string in rope form
 // down to a simple UString representation.  It does so by building up the string
 // backwards, since we want to avoid recursion, we expect that the tree structure
 // representing the rope is likely imbalanced with more nodes down the left side
 // down to a simple UString representation.  It does so by building up the string
 // backwards, since we want to avoid recursion, we expect that the tree structure
 // representing the rope is likely imbalanced with more nodes down the left side
@@ -90,174 +135,78 @@ void JSString::resolveRope(ExecState* exec) const
 // 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.)    
 // 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::resolveRopeSlowCase(ExecState* exec, UChar* buffer) const
+void JSRopeString::resolveRopeSlowCase8(LChar* buffer) const
 {
 {
-    UNUSED_PARAM(exec);
-
-    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_fibers[i]);
-    currentFiber = m_fibers[m_fiberCount - 1];
-    while (true) {
-        if (RopeImpl::isRope(currentFiber)) {
-            RopeImpl* rope = static_cast<RopeImpl*>(currentFiber);
-            // Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber'
-            // (we will be working backwards over the rope).
-            unsigned fiberCountMinusOne = rope->fiberCount() - 1;
-            for (unsigned i = 0; i < fiberCountMinusOne; ++i)
-                workQueue.append(rope->fibers()[i]);
-            currentFiber = rope->fibers()[fiberCountMinusOne];
-        } else {
-            StringImpl* string = static_cast<StringImpl*>(currentFiber);
-            unsigned length = string->length();
-            position -= length;
-            StringImpl::copyChars(position, string->characters(), length);
-
-            // Was this the last item in the work queue?
-            if (workQueue.isEmpty()) {
-                // Create a string from the UChar buffer, clear the rope RefPtr.
-                ASSERT(buffer == position);
-                for (unsigned i = 0; i < m_fiberCount; ++i) {
-                    RopeImpl::deref(m_fibers[i]);
-                    m_fibers[i] = 0;
-                }
-                m_fiberCount = 0;
-                
-                ASSERT(!isRope());
-                return;
-            }
-
-            // No! - set the next item up to process.
-            currentFiber = workQueue.last();
-            workQueue.removeLast();
-        }
+    LChar* position = buffer + m_length; // We will be working backwards over the rope.
+    Vector<JSString*, 32> workQueue; // Putting strings into a Vector is only OK because there are no GC points in this method.
+    
+    for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
+        workQueue.append(m_fibers[i].get());
+        // Clearing here works only because there are no GC points in this method.
+        m_fibers[i].clear();
     }
     }
-}
 
 
-void JSString::outOfMemory(ExecState* exec) const
-{
-    for (unsigned i = 0; i < m_fiberCount; ++i) {
-        RopeImpl::deref(m_fibers[i]);
-        m_fibers[i] = 0;
-    }
-    m_fiberCount = 0;
-    ASSERT(!isRope());
-    ASSERT(m_value == UString());
-    if (exec)
-        throwOutOfMemoryError(exec);
-}
-
-// This function construsts a substring out of a rope without flattening by reusing the existing fibers.
-// This can reduce memory usage substantially. Since traversing ropes is slow the function will revert 
-// back to flattening if the rope turns out to be long.
-JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart, unsigned substringLength)
-{
-    ASSERT(isRope());
-    ASSERT(substringLength);
-    
-    JSGlobalData* globalData = &exec->globalData();
+    while (!workQueue.isEmpty()) {
+        JSString* currentFiber = workQueue.last();
+        workQueue.removeLast();
 
 
-    UString substringFibers[3];
-    
-    unsigned fiberCount = 0;
-    unsigned substringFiberCount = 0;
-    unsigned substringEnd = substringStart + substringLength;
-    unsigned fiberEnd = 0;
-
-    RopeIterator end;
-    for (RopeIterator it(m_fibers.data(), m_fiberCount); it != end; ++it) {
-        ++fiberCount;
-        StringImpl* fiberString = *it;
-        unsigned fiberStart = fiberEnd;
-        fiberEnd = fiberStart + fiberString->length();
-        if (fiberEnd <= substringStart)
+        if (currentFiber->isRope()) {
+            JSRopeString* currentFiberAsRope = static_cast<JSRopeString*>(currentFiber);
+            for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->m_fibers[i]; ++i)
+                workQueue.append(currentFiberAsRope->m_fibers[i].get());
             continue;
             continue;
-        unsigned copyStart = std::max(substringStart, fiberStart);
-        unsigned copyEnd = std::min(substringEnd, fiberEnd);
-        if (copyStart == fiberStart && copyEnd == fiberEnd)
-            substringFibers[substringFiberCount++] = UString(fiberString);
-        else
-            substringFibers[substringFiberCount++] = UString(StringImpl::create(fiberString, copyStart - fiberStart, copyEnd - copyStart));
-        if (fiberEnd >= substringEnd)
-            break;
-        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);
         }
         }
-    }
-    ASSERT(substringFiberCount && substringFiberCount <= 3);
 
 
-    if (substringLength == 1) {
-        ASSERT(substringFiberCount == 1);
-        UChar c = substringFibers[0].characters()[0];
-        if (c <= maxSingleCharacterString)
-            return globalData->smallStrings.singleCharacterString(globalData, c);
+        StringImpl* string = static_cast<StringImpl*>(currentFiber->m_value.impl());
+        unsigned length = string->length();
+        position -= length;
+        StringImpl::copyChars(position, string->characters8(), length);
     }
     }
-    if (substringFiberCount == 1)
-        return new (globalData) JSString(globalData, substringFibers[0]);
-    if (substringFiberCount == 2)
-        return new (globalData) JSString(globalData, substringFibers[0], substringFibers[1]);
-    return new (globalData) JSString(globalData, substringFibers[0], substringFibers[1], substringFibers[2]);
+
+    ASSERT(buffer == position);
+    ASSERT(!isRope());
 }
 
 }
 
-JSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UString& replacement)
+void JSRopeString::resolveRopeSlowCase(UChar* buffer) const
 {
 {
-    if (!isRope()) {
-        size_t matchPosition = m_value.find(character);
-        if (matchPosition == notFound)
-            return JSValue(this);
-        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;
-    StringImpl* matchString = 0;
-    size_t matchPosition = notFound;
-    for (RopeIterator it(m_fibers.data(), m_fiberCount); it != end; ++it) {
-        ++fiberCount;
-        if (matchString)
-            continue;
-
-        StringImpl* string = *it;
-        matchPosition = string->find(character);
-        if (matchPosition == notFound)
-            continue;
-        matchString = string;
-    }
+    UChar* position = buffer + m_length; // We will be working backwards over the rope.
+    Vector<JSString*, 32> workQueue; // These strings are kept alive by the parent rope, so using a Vector is OK.
 
 
-    if (!matchString)
-        return this;
+    for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i)
+        workQueue.append(m_fibers[i].get());
 
 
-    RopeBuilder builder(replacement.length() ? fiberCount + 2 : fiberCount + 1);
-    if (UNLIKELY(builder.isOutOfMemory()))
-        return throwOutOfMemoryError(exec);
+    while (!workQueue.isEmpty()) {
+        JSString* currentFiber = workQueue.last();
+        workQueue.removeLast();
 
 
-    for (RopeIterator it(m_fibers.data(), m_fiberCount); it != end; ++it) {
-        StringImpl* string = *it;
-        if (string != matchString) {
-            builder.append(UString(string));
+        if (currentFiber->isRope()) {
+            JSRopeString* currentFiberAsRope = static_cast<JSRopeString*>(currentFiber);
+            for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->m_fibers[i]; ++i)
+                workQueue.append(currentFiberAsRope->m_fibers[i].get());
             continue;
         }
 
             continue;
         }
 
-        builder.append(UString(string).substringSharingImpl(0, matchPosition));
-        if (replacement.length())
-            builder.append(replacement);
-        builder.append(UString(string).substringSharingImpl(matchPosition + 1));
-        matchString = 0;
+        StringImpl* string = static_cast<StringImpl*>(currentFiber->m_value.impl());
+        unsigned length = string->length();
+        position -= length;
+        StringImpl::copyChars(position, string->characters(), length);
     }
 
     }
 
-    JSGlobalData* globalData = &exec->globalData();
-    return JSValue(new (globalData) JSString(globalData, builder.release()));
+    ASSERT(buffer == position);
+    ASSERT(!isRope());
+}
+
+void JSRopeString::outOfMemory(ExecState* exec) const
+{
+    for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i)
+        m_fibers[i].clear();
+    ASSERT(isRope());
+    ASSERT(m_value == UString());
+    if (exec)
+        throwOutOfMemoryError(exec);
 }
 
 }
 
-JSString* JSString::getIndexSlowCase(ExecState* exec, unsigned i)
+JSString* JSRopeString::getIndexSlowCase(ExecState* exec, unsigned i)
 {
     ASSERT(isRope());
     resolveRope(exec);
 {
     ASSERT(isRope());
     resolveRope(exec);
@@ -274,7 +223,7 @@ JSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const
     return const_cast<JSString*>(this);
 }
 
     return const_cast<JSString*>(this);
 }
 
-bool JSString::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result)
+bool JSString::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result) const
 {
     result = this;
     number = jsToNumber(value(exec));
 {
     result = this;
     number = jsToNumber(value(exec));
@@ -291,14 +240,11 @@ double JSString::toNumber(ExecState* exec) const
     return jsToNumber(value(exec));
 }
 
     return jsToNumber(value(exec));
 }
 
-UString JSString::toString(ExecState* exec) const
-{
-    return value(exec);
-}
-
 inline StringObject* StringObject::create(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
 {
 inline StringObject* StringObject::create(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
 {
-    return new (exec) StringObject(exec->globalData(), globalObject->stringObjectStructure(), string);
+    StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->globalData(), globalObject->stringObjectStructure());
+    object->finishCreation(exec->globalData(), string);
+    return object;
 }
 
 JSObject* JSString::toObject(ExecState* exec, JSGlobalObject* globalObject) const
 }
 
 JSObject* JSString::toObject(ExecState* exec, JSGlobalObject* globalObject) const
@@ -306,26 +252,23 @@ JSObject* JSString::toObject(ExecState* exec, JSGlobalObject* globalObject) cons
     return StringObject::create(exec, globalObject, const_cast<JSString*>(this));
 }
 
     return StringObject::create(exec, globalObject, const_cast<JSString*>(this));
 }
 
-JSObject* JSString::toThisObject(ExecState* exec) const
+JSObject* JSString::toThisObject(JSCell* cell, ExecState* exec)
 {
 {
-    return StringObject::create(exec, exec->lexicalGlobalObject(), const_cast<JSString*>(this));
+    return StringObject::create(exec, exec->lexicalGlobalObject(), jsCast<JSString*>(cell));
 }
 
 }
 
-bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+bool JSString::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
+    JSString* thisObject = jsCast<JSString*>(cell);
     // The semantics here are really getPropertySlot, not getOwnPropertySlot.
     // This function should only be called by JSValue::get.
     // The semantics here are really getPropertySlot, not getOwnPropertySlot.
     // This function should only be called by JSValue::get.
-    if (getStringPropertySlot(exec, propertyName, slot))
-        return true;
-    if (propertyName == exec->propertyNames().underscoreProto) {
-        slot.setValue(exec->lexicalGlobalObject()->stringPrototype());
+    if (thisObject->getStringPropertySlot(exec, propertyName, slot))
         return true;
         return true;
-    }
-    slot.setBase(this);
+    slot.setBase(thisObject);
     JSObject* object;
     for (JSValue prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype.isNull(); prototype = object->prototype()) {
         object = asObject(prototype);
     JSObject* object;
     for (JSValue prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype.isNull(); prototype = object->prototype()) {
         object = asObject(prototype);
-        if (object->getOwnPropertySlot(exec, propertyName, slot))
+        if (object->methodTable()->getOwnPropertySlot(object, exec, propertyName, slot))
             return true;
     }
     slot.setUndefined();
             return true;
     }
     slot.setUndefined();
@@ -349,23 +292,14 @@ bool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& pr
     return false;
 }
 
     return false;
 }
 
-bool JSString::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
-{
-    if (getStringPropertyDescriptor(exec, propertyName, descriptor))
-        return true;
-    if (propertyName != exec->propertyNames().underscoreProto)
-        return false;
-    descriptor.setDescriptor(exec->lexicalGlobalObject()->stringPrototype(), DontEnum);
-    return true;
-}
-
-bool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+bool JSString::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)
 {
 {
+    JSString* thisObject = jsCast<JSString*>(cell);
     // The semantics here are really getPropertySlot, not getOwnPropertySlot.
     // This function should only be called by JSValue::get.
     // The semantics here are really getPropertySlot, not getOwnPropertySlot.
     // This function should only be called by JSValue::get.
-    if (getStringPropertySlot(exec, propertyName, slot))
+    if (thisObject->getStringPropertySlot(exec, propertyName, slot))
         return true;
         return true;
-    return JSString::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
+    return JSString::getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 668064f854a8030ad383ddc66d11d0c92d732317..10ec799e583d4760222d0afeaab5f0af8618805d 100644 (file)
 
 #ifndef JSString_h
 #define JSString_h
 
 #ifndef JSString_h
 #define JSString_h
-
 #include "CallFrame.h"
 #include "CommonIdentifiers.h"
 #include "Identifier.h"
 #include "PropertyDescriptor.h"
 #include "PropertySlot.h"
 #include "CallFrame.h"
 #include "CommonIdentifiers.h"
 #include "Identifier.h"
 #include "PropertyDescriptor.h"
 #include "PropertySlot.h"
-#include "RopeImpl.h"
 #include "Structure.h"
 
 namespace JSC {
 
     class JSString;
 #include "Structure.h"
 
 namespace JSC {
 
     class JSString;
+    class JSRopeString;
+    class LLIntOffsetsExtractor;
 
     JSString* jsEmptyString(JSGlobalData*);
     JSString* jsEmptyString(ExecState*);
 
     JSString* jsEmptyString(JSGlobalData*);
     JSString* jsEmptyString(ExecState*);
@@ -59,378 +59,244 @@ namespace JSC {
     JSString* jsOwnedString(JSGlobalData*, const UString&); 
     JSString* jsOwnedString(ExecState*, const UString&); 
 
     JSString* jsOwnedString(JSGlobalData*, const UString&); 
     JSString* jsOwnedString(ExecState*, const UString&); 
 
-    class JS_EXPORTCLASS JSString : public JSCell {
+    JSRopeString* jsStringBuilder(JSGlobalData*);
+
+    class JSString : public JSCell {
     public:
         friend class JIT;
         friend class JSGlobalData;
         friend class SpecializedThunkJIT;
     public:
         friend class JIT;
         friend class JSGlobalData;
         friend class SpecializedThunkJIT;
+        friend class JSRopeString;
         friend struct ThunkHelpers;
 
         friend struct ThunkHelpers;
 
-        class RopeBuilder {
-        public:
-            RopeBuilder(unsigned fiberCount)
-                : m_index(0)
-                , m_rope(RopeImpl::tryCreateUninitialized(fiberCount))
-            {
-            }
-
-            bool isOutOfMemory() { return !m_rope; }
-
-            void append(RopeImpl::Fiber& fiber)
-            {
-                ASSERT(m_rope);
-                m_rope->initializeFiber(m_index, fiber);
-            }
-            void append(const UString& string)
-            {
-                ASSERT(m_rope);
-                m_rope->initializeFiber(m_index, string.impl());
-            }
-            void append(JSString* jsString)
-            {
-                if (jsString->isRope()) {
-                    for (unsigned i = 0; i < jsString->m_fiberCount; ++i)
-                        append(jsString->m_fibers[i]);
-                } else
-                    append(jsString->string());
-            }
-
-            PassRefPtr<RopeImpl> release()
-            {
-                ASSERT(m_index == m_rope->fiberCount());
-                return m_rope.release();
-            }
-
-            unsigned length() { return m_rope->length(); }
+        typedef JSCell Base;
 
 
-        private:
-            unsigned m_index;
-            RefPtr<RopeImpl> m_rope;
-        };
+        static void destroy(JSCell*);
 
 
-        class RopeIterator {
-            public:
-                RopeIterator() { }
-
-                RopeIterator(RopeImpl::Fiber* fibers, size_t fiberCount)
-                {
-                    ASSERT(fiberCount);
-                    m_workQueue.append(WorkItem(fibers, fiberCount));
-                    skipRopes();
-                }
-
-                RopeIterator& operator++()
-                {
-                    WorkItem& item = m_workQueue.last();
-                    ASSERT(!RopeImpl::isRope(item.fibers[item.i]));
-                    if (++item.i == item.fiberCount)
-                        m_workQueue.removeLast();
-                    skipRopes();
-                    return *this;
-                }
-
-                StringImpl* operator*()
-                {
-                    WorkItem& item = m_workQueue.last();
-                    RopeImpl::Fiber fiber = item.fibers[item.i];
-                    ASSERT(!RopeImpl::isRope(fiber));
-                    return static_cast<StringImpl*>(fiber);
-                }
-
-                bool operator!=(const RopeIterator& other) const
-                {
-                    return m_workQueue != other.m_workQueue;
-                }
-
-            private:
-                struct WorkItem {
-                    WorkItem(RopeImpl::Fiber* fibers, size_t fiberCount)
-                        : fibers(fibers)
-                        , fiberCount(fiberCount)
-                        , i(0)
-                    {
-                    }
-
-                    bool operator!=(const WorkItem& other) const
-                    {
-                        return fibers != other.fibers || fiberCount != other.fiberCount || i != other.i;
-                    }
-
-                    RopeImpl::Fiber* fibers;
-                    size_t fiberCount;
-                    size_t i;
-                };
-
-                void skipRopes()
-                {
-                    if (m_workQueue.isEmpty())
-                        return;
-
-                    while (1) {
-                        WorkItem& item = m_workQueue.last();
-                        RopeImpl::Fiber fiber = item.fibers[item.i];
-                        if (!RopeImpl::isRope(fiber))
-                            break;
-                        RopeImpl* rope = static_cast<RopeImpl*>(fiber);
-                        if (++item.i == item.fiberCount)
-                            m_workQueue.removeLast();
-                        m_workQueue.append(WorkItem(rope->fibers(), rope->fiberCount()));
-                    }
-                }
-
-                Vector<WorkItem, 16> m_workQueue;
-        };
-
-        ALWAYS_INLINE JSString(JSGlobalData* globalData, const UString& value)
-            : JSCell(*globalData, globalData->stringStructure.get())
-            , m_length(value.length())
+    private:
+        JSString(JSGlobalData& globalData, PassRefPtr<StringImpl> value)
+            : JSCell(globalData, globalData.stringStructure.get())
             , m_value(value)
             , m_value(value)
-            , m_fiberCount(0)
         {
         {
-            ASSERT(!m_value.isNull());
-            Heap::heap(this)->reportExtraMemoryCost(value.impl()->cost());
         }
 
         }
 
-        enum HasOtherOwnerType { HasOtherOwner };
-        JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType)
-            : JSCell(*globalData, globalData->stringStructure.get())
-            , m_length(value.length())
-            , m_value(value)
-            , m_fiberCount(0)
+        JSString(JSGlobalData& globalData)
+            : JSCell(globalData, globalData.stringStructure.get())
         {
         {
-            ASSERT(!m_value.isNull());
-        }
-        JSString(JSGlobalData* globalData, PassRefPtr<StringImpl> value, HasOtherOwnerType)
-            : JSCell(*globalData, globalData->stringStructure.get())
-            , m_length(value->length())
-            , m_value(value)
-            , m_fiberCount(0)
-        {
-            ASSERT(!m_value.isNull());
-        }
-        JSString(JSGlobalData* globalData, PassRefPtr<RopeImpl> rope)
-            : JSCell(*globalData, globalData->stringStructure.get())
-            , m_length(rope->length())
-            , m_fiberCount(1)
-        {
-            m_fibers[0] = rope.leakRef();
-        }
-        // This constructor constructs a new string by concatenating s1 & s2.
-        // This should only be called with fiberCount <= 3.
-        JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, JSString* s2)
-            : JSCell(*globalData, globalData->stringStructure.get())
-            , m_length(s1->length() + s2->length())
-            , m_fiberCount(fiberCount)
-        {
-            ASSERT(fiberCount <= s_maxInternalRopeLength);
-            unsigned index = 0;
-            appendStringInConstruct(index, s1);
-            appendStringInConstruct(index, s2);
-            ASSERT(fiberCount == index);
-        }
-        // 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, globalData->stringStructure.get())
-            , m_length(s1->length() + u2.length())
-            , m_fiberCount(fiberCount)
-        {
-            ASSERT(fiberCount <= s_maxInternalRopeLength);
-            unsigned index = 0;
-            appendStringInConstruct(index, s1);
-            appendStringInConstruct(index, u2);
-            ASSERT(fiberCount == index);
-        }
-        // 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, globalData->stringStructure.get())
-            , m_length(u1.length() + s2->length())
-            , m_fiberCount(fiberCount)
-        {
-            ASSERT(fiberCount <= s_maxInternalRopeLength);
-            unsigned index = 0;
-            appendStringInConstruct(index, u1);
-            appendStringInConstruct(index, s2);
-            ASSERT(fiberCount == index);
-        }
-        // This constructor constructs a new string by concatenating v1, v2 & v3.
-        // This should only be called with fiberCount <= 3 ... which since every
-        // 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(), exec->globalData().stringStructure.get())
-            , m_length(0)
-            , m_fiberCount(s_maxInternalRopeLength)
-        {
-            unsigned index = 0;
-            appendValueInConstructAndIncrementLength(exec, index, v1);
-            appendValueInConstructAndIncrementLength(exec, index, v2);
-            appendValueInConstructAndIncrementLength(exec, index, v3);
-            ASSERT(index == s_maxInternalRopeLength);
         }
 
         }
 
-        // This constructor constructs a new string by concatenating u1 & u2.
-        JSString(JSGlobalData* globalData, const UString& u1, const UString& u2)
-            : JSCell(*globalData, globalData->stringStructure.get())
-            , m_length(u1.length() + u2.length())
-            , m_fiberCount(2)
+        void finishCreation(JSGlobalData& globalData, size_t length)
         {
         {
-            unsigned index = 0;
-            appendStringInConstruct(index, u1);
-            appendStringInConstruct(index, u2);
-            ASSERT(index <= s_maxInternalRopeLength);
+            ASSERT(!m_value.isNull());
+            Base::finishCreation(globalData);
+            m_length = length;
+            m_is8Bit = m_value.impl()->is8Bit();
         }
 
         }
 
-        // 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, globalData->stringStructure.get())
-            , m_length(u1.length() + u2.length() + u3.length())
-            , m_fiberCount(s_maxInternalRopeLength)
+        void finishCreation(JSGlobalData& globalData, size_t length, size_t cost)
         {
         {
-            unsigned index = 0;
-            appendStringInConstruct(index, u1);
-            appendStringInConstruct(index, u2);
-            appendStringInConstruct(index, u3);
-            ASSERT(index <= s_maxInternalRopeLength);
+            ASSERT(!m_value.isNull());
+            Base::finishCreation(globalData);
+            m_length = length;
+            m_is8Bit = m_value.impl()->is8Bit();
+            Heap::heap(this)->reportExtraMemoryCost(cost);
         }
 
         }
 
-        ~JSString()
+    protected:
+        void finishCreation(JSGlobalData& globalData)
         {
         {
-            ASSERT(vptr() == JSGlobalData::jsStringVPtr);
-            for (unsigned i = 0; i < m_fiberCount; ++i)
-                RopeImpl::deref(m_fibers[i]);
+            Base::finishCreation(globalData);
+            m_length = 0;
+            m_is8Bit = true;
         }
         }
-
-        const UString& value(ExecState* exec) const
+        
+    public:
+        static JSString* create(JSGlobalData& globalData, PassRefPtr<StringImpl> value)
         {
         {
-            if (isRope())
-                resolveRope(exec);
-            return m_value;
+            ASSERT(value);
+            size_t length = value->length();
+            size_t cost = value->cost();
+            JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData, value);
+            newString->finishCreation(globalData, length, cost);
+            return newString;
         }
         }
-        const UString& tryGetValue() const
+        static JSString* createHasOtherOwner(JSGlobalData& globalData, PassRefPtr<StringImpl> value)
         {
         {
-            if (isRope())
-                resolveRope(0);
-            return m_value;
+            ASSERT(value);
+            size_t length = value->length();
+            JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData, value);
+            newString->finishCreation(globalData, length);
+            return newString;
         }
         }
+
+        const UString& value(ExecState*) const;
+        const UString& tryGetValue() const;
         unsigned length() { return m_length; }
 
         unsigned length() { return m_length; }
 
+        JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+        JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const;
+        bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
+        JSObject* toObject(ExecState*, JSGlobalObject*) const;
+        double toNumber(ExecState*) const;
+        
         bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
         bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
 
         bool canGetIndex(unsigned i) { return i < m_length; }
         JSString* getIndex(ExecState*, unsigned);
         bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
         bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
 
         bool canGetIndex(unsigned i) { return i < m_length; }
         JSString* getIndex(ExecState*, unsigned);
-        JSString* getIndexSlowCase(ExecState*, unsigned);
-
-        JSValue replaceCharacter(ExecState*, UChar, const UString& replacement);
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
         {
         {
-            return Structure::create(globalData, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot), &s_info);
         }
         }
+
+        static size_t offsetOfLength() { return OBJECT_OFFSETOF(JSString, m_length); }
+        static size_t offsetOfValue() { return OBJECT_OFFSETOF(JSString, m_value); }
+
+        static JS_EXPORTDATA const ClassInfo s_info;
+
+        static void visitChildren(JSCell*, SlotVisitor&);
+
+    protected:
+        bool isRope() const { return m_value.isNull(); }
+        bool is8Bit() const { return m_is8Bit; }
+
+        // A string is represented either by a UString or a rope of fibers.
+        bool m_is8Bit : 1;
+        unsigned m_length;
+        mutable UString m_value;
+
+    private:
+        friend class LLIntOffsetsExtractor;
         
         
-        static const ClassInfo s_info;
+        static JSObject* toThisObject(JSCell*, ExecState*);
+
+        // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
+        static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+
+        UString& string() { ASSERT(!isRope()); return m_value; }
+
+        friend JSValue jsString(ExecState*, JSString*, JSString*);
+        friend JSString* jsSubstring(ExecState*, JSString*, unsigned offset, unsigned length);
+    };
+
+    class JSRopeString : public JSString {
+        friend class JSString;
 
 
+        friend JSRopeString* jsStringBuilder(JSGlobalData*);
+
+        class RopeBuilder {
+        public:
+            RopeBuilder(JSGlobalData& globalData)
+            : m_globalData(globalData)
+            , m_jsString(jsStringBuilder(&globalData))
+            , m_index(0)
+            {
+            }
+
+            void append(JSString* jsString)
+            {
+                if (m_index == JSRopeString::s_maxInternalRopeLength)
+                    expand();
+                m_jsString->m_fibers[m_index++].set(m_globalData, m_jsString, jsString);
+                m_jsString->m_length += jsString->m_length;
+                m_jsString->m_is8Bit = m_jsString->m_is8Bit && jsString->m_is8Bit;
+            }
+
+            JSRopeString* release()
+            {
+                JSRopeString* tmp = m_jsString;
+                m_jsString = 0;
+                return tmp;
+            }
+
+            unsigned length() { return m_jsString->m_length; }
+
+        private:
+            void expand();
+            
+            JSGlobalData& m_globalData;
+            JSRopeString* m_jsString;
+            size_t m_index;
+        };
+        
     private:
     private:
-        JSString(VPtrStealingHackType) 
-            : JSCell(VPtrStealingHack)
-            , m_fiberCount(0)
+        JSRopeString(JSGlobalData& globalData)
+            : JSString(globalData)
         {
         }
 
         {
         }
 
-        void resolveRope(ExecState*) const;
-        void resolveRopeSlowCase(ExecState*, UChar*) const;
-        void outOfMemory(ExecState*) const;
-        JSString* substringFromRope(ExecState*, unsigned offset, unsigned length);
+        void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2)
+        {
+            Base::finishCreation(globalData);
+            m_length = s1->length() + s2->length();
+            m_is8Bit = (s1->is8Bit() && s2->is8Bit());
+            m_fibers[0].set(globalData, this, s1);
+            m_fibers[1].set(globalData, this, s2);
+        }
+        
+        void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3)
+        {
+            Base::finishCreation(globalData);
+            m_length = s1->length() + s2->length() + s3->length();
+            m_is8Bit = (s1->is8Bit() && s2->is8Bit() &&  s3->is8Bit());
+            m_fibers[0].set(globalData, this, s1);
+            m_fibers[1].set(globalData, this, s2);
+            m_fibers[2].set(globalData, this, s3);
+        }
 
 
-        void appendStringInConstruct(unsigned& index, const UString& string)
+        void finishCreation(JSGlobalData& globalData)
         {
         {
-            StringImpl* impl = string.impl();
-            impl->ref();
-            m_fibers[index++] = impl;
+            JSString::finishCreation(globalData);
         }
 
         }
 
-        void appendStringInConstruct(unsigned& index, JSString* jsString)
+        static JSRopeString* createNull(JSGlobalData& globalData)
         {
         {
-            if (jsString->isRope()) {
-                for (unsigned i = 0; i < jsString->m_fiberCount; ++i) {
-                    RopeImpl::Fiber fiber = jsString->m_fibers[i];
-                    fiber->ref();
-                    m_fibers[index++] = fiber;
-                }
-            } else
-                appendStringInConstruct(index, jsString->string());
+            JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData);
+            newString->finishCreation(globalData);
+            return newString;
         }
 
         }
 
-        void appendValueInConstructAndIncrementLength(ExecState* exec, unsigned& index, JSValue v)
+    public:
+        static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2)
         {
         {
-            if (v.isString()) {
-                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));
-                StringImpl* impl = u.impl();
-                impl->ref();
-                m_fibers[index++] = impl;
-                m_length += u.length();
-            }
+            JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData);
+            newString->finishCreation(globalData, s1, s2);
+            return newString;
+        }
+        static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3)
+        {
+            JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData);
+            newString->finishCreation(globalData, s1, s2, s3);
+            return newString;
         }
 
         }
 
-        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 JSObject* toObject(ExecState*, JSGlobalObject*) const;
-        virtual UString toString(ExecState*) const;
+        void visitFibers(SlotVisitor&);
 
 
-        virtual JSObject* toThisObject(ExecState*) const;
+    private:
+        friend JSValue jsString(ExecState*, Register*, unsigned);
+        friend JSValue jsStringFromArguments(ExecState*, JSValue);
 
 
-        // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
-        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        JS_EXPORT_PRIVATE void resolveRope(ExecState*) const;
+        void resolveRopeSlowCase8(LChar*) const;
+        void resolveRopeSlowCase(UChar*) const;
+        void outOfMemory(ExecState*) const;
+        
+        JSString* getIndexSlowCase(ExecState*, unsigned);
 
         static const unsigned s_maxInternalRopeLength = 3;
 
         static const unsigned s_maxInternalRopeLength = 3;
-
-        // A string is represented either by a UString or a RopeImpl.
-        unsigned m_length;
-        mutable UString m_value;
-        mutable unsigned m_fiberCount;
-        mutable FixedArray<RopeImpl::Fiber, s_maxInternalRopeLength> m_fibers;
-
-        bool isRope() const { return m_fiberCount; }
-        UString& string() { ASSERT(!isRope()); return m_value; }
-        unsigned fiberCount() { return m_fiberCount ? m_fiberCount : 1; }
-
-        friend JSValue jsString(ExecState* exec, JSString* s1, JSString* s2);
-        friend JSValue jsString(ExecState* exec, const UString& u1, JSString* s2);
-        friend JSValue jsString(ExecState* exec, JSString* s1, const UString& u2);
-        friend JSValue jsString(ExecState* exec, Register* strings, unsigned count);
-        friend JSValue jsString(ExecState* exec, JSValue thisValue);
-        friend JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length);
+        
+        mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers;
     };
 
     JSString* asString(JSValue);
 
     };
 
     JSString* asString(JSValue);
 
-    // When an object is created from a different DLL, MSVC changes vptr to a "local" one right after invoking a constructor,
-    // see <http://groups.google.com/group/microsoft.public.vc.language/msg/55cdcefeaf770212>.
-    // This breaks isJSString(), and we don't need that hack anyway, so we change vptr back to primary one.
-    // The below function must be called by any inline function that invokes a JSString constructor.
-#if COMPILER(MSVC) && !defined(BUILDING_JavaScriptCore)
-    inline JSString* fixupVPtr(JSGlobalData* globalData, JSString* string) { string->setVPtr(globalData->jsStringVPtr); return string; }
-#else
-    inline JSString* fixupVPtr(JSGlobalData*, JSString* string) { return string; }
-#endif
-
     inline JSString* asString(JSValue value)
     {
         ASSERT(value.asCell()->isString());
     inline JSString* asString(JSValue value)
     {
         ASSERT(value.asCell()->isString());
-        return static_cast<JSString*>(value.asCell());
+        return jsCast<JSString*>(value.asCell());
     }
 
     inline JSString* jsEmptyString(JSGlobalData* globalData)
     }
 
     inline JSString* jsEmptyString(JSGlobalData* globalData)
@@ -438,21 +304,21 @@ namespace JSC {
         return globalData->smallStrings.emptyString(globalData);
     }
 
         return globalData->smallStrings.emptyString(globalData);
     }
 
-    inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c)
+    ALWAYS_INLINE JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c)
     {
         if (c <= maxSingleCharacterString)
             return globalData->smallStrings.singleCharacterString(globalData, c);
     {
         if (c <= maxSingleCharacterString)
             return globalData->smallStrings.singleCharacterString(globalData, c);
-        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(&c, 1)));
+        return JSString::create(*globalData, UString(&c, 1).impl());
     }
 
     }
 
-    inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset)
+    ALWAYS_INLINE JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset)
     {
         JSGlobalData* globalData = &exec->globalData();
         ASSERT(offset < static_cast<unsigned>(s.length()));
     {
         JSGlobalData* globalData = &exec->globalData();
         ASSERT(offset < static_cast<unsigned>(s.length()));
-        UChar c = s.characters()[offset];
+        UChar c = s[offset];
         if (c <= maxSingleCharacterString)
             return globalData->smallStrings.singleCharacterString(globalData, c);
         if (c <= maxSingleCharacterString)
             return globalData->smallStrings.singleCharacterString(globalData, c);
-        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, 1))));
+        return JSString::create(*globalData, StringImpl::create(s.impl(), offset, 1));
     }
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s)
     }
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s)
@@ -460,20 +326,34 @@ namespace JSC {
         ASSERT(s);
         ASSERT(s[0]);
         ASSERT(s[1]);
         ASSERT(s);
         ASSERT(s[0]);
         ASSERT(s[1]);
-        return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
+        return JSString::create(*globalData, UString(s).impl());
     }
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
     {
         ASSERT(s.length() > 1);
     }
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
     {
         ASSERT(s.length() > 1);
-        return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
+        return JSString::create(*globalData, s.impl());
+    }
+
+    inline const UString& JSString::value(ExecState* exec) const
+    {
+        if (isRope())
+            static_cast<const JSRopeString*>(this)->resolveRope(exec);
+        return m_value;
+    }
+
+    inline const UString& JSString::tryGetValue() const
+    {
+        if (isRope())
+            static_cast<const JSRopeString*>(this)->resolveRope(0);
+        return m_value;
     }
 
     inline JSString* JSString::getIndex(ExecState* exec, unsigned i)
     {
         ASSERT(canGetIndex(i));
         if (isRope())
     }
 
     inline JSString* JSString::getIndex(ExecState* exec, unsigned i)
     {
         ASSERT(canGetIndex(i));
         if (isRope())
-            return getIndexSlowCase(exec, i);
+            return static_cast<JSRopeString*>(this)->getIndexSlowCase(exec, i);
         ASSERT(i < m_value.length());
         return jsSingleCharacterSubstring(exec, m_value, i);
     }
         ASSERT(i < m_value.length());
         return jsSingleCharacterSubstring(exec, m_value, i);
     }
@@ -484,11 +364,11 @@ namespace JSC {
         if (!size)
             return globalData->smallStrings.emptyString(globalData);
         if (size == 1) {
         if (!size)
             return globalData->smallStrings.emptyString(globalData);
         if (size == 1) {
-            UChar c = s.characters()[0];
+            UChar c = s[0];
             if (c <= maxSingleCharacterString)
                 return globalData->smallStrings.singleCharacterString(globalData, c);
         }
             if (c <= maxSingleCharacterString)
                 return globalData->smallStrings.singleCharacterString(globalData, c);
         }
-        return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
+        return JSString::create(*globalData, s.impl());
     }
 
     inline JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length)
     }
 
     inline JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length)
@@ -499,9 +379,22 @@ namespace JSC {
         JSGlobalData* globalData = &exec->globalData();
         if (!length)
             return globalData->smallStrings.emptyString(globalData);
         JSGlobalData* globalData = &exec->globalData();
         if (!length)
             return globalData->smallStrings.emptyString(globalData);
-        if (s->isRope())
-            return s->substringFromRope(exec, offset, length);
-        return jsSubstring(globalData, s->m_value, offset, length);
+        return jsSubstring(globalData, s->value(exec), offset, length);
+    }
+
+    inline JSString* jsSubstring8(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
+    {
+        ASSERT(offset <= static_cast<unsigned>(s.length()));
+        ASSERT(length <= static_cast<unsigned>(s.length()));
+        ASSERT(offset + length <= static_cast<unsigned>(s.length()));
+        if (!length)
+            return globalData->smallStrings.emptyString(globalData);
+        if (length == 1) {
+            UChar c = s[offset];
+            if (c <= maxSingleCharacterString)
+                return globalData->smallStrings.singleCharacterString(globalData, c);
+        }
+        return JSString::createHasOtherOwner(*globalData, StringImpl::create8(s.impl(), offset, length));
     }
 
     inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
     }
 
     inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
@@ -512,11 +405,11 @@ namespace JSC {
         if (!length)
             return globalData->smallStrings.emptyString(globalData);
         if (length == 1) {
         if (!length)
             return globalData->smallStrings.emptyString(globalData);
         if (length == 1) {
-            UChar c = s.characters()[offset];
+            UChar c = s[offset];
             if (c <= maxSingleCharacterString)
                 return globalData->smallStrings.singleCharacterString(globalData, c);
         }
             if (c <= maxSingleCharacterString)
                 return globalData->smallStrings.singleCharacterString(globalData, c);
         }
-        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, length)), JSString::HasOtherOwner));
+        return JSString::createHasOtherOwner(*globalData, StringImpl::create(s.impl(), offset, length));
     }
 
     inline JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
     }
 
     inline JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
@@ -525,16 +418,22 @@ namespace JSC {
         if (!size)
             return globalData->smallStrings.emptyString(globalData);
         if (size == 1) {
         if (!size)
             return globalData->smallStrings.emptyString(globalData);
         if (size == 1) {
-            UChar c = s.characters()[0];
+            UChar c = s[0];
             if (c <= maxSingleCharacterString)
                 return globalData->smallStrings.singleCharacterString(globalData, c);
         }
             if (c <= maxSingleCharacterString)
                 return globalData->smallStrings.singleCharacterString(globalData, c);
         }
-        return fixupVPtr(globalData, new (globalData) JSString(globalData, s, JSString::HasOtherOwner));
+        return JSString::createHasOtherOwner(*globalData, s.impl());
+    }
+
+    inline JSRopeString* jsStringBuilder(JSGlobalData* globalData)
+    {
+        return JSRopeString::createNull(*globalData);
     }
 
     inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }
     inline JSString* jsString(ExecState* exec, const UString& s) { return jsString(&exec->globalData(), s); }
     inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->globalData(), c); }
     }
 
     inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }
     inline JSString* jsString(ExecState* exec, const UString& s) { return jsString(&exec->globalData(), s); }
     inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->globalData(), c); }
+    inline JSString* jsSubstring8(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring8(&exec->globalData(), s, offset, length); }
     inline JSString* jsSubstring(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring(&exec->globalData(), s, offset, length); }
     inline JSString* jsNontrivialString(ExecState* exec, const UString& s) { return jsNontrivialString(&exec->globalData(), s); }
     inline JSString* jsNontrivialString(ExecState* exec, const char* s) { return jsNontrivialString(&exec->globalData(), s); }
     inline JSString* jsSubstring(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring(&exec->globalData(), s, offset, length); }
     inline JSString* jsNontrivialString(ExecState* exec, const UString& s) { return jsNontrivialString(&exec->globalData(), s); }
     inline JSString* jsNontrivialString(ExecState* exec, const char* s) { return jsNontrivialString(&exec->globalData(), s); }
@@ -567,47 +466,66 @@ namespace JSC {
         return false;
     }
 
         return false;
     }
 
-    inline bool isJSString(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsStringVPtr; }
+    inline bool isJSString(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSString::s_info; }
+
+    inline bool JSCell::toBoolean(ExecState* exec) const
+    {
+        if (isString()) 
+            return static_cast<const JSString*>(this)->toBoolean(exec);
+        return !structure()->typeInfo().masqueradesAsUndefined();
+    }
 
     // --- JSValue inlines ----------------------------
 
     // --- JSValue inlines ----------------------------
+    
+    inline bool JSValue::toBoolean(ExecState* exec) const
+    {
+        if (isInt32())
+            return asInt32();
+        if (isDouble())
+            return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN
+        if (isCell())
+            return asCell()->toBoolean(exec);
+        return isTrue(); // false, null, and undefined all convert to false.
+    }
 
 
-    inline UString JSValue::toString(ExecState* exec) const
+    inline JSString* JSValue::toString(ExecState* exec) const
+    {
+        if (isString())
+            return jsCast<JSString*>(asCell());
+        return toStringSlowCase(exec);
+    }
+
+    inline UString JSValue::toUString(ExecState* exec) const
     {
         if (isString())
             return static_cast<JSString*>(asCell())->value(exec);
     {
         if (isString())
             return static_cast<JSString*>(asCell())->value(exec);
-        if (isInt32())
-            return exec->globalData().numericStrings.add(asInt32());
-        if (isDouble())
-            return exec->globalData().numericStrings.add(asDouble());
-        if (isTrue())
-            return "true";
-        if (isFalse())
-            return "false";
-        if (isNull())
-            return "null";
-        if (isUndefined())
-            return "undefined";
-        ASSERT(isCell());
-        return asCell()->toString(exec);
+        return toUStringSlowCase(exec);
     }
 
     }
 
-    inline UString JSValue::toPrimitiveString(ExecState* exec) const
+    ALWAYS_INLINE UString inlineJSValueNotStringtoUString(const JSValue& value, ExecState* exec)
     {
     {
-        ASSERT(!isString());
-        if (isInt32())
-            return exec->globalData().numericStrings.add(asInt32());
-        if (isDouble())
-            return exec->globalData().numericStrings.add(asDouble());
-        if (isTrue())
-            return "true";
-        if (isFalse())
-            return "false";
-        if (isNull())
-            return "null";
-        if (isUndefined())
-            return "undefined";
-        ASSERT(isCell());
-        return asCell()->toPrimitive(exec, NoPreference).toString(exec);
+        JSGlobalData& globalData = exec->globalData();
+        if (value.isInt32())
+            return globalData.numericStrings.add(value.asInt32());
+        if (value.isDouble())
+            return globalData.numericStrings.add(value.asDouble());
+        if (value.isTrue())
+            return globalData.propertyNames->trueKeyword.ustring();
+        if (value.isFalse())
+            return globalData.propertyNames->falseKeyword.ustring();
+        if (value.isNull())
+            return globalData.propertyNames->nullKeyword.ustring();
+        if (value.isUndefined())
+            return globalData.propertyNames->undefinedKeyword.ustring();
+        return value.toString(exec)->value(exec);
+    }
+
+    ALWAYS_INLINE UString JSValue::toUStringInline(ExecState* exec) const
+    {
+        if (isString())
+            return static_cast<JSString*>(asCell())->value(exec);
+
+        return inlineJSValueNotStringtoUString(*this, exec);
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
index 49d4a6377735ec9a0bb06beb1c2588be2fec973b..1a2b812f0f2ad208576c0c98caa72c6a27a5b2a4 100644 (file)
@@ -29,7 +29,7 @@
 #include "ExceptionHelpers.h"
 #include "JSString.h"
 #include "UStringConcatenate.h"
 #include "ExceptionHelpers.h"
 #include "JSString.h"
 #include "UStringConcatenate.h"
-#include "Vector.h"
+#include <wtf/Vector.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -37,12 +37,21 @@ class JSStringBuilder {
 public:
     JSStringBuilder()
         : m_okay(true)
 public:
     JSStringBuilder()
         : m_okay(true)
+        , m_is8Bit(true)
     {
     }
 
     void append(const UChar u)
     {
     {
     }
 
     void append(const UChar u)
     {
-        m_okay &= buffer.tryAppend(&u, 1);
+        if (m_is8Bit) {
+            if (u < 0xff) {
+                LChar c = u;
+                m_okay &= buffer8.tryAppend(&c, 1);
+                return;
+            }
+            upConvert();
+        }
+        m_okay &= buffer16.tryAppend(&u, 1);
     }
 
     void append(const char* str)
     }
 
     void append(const char* str)
@@ -52,36 +61,87 @@ public:
 
     void append(const char* str, size_t len)
     {
 
     void append(const char* str, size_t len)
     {
-        m_okay &= buffer.tryReserveCapacity(buffer.size() + len);
+        if (m_is8Bit) {
+            m_okay &= buffer8.tryAppend(reinterpret_cast<const LChar*>(str), len);
+            return;
+        }
+        m_okay &= buffer8.tryReserveCapacity(buffer16.size() + len);
         for (size_t i = 0; i < len; i++) {
             UChar u = static_cast<unsigned char>(str[i]);
         for (size_t i = 0; i < len; i++) {
             UChar u = static_cast<unsigned char>(str[i]);
-            m_okay &= buffer.tryAppend(&u, 1);
+            m_okay &= buffer16.tryAppend(&u, 1);
         }
     }
 
         }
     }
 
+    void append(const LChar* str, size_t len)
+    {
+        if (m_is8Bit) {
+            m_okay &= buffer8.tryAppend(str, len);
+            return;
+        }
+        m_okay &= buffer8.tryReserveCapacity(buffer16.size() + len);
+        for (size_t i = 0; i < len; i++) {
+            UChar u = str[i];
+            m_okay &= buffer16.tryAppend(&u, 1);
+        }
+    }
+    
     void append(const UChar* str, size_t len)
     {
     void append(const UChar* str, size_t len)
     {
-        m_okay &= buffer.tryAppend(str, len);
+        if (m_is8Bit)
+            upConvert(); // FIXME: We could check character by character its size.
+        m_okay &= buffer16.tryAppend(str, len);
     }
 
     void append(const UString& str)
     {
     }
 
     void append(const UString& str)
     {
-        m_okay &= buffer.tryAppend(str.characters(), str.length());
+        unsigned length = str.length();
+
+        if (!length)
+            return;
+
+        if (m_is8Bit) {
+            if (str.is8Bit()) {
+                m_okay &= buffer8.tryAppend(str.characters8(), length);
+                return;
+            }
+            upConvert();
+        }
+        m_okay &= buffer16.tryAppend(str.characters(), length);
+    }
+
+    void upConvert()
+    {
+        ASSERT(m_is8Bit);
+        size_t len = buffer8.size();
+
+        for (size_t i = 0; i < len; i++)
+            buffer16.append(buffer8[i]);
+
+        buffer8.clear();
+        m_is8Bit = false;
     }
 
     JSValue build(ExecState* exec)
     {
         if (!m_okay)
             return throwOutOfMemoryError(exec);
     }
 
     JSValue build(ExecState* exec)
     {
         if (!m_okay)
             return throwOutOfMemoryError(exec);
-        buffer.shrinkToFit();
-        if (!buffer.data())
+        if (m_is8Bit) {
+            buffer8.shrinkToFit();
+            if (!buffer8.data())
+                return throwOutOfMemoryError(exec);
+            return jsString(exec, UString::adopt(buffer8));
+        }
+        buffer16.shrinkToFit();
+        if (!buffer16.data())
             return throwOutOfMemoryError(exec);
             return throwOutOfMemoryError(exec);
-        return jsString(exec, UString::adopt(buffer));
+        return jsString(exec, UString::adopt(buffer16));
     }
 
 protected:
     }
 
 protected:
-    Vector<UChar, 64> buffer;
+    Vector<LChar, 64> buffer8;
+    Vector<UChar, 64> buffer16;
     bool m_okay;
     bool m_okay;
+    bool m_is8Bit;
 };
 
 template<typename StringType1, typename StringType2>
 };
 
 template<typename StringType1, typename StringType2>
diff --git a/runtime/JSStringJoiner.cpp b/runtime/JSStringJoiner.cpp
new file mode 100644 (file)
index 0000000..ea26024
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSStringJoiner.h"
+
+#include "ExceptionHelpers.h"
+#include "JSString.h"
+#include "ScopeChain.h"
+#include <wtf/text/StringImpl.h>
+
+
+namespace JSC {
+
+// The destination is 16bits, at least one string is 16 bits.
+static inline void appendStringToData(UChar*& data, const UString& string)
+{
+    if (string.isNull())
+        return;
+
+    unsigned length = string.length();
+    const StringImpl* stringImpl = string.impl();
+
+    if (stringImpl->is8Bit()) {
+        for (unsigned i = 0; i < length; ++i) {
+            *data = stringImpl->characters8()[i];
+            ++data;
+        }
+    } else {
+        for (unsigned i = 0; i < length; ++i) {
+            *data = stringImpl->characters16()[i];
+            ++data;
+        }
+    }
+}
+
+// If the destination is 8bits, we know every string has to be 8bit.
+static inline void appendStringToData(LChar*& data, const UString& string)
+{
+    if (string.isNull())
+        return;
+    ASSERT(string.is8Bit());
+
+    unsigned length = string.length();
+    const StringImpl* stringImpl = string.impl();
+
+    for (unsigned i = 0; i < length; ++i) {
+        *data = stringImpl->characters8()[i];
+        ++data;
+    }
+}
+
+template<typename CharacterType>
+static inline PassRefPtr<StringImpl> joinStrings(const Vector<UString>& strings, const UString& separator, unsigned outputLength)
+{
+    ASSERT(outputLength);
+
+    CharacterType* data;
+    RefPtr<StringImpl> outputStringImpl = StringImpl::tryCreateUninitialized(outputLength, data);
+    if (!outputStringImpl)
+        return PassRefPtr<StringImpl>();
+
+    const UString firstString = strings.first();
+    appendStringToData(data, firstString);
+
+    for (size_t i = 1; i < strings.size(); ++i) {
+        appendStringToData(data, separator);
+        appendStringToData(data, strings[i]);
+    }
+
+    ASSERT(data == (outputStringImpl->getCharacters<CharacterType>() + outputStringImpl->length()));
+    return outputStringImpl.release();
+}
+
+JSValue JSStringJoiner::build(ExecState* exec)
+{
+    if (!m_isValid)
+        return throwOutOfMemoryError(exec);
+
+    if (!m_strings.size())
+        return jsEmptyString(exec);
+
+    size_t separatorLength = m_separator.length();
+    // FIXME: add special cases of joinStrings() for (separatorLength == 0) and (separatorLength == 1).
+    ASSERT(m_strings.size() > 0);
+    size_t totalSeparactorsLength = separatorLength * (m_strings.size() - 1);
+    size_t outputStringSize = totalSeparactorsLength + m_cumulatedStringsLength;
+
+    if (!outputStringSize)
+        return jsEmptyString(exec);
+
+    RefPtr<StringImpl> outputStringImpl;
+    if (m_is8Bits)
+        outputStringImpl = joinStrings<LChar>(m_strings, m_separator, outputStringSize);
+    else
+        outputStringImpl = joinStrings<UChar>(m_strings, m_separator, outputStringSize);
+
+    if (!outputStringImpl)
+        return throwOutOfMemoryError(exec);
+
+    return JSString::create(exec->globalData(), outputStringImpl.release());
+}
+
+}
diff --git a/runtime/JSStringJoiner.h b/runtime/JSStringJoiner.h
new file mode 100644 (file)
index 0000000..49f846c
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSStringJoiner_h
+#define JSStringJoiner_h
+
+#include "JSValue.h"
+#include "UString.h"
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class ExecState;
+
+
+class JSStringJoiner {
+public:
+    JSStringJoiner(const UString& separator, size_t stringCount);
+
+    void append(const UString&);
+    JSValue build(ExecState*);
+
+private:
+    UString m_separator;
+    Vector<UString> m_strings;
+
+    unsigned m_cumulatedStringsLength;
+    bool m_isValid;
+    bool m_is8Bits;
+};
+
+inline JSStringJoiner::JSStringJoiner(const UString& separator, size_t stringCount)
+    : m_separator(separator)
+    , m_cumulatedStringsLength(0)
+    , m_isValid(true)
+    , m_is8Bits(m_separator.is8Bit())
+{
+    ASSERT(!m_separator.isNull());
+    m_isValid = m_strings.tryReserveCapacity(stringCount);
+}
+
+inline void JSStringJoiner::append(const UString& str)
+{
+    if (!m_isValid)
+        return;
+
+    m_strings.uncheckedAppend(str);
+    if (!str.isNull()) {
+        m_cumulatedStringsLength += str.length();
+        m_is8Bits = m_is8Bits && str.is8Bit();
+    }
+}
+
+}
+
+#endif
index dba03f63d148a4dba35d605a43d54fe46ddad01e..880240e609acad086de08778886ac0cd9727886a 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- *  Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2006, 2007, 2008, 2009, 2010, 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
 
 namespace JSC {
 
 
 namespace JSC {
 
-    /**
-     * Primitive types
-     */
-    enum JSType {
-        UnspecifiedType   = 0,
-        UndefinedType     = 1,
-        BooleanType       = 2,
-        NumberType        = 3,
-        NullType          = 4,
-        StringType        = 5,
-        LeafType          = 6,
-        // The CompoundType value must come before any JSType that may have children
-        CompoundType      = 7,
-        ObjectType        = 8,
-        GetterSetterType  = 9
-    };
+enum JSType {
+    UnspecifiedType,
+    UndefinedType,
+    BooleanType,
+    NumberType,
+    NullType,
+    StringType,
+    LeafType,
+
+    // The CompoundType value must come before any JSType that may have children.
+    CompoundType,
+    GetterSetterType,
+    APIValueWrapperType,
+
+    EvalExecutableType,
+    ProgramExecutableType,
+    FunctionExecutableType,
+
+    // The ObjectType value must come before any JSType that is a subclass of JSObject.
+    ObjectType,
+    FinalObjectType,
+    JSFunctionType,
+    NumberObjectType,
+    ErrorInstanceType,
+    GlobalThisType,
+
+    StaticScopeObjectType,
+    // VariableObjectType must be less than MOST of the types of its subclasses and only its subclasses.
+    // We use >=VariableObjectType checks to test for Global & Activation objects, but exclude StaticScopes.
+    VariableObjectType,
+    GlobalObjectType,
+    ActivationObjectType,
+};
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index 1c63a91e7870b02f142b4deca0e657cada284aa5..83a3594db80cdfa3b40ceeeab88b0d3d1b1e9fcd 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    static const unsigned MasqueradesAsUndefined = 1; // WebCore uses MasqueradesAsUndefined to make document.all and style.filter undetectable.
+    class LLIntOffsetsExtractor;
+
+    static const unsigned MasqueradesAsUndefined = 1; // WebCore uses MasqueradesAsUndefined to make document.all undetectable.
     static const unsigned ImplementsHasInstance = 1 << 1;
     static const unsigned OverridesHasInstance = 1 << 2;
     static const unsigned ImplementsDefaultHasInstance = 1 << 3;
     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 IsEnvironmentRecord = 1 << 4;
     static const unsigned OverridesGetOwnPropertySlot = 1 << 5;
     static const unsigned OverridesVisitChildren = 1 << 6;
     static const unsigned OverridesGetPropertyNames = 1 << 7;
     static const unsigned OverridesGetOwnPropertySlot = 1 << 5;
     static const unsigned OverridesVisitChildren = 1 << 6;
     static const unsigned OverridesGetPropertyNames = 1 << 7;
-    static const unsigned IsJSFinalObject = 1 << 8;
-    static const unsigned ProhibitsPropertyCaching = 1 << 9;
+    static const unsigned ProhibitsPropertyCaching = 1 << 8;
 
     class TypeInfo {
     public:
 
     class TypeInfo {
     public:
@@ -55,23 +56,27 @@ namespace JSC {
             ASSERT(flags <= 0x3ff);
             ASSERT(type <= 0xff);
             ASSERT(type >= CompoundType || !(flags & OverridesVisitChildren));
             ASSERT(flags <= 0x3ff);
             ASSERT(type <= 0xff);
             ASSERT(type >= CompoundType || !(flags & OverridesVisitChildren));
+            // No object that doesn't ImplementsHasInstance should override it!
+            ASSERT((m_flags & (ImplementsHasInstance | OverridesHasInstance)) != OverridesHasInstance);
             // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance)
             if ((m_flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
                 m_flags |= ImplementsDefaultHasInstance;
         }
 
             // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance)
             if ((m_flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
                 m_flags |= ImplementsDefaultHasInstance;
         }
 
-        JSType type() const { return (JSType)m_type; }
+        JSType type() const { return static_cast<JSType>(m_type); }
+        bool isObject() const { return type() >= ObjectType; }
+        bool isFinalObject() const { return type() == FinalObjectType; }
+        bool isNumberObject() const { return type() == NumberObjectType; }
 
 
-        bool masqueradesAsUndefined() const { return m_flags & MasqueradesAsUndefined; }
-        bool implementsHasInstance() const { return m_flags & ImplementsHasInstance; }
-        bool overridesHasInstance() const { return m_flags & OverridesHasInstance; }
-        bool needsThisConversion() const { return m_flags & NeedsThisConversion; }
-        bool overridesGetOwnPropertySlot() const { return m_flags & OverridesGetOwnPropertySlot; }
-        bool overridesVisitChildren() const { return m_flags & OverridesVisitChildren; }
-        bool overridesGetPropertyNames() const { return m_flags & OverridesGetPropertyNames; }
-        unsigned isFinal() const { return m_flags2 & (IsJSFinalObject >> 8); }
-        unsigned prohibitsPropertyCaching() const { return m_flags2 & (ProhibitsPropertyCaching >> 8); }
-        unsigned flags() const { return m_flags; }
+        bool masqueradesAsUndefined() const { return isSetOnFlags1(MasqueradesAsUndefined); }
+        bool implementsHasInstance() const { return isSetOnFlags1(ImplementsHasInstance); }
+        bool isEnvironmentRecord() const { return isSetOnFlags1(IsEnvironmentRecord); }
+        bool overridesHasInstance() const { return isSetOnFlags1(OverridesHasInstance); }
+        bool implementsDefaultHasInstance() const { return isSetOnFlags1(ImplementsDefaultHasInstance); }
+        bool overridesGetOwnPropertySlot() const { return isSetOnFlags1(OverridesGetOwnPropertySlot); }
+        bool overridesVisitChildren() const { return isSetOnFlags1(OverridesVisitChildren); }
+        bool overridesGetPropertyNames() const { return isSetOnFlags1(OverridesGetPropertyNames); }
+        bool prohibitsPropertyCaching() const { return isSetOnFlags2(ProhibitsPropertyCaching); }
 
         static ptrdiff_t flagsOffset()
         {
 
         static ptrdiff_t flagsOffset()
         {
@@ -84,6 +89,11 @@ namespace JSC {
         }
 
     private:
         }
 
     private:
+        friend class LLIntOffsetsExtractor;
+        
+        bool isSetOnFlags1(unsigned flag) const { ASSERT(flag <= (1 << 7)); return m_flags & flag; }
+        bool isSetOnFlags2(unsigned flag) const { ASSERT(flag >= (1 << 8)); return m_flags2 & (flag >> 8); }
+
         unsigned char m_type;
         unsigned char m_flags;
         unsigned char m_flags2;
         unsigned char m_type;
         unsigned char m_flags;
         unsigned char m_flags2;
index d3ee89ea86b75d9bb7714110b5084488aa7a060f..088f214b980a27a34f69e895b7f0eb8c03d856d4 100644 (file)
@@ -27,6 +27,7 @@
 #include "BooleanPrototype.h"
 #include "Error.h"
 #include "ExceptionHelpers.h"
 #include "BooleanPrototype.h"
 #include "Error.h"
 #include "ExceptionHelpers.h"
+#include "GetterSetter.h"
 #include "JSGlobalObject.h"
 #include "JSFunction.h"
 #include "JSNotAnObject.h"
 #include "JSGlobalObject.h"
 #include "JSFunction.h"
 #include "JSNotAnObject.h"
@@ -54,6 +55,16 @@ double JSValue::toIntegerPreserveNaN(ExecState* exec) const
     return trunc(toNumber(exec));
 }
 
     return trunc(toNumber(exec));
 }
 
+double JSValue::toNumberSlowCase(ExecState* exec) const
+{
+    ASSERT(!isInt32() && !isDouble());
+    if (isCell())
+        return asCell()->toNumber(exec);
+    if (isTrue())
+        return 1.0;
+    return isUndefined() ? std::numeric_limits<double>::quiet_NaN() : 0; // null and false both convert to 0.
+}
+
 JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const
 {
     ASSERT(!isCell());
 JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const
 {
     ASSERT(!isCell());
@@ -65,7 +76,7 @@ JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObjec
 
     ASSERT(isUndefinedOrNull());
     throwError(exec, createNotAnObjectError(exec, *this));
 
     ASSERT(isUndefinedOrNull());
     throwError(exec, createNotAnObjectError(exec, *this));
-    return new (exec) JSNotAnObject(exec);
+    return JSNotAnObject::create(exec);
 }
 
 JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
 }
 
 JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
@@ -80,45 +91,108 @@ JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
     return exec->globalThisValue();
 }
 
     return exec->globalThisValue();
 }
 
-JSObject* JSValue::synthesizeObject(ExecState* exec) const
+JSObject* JSValue::synthesizePrototype(ExecState* exec) const
 {
 {
-    ASSERT(!isCell());
+    if (isCell()) {
+        ASSERT(isString());
+        return exec->lexicalGlobalObject()->stringPrototype();
+    }
+
     if (isNumber())
     if (isNumber())
-        return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
+        return exec->lexicalGlobalObject()->numberPrototype();
     if (isBoolean())
     if (isBoolean())
-        return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
+        return exec->lexicalGlobalObject()->booleanPrototype();
 
     ASSERT(isUndefinedOrNull());
     throwError(exec, createNotAnObjectError(exec, *this));
 
     ASSERT(isUndefinedOrNull());
     throwError(exec, createNotAnObjectError(exec, *this));
-    return new (exec) JSNotAnObject(exec);
+    return JSNotAnObject::create(exec);
 }
 
 }
 
-JSObject* JSValue::synthesizePrototype(ExecState* exec) const
+// ECMA 8.7.2
+void JSValue::putToPrimitive(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
-    ASSERT(!isCell());
-    if (isNumber())
-        return exec->lexicalGlobalObject()->numberPrototype();
-    if (isBoolean())
-        return exec->lexicalGlobalObject()->booleanPrototype();
+    JSGlobalData& globalData = exec->globalData();
 
 
-    ASSERT(isUndefinedOrNull());
-    throwError(exec, createNotAnObjectError(exec, *this));
-    return new (exec) JSNotAnObject(exec);
+    // Check if there are any setters or getters in the prototype chain
+    JSObject* obj = synthesizePrototype(exec);
+    JSValue prototype;
+    if (propertyName != exec->propertyNames().underscoreProto) {
+        for (; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {
+            prototype = obj->prototype();
+            if (prototype.isNull()) {
+                if (slot.isStrictMode())
+                    throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+                return;
+            }
+        }
+    }
+
+    for (; ; obj = asObject(prototype)) {
+        unsigned attributes;
+        JSCell* specificValue;
+        size_t offset = obj->structure()->get(globalData, propertyName, attributes, specificValue);
+        if (offset != WTF::notFound) {
+            if (attributes & ReadOnly) {
+                if (slot.isStrictMode())
+                    throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
+                return;
+            }
+
+            JSValue gs = obj->getDirectOffset(offset);
+            if (gs.isGetterSetter()) {
+                JSObject* setterFunc = asGetterSetter(gs)->setter();        
+                if (!setterFunc) {
+                    if (slot.isStrictMode())
+                        throwError(exec, createTypeError(exec, "setting a property that has only a getter"));
+                    return;
+                }
+                
+                CallData callData;
+                CallType callType = setterFunc->methodTable()->getCallData(setterFunc, callData);
+                MarkedArgumentBuffer args;
+                args.append(value);
+
+                // If this is WebCore's global object then we need to substitute the shell.
+                call(exec, setterFunc, callType, callData, *this, args);
+                return;
+            }
+
+            // If there's an existing property on the object or one of its 
+            // prototypes it should be replaced, so break here.
+            break;
+        }
+
+        prototype = obj->prototype();
+        if (prototype.isNull())
+            break;
+    }
+    
+    if (slot.isStrictMode())
+        throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+    return;
 }
 
 }
 
-#ifndef NDEBUG
 char* JSValue::description()
 {
 char* JSValue::description()
 {
-    static const size_t size = 32;
+    static const size_t size = 128;
     static char description[size];
 
     if (!*this)
         snprintf(description, size, "<JSValue()>");
     else if (isInt32())
         snprintf(description, size, "Int32: %d", asInt32());
     static char description[size];
 
     if (!*this)
         snprintf(description, size, "<JSValue()>");
     else if (isInt32())
         snprintf(description, size, "Int32: %d", asInt32());
-    else if (isDouble())
-        snprintf(description, size, "Double: %lf", asDouble());
-    else if (isCell())
+    else if (isDouble()) {
+#if USE(JSVALUE64)
+        snprintf(description, size, "Double: %lx, %lf", reinterpretDoubleToIntptr(asDouble()), asDouble());
+#else
+        union {
+            double asDouble;
+            uint32_t asTwoInt32s[2];
+        } u;
+        u.asDouble = asDouble();
+        snprintf(description, size, "Double: %08x:%08x, %lf", u.asTwoInt32s[1], u.asTwoInt32s[0], asDouble());
+#endif
+    } else if (isCell())
         snprintf(description, size, "Cell: %p", asCell());
     else if (isTrue())
         snprintf(description, size, "True");
         snprintf(description, size, "Cell: %p", asCell());
     else if (isTrue())
         snprintf(description, size, "True");
@@ -133,7 +207,6 @@ char* JSValue::description()
 
     return description;
 }
 
     return description;
 }
-#endif
 
 // 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
 
 // 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
@@ -180,18 +253,39 @@ int32_t toInt32(double number)
     return bits < 0 ? -result : result;
 }
 
     return bits < 0 ? -result : result;
 }
 
-NEVER_INLINE double nonInlineNaN()
+bool JSValue::isValidCallee()
 {
 {
-#if OS(SYMBIAN)
-    return nanval();
-#else
-    return std::numeric_limits<double>::quiet_NaN();
-#endif
+    return asObject(asCell())->globalObject();
 }
 
 }
 
-bool JSValue::isValidCallee()
+JSString* JSValue::toStringSlowCase(ExecState* exec) const
+{
+    JSGlobalData& globalData = exec->globalData();
+    ASSERT(!isString());
+    if (isInt32())
+        return jsString(&globalData, globalData.numericStrings.add(asInt32()));
+    if (isDouble())
+        return jsString(&globalData, globalData.numericStrings.add(asDouble()));
+    if (isTrue())
+        return globalData.smallStrings.trueString(&globalData);
+    if (isFalse())
+        return globalData.smallStrings.falseString(&globalData);
+    if (isNull())
+        return globalData.smallStrings.nullString(&globalData);
+    if (isUndefined())
+        return globalData.smallStrings.undefinedString(&globalData);
+
+    ASSERT(isCell());
+    JSValue value = asCell()->toPrimitive(exec, PreferString);
+    if (exec->hadException())
+        return jsEmptyString(exec);
+    ASSERT(!value.isObject());
+    return value.toString(exec);
+}
+
+UString JSValue::toUStringSlowCase(ExecState* exec) const
 {
 {
-    return asObject(asObject(asCell())->getAnonymousValue(0))->isGlobalObject();
+    return inlineJSValueNotStringtoUString(*this, exec);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index ce3b3d3dd1d750f823c702a63489dfe4b75061d6..7facb935390a6039cbf74e123003e62c4acb8500 100644 (file)
 #include <stdint.h>
 #include <wtf/AlwaysInline.h>
 #include <wtf/Assertions.h>
 #include <stdint.h>
 #include <wtf/AlwaysInline.h>
 #include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
 #include <wtf/HashTraits.h>
 #include <wtf/MathExtras.h>
 #include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
 #include <wtf/HashTraits.h>
 #include <wtf/MathExtras.h>
 #include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
-    extern const double NaN;
-    extern const double Inf;
-
     class ExecState;
     class Identifier;
     class JSCell;
     class ExecState;
     class Identifier;
     class JSCell;
@@ -47,9 +45,23 @@ namespace JSC {
     class PropertySlot;
     class PutPropertySlot;
     class UString;
     class PropertySlot;
     class PutPropertySlot;
     class UString;
+#if ENABLE(DFG_JIT)
+    namespace DFG {
+        class AssemblyHelpers;
+        class JITCompiler;
+        class JITCodeGenerator;
+        class JSValueSource;
+        class OSRExitCompiler;
+        class SpeculativeJIT;
+    }
+#endif
+    namespace LLInt {
+        class Data;
+    }
 
     struct ClassInfo;
     struct Instruction;
 
     struct ClassInfo;
     struct Instruction;
+    struct MethodTable;
 
     template <class T> class WriteBarrierBase;
 
 
     template <class T> class WriteBarrierBase;
 
@@ -83,10 +95,8 @@ namespace JSC {
 #endif
     };
 
 #endif
     };
 
-    double nonInlineNaN();
-
     // This implements ToInt32, defined in ECMA-262 9.5.
     // This implements ToInt32, defined in ECMA-262 9.5.
-    int32_t toInt32(double);
+    JS_EXPORT_PRIVATE int32_t toInt32(double);
 
     // This implements ToUInt32, defined in ECMA-262 9.6.
     inline uint32_t toUInt32(double number)
 
     // This implements ToUInt32, defined in ECMA-262 9.6.
     inline uint32_t toUInt32(double number)
@@ -103,6 +113,15 @@ namespace JSC {
         friend class JITStubCall;
         friend class JSInterfaceJIT;
         friend class SpecializedThunkJIT;
         friend class JITStubCall;
         friend class JSInterfaceJIT;
         friend class SpecializedThunkJIT;
+#if ENABLE(DFG_JIT)
+        friend class DFG::AssemblyHelpers;
+        friend class DFG::JITCompiler;
+        friend class DFG::JITCodeGenerator;
+        friend class DFG::JSValueSource;
+        friend class DFG::OSRExitCompiler;
+        friend class DFG::SpeculativeJIT;
+#endif
+        friend class LLInt::Data;
 
     public:
         static EncodedJSValue encode(JSValue);
 
     public:
         static EncodedJSValue encode(JSValue);
@@ -149,23 +168,24 @@ namespace JSC {
         int32_t asInt32() const;
         uint32_t asUInt32() const;
         double asDouble() const;
         int32_t asInt32() const;
         uint32_t asUInt32() const;
         double asDouble() const;
+        bool asBoolean() const;
+        double asNumber() const;
 
         // Querying the type.
 
         // Querying the type.
+        bool isEmpty() const;
+        bool isFunction() const;
         bool isUndefined() const;
         bool isNull() const;
         bool isUndefinedOrNull() const;
         bool isBoolean() const;
         bool isNumber() const;
         bool isString() const;
         bool isUndefined() const;
         bool isNull() const;
         bool isUndefinedOrNull() const;
         bool isBoolean() const;
         bool isNumber() const;
         bool isString() const;
+        bool isPrimitive() const;
         bool isGetterSetter() const;
         bool isObject() const;
         bool inherits(const ClassInfo*) const;
         
         // Extracting the value.
         bool isGetterSetter() const;
         bool isObject() const;
         bool inherits(const ClassInfo*) const;
         
         // Extracting the value.
-        bool getBoolean(bool&) const;
-        bool getBoolean() const; // false if not a boolean
-        bool getNumber(double&) const;
-        double uncheckedGetNumber() const;
         bool getString(ExecState* exec, UString&) const;
         UString getString(ExecState* exec) const; // null string if not a string
         JSObject* getObject() const; // 0 if not an object
         bool getString(ExecState* exec, UString&) const;
         UString getString(ExecState* exec) const; // null string if not a string
         JSObject* getObject() const; // 0 if not an object
@@ -182,22 +202,18 @@ namespace JSC {
         // toNumber conversion is expected to be side effect free if an exception has
         // been set in the ExecState already.
         double toNumber(ExecState*) const;
         // toNumber conversion is expected to be side effect free if an exception has
         // been set in the ExecState already.
         double toNumber(ExecState*) const;
-        JSValue toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number.
-        UString toString(ExecState*) const;
-        UString toPrimitiveString(ExecState*) const;
+        JSString* toString(ExecState*) const;
+        UString toUString(ExecState*) const;
+        UString toUStringInline(ExecState*) const;
         JSObject* toObject(ExecState*) const;
         JSObject* toObject(ExecState*, JSGlobalObject*) const;
 
         // Integer conversions.
         JSObject* toObject(ExecState*) const;
         JSObject* toObject(ExecState*, JSGlobalObject*) const;
 
         // Integer conversions.
-        double toInteger(ExecState*) const;
+        JS_EXPORT_PRIVATE double toInteger(ExecState*) const;
         double toIntegerPreserveNaN(ExecState*) const;
         int32_t toInt32(ExecState*) const;
         uint32_t toUInt32(ExecState*) const;
 
         double toIntegerPreserveNaN(ExecState*) const;
         int32_t toInt32(ExecState*) const;
         uint32_t toUInt32(ExecState*) const;
 
-#if ENABLE(JSC_ZOMBIES)
-        bool isZombie() const;
-#endif
-
         // Floating point conversions (this is a convenience method for webcore;
         // signle precision float is not a representation used in JS or JSC).
         float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
         // Floating point conversions (this is a convenience method for webcore;
         // signle precision float is not a representation used in JS or JSC).
         float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
@@ -208,14 +224,10 @@ namespace JSC {
         JSValue get(ExecState*, unsigned propertyName) const;
         JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
         void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         JSValue get(ExecState*, unsigned propertyName) const;
         JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
         void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
-        void putDirect(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
-        void put(ExecState*, unsigned propertyName, JSValue);
+        void putToPrimitive(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+        void putByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
 
 
-        bool needsThisConversion() const;
         JSObject* toThisObject(ExecState*) const;
         JSObject* toThisObject(ExecState*) const;
-        JSValue toStrictThisObject(ExecState*) const;
-        UString toThisString(ExecState*) const;
-        JSString* toThisJSString(ExecState*) const;
 
         static bool equal(ExecState* exec, JSValue v1, JSValue v2);
         static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
 
         static bool equal(ExecState* exec, JSValue v1, JSValue v2);
         static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
@@ -224,15 +236,13 @@ namespace JSC {
         static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2);
         static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
 
         static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2);
         static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
 
-        JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object
-
         bool isCell() const;
         JSCell* asCell() const;
         bool isCell() const;
         JSCell* asCell() const;
-        bool isValidCallee();
+        JS_EXPORT_PRIVATE bool isValidCallee();
 
 
-#ifndef NDEBUG
         char* description();
         char* description();
-#endif
+
+        JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const;
 
     private:
         template <class T> JSValue(WriteBarrierBase<T>);
 
     private:
         template <class T> JSValue(WriteBarrierBase<T>);
@@ -241,11 +251,11 @@ namespace JSC {
         JSValue(HashTableDeletedValueTag);
 
         inline const JSValue asValue() const { return *this; }
         JSValue(HashTableDeletedValueTag);
 
         inline const JSValue asValue() const { return *this; }
-        JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
-        JSObject* toThisObjectSlowCase(ExecState*) const;
-
-        JSObject* synthesizePrototype(ExecState*) const;
-        JSObject* synthesizeObject(ExecState*) const;
+        JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const;
+        JS_EXPORT_PRIVATE JSString* toStringSlowCase(ExecState*) const;
+        JS_EXPORT_PRIVATE UString toUStringSlowCase(ExecState*) const;
+        JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
+        JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;
 
 #if USE(JSVALUE32_64)
         /*
 
 #if USE(JSVALUE32_64)
         /*
@@ -382,6 +392,8 @@ namespace JSC {
     };
 #endif
 
     };
 #endif
 
+    typedef HashMap<EncodedJSValue, unsigned, EncodedJSValueHash, EncodedJSValueHashTraits> JSValueMap;
+
     // Stand-alone helper functions.
     inline JSValue jsNull()
     {
     // Stand-alone helper functions.
     inline JSValue jsNull()
     {
@@ -466,8 +478,6 @@ 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; }
 
-    bool isZombie(const JSCell*);
-
 } // namespace JSC
 
 #endif // JSValue_h
 } // namespace JSC
 
 #endif // JSValue_h
index b4f6f80a502917c5001b6fb18737e416ef55570d..1373558f7af9b7216be2d056bfc9c2564b2f61df 100644 (file)
@@ -54,47 +54,15 @@ namespace JSC {
         return asInt32();
     }
 
         return asInt32();
     }
 
-    inline double JSValue::uncheckedGetNumber() const
+    inline double JSValue::asNumber() const
     {
         ASSERT(isNumber());
         return isInt32() ? asInt32() : asDouble();
     }
 
     {
         ASSERT(isNumber());
         return isInt32() ? asInt32() : asDouble();
     }
 
-    ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
-    {
-        return isNumber() ? asValue() : jsNumber(this->toNumber(exec));
-    }
-
     inline JSValue jsNaN()
     {
     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;
+        return JSValue(std::numeric_limits<double>::quiet_NaN());
     }
 
     inline JSValue::JSValue(char i)
     }
 
     inline JSValue::JSValue(char i)
@@ -228,9 +196,6 @@ namespace JSC {
         else
             u.asBits.tag = EmptyValueTag;
         u.asBits.payload = reinterpret_cast<int32_t>(ptr);
         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)
     }
 
     inline JSValue::JSValue(const JSCell* ptr)
@@ -240,9 +205,6 @@ namespace JSC {
         else
             u.asBits.tag = EmptyValueTag;
         u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
         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
     }
 
     inline JSValue::operator bool() const
@@ -261,6 +223,11 @@ namespace JSC {
         return u.asInt64 != other.u.asInt64;
     }
 
         return u.asInt64 != other.u.asInt64;
     }
 
+    inline bool JSValue::isEmpty() const
+    {
+        return tag() == EmptyValueTag;
+    }
+
     inline bool JSValue::isUndefined() const
     {
         return tag() == UndefinedTag;
     inline bool JSValue::isUndefined() const
     {
         return tag() == UndefinedTag;
@@ -350,7 +317,7 @@ namespace JSC {
         return isTrue() || isFalse();
     }
 
         return isTrue() || isFalse();
     }
 
-    inline bool JSValue::getBoolean() const
+    inline bool JSValue::asBoolean() const
     {
         ASSERT(isBoolean());
         return payload();
     {
         ASSERT(isBoolean());
         return payload();
@@ -384,17 +351,11 @@ namespace JSC {
     inline JSValue::JSValue(JSCell* ptr)
     {
         u.ptr = ptr;
     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);
     }
 
     inline JSValue::JSValue(const JSCell* ptr)
     {
         u.ptr = const_cast<JSCell*>(ptr);
-#if ENABLE(JSC_ZOMBIES)
-        ASSERT(!isZombie());
-#endif
     }
 
     inline JSValue::operator bool() const
     }
 
     inline JSValue::operator bool() const
@@ -412,14 +373,19 @@ namespace JSC {
         return u.ptr != other.u.ptr;
     }
 
         return u.ptr != other.u.ptr;
     }
 
+    inline bool JSValue::isEmpty() const
+    {
+        return u.asInt64 == ValueEmpty;
+    }
+
     inline bool JSValue::isUndefined() const
     {
     inline bool JSValue::isUndefined() const
     {
-        return asValue() == jsUndefined();
+        return asValue() == JSValue(JSUndefined);
     }
 
     inline bool JSValue::isNull() const
     {
     }
 
     inline bool JSValue::isNull() const
     {
-        return asValue() == jsNull();
+        return asValue() == JSValue(JSNull);
     }
 
     inline bool JSValue::isTrue() const
     }
 
     inline bool JSValue::isTrue() const
@@ -432,10 +398,10 @@ namespace JSC {
         return asValue() == JSValue(JSFalse);
     }
 
         return asValue() == JSValue(JSFalse);
     }
 
-    inline bool JSValue::getBoolean() const
+    inline bool JSValue::asBoolean() const
     {
     {
-        ASSERT(asValue() == jsBoolean(true) || asValue() == jsBoolean(false));
-        return asValue() == jsBoolean(true);
+        ASSERT(isBoolean());
+        return asValue() == JSValue(JSTrue);
     }
 
     inline int32_t JSValue::asInt32() const
     }
 
     inline int32_t JSValue::asInt32() const
@@ -511,6 +477,7 @@ namespace JSC {
 
     inline double JSValue::asDouble() const
     {
 
     inline double JSValue::asDouble() const
     {
+        ASSERT(isDouble());
         return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset);
     }
 
         return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset);
     }
 
index abe9bbbc2f5d62953fe59c417b36c729eaa82a30..8ca6950745119c0496f7d6e01dc1cec8f2894d98 100644 (file)
 #include "config.h"
 #include "JSVariableObject.h"
 
 #include "config.h"
 #include "JSVariableObject.h"
 
+#include "JSActivation.h"
+#include "JSGlobalObject.h"
+#include "JSStaticScopeObject.h"
 #include "PropertyNameArray.h"
 #include "PropertyDescriptor.h"
 
 namespace JSC {
 
 #include "PropertyNameArray.h"
 #include "PropertyDescriptor.h"
 
 namespace JSC {
 
-bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
+void JSVariableObject::destroy(JSCell* cell)
 {
 {
-    if (symbolTable().contains(propertyName.impl()))
+    jsCast<JSVariableObject*>(cell)->JSVariableObject::~JSVariableObject();
+}
+
+bool JSVariableObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
+{
+    JSVariableObject* thisObject = jsCast<JSVariableObject*>(cell);
+    if (thisObject->symbolTable().contains(propertyName.impl()))
         return false;
 
         return false;
 
-    return JSObject::deleteProperty(exec, propertyName);
+    return JSObject::deleteProperty(thisObject, exec, propertyName);
 }
 
 }
 
-void JSVariableObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void JSVariableObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
-    SymbolTable::const_iterator end = symbolTable().end();
-    for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
+    JSVariableObject* thisObject = jsCast<JSVariableObject*>(object);
+    SymbolTable::const_iterator end = thisObject->symbolTable().end();
+    for (SymbolTable::const_iterator it = thisObject->symbolTable().begin(); it != end; ++it) {
         if (!(it->second.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties))
             propertyNames.add(Identifier(exec, it->first.get()));
     }
     
         if (!(it->second.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties))
             propertyNames.add(Identifier(exec, it->first.get()));
     }
     
-    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
-}
-
-bool JSVariableObject::isVariableObject() const
-{
-    return true;
+    JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
 }
 
 bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDescriptor& descriptor)
 }
 
 bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDescriptor& descriptor)
@@ -68,4 +73,26 @@ bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDe
     return false;
 }
 
     return false;
 }
 
+void JSVariableObject::putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned)
+{
+    ASSERT_NOT_REACHED();
+}
+
+bool JSVariableObject::isDynamicScope(bool& requiresDynamicChecks) const
+{
+    switch (structure()->typeInfo().type()) {
+    case GlobalObjectType:
+        return static_cast<const JSGlobalObject*>(this)->isDynamicScope(requiresDynamicChecks);
+    case ActivationObjectType:
+        return static_cast<const JSActivation*>(this)->isDynamicScope(requiresDynamicChecks);
+    case StaticScopeObjectType:
+        return static_cast<const JSStaticScopeObject*>(this)->isDynamicScope(requiresDynamicChecks);
+    default:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+
+    return false;
+}
+
 } // namespace JSC
 } // namespace JSC
index 89bb6b02b67d99ac2dc3d45cf538379fcdfcf4b5..bcfe4ab895f60a9928c4219a4b41d36e173c4cad 100644 (file)
 #include "JSObject.h"
 #include "Register.h"
 #include "SymbolTable.h"
 #include "JSObject.h"
 #include "Register.h"
 #include "SymbolTable.h"
-#include "UnusedParam.h"
+#include <wtf/UnusedParam.h>
 #include <wtf/OwnArrayPtr.h>
 #include <wtf/UnusedParam.h>
 
 namespace JSC {
 
 #include <wtf/OwnArrayPtr.h>
 #include <wtf/UnusedParam.h>
 
 namespace JSC {
 
+    class LLIntOffsetsExtractor;
     class Register;
 
     class JSVariableObject : public JSNonFinalObject {
         friend class JIT;
     class Register;
 
     class JSVariableObject : public JSNonFinalObject {
         friend class JIT;
+        friend class LLIntOffsetsExtractor;
 
     public:
 
     public:
+        typedef JSNonFinalObject Base;
+
         SymbolTable& symbolTable() const { return *m_symbolTable; }
 
         SymbolTable& symbolTable() const { return *m_symbolTable; }
 
-        virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0;
+        JS_EXPORT_PRIVATE static void destroy(JSCell*);
 
 
-        virtual bool deleteProperty(ExecState*, const Identifier&);
-        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+        static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
+
+        JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier&);
+        JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
         
         
-        virtual bool isVariableObject() const;
-        virtual bool isDynamicScope(bool& requiresDynamicChecks) const = 0;
+        bool isDynamicScope(bool& requiresDynamicChecks) const;
 
         WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; }
 
         WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; }
 
         WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; }
 
         WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; }
+        static size_t offsetOfRegisters() { return OBJECT_OFFSETOF(JSVariableObject, m_registers); }
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(VariableObjectType, StructureFlags), &s_info);
         }
         
     protected:
         }
         
     protected:
-        static const unsigned StructureFlags = OverridesGetPropertyNames | JSObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesGetPropertyNames | JSNonFinalObject::StructureFlags;
 
         JSVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable, Register* registers)
             : JSNonFinalObject(globalData, structure)
             , m_symbolTable(symbolTable)
             , m_registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers))
         {
 
         JSVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable, Register* registers)
             : JSNonFinalObject(globalData, structure)
             , m_symbolTable(symbolTable)
             , m_registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers))
         {
+        }
+
+        void finishCreation(JSGlobalData& globalData)
+        {
+            Base::finishCreation(globalData);
             ASSERT(m_symbolTable);
             COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier);
         }
             ASSERT(m_symbolTable);
             COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier);
         }
@@ -79,9 +90,9 @@ namespace JSC {
         void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray);
 
         bool symbolTableGet(const Identifier&, PropertySlot&);
         void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray);
 
         bool symbolTableGet(const Identifier&, PropertySlot&);
-        bool symbolTableGet(const Identifier&, PropertyDescriptor&);
+        JS_EXPORT_PRIVATE bool symbolTableGet(const Identifier&, PropertyDescriptor&);
         bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
         bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
-        bool symbolTablePut(JSGlobalData&, const Identifier&, JSValue);
+        bool symbolTablePut(ExecState*, const Identifier&, JSValue, bool shouldThrow);
         bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes);
 
         SymbolTable* m_symbolTable; // Maps name -> offset from "r" in register file.
         bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes);
 
         SymbolTable* m_symbolTable; // Maps name -> offset from "r" in register file.
@@ -110,15 +121,19 @@ namespace JSC {
         return false;
     }
 
         return false;
     }
 
-    inline bool JSVariableObject::symbolTablePut(JSGlobalData& globalData, const Identifier& propertyName, JSValue value)
+    inline bool JSVariableObject::symbolTablePut(ExecState* exec, const Identifier& propertyName, JSValue value, bool shouldThrow)
     {
     {
+        JSGlobalData& globalData = exec->globalData();
         ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
         SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
         if (entry.isNull())
             return false;
         ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
         SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
         if (entry.isNull())
             return false;
-        if (entry.isReadOnly())
+        if (entry.isReadOnly()) {
+            if (shouldThrow)
+                throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
             return true;
             return true;
+        }
         registerAt(entry.getIndex()).set(globalData, this, value);
         return true;
     }
         registerAt(entry.getIndex()).set(globalData, this, value);
         return true;
     }
index 8d6387ec0ab20adf7afa53e1f10fdad0430f01e2..f8f5727d82cd67696226818eee790d9cd42d12aa 100644 (file)
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSWrapperObject);
 
 
-void JSWrapperObject::visitChildren(SlotVisitor& visitor) 
+void JSWrapperObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    JSWrapperObject* thisObject = jsCast<JSWrapperObject*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
-    JSObject::visitChildren(visitor);
-    if (m_internalValue)
-        visitor.append(&m_internalValue);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    JSObject::visitChildren(thisObject, visitor);
+    if (thisObject->m_internalValue)
+        visitor.append(&thisObject->m_internalValue);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 89726486584f40753525a5d9a8201480c73d01f3..65b4bdb7f61e00011152e1a0d5ace1eab777d97a 100644 (file)
@@ -29,24 +29,24 @@ namespace JSC {
     // This class is used as a base for classes such as String,
     // Number, Boolean and Date which are wrappers for primitive types.
     class JSWrapperObject : public JSNonFinalObject {
     // 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 JSNonFinalObject {
-    protected:
-        explicit JSWrapperObject(JSGlobalData&, Structure*);
-
     public:
     public:
+        typedef JSNonFinalObject Base;
+
         JSValue internalValue() const;
         void setInternalValue(JSGlobalData&, JSValue);
 
         JSValue internalValue() const;
         void setInternalValue(JSGlobalData&, JSValue);
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) 
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 
         { 
         { 
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
+        explicit JSWrapperObject(JSGlobalData&, Structure*);
         static const unsigned StructureFlags = OverridesVisitChildren | JSNonFinalObject::StructureFlags;
 
         static const unsigned StructureFlags = OverridesVisitChildren | JSNonFinalObject::StructureFlags;
 
+        static void visitChildren(JSCell*, SlotVisitor&);
+
     private:
     private:
-        virtual void visitChildren(SlotVisitor&);
-        
         WriteBarrier<Unknown> m_internalValue;
     };
 
         WriteBarrier<Unknown> m_internalValue;
     };
 
diff --git a/runtime/JSZombie.cpp b/runtime/JSZombie.cpp
deleted file mode 100644 (file)
index efabc93..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 "JSZombie.h"
-#include "ClassInfo.h"
-#include "JSObject.h"
-#include "ScopeChain.h"
-
-#if ENABLE(JSC_ZOMBIES)
-
-namespace JSC {
-
-const ClassInfo JSZombie::s_info = { "Zombie", 0, 0, 0 };
-
-}
-
-#endif // ENABLE(JSC_ZOMBIES)
diff --git a/runtime/JSZombie.h b/runtime/JSZombie.h
deleted file mode 100644 (file)
index 795036e..0000000
+++ /dev/null
@@ -1,84 +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 JSZombie_h
-#define JSZombie_h
-
-#include "JSCell.h"
-#include "Structure.h"
-
-#if ENABLE(JSC_ZOMBIES)
-namespace JSC {
-
-class JSZombie : public JSCell {
-public:
-    JSZombie(JSGlobalData& globalData, const ClassInfo* oldInfo, Structure* structure)
-        : JSCell(globalData, structure)
-        , m_oldInfo(oldInfo)
-    {
-        ASSERT(inherits(&s_info));
-    }
-
-    virtual bool isZombie() const { return true; }
-
-    virtual bool isGetterSetter() const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool isAPIValueWrapper() const { ASSERT_NOT_REACHED(); return false; }
-    virtual bool isPropertyNameIterator() const { ASSERT_NOT_REACHED(); return false; }
-    virtual CallType getCallData(CallData&) { ASSERT_NOT_REACHED(); return CallTypeNone; }
-    virtual ConstructType getConstructData(ConstructData&) { ASSERT_NOT_REACHED(); return ConstructTypeNone; }
-    virtual bool getUInt32(uint32_t&) const { ASSERT_NOT_REACHED(); return false; }
-    virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const { ASSERT_NOT_REACHED(); return jsNull(); }
-    virtual bool getPrimitiveNumber(ExecState*, double&, JSValue&) { ASSERT_NOT_REACHED(); return false; }
-    virtual bool toBoolean(ExecState*) const { ASSERT_NOT_REACHED(); return false; }
-    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 visitChildren(SlotVisitor&) { ASSERT_NOT_REACHED(); }
-    virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&) { ASSERT_NOT_REACHED(); }
-    virtual void put(ExecState*, unsigned, JSValue) { ASSERT_NOT_REACHED(); }
-    virtual bool deleteProperty(ExecState*, const Identifier&) { ASSERT_NOT_REACHED(); return false; }
-    virtual bool deleteProperty(ExecState*, unsigned) { ASSERT_NOT_REACHED(); return false; }
-    virtual JSObject* toThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return 0; }
-    virtual JSValue toStrictThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return JSValue(); }
-    virtual JSValue getJSNumber() { ASSERT_NOT_REACHED(); return jsNull(); }
-    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&) { ASSERT_NOT_REACHED(); return false; }
-    virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&) { ASSERT_NOT_REACHED(); return false; }
-    
-    static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
-    {
-        return Structure::create(globalData, prototype, TypeInfo(LeafType, 0), AnonymousSlotCount, &s_info);
-    }
-
-    static const ClassInfo s_info;
-
-private:
-    const ClassInfo* m_oldInfo;
-};
-
-}
-
-#endif // ENABLE(JSC_ZOMBIES)
-
-#endif // JSZombie_h
index ed42d0d2fd960f9ec0b26c59519437db1dfc9927..e1f85cefe6ea4e44e40c83ef6ff7c7650efe604a 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Apple Inc. All rights reserved.
 /*
  * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Mathias Bynens (mathias@qiwi.be)
  *
  * 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 "JSArray.h"
 #include "JSString.h"
 #include "Lexer.h"
 #include "JSArray.h"
 #include "JSString.h"
 #include "Lexer.h"
+#include "StrongInlines.h"
 #include "UStringBuilder.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/dtoa.h>
 
 namespace JSC {
 
 #include "UStringBuilder.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/dtoa.h>
 
 namespace JSC {
 
-static inline bool isJSONWhiteSpace(const UChar& c)
+template <typename CharType>
+static inline bool isJSONWhiteSpace(const CharType& c)
 {
     // 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;
 }
 
 {
     // 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)
+template <typename CharType>
+bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSourceInfo)
 {
     if (m_lexer.next() != TokIdentifier)
         return false;
     do {
         Vector<JSONPPathEntry> path;
         // Unguarded next to start off the lexer
 {
     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);
+        Identifier name = Identifier(&m_exec->globalData(), 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;
         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);
+            entry.m_pathEntryName = Identifier(&m_exec->globalData(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
             path.append(entry);
         } else {
             entry.m_type = JSONPPathEntryTypeDot;
             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);
+            entry.m_pathEntryName = Identifier(&m_exec->globalData(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
             path.append(entry);
         }
             path.append(entry);
         }
-        if (m_exec->globalData().lexer->isKeyword(entry.m_pathEntryName))
+        if (m_exec->globalData().keywords->isKeyword(entry.m_pathEntryName))
             return false;
         TokenType tokenType = m_lexer.next();
         while (tokenType != TokAssign) {
             return false;
         TokenType tokenType = m_lexer.next();
         while (tokenType != TokAssign) {
@@ -84,7 +88,7 @@ bool LiteralParser::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSour
                 entry.m_type = JSONPPathEntryTypeDot;
                 if (m_lexer.next() != TokIdentifier)
                     return false;
                 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);
+                entry.m_pathEntryName = Identifier(&m_exec->globalData(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
                 break;
             }
             case TokLParen: {
                 break;
             }
             case TokLParen: {
@@ -119,7 +123,8 @@ bool LiteralParser::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSour
     return m_lexer.currentToken().type == TokEnd;
 }
     
     return m_lexer.currentToken().type == TokEnd;
 }
     
-ALWAYS_INLINE const Identifier LiteralParser::makeIdentifier(const UChar* characters, size_t length)
+template <typename CharType>
+ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const LChar* characters, size_t length)
 {
     if (!length)
         return m_exec->globalData().propertyNames->emptyIdentifier;
 {
     if (!length)
         return m_exec->globalData().propertyNames->emptyIdentifier;
@@ -138,7 +143,28 @@ ALWAYS_INLINE const Identifier LiteralParser::makeIdentifier(const UChar* charac
     return m_recentIdentifiers[characters[0]];
 }
 
     return m_recentIdentifiers[characters[0]];
 }
 
-template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
+template <typename CharType>
+ALWAYS_INLINE const Identifier LiteralParser<CharType>::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 <typename CharType>
+template <ParserMode mode> TokenType LiteralParser<CharType>::Lexer::lex(LiteralParserToken<CharType>& token)
 {
     while (m_ptr < m_end && isJSONWhiteSpace(*m_ptr))
         ++m_ptr;
 {
     while (m_ptr < m_end && isJSONWhiteSpace(*m_ptr))
         ++m_ptr;
@@ -239,25 +265,48 @@ template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser
             token.end = ++m_ptr;
             return TokAssign;
         }
             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 (isASCIIAlpha(*m_ptr) || *m_ptr == '_' || *m_ptr == '$')
+            return lexIdentifier(token);
         if (*m_ptr == '\'') {
         if (*m_ptr == '\'') {
-            if (mode == StrictJSON)
+            if (mode == StrictJSON) {
+                m_lexErrorMessage = "Single quotes (\') are not allowed in JSON";
                 return TokError;
                 return TokError;
+            }
             return lexString<mode, '\''>(token);
         }
     }
             return lexString<mode, '\''>(token);
         }
     }
+    m_lexErrorMessage = String::format("Unrecognized token '%c'", *m_ptr).impl();
     return TokError;
 }
 
     return TokError;
 }
 
-LiteralParser::TokenType LiteralParser::Lexer::next()
+template <>
+ALWAYS_INLINE TokenType LiteralParser<LChar>::Lexer::lexIdentifier(LiteralParserToken<LChar>& token)
+{
+    while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$'))
+        m_ptr++;
+    token.stringIs8Bit = 1;
+    token.stringToken8 = token.start;
+    token.stringLength = m_ptr - token.start;
+    token.type = TokIdentifier;
+    token.end = m_ptr;
+    return TokIdentifier;
+}
+
+template <>
+ALWAYS_INLINE TokenType LiteralParser<UChar>::Lexer::lexIdentifier(LiteralParserToken<UChar>& token)
+{
+    while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$' || *m_ptr == 0x200C || *m_ptr == 0x200D))
+        m_ptr++;
+    token.stringIs8Bit = 0;
+    token.stringToken16 = token.start;
+    token.stringLength = m_ptr - token.start;
+    token.type = TokIdentifier;
+    token.end = m_ptr;
+    return TokIdentifier;
+}
+
+template <typename CharType>
+TokenType LiteralParser<CharType>::Lexer::next()
 {
     if (m_mode == NonStrictJSON)
         return lex<NonStrictJSON>(m_currentToken);
 {
     if (m_mode == NonStrictJSON)
         return lex<NonStrictJSON>(m_currentToken);
@@ -266,20 +315,39 @@ LiteralParser::TokenType LiteralParser::Lexer::next()
     return lex<StrictJSON>(m_currentToken);
 }
 
     return lex<StrictJSON>(m_currentToken);
 }
 
-template <LiteralParser::ParserMode mode, UChar terminator> static inline bool isSafeStringCharacter(UChar c)
+template <>
+ALWAYS_INLINE void setParserTokenString<LChar>(LiteralParserToken<LChar>& token, const LChar* string)
 {
 {
-    return (c >= ' ' && (mode == LiteralParser::StrictJSON || c <= 0xff) && c != '\\' && c != terminator) || c == '\t';
+    token.stringIs8Bit = 1;
+    token.stringToken8 = string;
 }
 
 }
 
-// "inline" is required here to help WINSCW compiler resolve specialized argument in templated functions.
-template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token)
+template <>
+ALWAYS_INLINE void setParserTokenString<UChar>(LiteralParserToken<UChar>& token, const UChar* string)
+{
+    token.stringIs8Bit = 0;
+    token.stringToken16 = string;
+}
+
+template <ParserMode mode, typename CharType, LChar terminator> static inline bool isSafeStringCharacter(LChar c)
+{
+    return (c >= ' ' && c != '\\' && c != terminator) || (c == '\t' && mode != StrictJSON);
+}
+
+template <ParserMode mode, typename CharType, UChar terminator> static inline bool isSafeStringCharacter(UChar c)
+{
+    return (c >= ' ' && (mode == StrictJSON || c <= 0xff) && c != '\\' && c != terminator) || (c == '\t' && mode != StrictJSON);
+}
+
+template <typename CharType>
+template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType LiteralParser<CharType>::Lexer::lexString(LiteralParserToken<CharType>& token)
 {
     ++m_ptr;
 {
     ++m_ptr;
-    const UChar* runStart = m_ptr;
+    const CharType* runStart = m_ptr;
     UStringBuilder builder;
     do {
         runStart = m_ptr;
     UStringBuilder builder;
     do {
         runStart = m_ptr;
-        while (m_ptr < m_end && isSafeStringCharacter<mode, terminator>(*m_ptr))
+        while (m_ptr < m_end && isSafeStringCharacter<mode, CharType, terminator>(*m_ptr))
             ++m_ptr;
         if (builder.length())
             builder.append(runStart, m_ptr - runStart);
             ++m_ptr;
         if (builder.length())
             builder.append(runStart, m_ptr - runStart);
@@ -287,8 +355,10 @@ template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser
             if (builder.isEmpty() && runStart < m_ptr)
                 builder.append(runStart, m_ptr - runStart);
             ++m_ptr;
             if (builder.isEmpty() && runStart < m_ptr)
                 builder.append(runStart, m_ptr - runStart);
             ++m_ptr;
-            if (m_ptr >= m_end)
+            if (m_ptr >= m_end) {
+                m_lexErrorMessage = "Unterminated string";
                 return TokError;
                 return TokError;
+            }
             switch (*m_ptr) {
                 case '"':
                     builder.append('"');
             switch (*m_ptr) {
                 case '"':
                     builder.append('"');
@@ -324,13 +394,17 @@ template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser
                     break;
 
                 case 'u':
                     break;
 
                 case 'u':
-                    if ((m_end - m_ptr) < 5) // uNNNN == 5 characters
+                    if ((m_end - m_ptr) < 5) { 
+                        m_lexErrorMessage = "\\u must be followed by 4 hex digits";
                         return TokError;
                         return TokError;
+                    } // uNNNN == 5 characters
                     for (int i = 1; i < 5; i++) {
                     for (int i = 1; i < 5; i++) {
-                        if (!isASCIIHexDigit(m_ptr[i]))
+                        if (!isASCIIHexDigit(m_ptr[i])) {
+                            m_lexErrorMessage = String::format("\"\\%s\" is not a valid unicode escape", UString(m_ptr, 5).ascii().data()).impl();
                             return TokError;
                             return TokError;
+                        }
                     }
                     }
-                    builder.append(JSC::Lexer::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
+                    builder.append(JSC::Lexer<CharType>::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
                     m_ptr += 5;
                     break;
 
                     m_ptr += 5;
                     break;
 
@@ -340,21 +414,30 @@ template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser
                         m_ptr++;
                         break;
                     }
                         m_ptr++;
                         break;
                     }
+                    m_lexErrorMessage = String::format("Invalid escape character %c", *m_ptr).impl();
                     return TokError;
             }
         }
     } while ((mode != NonStrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != terminator);
 
                     return TokError;
             }
         }
     } while ((mode != NonStrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != terminator);
 
-    if (m_ptr >= m_end || *m_ptr != terminator)
+    if (m_ptr >= m_end || *m_ptr != terminator) {
+        m_lexErrorMessage = "Unterminated string";
         return TokError;
         return TokError;
+    }
 
     if (builder.isEmpty()) {
         token.stringBuffer = UString();
 
     if (builder.isEmpty()) {
         token.stringBuffer = UString();
-        token.stringToken = runStart;
+        setParserTokenString<CharType>(token, runStart);
         token.stringLength = m_ptr - runStart;
     } else {
         token.stringBuffer = builder.toUString();
         token.stringLength = m_ptr - runStart;
     } else {
         token.stringBuffer = builder.toUString();
-        token.stringToken = token.stringBuffer.characters();
+        if (token.stringBuffer.is8Bit()) {
+            token.stringIs8Bit = 1;
+            token.stringToken8 = token.stringBuffer.characters8();
+        } else {
+            token.stringIs8Bit = 0;
+            token.stringToken16 = token.stringBuffer.characters16();
+        }
         token.stringLength = token.stringBuffer.length();
     }
     token.type = TokString;
         token.stringLength = token.stringBuffer.length();
     }
     token.type = TokString;
@@ -362,7 +445,8 @@ template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser
     return TokString;
 }
 
     return TokString;
 }
 
-LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& token)
+template <typename CharType>
+TokenType LiteralParser<CharType>::Lexer::lexNumber(LiteralParserToken<CharType>& token)
 {
     // ES5 and json.org define numbers as
     // number
 {
     // ES5 and json.org define numbers as
     // number
@@ -389,15 +473,19 @@ LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& tok
         // [0-9]*
         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
             ++m_ptr;
         // [0-9]*
         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
             ++m_ptr;
-    } else
+    } else {
+        m_lexErrorMessage = "Invalid number";
         return TokError;
         return TokError;
+    }
 
     // ('.' [0-9]+)?
     if (m_ptr < m_end && *m_ptr == '.') {
         ++m_ptr;
         // [0-9]+
 
     // ('.' [0-9]+)?
     if (m_ptr < m_end && *m_ptr == '.') {
         ++m_ptr;
         // [0-9]+
-        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr))
+        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
+            m_lexErrorMessage = "Invalid digits after decimal point";
             return TokError;
             return TokError;
+        }
 
         ++m_ptr;
         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
 
         ++m_ptr;
         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
@@ -406,7 +494,7 @@ LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& tok
         int result = 0;
         token.type = TokNumber;
         token.end = m_ptr;
         int result = 0;
         token.type = TokNumber;
         token.end = m_ptr;
-        const UChar* digit = token.start;
+        const CharType* digit = token.start;
         int negative = 1;
         if (*digit == '-') {
             negative = -1;
         int negative = 1;
         if (*digit == '-') {
             negative = -1;
@@ -429,8 +517,10 @@ LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& tok
             ++m_ptr;
 
         // [0-9]+
             ++m_ptr;
 
         // [0-9]+
-        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr))
+        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
+            m_lexErrorMessage = "Exponent symbols should be followed by an optional '+' or '-' and then by at least one number";
             return TokError;
             return TokError;
+        }
         
         ++m_ptr;
         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
         
         ++m_ptr;
         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
@@ -439,20 +529,13 @@ LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& tok
     
     token.type = TokNumber;
     token.end = m_ptr;
     
     token.type = TokNumber;
     token.end = m_ptr;
-    Vector<char, 64> buffer(token.end - token.start + 1);
-    int i;
-    for (i = 0; i < token.end - token.start; i++) {
-        ASSERT(static_cast<char>(token.start[i]) == token.start[i]);
-        buffer[i] = static_cast<char>(token.start[i]);
-    }
-    buffer[i] = 0;
-    char* end;
-    token.numberToken = WTF::strtod(buffer.data(), &end);
-    ASSERT(buffer.data() + (token.end - token.start) == end);
+    size_t parsedLength;
+    token.numberToken = parseDouble(token.start, token.end - token.start, parsedLength);
     return TokNumber;
 }
 
     return TokNumber;
 }
 
-JSValue LiteralParser::parse(ParserState initialState)
+template <typename CharType>
+JSValue LiteralParser<CharType>::parse(ParserState initialState)
 {
     ParserState state = initialState;
     MarkedArgumentBuffer objectStack;
 {
     ParserState state = initialState;
     MarkedArgumentBuffer objectStack;
@@ -471,8 +554,10 @@ JSValue LiteralParser::parse(ParserState initialState)
             case DoParseArrayStartExpression: {
                 TokenType lastToken = m_lexer.currentToken().type;
                 if (m_lexer.next() == TokRBracket) {
             case DoParseArrayStartExpression: {
                 TokenType lastToken = m_lexer.currentToken().type;
                 if (m_lexer.next() == TokRBracket) {
-                    if (lastToken == TokComma)
+                    if (lastToken == TokComma) {
+                        m_parseErrorMessage = "Unexpected comma at the end of array expression";
                         return JSValue();
                         return JSValue();
+                    }
                     m_lexer.next();
                     lastValue = objectStack.last();
                     objectStack.removeLast();
                     m_lexer.next();
                     lastValue = objectStack.last();
                     objectStack.removeLast();
@@ -488,8 +573,10 @@ JSValue LiteralParser::parse(ParserState initialState)
                 if (m_lexer.currentToken().type == TokComma)
                     goto doParseArrayStartExpression;
 
                 if (m_lexer.currentToken().type == TokComma)
                     goto doParseArrayStartExpression;
 
-                if (m_lexer.currentToken().type != TokRBracket)
+                if (m_lexer.currentToken().type != TokRBracket) {
+                    m_parseErrorMessage = "Expected ']'";
                     return JSValue();
                     return JSValue();
+                }
                 
                 m_lexer.next();
                 lastValue = objectStack.last();
                 
                 m_lexer.next();
                 lastValue = objectStack.last();
@@ -503,19 +590,26 @@ JSValue LiteralParser::parse(ParserState initialState)
 
                 TokenType type = m_lexer.next();
                 if (type == TokString || (m_mode != StrictJSON && type == TokIdentifier)) {
 
                 TokenType type = m_lexer.next();
                 if (type == TokString || (m_mode != StrictJSON && type == TokIdentifier)) {
-                    Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
+                    LiteralParserToken<CharType> identifierToken = m_lexer.currentToken();
 
                     // Check for colon
 
                     // Check for colon
-                    if (m_lexer.next() != TokColon)
+                    if (m_lexer.next() != TokColon) {
+                        m_parseErrorMessage = "Expected ':' before value in object property definition";
                         return JSValue();
                         return JSValue();
+                    }
                     
                     m_lexer.next();
                     
                     m_lexer.next();
-                    identifierStack.append(makeIdentifier(identifierToken.stringToken, identifierToken.stringLength));
+                    if (identifierToken.stringIs8Bit)
+                        identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength));
+                    else
+                        identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength));
                     stateStack.append(DoParseObjectEndExpression);
                     goto startParseExpression;
                 }
                     stateStack.append(DoParseObjectEndExpression);
                     goto startParseExpression;
                 }
-                if (type != TokRBrace) 
+                if (type != TokRBrace)  {
+                    m_parseErrorMessage = "Expected '}'";
                     return JSValue();
                     return JSValue();
+                }
                 m_lexer.next();
                 lastValue = objectStack.last();
                 objectStack.removeLast();
                 m_lexer.next();
                 lastValue = objectStack.last();
                 objectStack.removeLast();
@@ -524,16 +618,23 @@ JSValue LiteralParser::parse(ParserState initialState)
             doParseObjectStartExpression:
             case DoParseObjectStartExpression: {
                 TokenType type = m_lexer.next();
             doParseObjectStartExpression:
             case DoParseObjectStartExpression: {
                 TokenType type = m_lexer.next();
-                if (type != TokString && (m_mode == StrictJSON || type != TokIdentifier))
+                if (type != TokString && (m_mode == StrictJSON || type != TokIdentifier)) {
+                    m_parseErrorMessage = "Property name must be a string literal";
                     return JSValue();
                     return JSValue();
-                Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
+                }
+                LiteralParserToken<CharType> identifierToken = m_lexer.currentToken();
 
                 // Check for colon
 
                 // Check for colon
-                if (m_lexer.next() != TokColon)
+                if (m_lexer.next() != TokColon) {
+                    m_parseErrorMessage = "Expected ':'";
                     return JSValue();
                     return JSValue();
+                }
 
                 m_lexer.next();
 
                 m_lexer.next();
-                identifierStack.append(makeIdentifier(identifierToken.stringToken, identifierToken.stringLength));
+                if (identifierToken.stringIs8Bit)
+                    identifierStack.append(makeIdentifier(identifierToken.stringToken8, identifierToken.stringLength));
+                else
+                    identifierStack.append(makeIdentifier(identifierToken.stringToken16, identifierToken.stringLength));
                 stateStack.append(DoParseObjectEndExpression);
                 goto startParseExpression;
             }
                 stateStack.append(DoParseObjectEndExpression);
                 goto startParseExpression;
             }
@@ -543,8 +644,10 @@ JSValue LiteralParser::parse(ParserState initialState)
                 identifierStack.removeLast();
                 if (m_lexer.currentToken().type == TokComma)
                     goto doParseObjectStartExpression;
                 identifierStack.removeLast();
                 if (m_lexer.currentToken().type == TokComma)
                     goto doParseObjectStartExpression;
-                if (m_lexer.currentToken().type != TokRBrace)
+                if (m_lexer.currentToken().type != TokRBrace) {
+                    m_parseErrorMessage = "Expected '}'";
                     return JSValue();
                     return JSValue();
+                }
                 m_lexer.next();
                 lastValue = objectStack.last();
                 objectStack.removeLast();
                 m_lexer.next();
                 lastValue = objectStack.last();
                 objectStack.removeLast();
@@ -558,13 +661,16 @@ JSValue LiteralParser::parse(ParserState initialState)
                     case TokLBrace:
                         goto startParseObject;
                     case TokString: {
                     case TokLBrace:
                         goto startParseObject;
                     case TokString: {
-                        Lexer::LiteralParserToken stringToken = m_lexer.currentToken();
+                        LiteralParserToken<CharType> stringToken = m_lexer.currentToken();
                         m_lexer.next();
                         m_lexer.next();
-                        lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken, stringToken.stringLength).ustring());
+                        if (stringToken.stringIs8Bit)
+                            lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken8, stringToken.stringLength).ustring());
+                        else
+                            lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken16, stringToken.stringLength).ustring());
                         break;
                     }
                     case TokNumber: {
                         break;
                     }
                     case TokNumber: {
-                        Lexer::LiteralParserToken numberToken = m_lexer.currentToken();
+                        LiteralParserToken<CharType> numberToken = m_lexer.currentToken();
                         m_lexer.next();
                         lastValue = jsNumber(numberToken.numberToken);
                         break;
                         m_lexer.next();
                         lastValue = jsNumber(numberToken.numberToken);
                         break;
@@ -583,9 +689,48 @@ JSValue LiteralParser::parse(ParserState initialState)
                         m_lexer.next();
                         lastValue = jsBoolean(false);
                         break;
                         m_lexer.next();
                         lastValue = jsBoolean(false);
                         break;
-
+                    case TokRBracket:
+                        m_parseErrorMessage = "Unexpected token ']'";
+                        return JSValue();
+                    case TokRBrace:
+                        m_parseErrorMessage = "Unexpected token '}'";
+                        return JSValue();
+                    case TokIdentifier: {
+                        const LiteralParserToken<CharType>& token = m_lexer.currentToken();
+                        if (token.stringIs8Bit)
+                            m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken8, m_lexer.currentToken().stringLength).ascii().data()).impl();
+                        else
+                            m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken16, m_lexer.currentToken().stringLength).ascii().data()).impl();
+                        return JSValue();
+                    }
+                    case TokColon:
+                        m_parseErrorMessage = "Unexpected token ':'";
+                        return JSValue();
+                    case TokLParen:
+                        m_parseErrorMessage = "Unexpected token '('";
+                        return JSValue();
+                    case TokRParen:
+                        m_parseErrorMessage = "Unexpected token ')'";
+                        return JSValue();
+                    case TokComma:
+                        m_parseErrorMessage = "Unexpected token ','";
+                        return JSValue();
+                    case TokDot:
+                        m_parseErrorMessage = "Unexpected token '.'";
+                        return JSValue();
+                    case TokAssign:
+                        m_parseErrorMessage = "Unexpected token '='";
+                        return JSValue();
+                    case TokSemi:
+                        m_parseErrorMessage = "Unexpected token ';'";
+                        return JSValue();
+                    case TokEnd:
+                        m_parseErrorMessage = "Unexpected EOF";
+                        return JSValue();
+                    case TokError:
                     default:
                         // Error
                     default:
                         // Error
+                        m_parseErrorMessage = "Could not parse value expression";
                         return JSValue();
                 }
                 break;
                         return JSValue();
                 }
                 break;
@@ -602,7 +747,51 @@ JSValue LiteralParser::parse(ParserState initialState)
                         stateStack.append(StartParseStatementEndStatement);
                         goto startParseExpression;
                     }
                         stateStack.append(StartParseStatementEndStatement);
                         goto startParseExpression;
                     }
+                    case TokRBracket:
+                        m_parseErrorMessage = "Unexpected token ']'";
+                        return JSValue();
+                    case TokLBrace:
+                        m_parseErrorMessage = "Unexpected token '{'";
+                        return JSValue();
+                    case TokRBrace:
+                        m_parseErrorMessage = "Unexpected token '}'";
+                        return JSValue();
+                    case TokIdentifier:
+                        m_parseErrorMessage = "Unexpected identifier";
+                        return JSValue();
+                    case TokColon:
+                        m_parseErrorMessage = "Unexpected token ':'";
+                        return JSValue();
+                    case TokRParen:
+                        m_parseErrorMessage = "Unexpected token ')'";
+                        return JSValue();
+                    case TokComma:
+                        m_parseErrorMessage = "Unexpected token ','";
+                        return JSValue();
+                    case TokTrue:
+                        m_parseErrorMessage = "Unexpected token 'true'";
+                        return JSValue();
+                    case TokFalse:
+                        m_parseErrorMessage = "Unexpected token 'false'";
+                        return JSValue();
+                    case TokNull:
+                        m_parseErrorMessage = "Unexpected token 'null'";
+                        return JSValue();
+                    case TokEnd:
+                        m_parseErrorMessage = "Unexpected EOF";
+                        return JSValue();
+                    case TokDot:
+                        m_parseErrorMessage = "Unexpected token '.'";
+                        return JSValue();
+                    case TokAssign:
+                        m_parseErrorMessage = "Unexpected token '='";
+                        return JSValue();
+                    case TokSemi:
+                        m_parseErrorMessage = "Unexpected token ';'";
+                        return JSValue();
+                    case TokError:
                     default:
                     default:
+                        m_parseErrorMessage = "Could not parse statement";
                         return JSValue();
                 }
             }
                         return JSValue();
                 }
             }
@@ -612,6 +801,7 @@ JSValue LiteralParser::parse(ParserState initialState)
                     return JSValue();
                 if (m_lexer.next() == TokEnd)
                     return lastValue;
                     return JSValue();
                 if (m_lexer.next() == TokEnd)
                     return lastValue;
+                m_parseErrorMessage = "Unexpected content at end of JSON literal";
                 return JSValue();
             }
             default:
                 return JSValue();
             }
             default:
@@ -625,4 +815,8 @@ JSValue LiteralParser::parse(ParserState initialState)
     }
 }
 
     }
 }
 
+// Instantiate the two flavors of LiteralParser we need instead of putting most of this file in LiteralParser.h
+template class LiteralParser<LChar>;
+template class LiteralParser<UChar>;
+
 }
 }
index 40c3d586f59ae64c627fbf3aa5f15b788c360bbb..abe3f95b798cc35b2e46429117b87d11addfff89 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class LiteralParser {
+typedef enum { StrictJSON, NonStrictJSON, JSONP } ParserMode;
+
+enum JSONPPathEntryType {
+    JSONPPathEntryTypeDeclare, // var pathEntryName = JSON
+    JSONPPathEntryTypeDot, // <prior entries>.pathEntryName = JSON
+    JSONPPathEntryTypeLookup, // <prior entries>[pathIndex] = JSON
+    JSONPPathEntryTypeCall // <prior entries>(JSON)
+};
+
+enum ParserState { StartParseObject, StartParseArray, StartParseExpression, 
+                   StartParseStatement, StartParseStatementEndStatement, 
+                   DoParseObjectStartExpression, DoParseObjectEndExpression,
+                   DoParseArrayStartExpression, DoParseArrayEndExpression };
+enum TokenType { TokLBracket, TokRBracket, TokLBrace, TokRBrace, 
+                 TokString, TokIdentifier, TokNumber, TokColon, 
+                 TokLParen, TokRParen, TokComma, TokTrue, TokFalse,
+                 TokNull, TokEnd, TokDot, TokAssign, TokSemi, TokError };
+    
+struct JSONPPathEntry {
+    JSONPPathEntryType m_type;
+    Identifier m_pathEntryName;
+    int m_pathIndex;
+};
+
+struct JSONPData {
+    Vector<JSONPPathEntry> m_path;
+    Strong<Unknown> m_value;
+};
+
+template <typename CharType>
+struct LiteralParserToken {
+    TokenType type;
+    const CharType* start;
+    const CharType* end;
+    UString stringBuffer;
+    union {
+        double numberToken;
+        struct {
+            union {
+                const LChar* stringToken8;
+                const UChar* stringToken16;
+            };
+            unsigned stringIs8Bit : 1;
+            unsigned stringLength : 31;
+        };
+    };
+};
+
+template <typename CharType>
+ALWAYS_INLINE void setParserTokenString(LiteralParserToken<CharType>&, const CharType* string);
+
+template <typename CharType>
+class LiteralParser {
+public:
+    LiteralParser(ExecState* exec, const CharType* characters, unsigned length, ParserMode mode)
+        : m_exec(exec)
+        , m_lexer(characters, length, mode)
+        , m_mode(mode)
+    {
+    }
+    
+    UString getErrorMessage() 
+    { 
+        if (!m_lexer.getErrorMessage().isEmpty())
+            return String::format("JSON Parse error: %s", m_lexer.getErrorMessage().ascii().data()).impl();
+        if (!m_parseErrorMessage.isEmpty())
+            return String::format("JSON Parse error: %s", m_parseErrorMessage.ascii().data()).impl();
+        return "JSON Parse error: Unable to parse JSON string";
+    }
+    
+    JSValue tryLiteralParse()
+    {
+        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;
+    }
+    
+    bool tryJSONPParse(Vector<JSONPData>&, bool needsFullSourceInfo);
+
+private:
+    class Lexer {
     public:
     public:
-        typedef enum { StrictJSON, NonStrictJSON, JSONP } ParserMode;
-        LiteralParser(ExecState* exec, const UChar* characters, unsigned length, ParserMode mode)
-            : m_exec(exec)
-            , m_lexer(characters, length, mode)
-            , m_mode(mode)
+        Lexer(const CharType* characters, unsigned length, ParserMode mode)
+            : m_mode(mode)
+            , m_ptr(characters)
+            , m_end(characters + length)
         {
         }
         
         {
         }
         
-        JSValue tryLiteralParse()
+        TokenType next();
+        
+        const LiteralParserToken<CharType>& currentToken()
         {
         {
-            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;
+            return m_currentToken;
         }
         
         }
         
-        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, 
-                           DoParseObjectStartExpression, DoParseObjectEndExpression,
-                           DoParseArrayStartExpression, DoParseArrayEndExpression };
-        enum TokenType { TokLBracket, TokRBracket, TokLBrace, TokRBrace, 
-                         TokString, TokIdentifier, TokNumber, TokColon, 
-                         TokLParen, TokRParen, TokComma, TokTrue, TokFalse,
-                         TokNull, TokEnd, TokDot, TokAssign, TokSemi, TokError };
-        
-        class Lexer {
-        public:
-            struct LiteralParserToken {
-                TokenType type;
-                const UChar* start;
-                const UChar* end;
-                UString stringBuffer;
-                union {
-                    double numberToken;
-                    struct {
-                        const UChar* stringToken;
-                        int stringLength;
-                    };
-                };
-            };
-            Lexer(const UChar* characters, unsigned length, ParserMode mode)
-                : m_mode(mode)
-                , m_ptr(characters)
-                , m_end(characters + length)
-            {
-            }
-            
-            TokenType next();
-            
-            const LiteralParserToken& currentToken()
-            {
-                return m_currentToken;
-            }
-            
-        private:
-            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;
-            const UChar* m_ptr;
-            const UChar* m_end;
-        };
+        UString getErrorMessage() { return m_lexErrorMessage; }
         
         
-        class StackGuard;
-        JSValue parse(ParserState);
-
-        ExecState* m_exec;
-        LiteralParser::Lexer m_lexer;
+    private:
+        UString m_lexErrorMessage;
+        template <ParserMode mode> TokenType lex(LiteralParserToken<CharType>&);
+        ALWAYS_INLINE TokenType lexIdentifier(LiteralParserToken<CharType>&);
+        template <ParserMode mode, char terminator> ALWAYS_INLINE TokenType lexString(LiteralParserToken<CharType>&);
+        ALWAYS_INLINE TokenType lexNumber(LiteralParserToken<CharType>&);
+        LiteralParserToken<CharType> m_currentToken;
         ParserMode m_mode;
         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);
+        const CharType* m_ptr;
+        const CharType* m_end;
+    };
+    
+    class StackGuard;
+    JSValue parse(ParserState);
+
+    ExecState* m_exec;
+    typename LiteralParser<CharType>::Lexer m_lexer;
+    ParserMode m_mode;
+    UString m_parseErrorMessage;
+    static unsigned const MaximumCachableCharacter = 128;
+    FixedArray<Identifier, MaximumCachableCharacter> m_shortIdentifiers;
+    FixedArray<Identifier, MaximumCachableCharacter> m_recentIdentifiers;
+    ALWAYS_INLINE const Identifier makeIdentifier(const LChar* characters, size_t length);
+    ALWAYS_INLINE const Identifier makeIdentifier(const UChar* characters, size_t length);
     };
 
 }
     };
 
 }
index 25b516efb0fa26e1952f5432ff5199995ddfcb47..b935eb260c10a109f15c40c0442f6e2e52948041 100644 (file)
@@ -46,11 +46,7 @@ void HashTable::createTable(JSGlobalData* globalData) const
             entry = entry->next();
         }
 
             entry = entry->next();
         }
 
-        entry->initialize(identifier, values[i].attributes, values[i].value1, values[i].value2
-#if ENABLE(JIT)
-                          , values[i].generator
-#endif
-                          );
+        entry->initialize(identifier, values[i].attributes, values[i].value1, values[i].value2, values[i].intrinsic);
     }
     table = entries;
 }
     }
     table = entries;
 }
@@ -68,28 +64,25 @@ void HashTable::deleteTable() const
     }
 }
 
     }
 }
 
-void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
+bool 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(thisObj->globalObject());
     ASSERT(entry->attributes() & Function);
     WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(exec->globalData(), propertyName);
 
     if (!location) {
     ASSERT(entry->attributes() & Function);
     WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(exec->globalData(), propertyName);
 
     if (!location) {
-        JSFunction* function;
-        JSGlobalObject* globalObject = asGlobalObject(thisObj->getAnonymousValue(0).asCell());
-#if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
-        if (entry->generator())
-            function = new (exec) JSFunction(exec, globalObject, globalObject->functionStructure(), entry->functionLength(), propertyName, exec->globalData().getHostFunction(entry->function(), entry->generator()));
-        else
-#endif
-            function = new (exec) JSFunction(exec, globalObject, globalObject->functionStructure(), entry->functionLength(), propertyName, entry->function());
-
-        thisObj->putDirectFunction(exec->globalData(), propertyName, function, entry->attributes());
+        // If a property is ever deleted from an object with a static table, then we reify
+        // all static functions at that time - after this we shouldn't be re-adding anything.
+        if (thisObj->staticFunctionsReified())
+            return false;
+    
+        JSFunction* function = JSFunction::create(exec, thisObj->globalObject(), entry->functionLength(), propertyName, entry->function(), entry->intrinsic());
+        thisObj->putDirect(exec->globalData(), propertyName, function, entry->attributes());
         location = thisObj->getDirectLocation(exec->globalData(), propertyName);
     }
 
     slot.setValue(thisObj, location->get(), thisObj->offsetForLocation(location));
         location = thisObj->getDirectLocation(exec->globalData(), propertyName);
     }
 
     slot.setValue(thisObj, location->get(), thisObj->offsetForLocation(location));
+    return true;
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 43184e56dcaaed5e54a3daaa3165e7bc45f9a031..64d06b5037b1d6de1a0b75bae962512a98ed106d 100644 (file)
 #define Lookup_h
 
 #include "CallFrame.h"
 #define Lookup_h
 
 #include "CallFrame.h"
+#include "Intrinsic.h"
 #include "Identifier.h"
 #include "JSGlobalObject.h"
 #include "Identifier.h"
 #include "JSGlobalObject.h"
-#include "JSObject.h"
 #include "PropertySlot.h"
 #include <stdio.h>
 #include <wtf/Assertions.h>
 
 #include "PropertySlot.h"
 #include <stdio.h>
 #include <wtf/Assertions.h>
 
-// Bug #26843: Work around Metrowerks compiler bug
-#if COMPILER(WINSCW)
-#define JSC_CONST_HASHTABLE
-#else
-#define JSC_CONST_HASHTABLE const
-#endif
-
 namespace JSC {
     // Hash table generated by the create_hash_table script.
     struct HashTableValue {
 namespace JSC {
     // Hash table generated by the create_hash_table script.
     struct HashTableValue {
@@ -43,9 +36,7 @@ namespace JSC {
         unsigned char attributes; // JSObject attributes
         intptr_t value1;
         intptr_t value2;
         unsigned char attributes; // JSObject attributes
         intptr_t value1;
         intptr_t value2;
-#if ENABLE(JIT)
-        ThunkGenerator generator;
-#endif
+        Intrinsic intrinsic;
     };
 
     // FIXME: There is no reason this get function can't be simpler.
     };
 
     // FIXME: There is no reason this get function can't be simpler.
@@ -56,19 +47,13 @@ namespace JSC {
     class HashEntry {
         WTF_MAKE_FAST_ALLOCATED;
     public:
     class HashEntry {
         WTF_MAKE_FAST_ALLOCATED;
     public:
-        void initialize(StringImpl* key, unsigned char attributes, intptr_t v1, intptr_t v2
-#if ENABLE(JIT)
-                        , ThunkGenerator generator = 0
-#endif
-                        )
+        void initialize(StringImpl* key, unsigned char attributes, intptr_t v1, intptr_t v2, Intrinsic intrinsic)
         {
             m_key = key;
             m_attributes = attributes;
             m_u.store.value1 = v1;
             m_u.store.value2 = v2;
         {
             m_key = key;
             m_attributes = attributes;
             m_u.store.value1 = v1;
             m_u.store.value2 = v2;
-#if ENABLE(JIT)
-            m_u.function.generator = generator;
-#endif
+            m_u.function.intrinsic = intrinsic;
             m_next = 0;
         }
 
             m_next = 0;
         }
 
@@ -77,9 +62,12 @@ namespace JSC {
 
         unsigned char attributes() const { return m_attributes; }
 
 
         unsigned char attributes() const { return m_attributes; }
 
-#if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
-        ThunkGenerator generator() const { ASSERT(m_attributes & Function); return m_u.function.generator; }
-#endif
+        Intrinsic intrinsic() const
+        {
+            ASSERT(m_attributes & Function);
+            return m_u.function.intrinsic;
+        }
+
         NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; }
         unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast<unsigned char>(m_u.function.length); }
 
         NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; }
         unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast<unsigned char>(m_u.function.length); }
 
@@ -103,9 +91,7 @@ namespace JSC {
             struct {
                 NativeFunction functionValue;
                 intptr_t length; // number of arguments for function
             struct {
                 NativeFunction functionValue;
                 intptr_t length; // number of arguments for function
-#if ENABLE(JIT)
-                ThunkGenerator generator;
-#endif
+                Intrinsic intrinsic;
             } function;
             struct {
                 GetFunction get;
             } function;
             struct {
                 GetFunction get;
@@ -140,7 +126,7 @@ namespace JSC {
                 createTable(&exec->globalData());
         }
 
                 createTable(&exec->globalData());
         }
 
-        void deleteTable() const;
+        JS_EXPORT_PRIVATE void deleteTable() const;
 
         // Find an entry in the table, and return the entry.
         ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, const Identifier& identifier) const
 
         // Find an entry in the table, and return the entry.
         ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, const Identifier& identifier) const
@@ -155,6 +141,63 @@ namespace JSC {
             return entry(identifier);
         }
 
             return entry(identifier);
         }
 
+        class ConstIterator {
+        public:
+            ConstIterator(const HashTable* table, int position)
+                : m_table(table)
+                , m_position(position)
+            {
+                skipInvalidKeys();
+            }
+
+            const HashEntry* operator->()
+            {
+                return &m_table->table[m_position];
+            }
+
+            const HashEntry* operator*()
+            {
+                return &m_table->table[m_position];
+            }
+
+            bool operator!=(const ConstIterator& other)
+            {
+                ASSERT(m_table == other.m_table);
+                return m_position != other.m_position;
+            }
+            
+            ConstIterator& operator++()
+            {
+                ASSERT(m_position < m_table->compactSize);
+                ++m_position;
+                skipInvalidKeys();
+                return *this;
+            }
+
+        private:
+            void skipInvalidKeys()
+            {
+                ASSERT(m_position <= m_table->compactSize);
+                while (m_position < m_table->compactSize && !m_table->table[m_position].key())
+                    ++m_position;
+                ASSERT(m_position <= m_table->compactSize);
+            }
+            
+            const HashTable* m_table;
+            int m_position;
+        };
+
+        ConstIterator begin(JSGlobalData& globalData) const
+        {
+            initializeIfNeeded(&globalData);
+            return ConstIterator(this, 0);
+        }
+        ConstIterator end(JSGlobalData& globalData) const
+        {
+            initializeIfNeeded(&globalData);
+            return ConstIterator(this, compactSize);
+        }
+
     private:
         ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const
         {
     private:
         ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const
         {
@@ -175,10 +218,10 @@ namespace JSC {
         }
 
         // Convert the hash table keys to identifiers.
         }
 
         // Convert the hash table keys to identifiers.
-        void createTable(JSGlobalData*) const;
+        JS_EXPORT_PRIVATE void createTable(JSGlobalData*) const;
     };
 
     };
 
-    void setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&);
+    JS_EXPORT_PRIVATE bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&);
 
     /**
      * This method does it all (looking in the hashtable, checking for function
 
     /**
      * This method does it all (looking in the hashtable, checking for function
@@ -192,13 +235,12 @@ namespace JSC {
         const HashEntry* entry = table->entry(exec, propertyName);
 
         if (!entry) // not found, forward to parent
         const HashEntry* entry = table->entry(exec, propertyName);
 
         if (!entry) // not found, forward to parent
-            return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
+            return ParentImp::getOwnPropertySlot(thisObj, exec, propertyName, slot);
 
         if (entry->attributes() & Function)
 
         if (entry->attributes() & Function)
-            setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
-        else
-            slot.setCacheableCustom(thisObj, entry->propertyGetter());
+            return setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
 
 
+        slot.setCacheableCustom(thisObj, entry->propertyGetter());
         return true;
     }
 
         return true;
     }
 
@@ -208,14 +250,17 @@ namespace JSC {
         const HashEntry* entry = table->entry(exec, propertyName);
         
         if (!entry) // not found, forward to parent
         const HashEntry* entry = table->entry(exec, propertyName);
         
         if (!entry) // not found, forward to parent
-            return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+            return ParentImp::getOwnPropertyDescriptor(thisObj, exec, propertyName, descriptor);
  
         PropertySlot slot;
  
         PropertySlot slot;
-        if (entry->attributes() & Function)
-            setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
-        else
-            slot.setCustom(thisObj, entry->propertyGetter());
+        if (entry->attributes() & Function) {
+            bool present = setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
+            if (present)
+                descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+            return present;
+        }
 
 
+        slot.setCustom(thisObj, entry->propertyGetter());
         descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
         return true;
     }
         descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
         return true;
     }
@@ -228,15 +273,14 @@ namespace JSC {
     template <class ParentImp>
     inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
     {
     template <class ParentImp>
     inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
     {
-        if (static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertySlot(exec, propertyName, slot))
+        if (ParentImp::getOwnPropertySlot(thisObj, exec, propertyName, slot))
             return true;
 
         const HashEntry* entry = table->entry(exec, propertyName);
         if (!entry)
             return false;
 
             return true;
 
         const HashEntry* entry = table->entry(exec, propertyName);
         if (!entry)
             return false;
 
-        setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
-        return true;
+        return setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
     }
     
     /**
     }
     
     /**
@@ -247,7 +291,7 @@ namespace JSC {
     template <class ParentImp>
     inline bool getStaticFunctionDescriptor(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor)
     {
     template <class ParentImp>
     inline bool getStaticFunctionDescriptor(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor)
     {
-        if (static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor))
+        if (ParentImp::getOwnPropertyDescriptor(static_cast<ParentImp*>(thisObj), exec, propertyName, descriptor))
             return true;
         
         const HashEntry* entry = table->entry(exec, propertyName);
             return true;
         
         const HashEntry* entry = table->entry(exec, propertyName);
@@ -255,9 +299,10 @@ namespace JSC {
             return false;
         
         PropertySlot slot;
             return false;
         
         PropertySlot slot;
-        setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
-        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
-        return true;
+        bool present = setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
+        if (present)
+            descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+        return present;
     }
 
     /**
     }
 
     /**
@@ -270,7 +315,7 @@ namespace JSC {
         const HashEntry* entry = table->entry(exec, propertyName);
 
         if (!entry) // not found, forward to parent
         const HashEntry* entry = table->entry(exec, propertyName);
 
         if (!entry) // not found, forward to parent
-            return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot);
+            return ParentImp::getOwnPropertySlot(thisObj, exec, propertyName, slot);
 
         ASSERT(!(entry->attributes() & Function));
 
 
         ASSERT(!(entry->attributes() & Function));
 
@@ -288,7 +333,7 @@ namespace JSC {
         const HashEntry* entry = table->entry(exec, propertyName);
         
         if (!entry) // not found, forward to parent
         const HashEntry* entry = table->entry(exec, propertyName);
         
         if (!entry) // not found, forward to parent
-            return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+            return ParentImp::getOwnPropertyDescriptor(thisObj, exec, propertyName, descriptor);
         
         ASSERT(!(entry->attributes() & Function));
         PropertySlot slot;
         
         ASSERT(!(entry->attributes() & Function));
         PropertySlot slot;
@@ -303,20 +348,20 @@ namespace JSC {
      * is found it sets the value and returns true, else it returns false.
      */
     template <class ThisImp>
      * is found it sets the value and returns true, else it returns false.
      */
     template <class ThisImp>
-    inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj)
+    inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj, bool shouldThrow = false)
     {
         const HashEntry* entry = table->entry(exec, propertyName);
     {
         const HashEntry* entry = table->entry(exec, propertyName);
-
+        
         if (!entry)
             return false;
 
         if (!entry)
             return false;
 
-        if (entry->attributes() & Function) { // function: put as override property
-            if (LIKELY(value.isCell()))
-                thisObj->putDirectFunction(exec->globalData(), propertyName, value.asCell());
-            else
-                thisObj->putDirect(exec->globalData(), propertyName, value);
-        } else if (!(entry->attributes() & ReadOnly))
+        // If this is a function put it as an override property.
+        if (entry->attributes() & Function)
+            thisObj->putDirect(exec->globalData(), propertyName, value);
+        else if (!(entry->attributes() & ReadOnly))
             entry->propertyPutter()(exec, thisObj, value);
             entry->propertyPutter()(exec, thisObj, value);
+        else if (shouldThrow)
+            throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
 
         return true;
     }
 
         return true;
     }
@@ -330,8 +375,8 @@ namespace JSC {
     template <class ThisImp, class ParentImp>
     inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot)
     {
     template <class ThisImp, class ParentImp>
     inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot)
     {
-        if (!lookupPut<ThisImp>(exec, propertyName, value, table, thisObj))
-            thisObj->ParentImp::put(exec, propertyName, value, slot); // not found: forward to parent
+        if (!lookupPut<ThisImp>(exec, propertyName, value, table, thisObj, slot.isStrictMode()))
+            ParentImp::put(thisObj, exec, propertyName, value, slot); // not found: forward to parent
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
diff --git a/runtime/MatchResult.h b/runtime/MatchResult.h
new file mode 100644 (file)
index 0000000..d87c851
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef MatchResult_h
+#define MatchResult_h
+
+typedef uint64_t EncodedMatchResult;
+
+struct MatchResult {
+    ALWAYS_INLINE MatchResult(size_t start, size_t end)
+        : start(start)
+        , end(end)
+    {
+    }
+
+    explicit ALWAYS_INLINE MatchResult(EncodedMatchResult encoded)
+    {
+        union u {
+            uint64_t encoded;
+            struct s {
+                size_t start;
+                size_t end;
+            } split;
+        } value;
+        value.encoded = encoded;
+        start = value.split.start;
+        end = value.split.end;
+    }
+
+    ALWAYS_INLINE static MatchResult failed()
+    {
+        return MatchResult(WTF::notFound, 0);
+    }
+
+    ALWAYS_INLINE operator bool()
+    {
+        return start != WTF::notFound;
+    }
+
+    ALWAYS_INLINE bool empty()
+    {
+        return start == end;
+    }
+
+    size_t start;
+    size_t end;
+};
+
+#endif
index 9c85a697cda4038ab12058101071a856c8fccc43..854c2aece17e2525045085aa231b001b18c8ce26 100644 (file)
@@ -59,7 +59,9 @@ static EncodedJSValue JSC_HOST_CALL mathProtoFuncTan(ExecState*);
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo MathObject::s_info = { "Math", &JSObjectWithGlobalObject::s_info, 0, ExecState::mathTable };
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(MathObject);
+
+const ClassInfo MathObject::s_info = { "Math", &JSNonFinalObject::s_info, 0, ExecState::mathTable, CREATE_METHOD_TABLE(MathObject) };
 
 /* Source for MathObject.lut.h
 @begin mathTable
 
 /* Source for MathObject.lut.h
 @begin mathTable
@@ -84,9 +86,14 @@ const ClassInfo MathObject::s_info = { "Math", &JSObjectWithGlobalObject::s_info
 @end
 */
 
 @end
 */
 
-MathObject::MathObject(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
-    : JSObjectWithGlobalObject(globalObject, structure)
+MathObject::MathObject(JSGlobalObject* globalObject, Structure* structure)
+    : JSNonFinalObject(globalObject->globalData(), structure)
+{
+}
+
+void MathObject::finishCreation(ExecState* exec, JSGlobalObject* globalObject)
 {
 {
+    Base::finishCreation(globalObject->globalData());
     ASSERT(inherits(&s_info));
 
     putDirectWithoutTransition(exec->globalData(), Identifier(exec, "E"), jsNumber(exp(1.0)), DontDelete | DontEnum | ReadOnly);
     ASSERT(inherits(&s_info));
 
     putDirectWithoutTransition(exec->globalData(), Identifier(exec, "E"), jsNumber(exp(1.0)), DontDelete | DontEnum | ReadOnly);
@@ -99,14 +106,14 @@ MathObject::MathObject(ExecState* exec, JSGlobalObject* globalObject, Structure*
     putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SQRT2"), jsNumber(sqrt(2.0)), 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(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 {
-    return getStaticFunctionSlot<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<JSObject>(exec, ExecState::mathTable(exec), jsCast<MathObject*>(cell), propertyName, slot);
 }
 
 }
 
-bool MathObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool MathObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::mathTable(exec), jsCast<MathObject*>(object), propertyName, descriptor);
 }
 
 // ------------------------------ Functions --------------------------------
 }
 
 // ------------------------------ Functions --------------------------------
@@ -166,11 +173,11 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec)
 {
     unsigned argsCount = exec->argumentCount();
 EncodedJSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec)
 {
     unsigned argsCount = exec->argumentCount();
-    double result = -Inf;
+    double result = -std::numeric_limits<double>::infinity();
     for (unsigned k = 0; k < argsCount; ++k) {
         double val = exec->argument(k).toNumber(exec);
         if (isnan(val)) {
     for (unsigned k = 0; k < argsCount; ++k) {
         double val = exec->argument(k).toNumber(exec);
         if (isnan(val)) {
-            result = NaN;
+            result = std::numeric_limits<double>::quiet_NaN();
             break;
         }
         if (val > result || (val == 0 && result == 0 && !signbit(val)))
             break;
         }
         if (val > result || (val == 0 && result == 0 && !signbit(val)))
@@ -182,11 +189,11 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec)
 {
     unsigned argsCount = exec->argumentCount();
 EncodedJSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec)
 {
     unsigned argsCount = exec->argumentCount();
-    double result = +Inf;
+    double result = +std::numeric_limits<double>::infinity();
     for (unsigned k = 0; k < argsCount; ++k) {
         double val = exec->argument(k).toNumber(exec);
         if (isnan(val)) {
     for (unsigned k = 0; k < argsCount; ++k) {
         double val = exec->argument(k).toNumber(exec);
         if (isnan(val)) {
-            result = NaN;
+            result = std::numeric_limits<double>::quiet_NaN();
             break;
         }
         if (val < result || (val == 0 && result == 0 && signbit(val)))
             break;
         }
         if (val < result || (val == 0 && result == 0 && signbit(val)))
@@ -195,6 +202,43 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec)
     return JSValue::encode(jsNumber(result));
 }
 
     return JSValue::encode(jsNumber(result));
 }
 
+#if CPU(ARM_THUMB2)
+
+static double fdlibmPow(double x, double y);
+
+static ALWAYS_INLINE bool isDenormal(double x)
+{
+        static const uint64_t signbit = 0x8000000000000000ULL;
+        static const uint64_t minNormal = 0x0001000000000000ULL;
+        return (bitwise_cast<uint64_t>(x) & ~signbit) - 1 < minNormal - 1;
+}
+
+static ALWAYS_INLINE bool isEdgeCase(double x)
+{
+        static const uint64_t signbit = 0x8000000000000000ULL;
+        static const uint64_t infinity = 0x7fffffffffffffffULL;
+        return (bitwise_cast<uint64_t>(x) & ~signbit) - 1 >= infinity - 1;
+}
+
+static ALWAYS_INLINE double mathPow(double x, double y)
+{
+    if (!isDenormal(x) && !isDenormal(y)) {
+        double libmResult = pow(x,y);
+        if (libmResult || isEdgeCase(x) || isEdgeCase(y))
+            return libmResult;
+    }
+    return fdlibmPow(x,y);
+}
+
+#else
+
+ALWAYS_INLINE double mathPow(double x, double y)
+{
+    return pow(x, y);
+}
+
+#endif
+
 EncodedJSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec)
 {
     // ECMA 15.8.2.1.13
 EncodedJSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec)
 {
     // ECMA 15.8.2.1.13
@@ -206,7 +250,7 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec)
         return JSValue::encode(jsNaN());
     if (isinf(arg2) && fabs(arg) == 1)
         return JSValue::encode(jsNaN());
         return JSValue::encode(jsNaN());
     if (isinf(arg2) && fabs(arg) == 1)
         return JSValue::encode(jsNaN());
-    return JSValue::encode(jsNumber(pow(arg, arg2)));
+    return JSValue::encode(jsNumber(mathPow(arg, arg2)));
 }
 
 EncodedJSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec)
@@ -236,4 +280,353 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec)
     return JSValue::encode(jsDoubleNumber(tan(exec->argument(0).toNumber(exec))));
 }
 
     return JSValue::encode(jsDoubleNumber(tan(exec->argument(0).toNumber(exec))));
 }
 
+#if CPU(ARM_THUMB2)
+
+// The following code is taken from netlib.org:
+//   http://www.netlib.org/fdlibm/fdlibm.h
+//   http://www.netlib.org/fdlibm/e_pow.c
+//   http://www.netlib.org/fdlibm/s_scalbn.c
+//
+// And was originally distributed under the following license:
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+/*
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* __ieee754_pow(x,y) return x**y
+ *
+ *                   n
+ * Method:  Let x =  2   * (1+f)
+ *     1. Compute and return log2(x) in two pieces:
+ *             log2(x) = w1 + w2,
+ *        where w1 has 53-24 = 29 bit trailing zeros.
+ *     2. Perform y*log2(x) = n+y' by simulating muti-precision 
+ *        arithmetic, where |y'|<=0.5.
+ *     3. Return x**y = 2**n*exp(y'*log2)
+ *
+ * Special cases:
+ *     1.  (anything) ** 0  is 1
+ *     2.  (anything) ** 1  is itself
+ *     3.  (anything) ** NAN is NAN
+ *     4.  NAN ** (anything except 0) is NAN
+ *     5.  +-(|x| > 1) **  +INF is +INF
+ *     6.  +-(|x| > 1) **  -INF is +0
+ *     7.  +-(|x| < 1) **  +INF is +0
+ *     8.  +-(|x| < 1) **  -INF is +INF
+ *     9.  +-1         ** +-INF is NAN
+ *     10. +0 ** (+anything except 0, NAN)               is +0
+ *     11. -0 ** (+anything except 0, NAN, odd integer)  is +0
+ *     12. +0 ** (-anything except 0, NAN)               is +INF
+ *     13. -0 ** (-anything except 0, NAN, odd integer)  is +INF
+ *     14. -0 ** (odd integer) = -( +0 ** (odd integer) )
+ *     15. +INF ** (+anything except 0,NAN) is +INF
+ *     16. +INF ** (-anything except 0,NAN) is +0
+ *     17. -INF ** (anything)  = -0 ** (-anything)
+ *     18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
+ *     19. (-anything except 0 and inf) ** (non-integer) is NAN
+ *
+ * Accuracy:
+ *     pow(x,y) returns x**y nearly rounded. In particular
+ *                     pow(integer,integer)
+ *     always returns the correct integer provided it is 
+ *     representable.
+ *
+ * Constants :
+ * The hexadecimal values are the intended ones for the following 
+ * constants. The decimal values may be used, provided that the 
+ * compiler will convert from decimal to binary accurately enough 
+ * to produce the hexadecimal values shown.
+ */
+
+#define __HI(x) *(1+(int*)&x)
+#define __LO(x) *(int*)&x
+
+static const double
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
+dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
+zero    =  0.0,
+one    =  1.0,
+two    =  2.0,
+two53  =  9007199254740992.0,  /* 0x43400000, 0x00000000 */
+huge   =  1.0e300,
+tiny    =  1.0e-300,
+        /* for scalbn */
+two54   =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+twom54  =  5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
+       /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1  =  5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
+L2  =  4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
+L3  =  3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
+L4  =  2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
+L5  =  2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
+L6  =  2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
+P1   =  1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
+P2   = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
+P3   =  6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
+P4   = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
+P5   =  4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
+lg2  =  6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
+lg2_h  =  6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
+lg2_l  = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
+ovt =  8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
+cp    =  9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
+cp_h  =  9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
+cp_l  = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
+ivln2    =  1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
+ivln2_h  =  1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
+ivln2_l  =  1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
+
+inline double fdlibmScalbn (double x, int n)
+{
+       int  k,hx,lx;
+       hx = __HI(x);
+       lx = __LO(x);
+        k = (hx&0x7ff00000)>>20;               /* extract exponent */
+        if (k==0) {                            /* 0 or subnormal x */
+            if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
+           x *= two54; 
+           hx = __HI(x);
+           k = ((hx&0x7ff00000)>>20) - 54; 
+            if (n< -50000) return tiny*x;      /*underflow*/
+           }
+        if (k==0x7ff) return x+x;              /* NaN or Inf */
+        k = k+n; 
+        if (k >  0x7fe) return huge*copysign(huge,x); /* overflow  */
+        if (k > 0)                             /* normal result */
+           {__HI(x) = (hx&0x800fffff)|(k<<20); return x;}
+        if (k <= -54) {
+            if (n > 50000)     /* in case integer overflow in n+k */
+               return huge*copysign(huge,x);   /*overflow*/
+           else return tiny*copysign(tiny,x);  /*underflow*/
+        }
+        k += 54;                               /* subnormal result */
+        __HI(x) = (hx&0x800fffff)|(k<<20);
+        return x*twom54;
+}
+
+double fdlibmPow(double x, double y)
+{
+       double z,ax,z_h,z_l,p_h,p_l;
+       double y1,t1,t2,r,s,t,u,v,w;
+       int i0,i1,i,j,k,yisint,n;
+       int hx,hy,ix,iy;
+       unsigned lx,ly;
+
+       i0 = ((*(int*)&one)>>29)^1; i1=1-i0;
+       hx = __HI(x); lx = __LO(x);
+       hy = __HI(y); ly = __LO(y);
+       ix = hx&0x7fffffff;  iy = hy&0x7fffffff;
+
+    /* y==zero: x**0 = 1 */
+       if((iy|ly)==0) return one;      
+
+    /* +-NaN return x+y */
+       if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
+          iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) 
+               return x+y;     
+
+    /* determine if y is an odd int when x < 0
+     * yisint = 0      ... y is not an integer
+     * yisint = 1      ... y is an odd int
+     * yisint = 2      ... y is an even int
+     */
+       yisint  = 0;
+       if(hx<0) {      
+           if(iy>=0x43400000) yisint = 2; /* even integer y */
+           else if(iy>=0x3ff00000) {
+               k = (iy>>20)-0x3ff;        /* exponent */
+               if(k>20) {
+                   j = ly>>(52-k);
+                   if(static_cast<unsigned>(j<<(52-k))==ly) yisint = 2-(j&1);
+               } else if(ly==0) {
+                   j = iy>>(20-k);
+                   if((j<<(20-k))==iy) yisint = 2-(j&1);
+               }
+           }           
+       } 
+
+    /* special value of y */
+       if(ly==0) {     
+           if (iy==0x7ff00000) {       /* y is +-inf */
+               if(((ix-0x3ff00000)|lx)==0)
+                   return  y - y;      /* inf**+-1 is NaN */
+               else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
+                   return (hy>=0)? y: zero;
+               else                    /* (|x|<1)**-,+inf = inf,0 */
+                   return (hy<0)?-y: zero;
+           } 
+           if(iy==0x3ff00000) {        /* y is  +-1 */
+               if(hy<0) return one/x; else return x;
+           }
+           if(hy==0x40000000) return x*x; /* y is  2 */
+           if(hy==0x3fe00000) {        /* y is  0.5 */
+               if(hx>=0)       /* x >= +0 */
+               return sqrt(x); 
+           }
+       }
+
+       ax   = fabs(x);
+    /* special value of x */
+       if(lx==0) {
+           if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
+               z = ax;                 /*x is +-0,+-inf,+-1*/
+               if(hy<0) z = one/z;     /* z = (1/|x|) */
+               if(hx<0) {
+                   if(((ix-0x3ff00000)|yisint)==0) {
+                       z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+                   } else if(yisint==1) 
+                       z = -z;         /* (x<0)**odd = -(|x|**odd) */
+               }
+               return z;
+           }
+       }
+    
+       n = (hx>>31)+1;
+
+    /* (x<0)**(non-int) is NaN */
+       if((n|yisint)==0) return (x-x)/(x-x);
+
+       s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
+       if((n|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */
+
+    /* |y| is huge */
+       if(iy>0x41e00000) { /* if |y| > 2**31 */
+           if(iy>0x43f00000){  /* if |y| > 2**64, must o/uflow */
+               if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
+               if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
+           }
+       /* over/underflow if x is not close to one */
+           if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny;
+           if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny;
+       /* now |1-x| is tiny <= 2**-20, suffice to compute 
+          log(x) by x-x^2/2+x^3/3-x^4/4 */
+           t = ax-one;         /* t has 20 trailing zeros */
+           w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
+           u = ivln2_h*t;      /* ivln2_h has 21 sig. bits */
+           v = t*ivln2_l-w*ivln2;
+           t1 = u+v;
+           __LO(t1) = 0;
+           t2 = v-(t1-u);
+       } else {
+           double ss,s2,s_h,s_l,t_h,t_l;
+           n = 0;
+       /* take care subnormal number */
+           if(ix<0x00100000)
+               {ax *= two53; n -= 53; ix = __HI(ax); }
+           n  += ((ix)>>20)-0x3ff;
+           j  = ix&0x000fffff;
+       /* determine interval */
+           ix = j|0x3ff00000;          /* normalize ix */
+           if(j<=0x3988E) k=0;         /* |x|<sqrt(3/2) */
+           else if(j<0xBB67A) k=1;     /* |x|<sqrt(3)   */
+           else {k=0;n+=1;ix -= 0x00100000;}
+           __HI(ax) = ix;
+
+       /* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+           u = ax-bp[k];               /* bp[0]=1.0, bp[1]=1.5 */
+           v = one/(ax+bp[k]);
+           ss = u*v;
+           s_h = ss;
+           __LO(s_h) = 0;
+       /* t_h=ax+bp[k] High */
+           t_h = zero;
+           __HI(t_h)=((ix>>1)|0x20000000)+0x00080000+(k<<18); 
+           t_l = ax - (t_h-bp[k]);
+           s_l = v*((u-s_h*t_h)-s_h*t_l);
+       /* compute log(ax) */
+           s2 = ss*ss;
+           r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+           r += s_l*(s_h+ss);
+           s2  = s_h*s_h;
+           t_h = 3.0+s2+r;
+           __LO(t_h) = 0;
+           t_l = r-((t_h-3.0)-s2);
+       /* u+v = ss*(1+...) */
+           u = s_h*t_h;
+           v = s_l*t_h+t_l*ss;
+       /* 2/(3log2)*(ss+...) */
+           p_h = u+v;
+           __LO(p_h) = 0;
+           p_l = v-(p_h-u);
+           z_h = cp_h*p_h;             /* cp_h+cp_l = 2/(3*log2) */
+           z_l = cp_l*p_h+p_l*cp+dp_l[k];
+       /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+           t = (double)n;
+           t1 = (((z_h+z_l)+dp_h[k])+t);
+           __LO(t1) = 0;
+           t2 = z_l-(((t1-t)-dp_h[k])-z_h);
+       }
+
+    /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+       y1  = y;
+       __LO(y1) = 0;
+       p_l = (y-y1)*t1+y*t2;
+       p_h = y1*t1;
+       z = p_l+p_h;
+       j = __HI(z);
+       i = __LO(z);
+       if (j>=0x40900000) {                            /* z >= 1024 */
+           if(((j-0x40900000)|i)!=0)                   /* if z > 1024 */
+               return s*huge*huge;                     /* overflow */
+           else {
+               if(p_l+ovt>z-p_h) return s*huge*huge;   /* overflow */
+           }
+       } else if((j&0x7fffffff)>=0x4090cc00 ) {        /* z <= -1075 */
+           if(((j-0xc090cc00)|i)!=0)           /* z < -1075 */
+               return s*tiny*tiny;             /* underflow */
+           else {
+               if(p_l<=z-p_h) return s*tiny*tiny;      /* underflow */
+           }
+       }
+    /*
+     * compute 2**(p_h+p_l)
+     */
+       i = j&0x7fffffff;
+       k = (i>>20)-0x3ff;
+       n = 0;
+       if(i>0x3fe00000) {              /* if |z| > 0.5, set n = [z+0.5] */
+           n = j+(0x00100000>>(k+1));
+           k = ((n&0x7fffffff)>>20)-0x3ff;     /* new k for n */
+           t = zero;
+           __HI(t) = (n&~(0x000fffff>>k));
+           n = ((n&0x000fffff)|0x00100000)>>(20-k);
+           if(j<0) n = -n;
+           p_h -= t;
+       } 
+       t = p_l+p_h;
+       __LO(t) = 0;
+       u = t*lg2_h;
+       v = (p_l-(t-p_h))*lg2+t*lg2_l;
+       z = u+v;
+       w = v-(z-u);
+       t  = z*z;
+       t1  = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+       r  = (z*t1)/(t1-two)-(w+z*w);
+       z  = one-(r-z);
+       j  = __HI(z);
+       j += (n<<20);
+       if((j>>20)<=0) z = fdlibmScalbn(z,n);   /* subnormal output */
+       else __HI(z) += (n<<20);
+       return s*z;
+}
+
+#endif
+
 } // namespace JSC
 } // namespace JSC
index 75753be2922e9b794be2a14820bd5af8175f48f5..d8da039d801ca1bc8a6e05d9b5208b25e8bf6016 100644 (file)
 #ifndef MathObject_h
 #define MathObject_h
 
 #ifndef MathObject_h
 #define MathObject_h
 
-#include "JSObjectWithGlobalObject.h"
+#include "JSObject.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class MathObject : public JSObjectWithGlobalObject {
+    class MathObject : public JSNonFinalObject {
+    private:
+        MathObject(JSGlobalObject*, Structure*);
+
     public:
     public:
-        MathObject(ExecState*, JSGlobalObject*, Structure*);
+        typedef JSNonFinalObject Base;
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static MathObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+        {
+            MathObject* object = new (NotNull, allocateCell<MathObject>(*exec->heap())) MathObject(globalObject, structure);
+            object->finishCreation(exec, globalObject);
+            return object;
+        }
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
         static const ClassInfo s_info;
 
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
+        void finishCreation(ExecState*, JSGlobalObject*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
     };
 
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
     };
 
index d4b8b6fc1018ac06a84572e629cefceb3a60c4eb..9a86df29685822da95b584bf7eb748aaa2144d2b 100644 (file)
@@ -37,7 +37,7 @@ struct GlobalMemoryStatistics {
     size_t JITBytes;
 };
 
     size_t JITBytes;
 };
 
-GlobalMemoryStatistics globalMemoryStatistics();
+JS_EXPORT_PRIVATE GlobalMemoryStatistics globalMemoryStatistics();
 
 }
 
 
 }
 
index 2a7a7f5d45e3057ea6c550b34eae920d518d6b3b..b6aff916e4dd4b8b123966463cd5868273a8b0f7 100644 (file)
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(NativeErrorConstructor);
 
 
-const ClassInfo NativeErrorConstructor::s_info = { "Function", &InternalFunction::s_info, 0, 0 };
+const ClassInfo NativeErrorConstructor::s_info = { "Function", &InternalFunction::s_info, 0, 0, CREATE_METHOD_TABLE(NativeErrorConstructor) };
 
 
-NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* prototypeStructure, const UString& nameAndMessage)
-    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, nameAndMessage))
+NativeErrorConstructor::NativeErrorConstructor(JSGlobalObject* globalObject, Structure* structure)
+    : InternalFunction(globalObject, structure)
 {
 {
-    ASSERT(inherits(&s_info));
-
-    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);
 }
 
 }
 
-void NativeErrorConstructor::visitChildren(SlotVisitor& visitor)
+void NativeErrorConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    NativeErrorConstructor* thisObject = jsCast<NativeErrorConstructor*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
-    InternalFunction::visitChildren(visitor);
-    if (m_errorStructure)
-        visitor.append(&m_errorStructure);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    InternalFunction::visitChildren(thisObject, visitor);
+    if (thisObject->m_errorStructure)
+        visitor.append(&thisObject->m_errorStructure);
 }
 
 static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState* exec)
 }
 
 static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState* exec)
@@ -64,7 +57,7 @@ static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecStat
     return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
     return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
-ConstructType NativeErrorConstructor::getConstructData(ConstructData& constructData)
+ConstructType NativeErrorConstructor::getConstructData(JSCell*, ConstructData& constructData)
 {
     constructData.native.function = constructWithNativeErrorConstructor;
     return ConstructTypeHost;
 {
     constructData.native.function = constructWithNativeErrorConstructor;
     return ConstructTypeHost;
@@ -77,7 +70,7 @@ static EncodedJSValue JSC_HOST_CALL callNativeErrorConstructor(ExecState* exec)
     return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
     return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
-CallType NativeErrorConstructor::getCallData(CallData& callData)
+CallType NativeErrorConstructor::getCallData(JSCell*, CallData& callData)
 {
     callData.native.function = callNativeErrorConstructor;
     return CallTypeHost;
 {
     callData.native.function = callNativeErrorConstructor;
     return CallTypeHost;
index 4fb16f1a382e8b4c66119516282fb1687732f5e4..41e4235fad82fac665aef0b641e6df798dd5af3e 100644 (file)
@@ -22,6 +22,7 @@
 #define NativeErrorConstructor_h
 
 #include "InternalFunction.h"
 #define NativeErrorConstructor_h
 
 #include "InternalFunction.h"
+#include "NativeErrorPrototype.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -31,22 +32,45 @@ namespace JSC {
 
     class NativeErrorConstructor : public InternalFunction {
     public:
 
     class NativeErrorConstructor : public InternalFunction {
     public:
-        NativeErrorConstructor(ExecState*, JSGlobalObject*, Structure*, Structure* prototypeStructure, const UString&);
+        typedef InternalFunction Base;
 
 
+        static NativeErrorConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* prototypeStructure, const UString& name)
+        {
+            NativeErrorConstructor* constructor = new (NotNull, allocateCell<NativeErrorConstructor>(*exec->heap())) NativeErrorConstructor(globalObject, structure);
+            constructor->finishCreation(exec, globalObject, prototypeStructure, name);
+            return constructor;
+        }
+        
         static const ClassInfo s_info;
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
         Structure* errorStructure() { return m_errorStructure.get(); }
 
         }
 
         Structure* errorStructure() { return m_errorStructure.get(); }
 
+    protected:
+        void finishCreation(ExecState* exec, JSGlobalObject* globalObject, Structure* prototypeStructure, const UString& name)
+        {
+            Base::finishCreation(exec->globalData(), Identifier(exec, name));
+            ASSERT(inherits(&s_info));
+
+            NativeErrorPrototype* prototype = NativeErrorPrototype::create(exec, globalObject, prototypeStructure, name, 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(), globalObject, prototype));
+            ASSERT(m_errorStructure);
+            ASSERT(m_errorStructure->isObject());
+        }
+
     private:
     private:
+        NativeErrorConstructor(JSGlobalObject*, Structure*);
         static const unsigned StructureFlags = OverridesVisitChildren | InternalFunction::StructureFlags;
         static const unsigned StructureFlags = OverridesVisitChildren | InternalFunction::StructureFlags;
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
-        virtual void visitChildren(SlotVisitor&);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
+        static void visitChildren(JSCell*, SlotVisitor&);
 
         WriteBarrier<Structure> m_errorStructure;
     };
 
         WriteBarrier<Structure> m_errorStructure;
     };
index de27d59ee4e2ea05af5a00ac47d0fcb203ac82a1..dfdd87f85321b9197977bf5d7f59bc037b08764b 100644 (file)
@@ -21,7 +21,6 @@
 #include "config.h"
 #include "NativeErrorPrototype.h"
 
 #include "config.h"
 #include "NativeErrorPrototype.h"
 
-#include "ErrorPrototype.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
 #include "NativeErrorConstructor.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
 #include "NativeErrorConstructor.h"
@@ -31,11 +30,16 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype);
 
 
 ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype);
 
-NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const UString& nameAndMessage, NativeErrorConstructor* constructor)
-    : JSObjectWithGlobalObject(globalObject, structure)
+NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, Structure* structure)
+    : ErrorPrototype(exec, structure)
 {
 {
-    putDirect(exec->globalData(), exec->propertyNames().name, jsString(exec, nameAndMessage), 0);
-    putDirect(exec->globalData(), exec->propertyNames().message, jsString(exec, nameAndMessage), 0);
+}
+
+void NativeErrorPrototype::finishCreation(ExecState* exec, JSGlobalObject* globalObject, const UString& nameAndMessage, NativeErrorConstructor* constructor)
+{
+    Base::finishCreation(exec, globalObject);
+    putDirect(exec->globalData(), exec->propertyNames().name, jsString(exec, nameAndMessage), DontEnum);
+    putDirect(exec->globalData(), exec->propertyNames().message, jsEmptyString(exec), DontEnum);
     putDirect(exec->globalData(), exec->propertyNames().constructor, constructor, DontEnum);
 }
 
     putDirect(exec->globalData(), exec->propertyNames().constructor, constructor, DontEnum);
 }
 
index e1b05ceb82bc3f402f31d73659b3829257a10f6d..4bceb883a820b1e16c7c57a5a177edd1d640f170 100644 (file)
 #ifndef NativeErrorPrototype_h
 #define NativeErrorPrototype_h
 
 #ifndef NativeErrorPrototype_h
 #define NativeErrorPrototype_h
 
-#include "JSObjectWithGlobalObject.h"
+#include "ErrorPrototype.h"
 
 namespace JSC {
     class NativeErrorConstructor;
 
 
 namespace JSC {
     class NativeErrorConstructor;
 
-    class NativeErrorPrototype : public JSObjectWithGlobalObject {
+    class NativeErrorPrototype : public ErrorPrototype {
+    private:
+        NativeErrorPrototype(ExecState*, Structure*);
+    
     public:
     public:
-        NativeErrorPrototype(ExecState*, JSGlobalObject*, Structure*, const UString&, NativeErrorConstructor*);
+        typedef ErrorPrototype Base;
+
+        static NativeErrorPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const UString& name, NativeErrorConstructor* constructor)
+        {
+            NativeErrorPrototype* prototype = new (NotNull, allocateCell<NativeErrorPrototype>(*exec->heap())) NativeErrorPrototype(exec, structure);
+            prototype->finishCreation(exec, globalObject, name, constructor);
+            return prototype;
+        }
+
+    protected:
+        void finishCreation(ExecState*, JSGlobalObject*, const UString& nameAndMessage, NativeErrorConstructor*);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 6e469699a8320693e3095940c0b7723525ecec8f..e1ff62f3251e7dee580337db16bc573d5c6cedf6 100644 (file)
@@ -42,7 +42,9 @@ static JSValue numberConstructorMinValue(ExecState*, JSValue, const Identifier&)
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo NumberConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::numberConstructorTable };
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(NumberConstructor);
+
+const ClassInfo NumberConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::numberConstructorTable, CREATE_METHOD_TABLE(NumberConstructor) };
 
 /* Source for NumberConstructor.lut.h
 @begin numberConstructorTable
 
 /* Source for NumberConstructor.lut.h
 @begin numberConstructorTable
@@ -54,9 +56,14 @@ const ClassInfo NumberConstructor::s_info = { "Function", &InternalFunction::s_i
 @end
 */
 
 @end
 */
 
-NumberConstructor::NumberConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, NumberPrototype* numberPrototype)
-    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, numberPrototype->s_info.className))
+NumberConstructor::NumberConstructor(JSGlobalObject* globalObject, Structure* structure)
+    : InternalFunction(globalObject, structure) 
+{
+}
+
+void NumberConstructor::finishCreation(ExecState* exec, NumberPrototype* numberPrototype)
 {
 {
+    Base::finishCreation(exec->globalData(), Identifier(exec, numberPrototype->s_info.className));
     ASSERT(inherits(&s_info));
 
     // Number.Prototype
     ASSERT(inherits(&s_info));
 
     // Number.Prototype
@@ -66,14 +73,19 @@ NumberConstructor::NumberConstructor(ExecState* exec, JSGlobalObject* globalObje
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(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(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+    return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberConstructorTable(exec), jsCast<NumberConstructor*>(cell), propertyName, slot);
+}
+
+bool NumberConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberConstructorTable(exec), this, propertyName, slot);
+    return getStaticValueDescriptor<NumberConstructor, InternalFunction>(exec, ExecState::numberConstructorTable(exec), jsCast<NumberConstructor*>(object), propertyName, descriptor);
 }
 
 }
 
-bool NumberConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+void NumberConstructor::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
-    return getStaticValueDescriptor<NumberConstructor, InternalFunction>(exec, ExecState::numberConstructorTable(exec), this, propertyName, descriptor);
+    lookupPut<NumberConstructor, InternalFunction>(exec, propertyName, value, ExecState::numberConstructorTable(exec), jsCast<NumberConstructor*>(cell), slot);
 }
 
 static JSValue numberConstructorNaNValue(ExecState*, JSValue, const Identifier&)
 }
 
 static JSValue numberConstructorNaNValue(ExecState*, JSValue, const Identifier&)
@@ -83,12 +95,12 @@ static JSValue numberConstructorNaNValue(ExecState*, JSValue, const Identifier&)
 
 static JSValue numberConstructorNegInfinity(ExecState*, JSValue, const Identifier&)
 {
 
 static JSValue numberConstructorNegInfinity(ExecState*, JSValue, const Identifier&)
 {
-    return jsNumber(-Inf);
+    return jsNumber(-std::numeric_limits<double>::infinity());
 }
 
 static JSValue numberConstructorPosInfinity(ExecState*, JSValue, const Identifier&)
 {
 }
 
 static JSValue numberConstructorPosInfinity(ExecState*, JSValue, const Identifier&)
 {
-    return jsNumber(Inf);
+    return jsNumber(std::numeric_limits<double>::infinity());
 }
 
 static JSValue numberConstructorMaxValue(ExecState*, JSValue, const Identifier&)
 }
 
 static JSValue numberConstructorMaxValue(ExecState*, JSValue, const Identifier&)
@@ -104,13 +116,13 @@ static JSValue numberConstructorMinValue(ExecState*, JSValue, const Identifier&)
 // ECMA 15.7.1
 static EncodedJSValue JSC_HOST_CALL constructWithNumberConstructor(ExecState* exec)
 {
 // ECMA 15.7.1
 static EncodedJSValue JSC_HOST_CALL constructWithNumberConstructor(ExecState* exec)
 {
-    NumberObject* object = new (exec) NumberObject(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->numberObjectStructure());
+    NumberObject* object = NumberObject::create(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);
 }
 
     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(JSCell*, ConstructData& constructData)
 {
     constructData.native.function = constructWithNumberConstructor;
     return ConstructTypeHost;
 {
     constructData.native.function = constructWithNumberConstructor;
     return ConstructTypeHost;
@@ -122,7 +134,7 @@ static EncodedJSValue JSC_HOST_CALL callNumberConstructor(ExecState* exec)
     return JSValue::encode(jsNumber(!exec->argumentCount() ? 0 : exec->argument(0).toNumber(exec)));
 }
 
     return JSValue::encode(jsNumber(!exec->argumentCount() ? 0 : exec->argument(0).toNumber(exec)));
 }
 
-CallType NumberConstructor::getCallData(CallData& callData)
+CallType NumberConstructor::getCallData(JSCell*, CallData& callData)
 {
     callData.native.function = callNumberConstructor;
     return CallTypeHost;
 {
     callData.native.function = callNumberConstructor;
     return CallTypeHost;
index 69aa8a1320a70d8083754deeacdf013acb0039a1..4ee5b0716a17869a5ad30e56cddad4e474f32688 100644 (file)
@@ -29,27 +29,38 @@ namespace JSC {
 
     class NumberConstructor : public InternalFunction {
     public:
 
     class NumberConstructor : public InternalFunction {
     public:
-        NumberConstructor(ExecState*, JSGlobalObject*, Structure*, NumberPrototype*);
+        typedef InternalFunction Base;
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static NumberConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, NumberPrototype* numberPrototype)
+        {
+            NumberConstructor* constructor = new (NotNull, allocateCell<NumberConstructor>(*exec->heap())) NumberConstructor(globalObject, structure);
+            constructor->finishCreation(exec, numberPrototype);
+            return constructor;
+        }
+
+        static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
         JSValue getValueProperty(ExecState*, int token) const;
 
         static const ClassInfo s_info;
 
         JSValue getValueProperty(ExecState*, int token) const;
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) 
         { 
         { 
-            return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
+            return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info); 
         }
 
         enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
 
     protected:
         }
 
         enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
 
     protected:
+        void finishCreation(ExecState*, NumberPrototype*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | InternalFunction::StructureFlags;
 
     private:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | InternalFunction::StructureFlags;
 
     private:
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
+        NumberConstructor(JSGlobalObject*, Structure*);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 6ee103b38562951e522c5835295a90a6315f2bc7..1fea254647a4ed03826691765542580e94b3dc15 100644 (file)
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(NumberObject);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(NumberObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(NumberObject);
 
 
-const ClassInfo NumberObject::s_info = { "Number", &JSWrapperObject::s_info, 0, 0 };
+const ClassInfo NumberObject::s_info = { "Number", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(NumberObject) };
 
 NumberObject::NumberObject(JSGlobalData& globalData, Structure* structure)
     : JSWrapperObject(globalData, structure)
 {
 
 NumberObject::NumberObject(JSGlobalData& globalData, Structure* structure)
     : JSWrapperObject(globalData, structure)
 {
-    ASSERT(inherits(&s_info));
 }
 
 }
 
-JSValue NumberObject::getJSNumber()
+void NumberObject::finishCreation(JSGlobalData& globalData)
 {
 {
-    return internalValue();
+    Base::finishCreation(globalData);
+    ASSERT(inherits(&s_info));
 }
 
 NumberObject* constructNumber(ExecState* exec, JSGlobalObject* globalObject, JSValue number)
 {
 }
 
 NumberObject* constructNumber(ExecState* exec, JSGlobalObject* globalObject, JSValue number)
 {
-    NumberObject* object = new (exec) NumberObject(exec->globalData(), globalObject->numberObjectStructure());
+    NumberObject* object = NumberObject::create(exec->globalData(), globalObject->numberObjectStructure());
     object->setInternalValue(exec->globalData(), number);
     return object;
 }
     object->setInternalValue(exec->globalData(), number);
     return object;
 }
index cba65dd0f724849f8da6ad7ee3737525b363f710..07334722b936fd9ab5242018fe36cf5f650ea68f 100644 (file)
 namespace JSC {
 
     class NumberObject : public JSWrapperObject {
 namespace JSC {
 
     class NumberObject : public JSWrapperObject {
+    protected:
+        NumberObject(JSGlobalData&, Structure*);
+        void finishCreation(JSGlobalData&);
+
     public:
     public:
-        explicit NumberObject(JSGlobalData&, Structure*);
+        typedef JSWrapperObject Base;
+
+        static NumberObject* create(JSGlobalData& globalData, Structure* structure)
+        {
+            NumberObject* number = new (NotNull, allocateCell<NumberObject>(globalData.heap)) NumberObject(globalData, structure);
+            number->finishCreation(globalData);
+            return number;
+        }
 
         static const ClassInfo s_info;
 
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(NumberObjectType, StructureFlags), &s_info);
         }
         }
-
-    private:
-        virtual JSValue getJSNumber();
     };
 
     NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue);
     };
 
     NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue);
index cbf29da1a3711980a8ea9cd0607f98b0be6c13fb..060a80107e12890fbd27f80572cea5aa21c9116d 100644 (file)
 #include "config.h"
 #include "NumberPrototype.h"
 
 #include "config.h"
 #include "NumberPrototype.h"
 
+#include "BigInteger.h"
 #include "Error.h"
 #include "JSFunction.h"
 #include "Error.h"
 #include "JSFunction.h"
+#include "JSGlobalObject.h"
 #include "JSString.h"
 #include "Operations.h"
 #include "JSString.h"
 #include "Operations.h"
-#include "dtoa.h"
+#include "Uint16WithFraction.h"
+#include <wtf/dtoa.h>
 #include <wtf/Assertions.h>
 #include <wtf/Assertions.h>
-#include <wtf/DecimalNumber.h>
 #include <wtf/MathExtras.h>
 #include <wtf/Vector.h>
 #include <wtf/MathExtras.h>
 #include <wtf/Vector.h>
+#include <wtf/dtoa/double-conversion.h>
+
+using namespace WTF::double_conversion;
+
+// To avoid conflict with WTF::StringBuilder.
+typedef WTF::double_conversion::StringBuilder DoubleConversionStringBuilder;
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -47,7 +55,7 @@ static EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*);
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo NumberPrototype::s_info = { "Number", &NumberObject::s_info, 0, ExecState::numberPrototypeTable };
+const ClassInfo NumberPrototype::s_info = { "Number", &NumberObject::s_info, 0, ExecState::numberPrototypeTable, CREATE_METHOD_TABLE(NumberPrototype) };
 
 /* Source for NumberPrototype.lut.h
 @begin numberPrototypeTable
 
 /* Source for NumberPrototype.lut.h
 @begin numberPrototypeTable
@@ -61,35 +69,51 @@ const ClassInfo NumberPrototype::s_info = { "Number", &NumberObject::s_info, 0,
 */
 
 ASSERT_CLASS_FITS_IN_CELL(NumberPrototype);
 */
 
 ASSERT_CLASS_FITS_IN_CELL(NumberPrototype);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(NumberPrototype);
 
 
-NumberPrototype::NumberPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+NumberPrototype::NumberPrototype(ExecState* exec, Structure* structure)
     : NumberObject(exec->globalData(), structure)
 {
     : NumberObject(exec->globalData(), structure)
 {
+}
+
+void NumberPrototype::finishCreation(ExecState* exec, JSGlobalObject*)
+{
+    Base::finishCreation(exec->globalData());
     setInternalValue(exec->globalData(), jsNumber(0));
 
     ASSERT(inherits(&s_info));
     setInternalValue(exec->globalData(), jsNumber(0));
 
     ASSERT(inherits(&s_info));
-    putAnonymousValue(globalObject->globalData(), 0, globalObject);
 }
 
 }
 
-bool NumberPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+bool NumberPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 {
-    return getStaticFunctionSlot<NumberObject>(exec, ExecState::numberPrototypeTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<NumberObject>(exec, ExecState::numberPrototypeTable(exec), jsCast<NumberPrototype*>(cell), propertyName, slot);
 }
 
 }
 
-bool NumberPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool NumberPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<NumberObject>(exec, ExecState::numberPrototypeTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<NumberObject>(exec, ExecState::numberPrototypeTable(exec), jsCast<NumberPrototype*>(object), propertyName, descriptor);
 }
 
 // ------------------------------ Functions ---------------------------
 
 }
 
 // ------------------------------ Functions ---------------------------
 
-static ALWAYS_INLINE bool toThisNumber(JSValue thisValue, double &x)
+static ALWAYS_INLINE bool toThisNumber(JSValue thisValue, doublex)
 {
 {
-    JSValue v = thisValue.getJSNumber();
-    if (UNLIKELY(!v))
-        return false;
-    x = v.uncheckedGetNumber();
-    return true;
+    if (thisValue.isInt32()) {
+        x = thisValue.asInt32();
+        return true;
+    }
+
+    if (thisValue.isDouble()) {
+        x = thisValue.asDouble();
+        return true;
+    }
+    
+    if (thisValue.isCell() && thisValue.asCell()->structure()->typeInfo().isNumberObject()) {
+        x = static_cast<const NumberObject*>(thisValue.asCell())->internalValue().asNumber();
+        return true;
+    }
+
+    return false;
 }
 
 static ALWAYS_INLINE bool getIntegerArgumentInRange(ExecState* exec, int low, int high, int& result, bool& isUndefined)
 }
 
 static ALWAYS_INLINE bool getIntegerArgumentInRange(ExecState* exec, int low, int high, int& result, bool& isUndefined)
@@ -111,13 +135,241 @@ static ALWAYS_INLINE bool getIntegerArgumentInRange(ExecState* exec, int low, in
     return true;
 }
 
     return true;
 }
 
+// The largest finite floating point number is 1.mantissa * 2^(0x7fe-0x3ff).
+// Since 2^N in binary is a one bit followed by N zero bits. 1 * 2^3ff requires
+// at most 1024 characters to the left of a decimal point, in base 2 (1025 if
+// we include a minus sign). For the fraction, a value with an exponent of 0
+// has up to 52 bits to the right of the decimal point. Each decrement of the
+// exponent down to a minimum of -0x3fe adds an additional digit to the length
+// of the fraction. As such the maximum fraction size is 1075 (1076 including
+// a point). We pick a buffer size such that can simply place the point in the
+// center of the buffer, and are guaranteed to have enough space in each direction
+// fo any number of digits an IEEE number may require to represent.
+typedef char RadixBuffer[2180];
+
+// Mapping from integers 0..35 to digit identifying this value, for radix 2..36.
+static const char radixDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+static char* toStringWithRadix(RadixBuffer& buffer, double number, unsigned radix)
+{
+    ASSERT(isfinite(number));
+    ASSERT(radix >= 2 && radix <= 36);
+
+    // Position the decimal point at the center of the string, set
+    // the startOfResultString pointer to point at the decimal point.
+    char* decimalPoint = buffer + sizeof(buffer) / 2;
+    char* startOfResultString = decimalPoint;
+
+    // Extract the sign.
+    bool isNegative = number < 0;
+    if (signbit(number))
+        number = -number;
+    double integerPart = floor(number);
+
+    // We use this to test for odd values in odd radix bases.
+    // Where the base is even, (e.g. 10), to determine whether a value is even we need only
+    // consider the least significant digit. For example, 124 in base 10 is even, because '4'
+    // is even. if the radix is odd, then the radix raised to an integer power is also odd.
+    // E.g. in base 5, 124 represents (1 * 125 + 2 * 25 + 4 * 5). Since each digit in the value
+    // is multiplied by an odd number, the result is even if the sum of all digits is even.
+    //
+    // For the integer portion of the result, we only need test whether the integer value is
+    // even or odd. For each digit of the fraction added, we should invert our idea of whether
+    // the number is odd if the new digit is odd.
+    //
+    // Also initialize digit to this value; for even radix values we only need track whether
+    // the last individual digit was odd.
+    bool integerPartIsOdd = integerPart <= static_cast<double>(0x1FFFFFFFFFFFFFull) && static_cast<int64_t>(integerPart) & 1;
+    ASSERT(integerPartIsOdd == static_cast<bool>(fmod(integerPart, 2)));
+    bool isOddInOddRadix = integerPartIsOdd;
+    uint32_t digit = integerPartIsOdd;
+
+    // Check if the value has a fractional part to convert.
+    double fractionPart = number - integerPart;
+    if (fractionPart) {
+        // Write the decimal point now.
+        *decimalPoint = '.';
+
+        // Higher precision representation of the fractional part.
+        Uint16WithFraction fraction(fractionPart);
+
+        bool needsRoundingUp = false;
+        char* endOfResultString = decimalPoint + 1;
+
+        // Calculate the delta from the current number to the next & previous possible IEEE numbers.
+        double nextNumber = nextafter(number, std::numeric_limits<double>::infinity());
+        double lastNumber = nextafter(number, -std::numeric_limits<double>::infinity());
+        ASSERT(isfinite(nextNumber) && !signbit(nextNumber));
+        ASSERT(isfinite(lastNumber) && !signbit(lastNumber));
+        double deltaNextDouble = nextNumber - number;
+        double deltaLastDouble = number - lastNumber;
+        ASSERT(isfinite(deltaNextDouble) && !signbit(deltaNextDouble));
+        ASSERT(isfinite(deltaLastDouble) && !signbit(deltaLastDouble));
+
+        // We track the delta from the current value to the next, to track how many digits of the
+        // fraction we need to write. For example, if the value we are converting is precisely
+        // 1.2345, so far we have written the digits "1.23" to a string leaving a remainder of
+        // 0.45, and we want to determine whether we can round off, or whether we need to keep
+        // appending digits ('4'). We can stop adding digits provided that then next possible
+        // lower IEEE value is further from 1.23 than the remainder we'd be rounding off (0.45),
+        // which is to say, less than 1.2255. Put another way, the delta between the prior
+        // possible value and this number must be more than 2x the remainder we'd be rounding off
+        // (or more simply half the delta between numbers must be greater than the remainder).
+        //
+        // Similarly we need track the delta to the next possible value, to dertermine whether
+        // to round up. In almost all cases (other than at exponent boundaries) the deltas to
+        // prior and subsequent values are identical, so we don't need track then separately.
+        if (deltaNextDouble != deltaLastDouble) {
+            // Since the deltas are different track them separately. Pre-multiply by 0.5.
+            Uint16WithFraction halfDeltaNext(deltaNextDouble, 1);
+            Uint16WithFraction halfDeltaLast(deltaLastDouble, 1);
+
+            while (true) {
+                // examine the remainder to determine whether we should be considering rounding
+                // up or down. If remainder is precisely 0.5 rounding is to even.
+                int dComparePoint5 = fraction.comparePoint5();
+                if (dComparePoint5 > 0 || (!dComparePoint5 && (radix & 1 ? isOddInOddRadix : digit & 1))) {
+                    // Check for rounding up; are we closer to the value we'd round off to than
+                    // the next IEEE value would be?
+                    if (fraction.sumGreaterThanOne(halfDeltaNext)) {
+                        needsRoundingUp = true;
+                        break;
+                    }
+                } else {
+                    // Check for rounding down; are we closer to the value we'd round off to than
+                    // the prior IEEE value would be?
+                    if (fraction < halfDeltaLast)
+                        break;
+                }
+
+                ASSERT(endOfResultString < (buffer + sizeof(buffer) - 1));
+                // Write a digit to the string.
+                fraction *= radix;
+                digit = fraction.floorAndSubtract();
+                *endOfResultString++ = radixDigits[digit];
+                // Keep track whether the portion written is currently even, if the radix is odd.
+                if (digit & 1)
+                    isOddInOddRadix = !isOddInOddRadix;
+
+                // Shift the fractions by radix.
+                halfDeltaNext *= radix;
+                halfDeltaLast *= radix;
+            }
+        } else {
+            // This code is identical to that above, except since deltaNextDouble != deltaLastDouble
+            // we don't need to track these two values separately.
+            Uint16WithFraction halfDelta(deltaNextDouble, 1);
+
+            while (true) {
+                int dComparePoint5 = fraction.comparePoint5();
+                if (dComparePoint5 > 0 || (!dComparePoint5 && (radix & 1 ? isOddInOddRadix : digit & 1))) {
+                    if (fraction.sumGreaterThanOne(halfDelta)) {
+                        needsRoundingUp = true;
+                        break;
+                    }
+                } else if (fraction < halfDelta)
+                    break;
+
+                ASSERT(endOfResultString < (buffer + sizeof(buffer) - 1));
+                fraction *= radix;
+                digit = fraction.floorAndSubtract();
+                if (digit & 1)
+                    isOddInOddRadix = !isOddInOddRadix;
+                *endOfResultString++ = radixDigits[digit];
+
+                halfDelta *= radix;
+            }
+        }
+
+        // Check if the fraction needs rounding off (flag set in the loop writing digits, above).
+        if (needsRoundingUp) {
+            // Whilst the last digit is the maximum in the current radix, remove it.
+            // e.g. rounding up the last digit in "12.3999" is the same as rounding up the
+            // last digit in "12.3" - both round up to "12.4".
+            while (endOfResultString[-1] == radixDigits[radix - 1])
+                --endOfResultString;
+
+            // Radix digits are sequential in ascii/unicode, except for '9' and 'a'.
+            // E.g. the first 'if' case handles rounding 67.89 to 67.8a in base 16.
+            // The 'else if' case handles rounding of all other digits.
+            if (endOfResultString[-1] == '9')
+                endOfResultString[-1] = 'a';
+            else if (endOfResultString[-1] != '.')
+                ++endOfResultString[-1];
+            else {
+                // One other possibility - there may be no digits to round up in the fraction
+                // (or all may be been rounded off already), in which case we may need to
+                // round into the integer portion of the number. Remove the decimal point.
+                --endOfResultString;
+                // In order to get here there must have been a non-zero fraction, in which case
+                // there must be at least one bit of the value's mantissa not in use in the
+                // integer part of the number. As such, adding to the integer part should not
+                // be able to lose precision.
+                ASSERT((integerPart + 1) - integerPart == 1);
+                ++integerPart;
+            }
+        } else {
+            // We only need to check for trailing zeros if the value does not get rounded up.
+            while (endOfResultString[-1] == '0')
+                --endOfResultString;
+        }
+
+        *endOfResultString = '\0';
+        ASSERT(endOfResultString < buffer + sizeof(buffer));
+    } else
+        *decimalPoint = '\0';
+
+    BigInteger units(integerPart);
+
+    // Always loop at least once, to emit at least '0'.
+    do {
+        ASSERT(buffer < startOfResultString);
+
+        // Read a single digit and write it to the front of the string.
+        // Divide by radix to remove one digit from the value.
+        digit = units.divide(radix);
+        *--startOfResultString = radixDigits[digit];
+    } while (!!units);
+
+    // If the number is negative, prepend '-'.
+    if (isNegative)
+        *--startOfResultString = '-';
+    ASSERT(buffer <= startOfResultString);
+
+    return startOfResultString;
+}
+
+static UString toUStringWithRadix(int32_t number, unsigned radix)
+{
+    LChar buf[1 + 32]; // Worst case is radix == 2, which gives us 32 digits + sign.
+    LChar* end = buf + WTF_ARRAY_LENGTH(buf);
+    LChar* p = end;
+
+    bool negative = false;
+    uint32_t positiveNumber = number;
+    if (number < 0) {
+        negative = true;
+        positiveNumber = -number;
+    }
+
+    while (positiveNumber) {
+        uint32_t index = positiveNumber % radix;
+        ASSERT(index < sizeof(radixDigits));
+        *--p = static_cast<LChar>(radixDigits[index]);
+        positiveNumber /= radix;
+    }
+    if (negative)
+        *--p = '-';
+
+    return UString(p, static_cast<unsigned>(end - p));
+}
+
 // 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)
 {
 // 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)
 {
-    // Get x (the double value of this, which should be a Number).
     double x;
     if (!toThisNumber(exec->hostThisValue(), x))
         return throwVMTypeError(exec);
     double x;
     if (!toThisNumber(exec->hostThisValue(), x))
         return throwVMTypeError(exec);
@@ -129,16 +381,18 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec)
         return throwVMError(exec, createRangeError(exec, "toExponential() argument must be between 0 and 20"));
 
     // Handle NaN and Infinity.
         return throwVMError(exec, createRangeError(exec, "toExponential() argument must be between 0 and 20"));
 
     // Handle NaN and Infinity.
-    if (isnan(x) || isinf(x))
+    if (!isfinite(x))
         return JSValue::encode(jsString(exec, UString::number(x)));
 
     // Round if the argument is not undefined, always format as exponential.
         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 JSValue::encode(jsString(exec, UString(buffer, length)));
+    char buffer[WTF::NumberToStringBufferLength];
+    DoubleConversionStringBuilder builder(buffer, WTF::NumberToStringBufferLength);
+    const DoubleToStringConverter& converter = DoubleToStringConverter::EcmaScriptConverter();
+    builder.Reset();
+    isUndefined
+        ? converter.ToExponential(x, -1, &builder)
+        : converter.ToExponential(x, decimalPlacesInExponent, &builder);
+    return JSValue::encode(jsString(exec, UString(builder.Finalize())));
 }
 
 // toFixed converts a number to a string, always formatting as an a decimal fraction.
 }
 
 // toFixed converts a number to a string, always formatting as an a decimal fraction.
@@ -147,12 +401,9 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec)
 // method will instead fallback to calling ToString. 
 EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec)
 {
 // method will instead fallback to calling ToString. 
 EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec)
 {
-    // Get x (the double value of this, which should be a Number).
-    JSValue thisValue = exec->hostThisValue();
-    JSValue v = thisValue.getJSNumber();
-    if (!v)
+    double x;
+    if (!toThisNumber(exec->hostThisValue(), x))
         return throwVMTypeError(exec);
         return throwVMTypeError(exec);
-    double x = v.uncheckedGetNumber();
 
     // Get the argument. 
     int decimalPlaces;
 
     // Get the argument. 
     int decimalPlaces;
@@ -168,12 +419,10 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec)
 
     // The check above will return false for NaN or Infinity, these will be
     // handled by numberToString.
 
     // The check above will return false for NaN or Infinity, these will be
     // handled by numberToString.
-    ASSERT(!isnan(x) && !isinf(x));
+    ASSERT(isfinite(x));
 
 
-    // Convert to decimal with rounding, and format as decimal.
     NumberToStringBuffer buffer;
     NumberToStringBuffer buffer;
-    unsigned length = DecimalNumber(x, RoundingDecimalPlaces, decimalPlaces).toStringDecimal(buffer, WTF::NumberToStringBufferLength);
-    return JSValue::encode(jsString(exec, UString(buffer, length)));
+    return JSValue::encode(jsString(exec, UString(numberToFixedWidthString(x, decimalPlaces, buffer))));
 }
 
 // toPrecision converts a number to a string, takeing an argument specifying a
 }
 
 // toPrecision converts a number to a string, takeing an argument specifying a
@@ -185,12 +434,9 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec)
 // with smaller values converted to exponential representation.
 EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec)
 {
 // 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)
+    double x;
+    if (!toThisNumber(exec->hostThisValue(), x))
         return throwVMTypeError(exec);
         return throwVMTypeError(exec);
-    double x = v.uncheckedGetNumber();
 
     // Get the argument. 
     int significantFigures;
 
     // Get the argument. 
     int significantFigures;
@@ -203,126 +449,87 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec)
         return JSValue::encode(jsString(exec, UString::number(x)));
 
     // Handle NaN and Infinity.
         return JSValue::encode(jsString(exec, UString::number(x)));
 
     // Handle NaN and Infinity.
-    if (isnan(x) || isinf(x))
+    if (!isfinite(x))
         return JSValue::encode(jsString(exec, UString::number(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;
     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)));
+    return JSValue::encode(jsString(exec, UString(numberToFixedPrecisionString(x, significantFigures, buffer))));
 }
 
 }
 
-EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec)
+static inline int32_t extractRadixFromArgs(ExecState* exec)
 {
 {
-    JSValue thisValue = exec->hostThisValue();
-    JSValue v = thisValue.getJSNumber();
-    if (!v)
-        return throwVMTypeError(exec);
-
     JSValue radixValue = exec->argument(0);
     JSValue radixValue = exec->argument(0);
-    int radix;
+    int32_t radix;
     if (radixValue.isInt32())
         radix = radixValue.asInt32();
     else if (radixValue.isUndefined())
         radix = 10;
     else
     if (radixValue.isInt32())
         radix = radixValue.asInt32();
     else if (radixValue.isUndefined())
         radix = 10;
     else
-        radix = static_cast<int>(radixValue.toInteger(exec)); // nan -> 0
+        radix = static_cast<int32_t>(radixValue.toInteger(exec)); // nan -> 0
 
 
-    if (radix == 10)
-        return JSValue::encode(jsString(exec, v.toString(exec)));
+    return radix;
+}
 
 
-    static const char* const digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+static inline EncodedJSValue integerValueToString(ExecState* exec, int32_t radix, int32_t value)
+{
+    // A negative value casted to unsigned would be bigger than 36 (the max radix).
+    if (static_cast<unsigned>(value) < static_cast<unsigned>(radix)) {
+        ASSERT(value <= 36);
+        ASSERT(value >= 0);
+        JSGlobalData* globalData = &exec->globalData();
+        return JSValue::encode(globalData->smallStrings.singleCharacterString(globalData, radixDigits[value]));
+    }
 
 
-    // Fast path for number to character conversion.
-    if (radix == 36) {
-        if (v.isInt32()) {
-            int x = v.asInt32();
-            if (static_cast<unsigned>(x) < 36) { // Exclude negatives
-                JSGlobalData* globalData = &exec->globalData();
-                return JSValue::encode(globalData->smallStrings.singleCharacterString(globalData, digits[x]));
-            }
-        }
+    if (radix == 10) {
+        JSGlobalData* globalData = &exec->globalData();
+        return JSValue::encode(jsString(globalData, globalData->numericStrings.add(value)));
     }
 
     }
 
-    if (radix < 2 || radix > 36)
-        return throwVMError(exec, createRangeError(exec, "toString() radix argument must be between 2 and 36"));
+    return JSValue::encode(jsString(exec, toUStringWithRadix(value, radix)));
 
 
-    // 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
-    // unless someone finds a precise rule.
-    char s[2048 + 3];
-    const char* lastCharInString = s + sizeof(s) - 1;
-    double x = v.uncheckedGetNumber();
-    if (isnan(x) || isinf(x))
-        return JSValue::encode(jsString(exec, UString::number(x)));
+}
 
 
-    bool isNegative = x < 0.0;
-    if (isNegative)
-        x = -x;
+EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec)
+{
+    double doubleValue;
+    if (!toThisNumber(exec->hostThisValue(), doubleValue))
+        return throwVMTypeError(exec);
 
 
-    double integerPart = floor(x);
-    char* decimalPoint = s + sizeof(s) / 2;
+    int32_t radix = extractRadixFromArgs(exec);
+    if (radix < 2 || radix > 36)
+        return throwVMError(exec, createRangeError(exec, "toString() radix argument must be between 2 and 36"));
 
 
-    // convert integer portion
-    char* p = decimalPoint;
-    double d = integerPart;
-    do {
-        int remainderDigit = static_cast<int>(fmod(d, radix));
-        *--p = digits[remainderDigit];
-        d /= radix;
-    } while ((d <= -1.0 || d >= 1.0) && s < p);
+    int32_t integerValue = static_cast<int32_t>(doubleValue);
+    if (integerValue == doubleValue)
+        return integerValueToString(exec, radix, integerValue);
 
 
-    if (isNegative)
-        *--p = '-';
-    char* startOfResultString = p;
-    ASSERT(s <= startOfResultString);
-
-    d = x - integerPart;
-    p = decimalPoint;
-    const double epsilon = 0.001; // TODO: guessed. base on radix ?
-    bool hasFractionalPart = (d < -epsilon || d > epsilon);
-    if (hasFractionalPart) {
-        *p++ = '.';
-        do {
-            d *= radix;
-            const int digit = static_cast<int>(d);
-            *p++ = digits[digit];
-            d -= digit;
-        } while ((d < -epsilon || d > epsilon) && p < lastCharInString);
+    if (radix == 10) {
+        JSGlobalData* globalData = &exec->globalData();
+        return JSValue::encode(jsString(globalData, globalData->numericStrings.add(doubleValue)));
     }
     }
-    *p = '\0';
-    ASSERT(p < s + sizeof(s));
 
 
-    return JSValue::encode(jsString(exec, startOfResultString));
+    if (!isfinite(doubleValue))
+        return JSValue::encode(jsString(exec, UString::number(doubleValue)));
+
+    RadixBuffer s;
+    return JSValue::encode(jsString(exec, toStringWithRadix(s, doubleValue, radix)));
 }
 
 EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec)
 {
 }
 
 EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec)
 {
-    JSValue thisValue = exec->hostThisValue();
-    // FIXME: Not implemented yet.
-
-    JSValue v = thisValue.getJSNumber();
-    if (!v)
+    double x;
+    if (!toThisNumber(exec->hostThisValue(), x))
         return throwVMTypeError(exec);
 
         return throwVMTypeError(exec);
 
-    return JSValue::encode(jsString(exec, v.toString(exec)));
+    return JSValue::encode(jsNumber(x).toString(exec));
 }
 
 EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec)
 {
 }
 
 EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec)
 {
-    JSValue thisValue = exec->hostThisValue();
-    JSValue v = thisValue.getJSNumber();
-    if (!v)
+    double x;
+    if (!toThisNumber(exec->hostThisValue(), x))
         return throwVMTypeError(exec);
         return throwVMTypeError(exec);
-
-    return JSValue::encode(v);
+    return JSValue::encode(jsNumber(x));
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 1f1323b687ee7abe47618f107539f271d5b1cd3e..d63cc3a6ff37c88e033bd17be50750d8764d8ec8 100644 (file)
@@ -27,22 +27,30 @@ namespace JSC {
 
     class NumberPrototype : public NumberObject {
     public:
 
     class NumberPrototype : public NumberObject {
     public:
-        NumberPrototype(ExecState*, JSGlobalObject*, Structure*);
+        typedef NumberObject Base;
 
 
+        static NumberPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+        {
+            NumberPrototype* prototype = new (NotNull, allocateCell<NumberPrototype>(*exec->heap())) NumberPrototype(exec, structure);
+            prototype->finishCreation(exec, globalObject);
+            return prototype;
+        }
+        
         static const ClassInfo s_info;
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(NumberObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
+        void finishCreation(ExecState*, JSGlobalObject*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NumberObject::StructureFlags;
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NumberObject::StructureFlags;
-        static const unsigned AnonymousSlotCount = NumberObject::AnonymousSlotCount + 1;
 
     private:
 
     private:
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        NumberPrototype(ExecState*, Structure*);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index d65f14265cdf63fb7449fa49e6f4ef8cdf00af1e..7fa20c44d50edaa2afc184d43c04d5e76b9e0bb2 100644 (file)
@@ -34,7 +34,7 @@ namespace JSC {
 
     class NumericStrings {
     public:
 
     class NumericStrings {
     public:
-        UString add(double d)
+        ALWAYS_INLINE UString add(double d)
         {
             CacheEntry<double>& entry = lookup(d);
             if (d == entry.key && !entry.value.isNull())
         {
             CacheEntry<double>& entry = lookup(d);
             if (d == entry.key && !entry.value.isNull())
@@ -44,7 +44,7 @@ namespace JSC {
             return entry.value;
         }
 
             return entry.value;
         }
 
-        UString add(int i)
+        ALWAYS_INLINE UString add(int i)
         {
             if (static_cast<unsigned>(i) < cacheSize)
                 return lookupSmallString(static_cast<unsigned>(i));
         {
             if (static_cast<unsigned>(i) < cacheSize)
                 return lookupSmallString(static_cast<unsigned>(i));
@@ -56,7 +56,7 @@ namespace JSC {
             return entry.value;
         }
 
             return entry.value;
         }
 
-        UString add(unsigned i)
+        ALWAYS_INLINE UString add(unsigned i)
         {
             if (i < cacheSize)
                 return lookupSmallString(static_cast<unsigned>(i));
         {
             if (i < cacheSize)
                 return lookupSmallString(static_cast<unsigned>(i));
@@ -79,7 +79,7 @@ namespace JSC {
         CacheEntry<double>& lookup(double d) { return doubleCache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; }
         CacheEntry<int>& lookup(int i) { return intCache[WTF::IntHash<int>::hash(i) & (cacheSize - 1)]; }
         CacheEntry<unsigned>& lookup(unsigned i) { return unsignedCache[WTF::IntHash<unsigned>::hash(i) & (cacheSize - 1)]; }
         CacheEntry<double>& lookup(double d) { return doubleCache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; }
         CacheEntry<int>& lookup(int i) { return intCache[WTF::IntHash<int>::hash(i) & (cacheSize - 1)]; }
         CacheEntry<unsigned>& lookup(unsigned i) { return unsignedCache[WTF::IntHash<unsigned>::hash(i) & (cacheSize - 1)]; }
-        const UString& lookupSmallString(unsigned i)
+        ALWAYS_INLINE const UString& lookupSmallString(unsigned i)
         {
             ASSERT(i < cacheSize);
             if (smallIntCache[i].isNull())
         {
             ASSERT(i < cacheSize);
             if (smallIntCache[i].isNull())
index 6efcea61fb23500bd450621d206d83f9eac2b49c..b7dd716556d54da2bcbf7042a9fd6d224062dd6e 100644 (file)
@@ -55,7 +55,9 @@ static EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState*);
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo ObjectConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::objectConstructorTable };
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ObjectConstructor);
+
+const ClassInfo ObjectConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::objectConstructorTable, CREATE_METHOD_TABLE(ObjectConstructor) };
 
 /* Source for ObjectConstructor.lut.h
 @begin objectConstructorTable
 
 /* Source for ObjectConstructor.lut.h
 @begin objectConstructorTable
@@ -75,23 +77,28 @@ const ClassInfo ObjectConstructor::s_info = { "Function", &InternalFunction::s_i
 @end
 */
 
 @end
 */
 
-ObjectConstructor::ObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ObjectPrototype* objectPrototype)
-    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, "Object"))
+ObjectConstructor::ObjectConstructor(JSGlobalObject* globalObject, Structure* structure)
+    : InternalFunction(globalObject, structure)
 {
 {
+}
+
+void ObjectConstructor::finishCreation(ExecState* exec, ObjectPrototype* objectPrototype)
+{
+    Base::finishCreation(exec->globalData(), Identifier(exec, "Object"));
     // ECMA 15.2.3.1
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
     // no. of arguments for constructor
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
 
     // ECMA 15.2.3.1
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
     // no. of arguments for constructor
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
 
-bool ObjectConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+bool ObjectConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 {
-    return getStaticFunctionSlot<JSObject>(exec, ExecState::objectConstructorTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<JSObject>(exec, ExecState::objectConstructorTable(exec), jsCast<ObjectConstructor*>(cell), propertyName, slot);
 }
 
 }
 
-bool ObjectConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool ObjectConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::objectConstructorTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::objectConstructorTable(exec), jsCast<ObjectConstructor*>(object), propertyName, descriptor);
 }
 
 // ECMA 15.2.2
 }
 
 // ECMA 15.2.2
@@ -109,7 +116,7 @@ static EncodedJSValue JSC_HOST_CALL constructWithObjectConstructor(ExecState* ex
     return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
     return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
-ConstructType ObjectConstructor::getConstructData(ConstructData& constructData)
+ConstructType ObjectConstructor::getConstructData(JSCell*, ConstructData& constructData)
 {
     constructData.native.function = constructWithObjectConstructor;
     return ConstructTypeHost;
 {
     constructData.native.function = constructWithObjectConstructor;
     return ConstructTypeHost;
@@ -121,7 +128,7 @@ static EncodedJSValue JSC_HOST_CALL callObjectConstructor(ExecState* exec)
     return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
     return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
-CallType ObjectConstructor::getCallData(CallData& callData)
+CallType ObjectConstructor::getCallData(JSCell*, CallData& callData)
 {
     callData.native.function = callObjectConstructor;
     return CallTypeHost;
 {
     callData.native.function = callObjectConstructor;
     return CallTypeHost;
@@ -131,23 +138,22 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec)
 {
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, "Requested prototype of a value that is not an object."));
 {
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, "Requested prototype of a value that is not an object."));
-        
-    // This uses JSValue::get() instead of directly accessing the prototype from the object
-    // (using JSObject::prototype()) in order to allow objects to override the behavior, such
-    // as returning jsUndefined() for cross-origin access.
-    return JSValue::encode(exec->argument(0).get(exec, exec->propertyNames().underscoreProto));
+    JSObject* object = asObject(exec->argument(0));
+    if (!object->allowsAccessFrom(exec->trueCallerFrame()))
+        return JSValue::encode(jsUndefined());
+    return JSValue::encode(object->prototype());
 }
 
 EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec)
 {
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, "Requested property descriptor of a value that is not an object."));
 }
 
 EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* 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);
+    UString propertyName = exec->argument(1).toString(exec)->value(exec);
     if (exec->hadException())
         return JSValue::encode(jsNull());
     JSObject* object = asObject(exec->argument(0));
     PropertyDescriptor descriptor;
     if (exec->hadException())
         return JSValue::encode(jsNull());
     JSObject* object = asObject(exec->argument(0));
     PropertyDescriptor descriptor;
-    if (!object->getOwnPropertyDescriptor(exec, Identifier(exec, propertyName), descriptor))
+    if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, Identifier(exec, propertyName), descriptor))
         return JSValue::encode(jsUndefined());
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
         return JSValue::encode(jsUndefined());
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
@@ -157,8 +163,10 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState
         description->putDirect(exec->globalData(), exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
         description->putDirect(exec->globalData(), exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
     } else {
         description->putDirect(exec->globalData(), exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
         description->putDirect(exec->globalData(), exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
     } else {
-        description->putDirect(exec->globalData(), exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0);
-        description->putDirect(exec->globalData(), exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0);
+        ASSERT(descriptor.getter());
+        ASSERT(descriptor.setter());
+        description->putDirect(exec->globalData(), exec->propertyNames().get, descriptor.getter(), 0);
+        description->putDirect(exec->globalData(), exec->propertyNames().set, descriptor.setter(), 0);
     }
     
     description->putDirect(exec->globalData(), exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
     }
     
     description->putDirect(exec->globalData(), exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
@@ -173,7 +181,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState* exe
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, "Requested property names of a value that is not an object."));
     PropertyNameArray properties(exec);
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, "Requested property names of a value that is not an object."));
     PropertyNameArray properties(exec);
-    asObject(exec->argument(0))->getOwnPropertyNames(exec, properties, IncludeDontEnumProperties);
+    asObject(exec->argument(0))->methodTable()->getOwnPropertyNames(asObject(exec->argument(0)), exec, properties, IncludeDontEnumProperties);
     JSArray* names = constructEmptyArray(exec);
     size_t numProperties = properties.size();
     for (size_t i = 0; i < numProperties; i++)
     JSArray* names = constructEmptyArray(exec);
     size_t numProperties = properties.size();
     for (size_t i = 0; i < numProperties; i++)
@@ -187,7 +195,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec)
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, "Requested keys of a value that is not an object."));
     PropertyNameArray properties(exec);
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, "Requested keys of a value that is not an object."));
     PropertyNameArray properties(exec);
-    asObject(exec->argument(0))->getOwnPropertyNames(exec, properties);
+    asObject(exec->argument(0))->methodTable()->getOwnPropertyNames(asObject(exec->argument(0)), exec, properties, ExcludeDontEnumProperties);
     JSArray* keys = constructEmptyArray(exec);
     size_t numProperties = properties.size();
     for (size_t i = 0; i < numProperties; i++)
     JSArray* keys = constructEmptyArray(exec);
     size_t numProperties = properties.size();
     for (size_t i = 0; i < numProperties; i++)
@@ -244,8 +252,7 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor
                 throwError(exec, createTypeError(exec, "Getter must be a function."));
                 return false;
             }
                 throwError(exec, createTypeError(exec, "Getter must be a function."));
                 return false;
             }
-        } else
-            get = JSValue();
+        }
         desc.setGetter(get);
     }
 
         desc.setGetter(get);
     }
 
@@ -260,9 +267,7 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor
                 throwError(exec, createTypeError(exec, "Setter must be a function."));
                 return false;
             }
                 throwError(exec, createTypeError(exec, "Setter must be a function."));
                 return false;
             }
-        } else
-            set = JSValue();
-
+        }
         desc.setSetter(set);
     }
 
         desc.setSetter(set);
     }
 
@@ -286,22 +291,22 @@ EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec)
     if (!exec->argument(0).isObject())
         return throwVMError(exec, createTypeError(exec, "Properties can only be defined on Objects."));
     JSObject* O = asObject(exec->argument(0));
     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);
+    UString propertyName = exec->argument(1).toString(exec)->value(exec);
     if (exec->hadException())
         return JSValue::encode(jsNull());
     PropertyDescriptor descriptor;
     if (!toPropertyDescriptor(exec, exec->argument(2), descriptor))
         return JSValue::encode(jsNull());
     if (exec->hadException())
         return JSValue::encode(jsNull());
     PropertyDescriptor descriptor;
     if (!toPropertyDescriptor(exec, exec->argument(2), descriptor))
         return JSValue::encode(jsNull());
-    ASSERT((descriptor.attributes() & (Getter | Setter)) || (!descriptor.isAccessorDescriptor()));
+    ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
     ASSERT(!exec->hadException());
     ASSERT(!exec->hadException());
-    O->defineOwnProperty(exec, Identifier(exec, propertyName), descriptor, true);
+    O->methodTable()->defineOwnProperty(O, exec, Identifier(exec, propertyName), descriptor, true);
     return JSValue::encode(O);
 }
 
 static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties)
 {
     PropertyNameArray propertyNames(exec);
     return JSValue::encode(O);
 }
 
 static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties)
 {
     PropertyNameArray propertyNames(exec);
-    asObject(properties)->getOwnPropertyNames(exec, propertyNames);
+    asObject(properties)->methodTable()->getOwnPropertyNames(asObject(properties), exec, propertyNames, ExcludeDontEnumProperties);
     size_t numProperties = propertyNames.size();
     Vector<PropertyDescriptor> descriptors;
     MarkedArgumentBuffer markBuffer;
     size_t numProperties = propertyNames.size();
     Vector<PropertyDescriptor> descriptors;
     MarkedArgumentBuffer markBuffer;
@@ -325,7 +330,7 @@ static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* pro
         }
     }
     for (size_t i = 0; i < numProperties; i++) {
         }
     }
     for (size_t i = 0; i < numProperties; i++) {
-        object->defineOwnProperty(exec, propertyNames[i], descriptors[i], true);
+        object->methodTable()->defineOwnProperty(object, exec, propertyNames[i], descriptors[i], true);
         if (exec->hadException())
             return jsNull();
     }
         if (exec->hadException())
             return jsNull();
     }
@@ -336,9 +341,7 @@ 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(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))));
+    return JSValue::encode(defineProperties(exec, asObject(exec->argument(0)), exec->argument(1).toObject(exec)));
 }
 
 EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec)
@@ -356,19 +359,79 @@ EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
 {
 
 EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
 {
+    // 1. If Type(O) is not Object throw a TypeError exception.
     JSValue obj = exec->argument(0);
     if (!obj.isObject())
         return throwVMError(exec, createTypeError(exec, "Object.seal can only be called on Objects."));
     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());
+    JSObject* object = asObject(obj);
+
+    if (isJSFinalObject(object)) {
+        object->seal(exec->globalData());
+        return JSValue::encode(obj);
+    }
+
+    // 2. For each named own property name P of O,
+    PropertyNameArray properties(exec);
+    object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
+    PropertyNameArray::const_iterator end = properties.end();
+    for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
+        // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
+        PropertyDescriptor desc;
+        if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, *iter, desc))
+            continue;
+        // b. If desc.[[Configurable]] is true, set desc.[[Configurable]] to false.
+        desc.setConfigurable(false);
+        // c. Call the [[DefineOwnProperty]] internal method of O with P, desc, and true as arguments.
+        object->methodTable()->defineOwnProperty(object, exec, *iter, desc, true);
+        if (exec->hadException())
+            return JSValue::encode(obj);
+    }
+
+    // 3. Set the [[Extensible]] internal property of O to false.
+    object->preventExtensions(exec->globalData());
+
+    // 4. Return O.
     return JSValue::encode(obj);
 }
 
 EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec)
 {
     return JSValue::encode(obj);
 }
 
 EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec)
 {
+    // 1. If Type(O) is not Object throw a TypeError exception.
     JSValue obj = exec->argument(0);
     if (!obj.isObject())
         return throwVMError(exec, createTypeError(exec, "Object.freeze can only be called on Objects."));
     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());
+    JSObject* object = asObject(obj);
+
+    if (isJSFinalObject(object)) {
+        object->freeze(exec->globalData());
+        return JSValue::encode(obj);
+    }
+
+    // 2. For each named own property name P of O,
+    PropertyNameArray properties(exec);
+    object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
+    PropertyNameArray::const_iterator end = properties.end();
+    for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
+        // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
+        PropertyDescriptor desc;
+        if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, *iter, desc))
+            continue;
+        // b. If IsDataDescriptor(desc) is true, then
+        // i. If desc.[[Writable]] is true, set desc.[[Writable]] to false.
+        if (desc.isDataDescriptor())
+            desc.setWritable(false);
+        // c. If desc.[[Configurable]] is true, set desc.[[Configurable]] to false.
+        desc.setConfigurable(false);
+        // d. Call the [[DefineOwnProperty]] internal method of O with P, desc, and true as arguments.
+        object->methodTable()->defineOwnProperty(object, exec, *iter, desc, true);
+        if (exec->hadException())
+            return JSValue::encode(obj);
+    }
+
+    // 3. Set the [[Extensible]] internal property of O to false.
+    object->preventExtensions(exec->globalData());
+
+    // 4. Return O.
     return JSValue::encode(obj);
 }
 
     return JSValue::encode(obj);
 }
 
@@ -383,18 +446,63 @@ EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState* exec)
 {
 
 EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState* exec)
 {
+    // 1. If Type(O) is not Object throw a TypeError exception.
     JSValue obj = exec->argument(0);
     if (!obj.isObject())
         return throwVMError(exec, createTypeError(exec, "Object.isSealed can only be called on Objects."));
     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())));
+    JSObject* object = asObject(obj);
+
+    if (isJSFinalObject(object))
+        return JSValue::encode(jsBoolean(object->isSealed(exec->globalData())));
+
+    // 2. For each named own property name P of O,
+    PropertyNameArray properties(exec);
+    object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
+    PropertyNameArray::const_iterator end = properties.end();
+    for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
+        // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
+        PropertyDescriptor desc;
+        if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, *iter, desc))
+            continue;
+        // b. If desc.[[Configurable]] is true, then return false.
+        if (desc.configurable())
+            return JSValue::encode(jsBoolean(false));
+    }
+
+    // 3. If the [[Extensible]] internal property of O is false, then return true.
+    // 4. Otherwise, return false.
+    return JSValue::encode(jsBoolean(!object->isExtensible()));
 }
 
 EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec)
 {
 }
 
 EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec)
 {
+    // 1. If Type(O) is not Object throw a TypeError exception.
     JSValue obj = exec->argument(0);
     if (!obj.isObject())
         return throwVMError(exec, createTypeError(exec, "Object.isFrozen can only be called on Objects."));
     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())));
+    JSObject* object = asObject(obj);
+
+    if (isJSFinalObject(object))
+        return JSValue::encode(jsBoolean(object->isFrozen(exec->globalData())));
+
+    // 2. For each named own property name P of O,
+    PropertyNameArray properties(exec);
+    object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
+    PropertyNameArray::const_iterator end = properties.end();
+    for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
+        // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
+        PropertyDescriptor desc;
+        if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, *iter, desc))
+            continue;
+        // b. If IsDataDescriptor(desc) is true then
+        // i. If desc.[[Writable]] is true, return false. c. If desc.[[Configurable]] is true, then return false.
+        if ((desc.isDataDescriptor() && desc.writable()) || desc.configurable())
+            return JSValue::encode(jsBoolean(false));
+    }
+
+    // 3. If the [[Extensible]] internal property of O is false, then return true.
+    // 4. Otherwise, return false.
+    return JSValue::encode(jsBoolean(!object->isExtensible()));
 }
 
 EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState* exec)
index 6ebafcdadfaa8c568414a206dfa0242eb36441f9..87c6414c4c3a5eb97aba8e6591bb64fa07c04f8f 100644 (file)
@@ -29,24 +29,33 @@ namespace JSC {
 
     class ObjectConstructor : public InternalFunction {
     public:
 
     class ObjectConstructor : public InternalFunction {
     public:
-        ObjectConstructor(ExecState*, JSGlobalObject*, Structure*, ObjectPrototype*);
+        typedef InternalFunction Base;
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static ObjectConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ObjectPrototype* objectPrototype)
+        {
+            ObjectConstructor* constructor = new (NotNull, allocateCell<ObjectConstructor>(*exec->heap())) ObjectConstructor(globalObject, structure);
+            constructor->finishCreation(exec, objectPrototype);
+            return constructor;
+        }
+
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
         static const ClassInfo s_info;
 
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
+        void finishCreation(ExecState*, ObjectPrototype*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
 
     private:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
 
     private:
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
+        ObjectConstructor(JSGlobalObject*, Structure*);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 2c1f96388a0fbcb8da09f524674d2d4dcd36c0fa..e980ac590b806b25912e786bd63fc5eabd31ce8b 100644 (file)
@@ -44,7 +44,9 @@ static EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*);
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo ObjectPrototype::s_info = { "Object", &JSNonFinalObject::s_info, 0, ExecState::objectPrototypeTable };
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ObjectPrototype);
+
+const ClassInfo ObjectPrototype::s_info = { "Object", &JSNonFinalObject::s_info, 0, ExecState::objectPrototypeTable, CREATE_METHOD_TABLE(ObjectPrototype) };
 
 /* Source for ObjectPrototype.lut.h
 @begin objectPrototypeTable
 
 /* Source for ObjectPrototype.lut.h
 @begin objectPrototypeTable
@@ -63,40 +65,60 @@ const ClassInfo ObjectPrototype::s_info = { "Object", &JSNonFinalObject::s_info,
 
 ASSERT_CLASS_FITS_IN_CELL(ObjectPrototype);
 
 
 ASSERT_CLASS_FITS_IN_CELL(ObjectPrototype);
 
-ObjectPrototype::ObjectPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* stucture)
+ObjectPrototype::ObjectPrototype(ExecState* exec, Structure* stucture)
     : JSNonFinalObject(exec->globalData(), stucture)
     , m_hasNoPropertiesWithUInt32Names(true)
 {
     : JSNonFinalObject(exec->globalData(), stucture)
     , m_hasNoPropertiesWithUInt32Names(true)
 {
+}
+
+void ObjectPrototype::finishCreation(JSGlobalData& globalData, JSGlobalObject*)
+{
+    Base::finishCreation(globalData);
     ASSERT(inherits(&s_info));
     ASSERT(inherits(&s_info));
-    putAnonymousValue(globalObject->globalData(), 0, globalObject);
 }
 
 }
 
-void ObjectPrototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void ObjectPrototype::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+{
+    ObjectPrototype* thisObject = jsCast<ObjectPrototype*>(cell);
+    Base::put(cell, exec, propertyName, value, slot);
+
+    if (thisObject->m_hasNoPropertiesWithUInt32Names) {
+        bool isUInt32;
+        propertyName.toUInt32(isUInt32);
+        thisObject->m_hasNoPropertiesWithUInt32Names = !isUInt32;
+    }
+}
+
+bool ObjectPrototype::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
 {
 {
-    JSNonFinalObject::put(exec, propertyName, value, slot);
+    ObjectPrototype* thisObject = jsCast<ObjectPrototype*>(object);
+    bool result = Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
 
 
-    if (m_hasNoPropertiesWithUInt32Names) {
+    if (thisObject->m_hasNoPropertiesWithUInt32Names) {
         bool isUInt32;
         propertyName.toUInt32(isUInt32);
         bool isUInt32;
         propertyName.toUInt32(isUInt32);
-        m_hasNoPropertiesWithUInt32Names = !isUInt32;
+        thisObject->m_hasNoPropertiesWithUInt32Names = !isUInt32;
     }
     }
+
+    return result;
 }
 
 }
 
-bool ObjectPrototype::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+bool ObjectPrototype::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)
 {
 {
-    if (m_hasNoPropertiesWithUInt32Names)
+    ObjectPrototype* thisObject = jsCast<ObjectPrototype*>(cell);
+    if (thisObject->m_hasNoPropertiesWithUInt32Names)
         return false;
         return false;
-    return JSNonFinalObject::getOwnPropertySlot(exec, propertyName, slot);
+    return Base::getOwnPropertySlotByIndex(thisObject, exec, propertyName, slot);
 }
 
 }
 
-bool ObjectPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+bool ObjectPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 {
-    return getStaticFunctionSlot<JSNonFinalObject>(exec, ExecState::objectPrototypeTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<JSNonFinalObject>(exec, ExecState::objectPrototypeTable(exec), jsCast<ObjectPrototype*>(cell), propertyName, slot);
 }
 
 }
 
-bool ObjectPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool ObjectPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<JSNonFinalObject>(exec, ExecState::objectPrototypeTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<JSNonFinalObject>(exec, ExecState::objectPrototypeTable(exec), jsCast<ObjectPrototype*>(object), propertyName, descriptor);
 }
 
 // ------------------------------ Functions --------------------------------
 }
 
 // ------------------------------ Functions --------------------------------
@@ -104,19 +126,19 @@ bool ObjectPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier
 EncodedJSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 EncodedJSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    return JSValue::encode(thisValue.toThisObject(exec));
+    return JSValue::encode(thisValue.toObject(exec));
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    return JSValue::encode(jsBoolean(thisValue.toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, exec->argument(0).toString(exec)))));
+    return JSValue::encode(jsBoolean(thisValue.toObject(exec)->hasOwnProperty(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)))));
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = thisValue.toObject(exec);
 
     if (!exec->argument(0).isObject())
         return JSValue::encode(jsBoolean(false));
 
     if (!exec->argument(0).isObject())
         return JSValue::encode(jsBoolean(false));
@@ -134,52 +156,116 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState* exec)
 {
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState* exec)
 {
-    JSValue thisValue = exec->hostThisValue();
+    JSObject* thisObject = exec->hostThisValue().toObject(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    JSValue get = exec->argument(1);
     CallData callData;
     CallData callData;
-    if (getCallData(exec->argument(1), callData) == CallTypeNone)
+    if (getCallData(get, callData) == CallTypeNone)
         return throwVMError(exec, createSyntaxError(exec, "invalid getter usage"));
         return throwVMError(exec, createSyntaxError(exec, "invalid getter usage"));
-    thisValue.toThisObject(exec)->defineGetter(exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1)));
+
+    PropertyDescriptor descriptor;
+    descriptor.setGetter(get);
+    descriptor.setEnumerable(true);
+    descriptor.setConfigurable(true);
+    thisObject->methodTable()->defineOwnProperty(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)), descriptor, false);
+
     return JSValue::encode(jsUndefined());
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec)
 {
     return JSValue::encode(jsUndefined());
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec)
 {
-    JSValue thisValue = exec->hostThisValue();
+    JSObject* thisObject = exec->hostThisValue().toObject(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    JSValue set = exec->argument(1);
     CallData callData;
     CallData callData;
-    if (getCallData(exec->argument(1), callData) == CallTypeNone)
+    if (getCallData(set, callData) == CallTypeNone)
         return throwVMError(exec, createSyntaxError(exec, "invalid setter usage"));
         return throwVMError(exec, createSyntaxError(exec, "invalid setter usage"));
-    thisValue.toThisObject(exec)->defineSetter(exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1)));
+
+    PropertyDescriptor descriptor;
+    descriptor.setSetter(set);
+    descriptor.setEnumerable(true);
+    descriptor.setConfigurable(true);
+    thisObject->methodTable()->defineOwnProperty(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)), descriptor, false);
+
     return JSValue::encode(jsUndefined());
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec)
 {
     return JSValue::encode(jsUndefined());
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec)
 {
-    JSValue thisValue = exec->hostThisValue();
-    return JSValue::encode(thisValue.toThisObject(exec)->lookupGetter(exec, Identifier(exec, exec->argument(0).toString(exec))));
+    JSObject* thisObject = exec->hostThisValue().toObject(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    PropertyDescriptor descriptor;
+    if (thisObject->getPropertyDescriptor(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)), descriptor)
+        && descriptor.getterPresent())
+        return JSValue::encode(descriptor.getter());
+
+    return JSValue::encode(jsUndefined());
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec)
 {
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec)
 {
-    JSValue thisValue = exec->hostThisValue();
-    return JSValue::encode(thisValue.toThisObject(exec)->lookupSetter(exec, Identifier(exec, exec->argument(0).toString(exec))));
+    JSObject* thisObject = exec->hostThisValue().toObject(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    PropertyDescriptor descriptor;
+    if (thisObject->getPropertyDescriptor(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)), descriptor)
+        && descriptor.setterPresent())
+        return JSValue::encode(descriptor.setter());
+
+    return JSValue::encode(jsUndefined());
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    return JSValue::encode(jsBoolean(thisValue.toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, exec->argument(0).toString(exec)))));
+    return JSValue::encode(jsBoolean(thisValue.toObject(exec)->propertyIsEnumerable(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)))));
 }
 
 }
 
+// 15.2.4.3 Object.prototype.toLocaleString()
 EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec)
 {
 EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec)
 {
-    JSValue thisValue = exec->hostThisValue();
-    return JSValue::encode(thisValue.toThisJSString(exec));
+    // 1. Let O be the result of calling ToObject passing the this value as the argument.
+    JSObject* object = exec->hostThisValue().toObject(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    // 2. Let toString be the result of calling the [[Get]] internal method of O passing "toString" as the argument.
+    JSValue toString = object->get(exec, exec->propertyNames().toString);
+
+    // 3. If IsCallable(toString) is false, throw a TypeError exception.
+    CallData callData;
+    CallType callType = getCallData(toString, callData);
+    if (callType == CallTypeNone)
+        return JSValue::encode(jsUndefined());
+
+    // 4. Return the result of calling the [[Call]] internal method of toString passing O as the this value and no arguments.
+    return JSValue::encode(call(exec, toString, callType, callData, object, exec->emptyList()));
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 }
 
 EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisValue.toThisObject(exec)->className(), "]"));
+    if (thisValue.isUndefinedOrNull())
+        return JSValue::encode(jsNontrivialString(exec, thisValue.isUndefined() ? "[object Undefined]" : "[object Null]"));
+    JSObject* thisObject = thisValue.toObject(exec);
+
+    JSString* result = thisObject->structure()->objectToStringValue();
+    if (!result) {
+        RefPtr<StringImpl> newString = WTF::tryMakeString("[object ", thisObject->methodTable()->className(thisObject), "]");
+        if (!newString)
+            return JSValue::encode(throwOutOfMemoryError(exec));
+
+        result = jsNontrivialString(exec, newString.release());
+        thisObject->structure()->setObjectToStringValue(exec->globalData(), thisObject, result);
+    }
+    return JSValue::encode(result);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index ec30b9c1feb80916e08ee707682f09dd3d03aaf4..b9b8a30d45258979a269609c6813b18b3c30dda4 100644 (file)
@@ -27,29 +27,40 @@ namespace JSC {
 
     class ObjectPrototype : public JSNonFinalObject {
     public:
 
     class ObjectPrototype : public JSNonFinalObject {
     public:
-        ObjectPrototype(ExecState*, JSGlobalObject*, Structure*);
+        typedef JSNonFinalObject Base;
+
+        static ObjectPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+        {
+            ObjectPrototype* prototype = new (NotNull, allocateCell<ObjectPrototype>(*exec->heap())) ObjectPrototype(exec, structure);
+            prototype->finishCreation(exec->globalData(), globalObject);
+            return prototype;
+        }
 
         static const ClassInfo s_info;
 
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSNonFinalObject::StructureFlags;
         }
 
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSNonFinalObject::StructureFlags;
-        static const unsigned AnonymousSlotCount = JSNonFinalObject::AnonymousSlotCount + 1;
+
+        void finishCreation(JSGlobalData&, JSGlobalObject*);
 
     private:
 
     private:
-        virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        ObjectPrototype(ExecState*, Structure*);
+        static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+        static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
+
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
         bool m_hasNoPropertiesWithUInt32Names;
     };
 
 
         bool m_hasNoPropertiesWithUInt32Names;
     };
 
-    EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*);
+    JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*);
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index f129a805580b0600711aeac6006cefbc2b311a20..4cb9de505e79660e34eded7ff2af01aeed3e7a5c 100644 (file)
@@ -47,11 +47,9 @@ NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
     JSValue p1 = v1.toPrimitive(callFrame);
     JSValue p2 = v2.toPrimitive(callFrame);
 
     JSValue p1 = v1.toPrimitive(callFrame);
     JSValue p2 = v2.toPrimitive(callFrame);
 
-    if (p1.isString()) {
-        return p2.isString()
-            ? jsString(callFrame, asString(p1), asString(p2))
-            : jsString(callFrame, asString(p1), p2.toString(callFrame));
-    }
+    if (p1.isString())
+        return jsString(callFrame, asString(p1), p2.toString(callFrame));
+
     if (p2.isString())
         return jsString(callFrame, p1.toString(callFrame), asString(p2));
 
     if (p2.isString())
         return jsString(callFrame, p1.toString(callFrame), asString(p2));
 
@@ -60,24 +58,26 @@ NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
 
 JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v)
 {
 
 JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v)
 {
+    JSGlobalData& globalData = callFrame->globalData();
     if (v.isUndefined())
     if (v.isUndefined())
-        return jsNontrivialString(callFrame, "undefined");
+        return globalData.smallStrings.undefinedString(&globalData);
     if (v.isBoolean())
     if (v.isBoolean())
-        return jsNontrivialString(callFrame, "boolean");
+        return globalData.smallStrings.booleanString(&globalData);
     if (v.isNumber())
     if (v.isNumber())
-        return jsNontrivialString(callFrame, "number");
+        return globalData.smallStrings.numberString(&globalData);
     if (v.isString())
     if (v.isString())
-        return jsNontrivialString(callFrame, "string");
+        return globalData.smallStrings.stringString(&globalData);
     if (v.isObject()) {
         // Return "undefined" for objects that should be treated
         // as null when doing comparisons.
         if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
     if (v.isObject()) {
         // Return "undefined" for objects that should be treated
         // as null when doing comparisons.
         if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
-            return jsNontrivialString(callFrame, "undefined");
+            return globalData.smallStrings.undefinedString(&globalData);
         CallData callData;
         CallData callData;
-        if (asObject(v)->getCallData(callData) != CallTypeNone)
-            return jsNontrivialString(callFrame, "function");
+        JSObject* object = asObject(v);
+        if (object->methodTable()->getCallData(object, callData) != CallTypeNone)
+            return globalData.smallStrings.functionString(&globalData);
     }
     }
-    return jsNontrivialString(callFrame, "object");
+    return globalData.smallStrings.objectString(&globalData);
 }
 
 bool jsIsObjectType(JSValue v)
 }
 
 bool jsIsObjectType(JSValue v)
@@ -88,11 +88,12 @@ bool jsIsObjectType(JSValue v)
     JSType type = v.asCell()->structure()->typeInfo().type();
     if (type == NumberType || type == StringType)
         return false;
     JSType type = v.asCell()->structure()->typeInfo().type();
     if (type == NumberType || type == StringType)
         return false;
-    if (type == ObjectType) {
+    if (type >= ObjectType) {
         if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
             return false;
         CallData callData;
         if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined())
             return false;
         CallData callData;
-        if (asObject(v)->getCallData(callData) != CallTypeNone)
+        JSObject* object = asObject(v);
+        if (object->methodTable()->getCallData(object, callData) != CallTypeNone)
             return false;
     }
     return true;
             return false;
     }
     return true;
@@ -102,7 +103,8 @@ bool jsIsFunctionType(JSValue v)
 {
     if (v.isObject()) {
         CallData callData;
 {
     if (v.isObject()) {
         CallData callData;
-        if (asObject(v)->getCallData(callData) != CallTypeNone)
+        JSObject* object = asObject(v);
+        if (object->methodTable()->getCallData(object, callData) != CallTypeNone)
             return true;
     }
     return false;
             return true;
     }
     return false;
index c102eebed3aa663699ffc519f5964797d4a1f1e6..b2081f3dd9bf89c83bb4d85cd431ac9c95034b9e 100644 (file)
@@ -36,6 +36,8 @@ namespace JSC {
 
     ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
     {
 
     ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
     {
+        JSGlobalData& globalData = exec->globalData();
+
         unsigned length1 = s1->length();
         if (!length1)
             return s2;
         unsigned length1 = s1->length();
         if (!length1)
             return s2;
@@ -45,194 +47,66 @@ namespace JSC {
         if ((length1 + length2) < length1)
             return throwOutOfMemoryError(exec);
 
         if ((length1 + length2) < length1)
             return throwOutOfMemoryError(exec);
 
-        unsigned fiberCount = s1->fiberCount() + s2->fiberCount();
-        JSGlobalData* globalData = &exec->globalData();
-
-        if (fiberCount <= JSString::s_maxInternalRopeLength)
-            return new (globalData) JSString(globalData, fiberCount, s1, s2);
-
-        JSString::RopeBuilder ropeBuilder(fiberCount);
-        if (UNLIKELY(ropeBuilder.isOutOfMemory()))
-            return throwOutOfMemoryError(exec);
-        ropeBuilder.append(s1);
-        ropeBuilder.append(s2);
-        return new (globalData) JSString(globalData, ropeBuilder.release());
-    }
-
-    ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, JSString* s2)
-    {
-        unsigned length1 = u1.length();
-        if (!length1)
-            return s2;
-        unsigned length2 = s2->length();
-        if (!length2)
-            return jsString(exec, u1);
-        if ((length1 + length2) < length1)
-            return throwOutOfMemoryError(exec);
-
-        unsigned fiberCount = 1 + s2->fiberCount();
-        JSGlobalData* globalData = &exec->globalData();
-
-        if (fiberCount <= JSString::s_maxInternalRopeLength)
-            return new (globalData) JSString(globalData, fiberCount, u1, s2);
-
-        JSString::RopeBuilder ropeBuilder(fiberCount);
-        if (UNLIKELY(ropeBuilder.isOutOfMemory()))
-            return throwOutOfMemoryError(exec);
-        ropeBuilder.append(u1);
-        ropeBuilder.append(s2);
-        return new (globalData) JSString(globalData, ropeBuilder.release());
+        return JSRopeString::create(globalData, s1, s2);
     }
 
     }
 
-    ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, const UString& u2)
-    {
-        unsigned length1 = s1->length();
-        if (!length1)
-            return jsString(exec, u2);
-        unsigned length2 = u2.length();
-        if (!length2)
-            return s1;
-        if ((length1 + length2) < length1)
-            return throwOutOfMemoryError(exec);
-
-        unsigned fiberCount = s1->fiberCount() + 1;
-        JSGlobalData* globalData = &exec->globalData();
-
-        if (fiberCount <= JSString::s_maxInternalRopeLength)
-            return new (globalData) JSString(globalData, fiberCount, s1, u2);
-
-        JSString::RopeBuilder ropeBuilder(fiberCount);
-        if (UNLIKELY(ropeBuilder.isOutOfMemory()))
-            return throwOutOfMemoryError(exec);
-        ropeBuilder.append(s1);
-        ropeBuilder.append(u2);
-        return new (globalData) JSString(globalData, ropeBuilder.release());
-    }
-
-    ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2)
+    ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2, const UString& u3)
     {
     {
-        unsigned length1 = u1.length();
-        if (!length1)
-            return jsString(exec, u2);
-        unsigned length2 = u2.length();
-        if (!length2)
-            return jsString(exec, u1);
-        if ((length1 + length2) < length1)
-            return throwOutOfMemoryError(exec);
-
         JSGlobalData* globalData = &exec->globalData();
         JSGlobalData* globalData = &exec->globalData();
-        return new (globalData) JSString(globalData, u1, u2);
-    }
 
 
-    ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2, const UString& u3)
-    {
         unsigned length1 = u1.length();
         unsigned length2 = u2.length();
         unsigned length3 = u3.length();
         if (!length1)
         unsigned length1 = u1.length();
         unsigned length2 = u2.length();
         unsigned length3 = u3.length();
         if (!length1)
-            return jsString(exec, u2, u3);
+            return jsString(exec, jsString(globalData, u2), jsString(globalData, u3));
         if (!length2)
         if (!length2)
-            return jsString(exec, u1, u3);
+            return jsString(exec, jsString(globalData, u1), jsString(globalData, u3));
         if (!length3)
         if (!length3)
-            return jsString(exec, u1, u2);
+            return jsString(exec, jsString(globalData, u1), jsString(globalData, u2));
 
         if ((length1 + length2) < length1)
             return throwOutOfMemoryError(exec);
         if ((length1 + length2 + length3) < length3)
             return throwOutOfMemoryError(exec);
 
 
         if ((length1 + length2) < length1)
             return throwOutOfMemoryError(exec);
         if ((length1 + length2 + length3) < length3)
             return throwOutOfMemoryError(exec);
 
-        JSGlobalData* globalData = &exec->globalData();
-        return new (globalData) JSString(globalData, u1, u2, u3);
+        return JSRopeString::create(exec->globalData(), jsString(globalData, u1), jsString(globalData, u2), jsString(globalData, u3));
     }
 
     ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count)
     {
     }
 
     ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count)
     {
-        ASSERT(count >= 3);
-
-        unsigned fiberCount = 0;
-        for (unsigned i = 0; i < count; ++i) {
-            JSValue v = strings[i].jsValue();
-            if (LIKELY(v.isString()))
-                fiberCount += asString(v)->fiberCount();
-            else
-                ++fiberCount;
-        }
-
         JSGlobalData* globalData = &exec->globalData();
         JSGlobalData* globalData = &exec->globalData();
-        if (fiberCount == 3)
-            return new (globalData) JSString(exec, strings[0].jsValue(), strings[1].jsValue(), strings[2].jsValue());
-
-        JSString::RopeBuilder ropeBuilder(fiberCount);
-        if (UNLIKELY(ropeBuilder.isOutOfMemory()))
-            return throwOutOfMemoryError(exec);
+        JSRopeString::RopeBuilder ropeBuilder(*globalData);
 
 
-        unsigned length = 0;
-        bool overflow = false;
+        unsigned oldLength = 0;
 
         for (unsigned i = 0; i < count; ++i) {
             JSValue v = strings[i].jsValue();
 
         for (unsigned i = 0; i < count; ++i) {
             JSValue v = strings[i].jsValue();
-            if (LIKELY(v.isString()))
-                ropeBuilder.append(asString(v));
-            else
-                ropeBuilder.append(v.toString(exec));
-
-            unsigned newLength = ropeBuilder.length();
-            if (newLength < length)
-                overflow = true;
-            length = newLength;
-        }
+            ropeBuilder.append(v.toString(exec));
 
 
-        if (overflow)
-            return throwOutOfMemoryError(exec);
+            if (ropeBuilder.length() < oldLength) // True for overflow
+                return throwOutOfMemoryError(exec);
+        }
 
 
-        return new (globalData) JSString(globalData, ropeBuilder.release());
+        return ropeBuilder.release();
     }
 
     }
 
-    ALWAYS_INLINE JSValue jsString(ExecState* exec, JSValue thisValue)
+    ALWAYS_INLINE JSValue jsStringFromArguments(ExecState* exec, JSValue thisValue)
     {
     {
-        unsigned fiberCount = 0;
-        if (LIKELY(thisValue.isString()))
-            fiberCount += asString(thisValue)->fiberCount();
-        else
-            ++fiberCount;
-        for (unsigned i = 0; i < exec->argumentCount(); ++i) {
-            JSValue v = exec->argument(i);
-            if (LIKELY(v.isString()))
-                fiberCount += asString(v)->fiberCount();
-            else
-                ++fiberCount;
-        }
-
-        JSString::RopeBuilder ropeBuilder(fiberCount);
-        if (UNLIKELY(ropeBuilder.isOutOfMemory()))
-            return throwOutOfMemoryError(exec);
-
-        if (LIKELY(thisValue.isString()))
-            ropeBuilder.append(asString(thisValue));
-        else
-            ropeBuilder.append(thisValue.toString(exec));
+        JSGlobalData* globalData = &exec->globalData();
+        JSRopeString::RopeBuilder ropeBuilder(*globalData);
+        ropeBuilder.append(thisValue.toString(exec));
 
 
-        unsigned length = 0;
-        bool overflow = false;
+        unsigned oldLength = 0;
 
         for (unsigned i = 0; i < exec->argumentCount(); ++i) {
             JSValue v = exec->argument(i);
 
         for (unsigned i = 0; i < exec->argumentCount(); ++i) {
             JSValue v = exec->argument(i);
-            if (LIKELY(v.isString()))
-                ropeBuilder.append(asString(v));
-            else
-                ropeBuilder.append(v.toString(exec));
-
-            unsigned newLength = ropeBuilder.length();
-            if (newLength < length)
-                overflow = true;
-            length = newLength;
-        }
+            ropeBuilder.append(v.toString(exec));
 
 
-        if (overflow)
-            return throwOutOfMemoryError(exec);
+            if (ropeBuilder.length() < oldLength) // True for overflow
+                return throwOutOfMemoryError(exec);
+        }
 
 
-        JSGlobalData* globalData = &exec->globalData();
-        return new (globalData) JSString(globalData, ropeBuilder.release());
+        return ropeBuilder.release();
     }
 
     // ECMA 11.9.3
     }
 
     // ECMA 11.9.3
@@ -248,7 +122,7 @@ namespace JSC {
     {
         do {
             if (v1.isNumber() && v2.isNumber())
     {
         do {
             if (v1.isNumber() && v2.isNumber())
-                return v1.uncheckedGetNumber() == v2.uncheckedGetNumber();
+                return v1.asNumber() == v2.asNumber();
 
             bool s1 = v1.isString();
             bool s2 = v2.isString();
 
             bool s1 = v1.isString();
             bool s2 = v2.isString();
@@ -299,10 +173,10 @@ namespace JSC {
 
             if (v1.isBoolean()) {
                 if (v2.isNumber())
 
             if (v1.isBoolean()) {
                 if (v2.isNumber())
-                    return static_cast<double>(v1.getBoolean()) == v2.uncheckedGetNumber();
+                    return static_cast<double>(v1.asBoolean()) == v2.asNumber();
             } else if (v2.isBoolean()) {
                 if (v1.isNumber())
             } else if (v2.isBoolean()) {
                 if (v1.isNumber())
-                    return v1.uncheckedGetNumber() == static_cast<double>(v2.getBoolean());
+                    return v1.asNumber() == static_cast<double>(v2.asBoolean());
             }
 
             return v1 == v2;
             }
 
             return v1 == v2;
@@ -326,7 +200,7 @@ namespace JSC {
             return v1 == v2;
 
         if (v1.isNumber() && v2.isNumber())
             return v1 == v2;
 
         if (v1.isNumber() && v2.isNumber())
-            return v1.uncheckedGetNumber() == v2.uncheckedGetNumber();
+            return v1.asNumber() == v2.asNumber();
 
         if (!v1.isCell() || !v2.isCell())
             return v1 == v2;
 
         if (!v1.isCell() || !v2.isCell())
             return v1 == v2;
@@ -334,53 +208,71 @@ namespace JSC {
         return strictEqualSlowCaseInline(exec, v1, v2);
     }
 
         return strictEqualSlowCaseInline(exec, v1, v2);
     }
 
+    // See ES5 11.8.1/11.8.2/11.8.5 for definition of leftFirst, this value ensures correct
+    // evaluation ordering for argument conversions for '<' and '>'. For '<' pass the value
+    // true, for leftFirst, for '>' pass the value false (and reverse operand order).
+    template<bool leftFirst>
     ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
     {
         if (v1.isInt32() && v2.isInt32())
             return v1.asInt32() < v2.asInt32();
 
     ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
     {
         if (v1.isInt32() && v2.isInt32())
             return v1.asInt32() < v2.asInt32();
 
-        double n1;
-        double n2;
-        if (v1.getNumber(n1) && v2.getNumber(n2))
-            return n1 < n2;
+        if (v1.isNumber() && v2.isNumber())
+            return v1.asNumber() < v2.asNumber();
 
 
-        JSGlobalData* globalData = &callFrame->globalData();
-        if (isJSString(globalData, v1) && isJSString(globalData, v2))
+        if (isJSString(v1) && isJSString(v2))
             return asString(v1)->value(callFrame) < asString(v2)->value(callFrame);
 
             return asString(v1)->value(callFrame) < asString(v2)->value(callFrame);
 
+        double n1;
+        double n2;
         JSValue p1;
         JSValue p2;
         JSValue p1;
         JSValue p2;
-        bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
-        bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+        bool wasNotString1;
+        bool wasNotString2;
+        if (leftFirst) {
+            wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
+            wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+        } else {
+            wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+            wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
+        }
 
         if (wasNotString1 | wasNotString2)
             return n1 < n2;
 
         if (wasNotString1 | wasNotString2)
             return n1 < n2;
-
         return asString(p1)->value(callFrame) < asString(p2)->value(callFrame);
     }
 
         return asString(p1)->value(callFrame) < asString(p2)->value(callFrame);
     }
 
-    inline bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
+    // See ES5 11.8.3/11.8.4/11.8.5 for definition of leftFirst, this value ensures correct
+    // evaluation ordering for argument conversions for '<=' and '=>'. For '<=' pass the
+    // value true, for leftFirst, for '=>' pass the value false (and reverse operand order).
+    template<bool leftFirst>
+    ALWAYS_INLINE bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
     {
         if (v1.isInt32() && v2.isInt32())
             return v1.asInt32() <= v2.asInt32();
 
     {
         if (v1.isInt32() && v2.isInt32())
             return v1.asInt32() <= v2.asInt32();
 
-        double n1;
-        double n2;
-        if (v1.getNumber(n1) && v2.getNumber(n2))
-            return n1 <= n2;
+        if (v1.isNumber() && v2.isNumber())
+            return v1.asNumber() <= v2.asNumber();
 
 
-        JSGlobalData* globalData = &callFrame->globalData();
-        if (isJSString(globalData, v1) && isJSString(globalData, v2))
+        if (isJSString(v1) && isJSString(v2))
             return !(asString(v2)->value(callFrame) < asString(v1)->value(callFrame));
 
             return !(asString(v2)->value(callFrame) < asString(v1)->value(callFrame));
 
+        double n1;
+        double n2;
         JSValue p1;
         JSValue p2;
         JSValue p1;
         JSValue p2;
-        bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
-        bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+        bool wasNotString1;
+        bool wasNotString2;
+        if (leftFirst) {
+            wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
+            wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+        } else {
+            wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+            wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
+        }
 
         if (wasNotString1 | wasNotString2)
             return n1 <= n2;
 
         if (wasNotString1 | wasNotString2)
             return n1 <= n2;
-
         return !(asString(p2)->value(callFrame) < asString(p1)->value(callFrame));
     }
 
         return !(asString(p2)->value(callFrame) < asString(p1)->value(callFrame));
     }
 
@@ -395,15 +287,11 @@ namespace JSC {
 
     ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
     {
 
     ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
     {
-        double left = 0.0, right;
-        if (v1.getNumber(left) && v2.getNumber(right))
-            return jsNumber(left + right);
+        if (v1.isNumber() && v2.isNumber())
+            return jsNumber(v1.asNumber() + v2.asNumber());
         
         
-        if (v1.isString()) {
-            return v2.isString()
-                ? jsString(callFrame, asString(v1), asString(v2))
-                : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
-        }
+        if (v1.isString() && !v2.isObject())
+            return jsString(callFrame, asString(v1), v2.toString(callFrame));
 
         // All other cases are pretty uncommon
         return jsAddSlowCase(callFrame, v1, v2);
 
         // All other cases are pretty uncommon
         return jsAddSlowCase(callFrame, v1, v2);
diff --git a/runtime/Options.cpp b/runtime/Options.cpp
new file mode 100644 (file)
index 0000000..8f5a050
--- /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. 
+ */
+
+#include "config.h"
+#include "Options.h"
+
+#include <limits>
+#include <wtf/NumberOfCores.h>
+#include <wtf/PageBlock.h>
+
+#if OS(DARWIN) && ENABLE(PARALLEL_GC)
+#include <sys/sysctl.h>
+#endif
+
+// Set to 1 to control the heuristics using environment variables.
+#define ENABLE_RUN_TIME_HEURISTICS 0
+
+#if ENABLE(RUN_TIME_HEURISTICS)
+#include <stdio.h>
+#include <stdlib.h>
+#include <wtf/StdLibExtras.h>
+#endif
+
+namespace JSC { namespace Options {
+
+bool useJIT;
+
+unsigned maximumOptimizationCandidateInstructionCount;
+
+unsigned maximumFunctionForCallInlineCandidateInstructionCount;
+unsigned maximumFunctionForConstructInlineCandidateInstructionCount;
+
+unsigned maximumInliningDepth;
+
+int32_t thresholdForJITAfterWarmUp;
+int32_t thresholdForJITSoon;
+
+int32_t thresholdForOptimizeAfterWarmUp;
+int32_t thresholdForOptimizeAfterLongWarmUp;
+int32_t thresholdForOptimizeSoon;
+
+int32_t executionCounterIncrementForLoop;
+int32_t executionCounterIncrementForReturn;
+
+unsigned desiredSpeculativeSuccessFailRatio;
+
+double likelyToTakeSlowCaseThreshold;
+double couldTakeSlowCaseThreshold;
+unsigned likelyToTakeSlowCaseMinimumCount;
+unsigned couldTakeSlowCaseMinimumCount;
+
+double osrExitProminenceForFrequentExitSite;
+
+unsigned largeFailCountThresholdBase;
+unsigned largeFailCountThresholdBaseForLoop;
+unsigned forcedOSRExitCountForReoptimization;
+
+unsigned reoptimizationRetryCounterMax;
+unsigned reoptimizationRetryCounterStep;
+
+unsigned minimumOptimizationDelay;
+unsigned maximumOptimizationDelay;
+double desiredProfileLivenessRate;
+double desiredProfileFullnessRate;
+
+double doubleVoteRatioForDoubleFormat;
+
+unsigned minimumNumberOfScansBetweenRebalance;
+unsigned gcMarkStackSegmentSize;
+unsigned minimumNumberOfCellsToKeep;
+unsigned maximumNumberOfSharedSegments;
+unsigned sharedStackWakeupThreshold;
+unsigned numberOfGCMarkers;
+unsigned opaqueRootMergeThreshold;
+
+#if ENABLE(RUN_TIME_HEURISTICS)
+static bool parse(const char* string, bool& value)
+{
+    if (!strcasecmp(string, "true") || !strcasecmp(string, "yes") || !strcmp(string, "1")) {
+        value = true;
+        return true;
+    }
+    if (!strcasecmp(string, "false") || !strcasecmp(string, "no") || !strcmp(string, "0")) {
+        value = false;
+        return true;
+    }
+    return false;
+}
+
+static bool parse(const char* string, int32_t& value)
+{
+    return sscanf(string, "%d", &value) == 1;
+}
+
+static bool parse(const char* string, unsigned& value)
+{
+    return sscanf(string, "%u", &value) == 1;
+}
+
+static bool parse(const char* string, double& value)
+{
+    return sscanf(string, "%lf", &value) == 1;
+}
+
+template<typename T, typename U>
+void setHeuristic(T& variable, const char* name, U value)
+{
+    const char* stringValue = getenv(name);
+    if (!stringValue) {
+        variable = safeCast<T>(value);
+        return;
+    }
+    
+    if (parse(stringValue, variable))
+        return;
+    
+    fprintf(stderr, "WARNING: failed to parse %s=%s\n", name, stringValue);
+    variable = safeCast<T>(value);
+}
+
+#define SET(variable, value) setHeuristic(variable, "JSC_" #variable, value)
+#else
+#define SET(variable, value) variable = value
+#endif
+
+void initializeOptions()
+{
+    SET(useJIT, true);
+    
+    SET(maximumOptimizationCandidateInstructionCount, 10000);
+    
+    SET(maximumFunctionForCallInlineCandidateInstructionCount, 180);
+    SET(maximumFunctionForConstructInlineCandidateInstructionCount, 100);
+    
+    SET(maximumInliningDepth, 5);
+
+    SET(thresholdForJITAfterWarmUp,     100);
+    SET(thresholdForJITSoon,            100);
+
+    SET(thresholdForOptimizeAfterWarmUp,     1000);
+    SET(thresholdForOptimizeAfterLongWarmUp, 5000);
+    SET(thresholdForOptimizeSoon,            1000);
+
+    SET(executionCounterIncrementForLoop,   1);
+    SET(executionCounterIncrementForReturn, 15);
+
+    SET(desiredSpeculativeSuccessFailRatio, 6);
+    
+    SET(likelyToTakeSlowCaseThreshold,    0.15);
+    SET(couldTakeSlowCaseThreshold,       0.05); // Shouldn't be zero because some ops will spuriously take slow case, for example for linking or caching.
+    SET(likelyToTakeSlowCaseMinimumCount, 100);
+    SET(couldTakeSlowCaseMinimumCount,    10);
+    
+    SET(osrExitProminenceForFrequentExitSite, 0.3);
+
+    SET(largeFailCountThresholdBase,         20);
+    SET(largeFailCountThresholdBaseForLoop,  1);
+    SET(forcedOSRExitCountForReoptimization, 250);
+
+    SET(reoptimizationRetryCounterStep, 1);
+
+    SET(minimumOptimizationDelay,   1);
+    SET(maximumOptimizationDelay,   5);
+    SET(desiredProfileLivenessRate, 0.75);
+    SET(desiredProfileFullnessRate, 0.35);
+    
+    SET(doubleVoteRatioForDoubleFormat, 2);
+    
+    SET(minimumNumberOfScansBetweenRebalance, 10000);
+    SET(gcMarkStackSegmentSize,               pageSize());
+    SET(minimumNumberOfCellsToKeep,           10);
+    SET(maximumNumberOfSharedSegments,        3);
+    SET(sharedStackWakeupThreshold,           1);
+    SET(opaqueRootMergeThreshold,             1000);
+
+    int cpusToUse = 1;
+#if ENABLE(PARALLEL_GC)
+    cpusToUse = WTF::numberOfProcessorCores();
+#endif
+    // We don't scale so well beyond 4.
+    if (cpusToUse > 4)
+        cpusToUse = 4;
+    // Be paranoid, it is the OS we're dealing with, after all.
+    if (cpusToUse < 1)
+        cpusToUse = 1;
+    
+    SET(numberOfGCMarkers, cpusToUse);
+
+    ASSERT(thresholdForOptimizeAfterLongWarmUp >= thresholdForOptimizeAfterWarmUp);
+    ASSERT(thresholdForOptimizeAfterWarmUp >= thresholdForOptimizeSoon);
+    ASSERT(thresholdForOptimizeAfterWarmUp >= 0);
+    
+    // Compute the maximum value of the reoptimization retry counter. This is simply
+    // the largest value at which we don't overflow the execute counter, when using it
+    // to left-shift the execution counter by this amount. Currently the value ends
+    // up being 18, so this loop is not so terrible; it probably takes up ~100 cycles
+    // total on a 32-bit processor.
+    reoptimizationRetryCounterMax = 0;
+    while ((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << (reoptimizationRetryCounterMax + 1)) <= static_cast<int64_t>(std::numeric_limits<int32_t>::max()))
+        reoptimizationRetryCounterMax++;
+    
+    ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) > 0);
+    ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) <= static_cast<int64_t>(std::numeric_limits<int32_t>::max()));
+}
+
+} } // namespace JSC::Options
+
+
diff --git a/runtime/Options.h b/runtime/Options.h
new file mode 100644 (file)
index 0000000..d1ad2ca
--- /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. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED 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 Options_h
+#define Options_h
+
+#include <stdint.h>
+
+namespace JSC { namespace Options {
+
+extern bool useJIT;
+
+extern unsigned maximumOptimizationCandidateInstructionCount;
+
+extern unsigned maximumFunctionForCallInlineCandidateInstructionCount;
+extern unsigned maximumFunctionForConstructInlineCandidateInstructionCount;
+
+extern unsigned maximumInliningDepth; // Depth of inline stack, so 1 = no inlining, 2 = one level, etc.
+
+extern int32_t thresholdForJITAfterWarmUp;
+extern int32_t thresholdForJITSoon;
+
+extern int32_t thresholdForOptimizeAfterWarmUp;
+extern int32_t thresholdForOptimizeAfterLongWarmUp;
+extern int32_t thresholdForOptimizeSoon;
+extern int32_t thresholdForOptimizeNextInvocation;
+
+extern int32_t executionCounterIncrementForLoop;
+extern int32_t executionCounterIncrementForReturn;
+
+extern unsigned desiredSpeculativeSuccessFailRatio;
+
+extern double likelyToTakeSlowCaseThreshold;
+extern double couldTakeSlowCaseThreshold;
+extern unsigned likelyToTakeSlowCaseMinimumCount;
+extern unsigned couldTakeSlowCaseMinimumCount;
+
+extern double osrExitProminenceForFrequentExitSite;
+
+extern unsigned largeFailCountThresholdBase;
+extern unsigned largeFailCountThresholdBaseForLoop;
+extern unsigned forcedOSRExitCountForReoptimization;
+
+extern unsigned reoptimizationRetryCounterMax;
+extern unsigned reoptimizationRetryCounterStep;
+
+extern unsigned minimumOptimizationDelay;
+extern unsigned maximumOptimizationDelay;
+extern double desiredProfileLivenessRate;
+extern double desiredProfileFullnessRate;
+
+extern double doubleVoteRatioForDoubleFormat;
+
+extern unsigned minimumNumberOfScansBetweenRebalance;
+extern unsigned gcMarkStackSegmentSize;
+extern unsigned minimumNumberOfCellsToKeep;
+extern unsigned maximumNumberOfSharedSegments;
+extern unsigned sharedStackWakeupThreshold;
+JS_EXPORTDATA extern unsigned numberOfGCMarkers;
+JS_EXPORTDATA extern unsigned opaqueRootMergeThreshold;
+
+void initializeOptions();
+
+} } // namespace JSC::Options
+
+#endif // Options_h
+
index 558ae28525d9384082db43af0657baaa904929ec..236a8e5aeec176757815072751d4eae48fc7a286 100644 (file)
@@ -84,31 +84,45 @@ JSValue PropertyDescriptor::setter() const
     return m_setter;
 }
 
     return m_setter;
 }
 
+JSObject* PropertyDescriptor::getterObject() const
+{
+    ASSERT(isAccessorDescriptor() && getterPresent());
+    return m_getter.isObject() ? asObject(m_getter) : 0;
+}
+
+JSObject* PropertyDescriptor::setterObject() const
+{
+    ASSERT(isAccessorDescriptor() && setterPresent());
+    return m_setter.isObject() ? asObject(m_setter) : 0;
+}
+
 void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
 {
     ASSERT(value);
 void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
 {
     ASSERT(value);
+    ASSERT(value.isGetterSetter() == !!(attributes & Accessor));
+
     m_attributes = attributes;
     m_attributes = attributes;
-    if (attributes & (Getter | Setter)) {
+    if (value.isGetterSetter()) {
+        m_attributes &= ~ReadOnly; // FIXME: we should be able to ASSERT this!
+
         GetterSetter* accessor = asGetterSetter(value);
         GetterSetter* accessor = asGetterSetter(value);
-        m_getter = accessor->getter();
-        m_setter = accessor->setter();
-        ASSERT(m_getter || m_setter);
+        m_getter = accessor->getter() ? accessor->getter() : jsUndefined();
+        m_setter = accessor->setter() ? accessor->setter() : jsUndefined();
         m_seenAttributes = EnumerablePresent | ConfigurablePresent;
         m_seenAttributes = EnumerablePresent | ConfigurablePresent;
-        m_attributes &= ~ReadOnly;
     } else {
         m_value = value;
         m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent;
     }
 }
 
     } else {
         m_value = value;
         m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent;
     }
 }
 
-void PropertyDescriptor::setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes)
+void PropertyDescriptor::setAccessorDescriptor(GetterSetter* accessor, unsigned attributes)
 {
 {
-    ASSERT(attributes & (Getter | Setter));
-    ASSERT(getter || setter);
+    ASSERT(attributes & Accessor);
+    attributes &= ~ReadOnly; // FIXME: we should be able to ASSERT this!
+
     m_attributes = attributes;
     m_attributes = attributes;
-    m_getter = getter;
-    m_setter = setter;
-    m_attributes &= ~ReadOnly;
+    m_getter = accessor->getter() ? accessor->getter() : jsUndefined();
+    m_setter = accessor->setter() ? accessor->setter() : jsUndefined();
     m_seenAttributes = EnumerablePresent | ConfigurablePresent;
 }
 
     m_seenAttributes = EnumerablePresent | ConfigurablePresent;
 }
 
@@ -142,27 +156,41 @@ void PropertyDescriptor::setConfigurable(bool configurable)
 void PropertyDescriptor::setSetter(JSValue setter)
 {
     m_setter = setter;
 void PropertyDescriptor::setSetter(JSValue setter)
 {
     m_setter = setter;
-    m_attributes |= Setter;
+    m_attributes |= Accessor;
     m_attributes &= ~ReadOnly;
 }
 
 void PropertyDescriptor::setGetter(JSValue getter)
 {
     m_getter = getter;
     m_attributes &= ~ReadOnly;
 }
 
 void PropertyDescriptor::setGetter(JSValue getter)
 {
     m_getter = getter;
-    m_attributes |= Getter;
+    m_attributes |= Accessor;
     m_attributes &= ~ReadOnly;
 }
 
     m_attributes &= ~ReadOnly;
 }
 
+// See ES5.1 9.12
+bool sameValue(ExecState* exec, JSValue a, JSValue b)
+{
+    if (!a.isNumber())
+        return JSValue::strictEqual(exec, a, b);
+    if (!b.isNumber())
+        return false;
+    double x = a.asNumber();
+    double y = b.asNumber();
+    if (isnan(x))
+        return isnan(y);
+    return bitwise_cast<uint64_t>(x) == bitwise_cast<uint64_t>(y);
+}
+
 bool PropertyDescriptor::equalTo(ExecState* exec, const PropertyDescriptor& other) const
 {
     if (!other.m_value == m_value ||
         !other.m_getter == m_getter ||
         !other.m_setter == m_setter)
         return false;
 bool PropertyDescriptor::equalTo(ExecState* exec, const PropertyDescriptor& other) const
 {
     if (!other.m_value == m_value ||
         !other.m_getter == m_getter ||
         !other.m_setter == m_setter)
         return false;
-    return (!m_value || JSValue::strictEqual(exec, other.m_value, m_value)) && 
-           (!m_getter || JSValue::strictEqual(exec, other.m_getter, m_getter)) && 
-           (!m_setter || JSValue::strictEqual(exec, other.m_setter, m_setter)) &&
-           attributesEqual(other);
+    return (!m_value || sameValue(exec, other.m_value, m_value))
+        && (!m_getter || JSValue::strictEqual(exec, other.m_getter, m_getter))
+        && (!m_setter || JSValue::strictEqual(exec, other.m_setter, m_setter))
+        && attributesEqual(other);
 }
 
 bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
 }
 
 bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
@@ -178,18 +206,21 @@ bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
     return true;
 }
 
     return true;
 }
 
-unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& other) const
-{
-    unsigned mismatch = other.m_attributes ^ m_attributes;
-    unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
-    unsigned newAttributes = m_attributes & defaultAttributes;
-    if (sharedSeen & WritablePresent && mismatch & ReadOnly)
-        newAttributes ^= ReadOnly;
-    if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
-        newAttributes ^= DontDelete;
-    if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
-        newAttributes ^= DontEnum;
-    return newAttributes;
+unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescriptor& current) const
+{
+    unsigned currentAttributes = current.m_attributes;
+    if (isDataDescriptor() && current.isAccessorDescriptor())
+        currentAttributes |= ReadOnly;
+    unsigned overrideMask = 0;
+    if (writablePresent())
+        overrideMask |= ReadOnly;
+    if (enumerablePresent())
+        overrideMask |= DontEnum;
+    if (configurablePresent())
+        overrideMask |= DontDelete;
+    if (isAccessorDescriptor())
+        overrideMask |= Accessor;
+    return (m_attributes & overrideMask) | (currentAttributes & ~overrideMask);
 }
 
 }
 }
 
 }
index ff9f1608b89b74ed428bb511fd8a9bde535da0f7..2c3878f578d8021bac25c318b7179c9d0cc152aa 100644 (file)
 #include "JSValue.h"
 
 namespace JSC {
 #include "JSValue.h"
 
 namespace JSC {
+    class GetterSetter;
+
+    // See ES5.1 9.12
+    bool sameValue(ExecState*, JSValue, JSValue);
+
     class PropertyDescriptor {
     public:
         PropertyDescriptor()
     class PropertyDescriptor {
     public:
         PropertyDescriptor()
@@ -36,25 +41,27 @@ namespace JSC {
             , m_seenAttributes(0)
         {
         }
             , m_seenAttributes(0)
         {
         }
-        bool writable() const;
-        bool enumerable() const;
-        bool configurable() const;
-        bool isDataDescriptor() const;
+        JS_EXPORT_PRIVATE bool writable() const;
+        JS_EXPORT_PRIVATE bool enumerable() const;
+        JS_EXPORT_PRIVATE bool configurable() const;
+        JS_EXPORT_PRIVATE bool isDataDescriptor() const;
         bool isGenericDescriptor() const;
         bool isGenericDescriptor() const;
-        bool isAccessorDescriptor() const;
+        JS_EXPORT_PRIVATE bool isAccessorDescriptor() const;
         unsigned attributes() const { return m_attributes; }
         JSValue value() const { return m_value; }
         unsigned attributes() const { return m_attributes; }
         JSValue value() const { return m_value; }
-        JSValue getter() const;
-        JSValue setter() const;
-        void setUndefined();
-        void setDescriptor(JSValue value, unsigned attributes);
-        void setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes);
-        void setWritable(bool);
-        void setEnumerable(bool);
-        void setConfigurable(bool);
+        JS_EXPORT_PRIVATE JSValue getter() const;
+        JS_EXPORT_PRIVATE JSValue setter() const;
+        JSObject* getterObject() const;
+        JSObject* setterObject() const;
+        JS_EXPORT_PRIVATE void setUndefined();
+        JS_EXPORT_PRIVATE void setDescriptor(JSValue value, unsigned attributes);
+        void setAccessorDescriptor(GetterSetter* accessor, unsigned attributes);
+        JS_EXPORT_PRIVATE void setWritable(bool);
+        JS_EXPORT_PRIVATE void setEnumerable(bool);
+        JS_EXPORT_PRIVATE void setConfigurable(bool);
         void setValue(JSValue value) { m_value = value; }
         void setValue(JSValue value) { m_value = value; }
-        void setSetter(JSValue);
-        void setGetter(JSValue);
+        JS_EXPORT_PRIVATE void setSetter(JSValue);
+        JS_EXPORT_PRIVATE void setGetter(JSValue);
         bool isEmpty() const { return !(m_value || m_getter || m_setter || m_seenAttributes); }
         bool writablePresent() const { return m_seenAttributes & WritablePresent; }
         bool enumerablePresent() const { return m_seenAttributes & EnumerablePresent; }
         bool isEmpty() const { return !(m_value || m_getter || m_setter || m_seenAttributes); }
         bool writablePresent() const { return m_seenAttributes & WritablePresent; }
         bool enumerablePresent() const { return m_seenAttributes & EnumerablePresent; }
@@ -63,9 +70,10 @@ namespace JSC {
         bool getterPresent() const { return m_getter; }
         bool equalTo(ExecState* exec, const PropertyDescriptor& other) const;
         bool attributesEqual(const PropertyDescriptor& other) const;
         bool getterPresent() const { return m_getter; }
         bool equalTo(ExecState* exec, const PropertyDescriptor& other) const;
         bool attributesEqual(const PropertyDescriptor& other) const;
-        unsigned attributesWithOverride(const PropertyDescriptor& other) const;
+        unsigned attributesOverridingCurrent(const PropertyDescriptor& current) const;
+
     private:
     private:
-        static unsigned defaultAttributes;
+        JS_EXPORTDATA static unsigned defaultAttributes;
         bool operator==(const PropertyDescriptor&){ return false; }
         enum { WritablePresent = 1, EnumerablePresent = 2, ConfigurablePresent = 4};
         // May be a getter/setter
         bool operator==(const PropertyDescriptor&){ return false; }
         enum { WritablePresent = 1, EnumerablePresent = 2, ConfigurablePresent = 4};
         // May be a getter/setter
index 28a9364948dda664804fadc54794566001f9a251..7c8cabb7b3b05be9facbcbf2ea845e605e85ba53 100644 (file)
@@ -154,7 +154,8 @@ public:
     const_iterator end() const;
 
     // Find a value in the table.
     const_iterator end() const;
 
     // Find a value in the table.
-    find_iterator find(const KeyType& key);
+    find_iterator find(const KeyType&);
+    find_iterator findWithString(const KeyType&);
     // Add a value to the table
     std::pair<find_iterator, bool> add(const ValueType& entry);
     // Remove a value from the table.
     // Add a value to the table
     std::pair<find_iterator, bool> add(const ValueType& entry);
     // Remove a value from the table.
@@ -324,6 +325,7 @@ inline PropertyTable::const_iterator PropertyTable::end() const
 inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key)
 {
     ASSERT(key);
 inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key)
 {
     ASSERT(key);
+    ASSERT(key->isIdentifier());
     unsigned hash = key->existingHash();
     unsigned step = 0;
 
     unsigned hash = key->existingHash();
     unsigned step = 0;
 
@@ -343,7 +345,39 @@ inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key)
 #endif
 
         if (!step)
 #endif
 
         if (!step)
-            step =WTF::doubleHash(key->existingHash()) | 1;
+            step = WTF::doubleHash(key->existingHash()) | 1;
+        hash += step;
+
+#if DUMP_PROPERTYMAP_STATS
+        ++numRehashes;
+#endif
+    }
+}
+
+inline PropertyTable::find_iterator PropertyTable::findWithString(const KeyType& key)
+{
+    ASSERT(key);
+    ASSERT(!key->isIdentifier() && !key->hasHash());
+    unsigned hash = key->hash();
+    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 (equal(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
         hash += step;
 
 #if DUMP_PROPERTYMAP_STATS
index 8efb4065e1739cf05d5d9166c75becd80dde30fc..9bae94097400852aca0c03f4b79e425bb4c3333f 100644 (file)
@@ -45,7 +45,7 @@ void PropertyNameArray::add(StringImpl* identifier)
             for (size_t i = 0; i < size; ++i)
                 m_set.add(m_data->propertyNameVector()[i].impl());
         }
             for (size_t i = 0; i < size; ++i)
                 m_set.add(m_data->propertyNameVector()[i].impl());
         }
-        if (!m_set.add(identifier).second)
+        if (!m_set.add(identifier).isNewEntry)
             return;
     }
 
             return;
     }
 
index 0da930f173f13f4a3e1b8c04d666a8c041a71ad5..dabda945b1965a3bf3cb459fbd673a2884c73410 100644 (file)
@@ -69,7 +69,7 @@ namespace JSC {
         JSGlobalData* globalData() { return m_globalData; }
 
         void add(const Identifier& identifier) { add(identifier.impl()); }
         JSGlobalData* globalData() { return m_globalData; }
 
         void add(const Identifier& identifier) { add(identifier.impl()); }
-        void add(StringImpl*);
+        JS_EXPORT_PRIVATE void add(StringImpl*);
         void addKnownUnique(StringImpl* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
 
         Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
         void addKnownUnique(StringImpl* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
 
         Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
index fd16c0c092b740e99fd91b3ec34a7527cfc1de48..8ac87411535af0e69ad60fefc4907de0cfc03987 100644 (file)
@@ -33,8 +33,8 @@ JSValue PropertySlot::functionGetter(ExecState* exec) const
         return exec->exception();
 
     CallData callData;
         return exec->exception();
 
     CallData callData;
-    CallType callType = m_data.getterFunc->getCallData(callData);
-    return call(exec, m_data.getterFunc, callType, callData, thisValue(), exec->emptyList());
+    CallType callType = m_data.getterFunc->methodTable()->getCallData(m_data.getterFunc, callData);
+    return call(exec, m_data.getterFunc, callType, callData, m_thisValue.isObject() ? m_thisValue.toThisObject(exec) : m_thisValue, exec->emptyList());
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index ce29ac4e6c7bb85553e7abcb79741adba36104f0..cfedf7876fb636544bd9e8ff4717a428300c689b 100644 (file)
@@ -212,15 +212,13 @@ namespace JSC {
 
         unsigned index() const { return m_data.index; }
 
 
         unsigned index() const { return m_data.index; }
 
-        JSValue thisValue() const { return m_thisValue; }
-
         GetValueFunc customGetter() const
         {
             ASSERT(m_cachedPropertyType == Custom);
             return m_getValue;
         }
     private:
         GetValueFunc customGetter() const
         {
             ASSERT(m_cachedPropertyType == Custom);
             return m_getValue;
         }
     private:
-        JSValue functionGetter(ExecState*) const;
+        JS_EXPORT_PRIVATE JSValue functionGetter(ExecState*) const;
 
         GetValueFunc m_getValue;
         GetIndexValueFunc m_getIndexValue;
 
         GetValueFunc m_getValue;
         GetIndexValueFunc m_getIndexValue;
index 9211a90ede39214b4f2ce4cd91d44d071696ac81..b0f67607e221b001161aa9a84b9e007c025f4434 100644 (file)
 #include <wtf/Assertions.h>
 #include <wtf/OwnArrayPtr.h>
 
 #include <wtf/Assertions.h>
 #include <wtf/OwnArrayPtr.h>
 
+
+#define REGEXP_FUNC_TEST_DATA_GEN 0
+
 namespace JSC {
 
 namespace JSC {
 
-const ClassInfo RegExp::s_info = { "RegExp", 0, 0, 0 };
+const ClassInfo RegExp::s_info = { "RegExp", 0, 0, 0, CREATE_METHOD_TABLE(RegExp) };
 
 RegExpFlags regExpFlags(const UString& string)
 {
     RegExpFlags flags = NoFlags;
 
     for (unsigned i = 0; i < string.length(); ++i) {
 
 RegExpFlags regExpFlags(const UString& string)
 {
     RegExpFlags flags = NoFlags;
 
     for (unsigned i = 0; i < string.length(); ++i) {
-        switch (string.characters()[i]) {
+        switch (string[i]) {
         case 'g':
             if (flags & FlagGlobal)
                 return InvalidFlags;
         case 'g':
             if (flags & FlagGlobal)
                 return InvalidFlags;
@@ -68,16 +71,154 @@ RegExpFlags regExpFlags(const UString& string)
 
     return flags;
 }
 
     return flags;
 }
-  
-struct RegExpRepresentation {
-#if ENABLE(YARR_JIT)
-    Yarr::YarrCodeBlock m_regExpJITCode;
-#endif
-    OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
+
+#if REGEXP_FUNC_TEST_DATA_GEN
+class RegExpFunctionalTestCollector {
+    // This class is not thread safe.
+protected:
+    static const char* const s_fileName;
+
+public:
+    static RegExpFunctionalTestCollector* get();
+
+    ~RegExpFunctionalTestCollector();
+
+    void outputOneTest(RegExp*, UString, int, int*, int);
+    void clearRegExp(RegExp* regExp)
+    {
+        if (regExp == m_lastRegExp)
+            m_lastRegExp = 0;
+    }
+
+private:
+    RegExpFunctionalTestCollector();
+
+    void outputEscapedUString(const UString&, bool escapeSlash = false);
+
+    static RegExpFunctionalTestCollector* s_instance;
+    FILE* m_file;
+    RegExp* m_lastRegExp;
 };
 
 };
 
-RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, RegExpFlags flags)
-    : JSCell(*globalData, globalData->regExpStructure.get())
+const char* const RegExpFunctionalTestCollector::s_fileName = "/tmp/RegExpTestsData";
+RegExpFunctionalTestCollector* RegExpFunctionalTestCollector::s_instance = 0;
+
+RegExpFunctionalTestCollector* RegExpFunctionalTestCollector::get()
+{
+    if (!s_instance)
+        s_instance = new RegExpFunctionalTestCollector();
+
+    return s_instance;
+}
+
+void RegExpFunctionalTestCollector::outputOneTest(RegExp* regExp, UString s, int startOffset, int* ovector, int result)
+{
+    if ((!m_lastRegExp) || (m_lastRegExp != regExp)) {
+        m_lastRegExp = regExp;
+        fputc('/', m_file);
+        outputEscapedUString(regExp->pattern(), true);
+        fputc('/', m_file);
+        if (regExp->global())
+            fputc('g', m_file);
+        if (regExp->ignoreCase())
+            fputc('i', m_file);
+        if (regExp->multiline())
+            fputc('m', m_file);
+        fprintf(m_file, "\n");
+    }
+
+    fprintf(m_file, " \"");
+    outputEscapedUString(s);
+    fprintf(m_file, "\", %d, %d, (", startOffset, result);
+    for (unsigned i = 0; i <= regExp->numSubpatterns(); i++) {
+        int subpatternBegin = ovector[i * 2];
+        int subpatternEnd = ovector[i * 2 + 1];
+        if (subpatternBegin == -1)
+            subpatternEnd = -1;
+        fprintf(m_file, "%d, %d", subpatternBegin, subpatternEnd);
+        if (i < regExp->numSubpatterns())
+            fputs(", ", m_file);
+    }
+
+    fprintf(m_file, ")\n");
+    fflush(m_file);
+}
+
+RegExpFunctionalTestCollector::RegExpFunctionalTestCollector()
+{
+    m_file = fopen(s_fileName, "r+");
+    if  (!m_file)
+        m_file = fopen(s_fileName, "w+");
+
+    fseek(m_file, 0L, SEEK_END);
+}
+
+RegExpFunctionalTestCollector::~RegExpFunctionalTestCollector()
+{
+    fclose(m_file);
+    s_instance = 0;
+}
+
+void RegExpFunctionalTestCollector::outputEscapedUString(const UString& s, bool escapeSlash)
+{
+    int len = s.length();
+    
+    for (int i = 0; i < len; ++i) {
+        UChar c = s[i];
+
+        switch (c) {
+        case '\0':
+            fputs("\\0", m_file);
+            break;
+        case '\a':
+            fputs("\\a", m_file);
+            break;
+        case '\b':
+            fputs("\\b", m_file);
+            break;
+        case '\f':
+            fputs("\\f", m_file);
+            break;
+        case '\n':
+            fputs("\\n", m_file);
+            break;
+        case '\r':
+            fputs("\\r", m_file);
+            break;
+        case '\t':
+            fputs("\\t", m_file);
+            break;
+        case '\v':
+            fputs("\\v", m_file);
+            break;
+        case '/':
+            if (escapeSlash)
+                fputs("\\/", m_file);
+            else
+                fputs("/", m_file);
+            break;
+        case '\"':
+            fputs("\\\"", m_file);
+            break;
+        case '\\':
+            fputs("\\\\", m_file);
+            break;
+        case '\?':
+            fputs("\?", m_file);
+            break;
+        default:
+            if (c > 0x7f)
+                fprintf(m_file, "\\u%04x", c);
+            else 
+                fputc(c, m_file);
+            break;
+        }
+    }
+}
+#endif
+
+RegExp::RegExp(JSGlobalData& globalData, const UString& patternString, RegExpFlags flags)
+    : JSCell(globalData, globalData.regExpStructure.get())
     , m_state(NotCompiled)
     , m_patternString(patternString)
     , m_flags(flags)
     , m_state(NotCompiled)
     , m_patternString(patternString)
     , m_flags(flags)
@@ -88,6 +229,11 @@ RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, RegExpFla
     , m_rtMatchFoundCount(0)
 #endif
 {
     , m_rtMatchFoundCount(0)
 #endif
 {
+}
+
+void RegExp::finishCreation(JSGlobalData& globalData)
+{
+    Base::finishCreation(globalData);
     Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
     if (m_constructionError)
         m_state = ParseError;
     Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
     if (m_constructionError)
         m_state = ParseError;
@@ -95,115 +241,256 @@ RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, RegExpFla
         m_numSubpatterns = pattern.m_numSubpatterns;
 }
 
         m_numSubpatterns = pattern.m_numSubpatterns;
 }
 
-RegExp::~RegExp()
+void RegExp::destroy(JSCell* cell)
 {
 {
+    RegExp* thisObject = jsCast<RegExp*>(cell);
+#if REGEXP_FUNC_TEST_DATA_GEN
+    RegExpFunctionalTestCollector::get()->clearRegExp(this);
+#endif
+    thisObject->RegExp::~RegExp();
 }
 
 }
 
-RegExp* RegExp::create(JSGlobalData* globalData, const UString& patternString, RegExpFlags flags)
+RegExp* RegExp::createWithoutCaching(JSGlobalData& globalData, const UString& patternString, RegExpFlags flags)
 {
 {
-    return globalData->regExpCache()->lookupOrCreate(patternString, flags);
+    RegExp* regExp = new (NotNull, allocateCell<RegExp>(globalData.heap)) RegExp(globalData, patternString, flags);
+    regExp->finishCreation(globalData);
+    return regExp;
 }
 
 }
 
-void RegExp::compile(JSGlobalData* globalData)
+RegExp* RegExp::create(JSGlobalData& globalData, const UString& patternString, RegExpFlags flags)
+{
+    return globalData.regExpCache()->lookupOrCreate(patternString, flags);
+}
+
+void RegExp::compile(JSGlobalData* globalData, Yarr::YarrCharSize charSize)
 {
 {
-    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;
     }
     Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
     if (m_constructionError) {
         ASSERT_NOT_REACHED();
         m_state = ParseError;
         return;
     }
-
-    globalData->regExpCache()->addToStrongCache(this);
-
     ASSERT(m_numSubpatterns == pattern.m_numSubpatterns);
 
     ASSERT(m_numSubpatterns == pattern.m_numSubpatterns);
 
+    if (!hasCode()) {
+        ASSERT(m_state == NotCompiled);
+        globalData->regExpCache()->addToStrongCache(this);
+        m_state = ByteCode;
+    }
+
 #if ENABLE(YARR_JIT)
 #if ENABLE(YARR_JIT)
-    if (!pattern.m_containsBackreferences && globalData->canUseJIT()) {
-        Yarr::jitCompile(pattern, globalData, m_representation->m_regExpJITCode);
+    if (!pattern.m_containsBackreferences && globalData->canUseRegExpJIT()) {
+        Yarr::jitCompile(pattern, charSize, globalData, m_regExpJITCode);
 #if ENABLE(YARR_JIT_DEBUG)
 #if ENABLE(YARR_JIT_DEBUG)
-        if (!m_representation->m_regExpJITCode.isFallBack())
+        if (!m_regExpJITCode.isFallBack())
             m_state = JITCode;
         else
             m_state = ByteCode;
 #else
             m_state = JITCode;
         else
             m_state = ByteCode;
 #else
-        if (!m_representation->m_regExpJITCode.isFallBack()) {
+        if (!m_regExpJITCode.isFallBack()) {
             m_state = JITCode;
             return;
         }
 #endif
     }
             m_state = JITCode;
             return;
         }
 #endif
     }
+#else
+    UNUSED_PARAM(charSize);
 #endif
 
 #endif
 
-    m_representation->m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
-
-    m_state = ByteCode;
+    m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
 }
 
 }
 
-int RegExp::match(JSGlobalData& globalData, const UString& s, int startOffset, Vector<int, 32>* ovector)
+void RegExp::compileIfNecessary(JSGlobalData& globalData, Yarr::YarrCharSize charSize)
 {
 {
-    if (startOffset < 0)
-        startOffset = 0;
+    if (hasCode()) {
+#if ENABLE(YARR_JIT)
+        if (m_state != JITCode)
+            return;
+        if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCode()))
+            return;
+        if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCode()))
+            return;
+#else
+        return;
+#endif
+    }
 
 
+    compile(&globalData, charSize);
+}
+
+int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset, Vector<int, 32>& ovector)
+{
 #if ENABLE(REGEXP_TRACING)
     m_rtMatchCallCount++;
 #endif
 
 #if ENABLE(REGEXP_TRACING)
     m_rtMatchCallCount++;
 #endif
 
-    if (static_cast<unsigned>(startOffset) > s.length() || s.isNull())
-        return -1;
+    ASSERT(m_state != ParseError);
+    compileIfNecessary(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
 
 
-    if (m_state != ParseError) {
-        compileIfNecessary(globalData);
+    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
+    ovector.resize(offsetVectorSize);
+    int* offsetVector = ovector.data();
 
 
-        int offsetVectorSize = (m_numSubpatterns + 1) * 2;
-        int* offsetVector;
-        Vector<int, 32> nonReturnedOvector;
-        if (ovector) {
-            ovector->resize(offsetVectorSize);
-            offsetVector = ovector->data();
-        } else {
-            nonReturnedOvector.resize(offsetVectorSize);
-            offsetVector = nonReturnedOvector.data();
+    int result;
+#if ENABLE(YARR_JIT)
+    if (m_state == JITCode) {
+        if (s.is8Bit())
+            result = m_regExpJITCode.execute(s.characters8(), startOffset, s.length(), offsetVector).start;
+        else
+            result = m_regExpJITCode.execute(s.characters16(), startOffset, s.length(), offsetVector).start;
+#if ENABLE(YARR_JIT_DEBUG)
+        matchCompareWithInterpreter(s, startOffset, offsetVector, result);
+#endif
+    } else
+#endif
+        result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
+
+    // FIXME: The YARR engine should handle unsigned or size_t length matches.
+    // The YARR Interpreter is "unsigned" clean, while the YARR JIT hasn't been addressed.
+    // The offset vector handling needs to change as well.
+    // Right now we convert a match where the offsets overflowed into match failure.
+    // There are two places in WebCore that call the interpreter directly that need to
+    // have their offsets changed to int as well. They are platform/text/RegularExpression.cpp
+    // and inspector/ContentSearchUtils.cpp.
+    if (s.length() > INT_MAX) {
+        bool overflowed = false;
+
+        if (result < -1)
+            overflowed = true;
+
+        for (unsigned i = 0; i <= m_numSubpatterns; i++) {
+            if ((offsetVector[i*2] < -1) || ((offsetVector[i*2] >= 0) && (offsetVector[i*2+1] < -1))) {
+                overflowed = true;
+                offsetVector[i*2] = -1;
+                offsetVector[i*2+1] = -1;
+            }
         }
 
         }
 
-        ASSERT(offsetVector);
-        // 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;
+        if (overflowed)
+            result = -1;
+    }
+
+    ASSERT(result >= -1);
+
+#if REGEXP_FUNC_TEST_DATA_GEN
+    RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
+#endif
+
+#if ENABLE(REGEXP_TRACING)
+    if (result != -1)
+        m_rtMatchFoundCount++;
+#endif
+
+    return result;
+}
+
+void RegExp::compileMatchOnly(JSGlobalData* globalData, Yarr::YarrCharSize charSize)
+{
+    Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
+    if (m_constructionError) {
+        ASSERT_NOT_REACHED();
+        m_state = ParseError;
+        return;
+    }
+    ASSERT(m_numSubpatterns == pattern.m_numSubpatterns);
+
+    if (!hasCode()) {
+        ASSERT(m_state == NotCompiled);
+        globalData->regExpCache()->addToStrongCache(this);
+        m_state = ByteCode;
+    }
 
 
-        int result;
 #if ENABLE(YARR_JIT)
 #if ENABLE(YARR_JIT)
-        if (m_state == JITCode) {
-            result = Yarr::execute(m_representation->m_regExpJITCode, s.characters(), startOffset, s.length(), offsetVector);
+    if (!pattern.m_containsBackreferences && globalData->canUseRegExpJIT()) {
+        Yarr::jitCompile(pattern, charSize, globalData, m_regExpJITCode, Yarr::MatchOnly);
 #if ENABLE(YARR_JIT_DEBUG)
 #if ENABLE(YARR_JIT_DEBUG)
-            matchCompareWithInterpreter(s, startOffset, offsetVector, result);
+        if (!m_regExpJITCode.isFallBack())
+            m_state = JITCode;
+        else
+            m_state = ByteCode;
+#else
+        if (!m_regExpJITCode.isFallBack()) {
+            m_state = JITCode;
+            return;
+        }
 #endif
 #endif
-        } else
+    }
+#else
+    UNUSED_PARAM(charSize);
 #endif
 #endif
-            result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s.characters(), startOffset, s.length(), offsetVector);
-        ASSERT(result >= -1);
 
 
+    m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
+}
+
+void RegExp::compileIfNecessaryMatchOnly(JSGlobalData& globalData, Yarr::YarrCharSize charSize)
+{
+    if (hasCode()) {
+#if ENABLE(YARR_JIT)
+        if (m_state != JITCode)
+            return;
+        if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCodeMatchOnly()))
+            return;
+        if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCodeMatchOnly()))
+            return;
+#else
+        return;
+#endif
+    }
+
+    compileMatchOnly(&globalData, charSize);
+}
+
+MatchResult RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset)
+{
 #if ENABLE(REGEXP_TRACING)
 #if ENABLE(REGEXP_TRACING)
-        if (result != -1)
-            m_rtMatchFoundCount++;
+    m_rtMatchCallCount++;
 #endif
 
 #endif
 
+    ASSERT(m_state != ParseError);
+    compileIfNecessaryMatchOnly(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
+
+#if ENABLE(YARR_JIT)
+    if (m_state == JITCode) {
+        MatchResult result = s.is8Bit() ?
+            m_regExpJITCode.execute(s.characters8(), startOffset, s.length()) :
+            m_regExpJITCode.execute(s.characters16(), startOffset, s.length());
+#if ENABLE(REGEXP_TRACING)
+        if (!result)
+            m_rtMatchFoundCount++;
+#endif
         return result;
     }
         return result;
     }
+#endif
+
+    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
+    int* offsetVector;
+    Vector<int, 32> nonReturnedOvector;
+    nonReturnedOvector.resize(offsetVectorSize);
+    offsetVector = nonReturnedOvector.data();
+    int r = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
+#if REGEXP_FUNC_TEST_DATA_GEN
+    RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
+#endif
+
+    if (r >= 0) {
+#if ENABLE(REGEXP_TRACING)
+        m_rtMatchFoundCount++;
+#endif
+        return MatchResult(r, reinterpret_cast<unsigned*>(offsetVector)[1]);
+    }
 
 
-    return -1;
+    return MatchResult::failed();
 }
 
 void RegExp::invalidateCode()
 {
 }
 
 void RegExp::invalidateCode()
 {
-    if (!m_representation || m_state == Compiling)
+    if (!hasCode())
         return;
     m_state = NotCompiled;
         return;
     m_state = NotCompiled;
-    m_representation.clear();
+#if ENABLE(YARR_JIT)
+    m_regExpJITCode.clear();
+#endif
+    m_regExpBytecode.clear();
 }
 
 #if ENABLE(YARR_JIT_DEBUG)
 }
 
 #if ENABLE(YARR_JIT_DEBUG)
@@ -222,7 +509,7 @@ void RegExp::matchCompareWithInterpreter(const UString& s, int startOffset, int*
     for (unsigned j = 0, i = 0; i < m_numSubpatterns + 1; j += 2, i++)
         interpreterOffsetVector[j] = -1;
 
     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);
+    interpreterResult = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, interpreterOffsetVector);
 
     if (jitResult != interpreterResult)
         differences++;
 
     if (jitResult != interpreterResult)
         differences++;
@@ -233,24 +520,24 @@ void RegExp::matchCompareWithInterpreter(const UString& s, int startOffset, int*
             differences++;
 
     if (differences) {
             differences++;
 
     if (differences) {
-        fprintf(stderr, "RegExp Discrepency for /%s/\n    string input ", pattern().utf8().data());
+        dataLog("RegExp Discrepency for /%s/\n    string input ", pattern().utf8().data());
         unsigned segmentLen = s.length() - static_cast<unsigned>(startOffset);
 
         unsigned segmentLen = s.length() - static_cast<unsigned>(startOffset);
 
-        fprintf(stderr, (segmentLen < 150) ? "\"%s\"\n" : "\"%148s...\"\n", s.utf8().data() + startOffset);
+        dataLog((segmentLen < 150) ? "\"%s\"\n" : "\"%148s...\"\n", s.utf8().data() + startOffset);
 
         if (jitResult != interpreterResult) {
 
         if (jitResult != interpreterResult) {
-            fprintf(stderr, "    JIT result = %d, blah interpreted result = %d\n", jitResult, interpreterResult);
+            dataLog("    JIT result = %d, blah interpreted result = %d\n", jitResult, interpreterResult);
             differences--;
         } else {
             differences--;
         } else {
-            fprintf(stderr, "    Correct result = %d\n", jitResult);
+            dataLog("    Correct result = %d\n", jitResult);
         }
 
         if (differences) {
             for (unsigned j = 2, i = 0; i < m_numSubpatterns; j +=2, i++) {
                 if (offsetVector[j] != interpreterOffsetVector[j])
         }
 
         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]);
+                    dataLog("    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]))
                 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]);
+                    dataLog("    JIT offset[%d] = %d, interpreted offset[%d] = %d\n", j+1, offsetVector[j+1], j+1, interpreterOffsetVector[j+1]);
             }
         }
     }
             }
         }
     }
@@ -271,7 +558,7 @@ void RegExp::matchCompareWithInterpreter(const UString& s, int startOffset, int*
         snprintf(formattedPattern, 41, (pattLen <= 38) ? "/%.38s/" : "/%.36s...", rawPattern);
 
 #if ENABLE(YARR_JIT)
         snprintf(formattedPattern, 41, (pattLen <= 38) ? "/%.38s/" : "/%.36s...", rawPattern);
 
 #if ENABLE(YARR_JIT)
-        Yarr::YarrCodeBlock& codeBlock = m_representation->m_regExpJITCode;
+        Yarr::YarrCodeBlock& codeBlock = m_regExpJITCode;
 
         const size_t jitAddrSize = 20;
         char jitAddr[jitAddrSize];
 
         const size_t jitAddrSize = 20;
         char jitAddr[jitAddrSize];
@@ -286,5 +573,5 @@ void RegExp::matchCompareWithInterpreter(const UString& s, int startOffset, int*
         printf("%-40.40s %16.16s %10d %10d\n", formattedPattern, jitAddr, m_rtMatchCallCount, m_rtMatchFoundCount);
     }
 #endif
         printf("%-40.40s %16.16s %10d %10d\n", formattedPattern, jitAddr, m_rtMatchCallCount, m_rtMatchFoundCount);
     }
 #endif
-    
+
 } // namespace JSC
 } // namespace JSC
index 79f4694ee134bfd60ef396a31bdeeb44bc94e3e2..ad1020376cb12b7eea0e9d62da32a669d25baa8b 100644 (file)
 #ifndef RegExp_h
 #define RegExp_h
 
 #ifndef RegExp_h
 #define RegExp_h
 
-#include "UString.h"
 #include "ExecutableAllocator.h"
 #include "ExecutableAllocator.h"
-#include "Structure.h"
+#include "MatchResult.h"
 #include "RegExpKey.h"
 #include "RegExpKey.h"
+#include "Structure.h"
+#include "UString.h"
+#include "yarr/Yarr.h"
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
 
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
 
+#if ENABLE(YARR_JIT)
+#include "yarr/YarrJIT.h"
+#endif
+
 namespace JSC {
 
     struct RegExpRepresentation;
     class JSGlobalData;
 
 namespace JSC {
 
     struct RegExpRepresentation;
     class JSGlobalData;
 
-    RegExpFlags regExpFlags(const UString&);
+    JS_EXPORT_PRIVATE RegExpFlags regExpFlags(const UString&);
 
     class RegExp : public JSCell {
     public:
 
     class RegExp : public JSCell {
     public:
-        static RegExp* create(JSGlobalData*, const UString& pattern, RegExpFlags);
-        ~RegExp();
+        typedef JSCell Base;
+
+        JS_EXPORT_PRIVATE static RegExp* create(JSGlobalData&, const UString& pattern, RegExpFlags);
+        static void destroy(JSCell*);
 
         bool global() const { return m_flags & FlagGlobal; }
         bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
 
         bool global() const { return m_flags & FlagGlobal; }
         bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
@@ -50,12 +58,13 @@ namespace JSC {
         bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; }
         const char* errorMessage() const { return m_constructionError; }
 
         bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; }
         const char* errorMessage() const { return m_constructionError; }
 
-        int match(JSGlobalData&, const UString&, int startOffset, Vector<int, 32>* ovector = 0);
+        JS_EXPORT_PRIVATE int match(JSGlobalData&, const UString&, unsigned startOffset, Vector<int, 32>& ovector);
+        MatchResult match(JSGlobalData&, const UString&, unsigned startOffset);
         unsigned numSubpatterns() const { return m_numSubpatterns; }
 
         bool hasCode()
         {
         unsigned numSubpatterns() const { return m_numSubpatterns; }
 
         bool hasCode()
         {
-            return m_representation;
+            return m_state != NotCompiled;
         }
 
         void invalidateCode();
         }
 
         void invalidateCode();
@@ -64,34 +73,36 @@ namespace JSC {
         void printTraceData();
 #endif
 
         void printTraceData();
 #endif
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(LeafType, 0), 0, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(LeafType, 0), &s_info);
         }
         
         }
         
-        static JS_EXPORTDATA const ClassInfo s_info;
+        static const ClassInfo s_info;
 
         RegExpKey key() { return RegExpKey(m_flags, m_patternString); }
 
 
         RegExpKey key() { return RegExpKey(m_flags, m_patternString); }
 
+    protected:
+        void finishCreation(JSGlobalData&);
+
     private:
         friend class RegExpCache;
     private:
         friend class RegExpCache;
-        RegExp(JSGlobalData* globalData, const UString& pattern, RegExpFlags);
+        RegExp(JSGlobalData&, const UString&, RegExpFlags);
+
+        static RegExp* createWithoutCaching(JSGlobalData&, const UString&, RegExpFlags);
 
         enum RegExpState {
             ParseError,
             JITCode,
             ByteCode,
 
         enum RegExpState {
             ParseError,
             JITCode,
             ByteCode,
-            NotCompiled,
-            Compiling
+            NotCompiled
         } m_state;
 
         } m_state;
 
-        void compile(JSGlobalData*);
-        void compileIfNecessary(JSGlobalData& globalData)
-        {
-            if (m_representation)
-                return;
-            compile(&globalData);
-        }
+        void compile(JSGlobalData*, Yarr::YarrCharSize);
+        void compileIfNecessary(JSGlobalData&, Yarr::YarrCharSize);
+
+        void compileMatchOnly(JSGlobalData*, Yarr::YarrCharSize);
+        void compileIfNecessaryMatchOnly(JSGlobalData&, Yarr::YarrCharSize);
 
 #if ENABLE(YARR_JIT_DEBUG)
         void matchCompareWithInterpreter(const UString&, int startOffset, int* offsetVector, int jitResult);
 
 #if ENABLE(YARR_JIT_DEBUG)
         void matchCompareWithInterpreter(const UString&, int startOffset, int* offsetVector, int jitResult);
@@ -106,7 +117,10 @@ namespace JSC {
         unsigned m_rtMatchFoundCount;
 #endif
 
         unsigned m_rtMatchFoundCount;
 #endif
 
-        OwnPtr<RegExpRepresentation> m_representation;
+#if ENABLE(YARR_JIT)
+        Yarr::YarrCodeBlock m_regExpJITCode;
+#endif
+        OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 2dce19797b8e185f130455a4edaf211fa9f35a70..36ea326e61c98388d0022afa924affeefe728364 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "RegExpCache.h"
 #include "RegExpObject.h"
 
 #include "RegExpCache.h"
 #include "RegExpObject.h"
+#include "StrongInlines.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -38,14 +39,14 @@ RegExp* RegExpCache::lookupOrCreate(const UString& patternString, RegExpFlags fl
     RegExpCacheMap::iterator result = m_weakCache.find(key);
     if (result != m_weakCache.end())
         return result->second.get();
     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);
+    RegExp* regExp = RegExp::createWithoutCaching(*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.
 #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));
+    m_weakCache.add(key, PassWeak<RegExp>(regExp, this));
     return regExp;
 }
 
     return regExp;
 }
 
diff --git a/runtime/RegExpCachedResult.cpp b/runtime/RegExpCachedResult.cpp
new file mode 100644 (file)
index 0000000..0788145
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "RegExpCachedResult.h"
+
+#include "RegExpMatchesArray.h"
+
+namespace JSC {
+
+void RegExpCachedResult::visitChildren(SlotVisitor& visitor)
+{
+    if (m_result) {
+        visitor.append(&m_lastInput);
+        visitor.append(&m_lastRegExp);
+    } else {
+        visitor.append(&m_reifiedInput);
+        visitor.append(&m_reifiedResult);
+    }
+}
+
+RegExpMatchesArray* RegExpCachedResult::lastResult(ExecState* exec, JSObject* owner)
+{
+    if (m_result) {
+        m_reifiedInput.set(exec->globalData(), owner, m_lastInput.get());
+        m_reifiedResult.set(exec->globalData(), owner, RegExpMatchesArray::create(exec, m_lastInput.get(), m_lastRegExp.get(), m_result));
+        m_result = MatchResult::failed();
+    }
+    return m_reifiedResult.get();
+}
+
+void RegExpCachedResult::setInput(ExecState* exec, JSObject* owner, JSString* input)
+{
+    // Make sure we're reified, otherwise m_reifiedInput will be ignored.
+    lastResult(exec, owner);
+    ASSERT(!m_result);
+    m_reifiedInput.set(exec->globalData(), owner, input);
+}
+
+} // namespace JSC
diff --git a/runtime/RegExpCachedResult.h b/runtime/RegExpCachedResult.h
new file mode 100644 (file)
index 0000000..a722440
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RegExpCachedResult_h
+#define RegExpCachedResult_h
+
+#include "RegExpObject.h"
+
+namespace JSC {
+
+    class JSString;
+    class RegExpMatchesArray;
+
+    // RegExpCachedResult is used to track the cached results of the last
+    // match, stores on the RegExp constructor (e.g. $&, $_, $1, $2 ...).
+    // These values will be lazily generated on demand, so the cached result
+    // may be in a lazy or reified state. A lazy state is indicated by a
+    // value of m_result indicating a successful match, and a reified state
+    // is indicated by setting m_result to MatchResult::failed().
+    // Following a successful match, m_result, m_lastInput and m_lastRegExp
+    // can be used to reify the results from the match, following reification
+    // m_reifiedResult and m_reifiedInput hold the cached results.
+    class RegExpCachedResult {
+    public:
+        RegExpCachedResult(JSGlobalData& globalData, JSObject* owner, RegExp* emptyRegExp)
+            : m_result(0, 0)
+        {
+            m_lastInput.set(globalData, owner, jsEmptyString(&globalData));
+            m_lastRegExp.set(globalData, owner, emptyRegExp);
+            m_reifiedResult.clear();
+            m_reifiedInput.clear();
+        }
+
+        ALWAYS_INLINE void record(JSGlobalData& globalData, JSObject* owner, RegExp* regExp, JSString* input, MatchResult result)
+        {
+            m_lastRegExp.set(globalData, owner, regExp);
+            m_lastInput.set(globalData, owner, input);
+            m_result = result;
+        }
+
+        RegExpMatchesArray* lastResult(ExecState*, JSObject* owner);
+        void setInput(ExecState*, JSObject* owner, JSString*);
+
+        JSString* input()
+        {
+            // If m_result showas a match then we're in a lazy state, so m_lastInput
+            // is the most recent value of the input property. If not then we have
+            // reified, in which case m_reifiedInput will contain the correct value.
+            return m_result ? m_lastInput.get() : m_reifiedInput.get();
+        }
+
+        void visitChildren(SlotVisitor&);
+
+    private:
+        MatchResult m_result;
+        WriteBarrier<JSString> m_lastInput;
+        WriteBarrier<RegExp> m_lastRegExp;
+        WriteBarrier<RegExpMatchesArray> m_reifiedResult;
+        WriteBarrier<JSString> m_reifiedInput;
+    };
+
+} // namespace JSC
+
+#endif // RegExpCachedResult_h
index 3e499bacbec0d22ec9eb684afed89f7cbab0f581..747ed051d24d2536736a9a3df0754b37d64dea5c 100644 (file)
 #include "config.h"
 #include "RegExpConstructor.h"
 
 #include "config.h"
 #include "RegExpConstructor.h"
 
-#include "ArrayPrototype.h"
 #include "Error.h"
 #include "Error.h"
-#include "ExceptionHelpers.h"
-#include "JSArray.h"
-#include "JSFunction.h"
-#include "JSString.h"
-#include "Lookup.h"
-#include "ObjectPrototype.h"
 #include "RegExpMatchesArray.h"
 #include "RegExpMatchesArray.h"
-#include "RegExpObject.h"
 #include "RegExpPrototype.h"
 #include "RegExpPrototype.h"
-#include "RegExp.h"
-#include "RegExpCache.h"
-#include "UStringConcatenate.h"
-#include <wtf/PassOwnPtr.h>
 
 #include <wtf/PassOwnPtr.h>
 
 
 #include <wtf/PassOwnPtr.h>
 
@@ -69,7 +57,7 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(RegExpConstructor);
 
 
 ASSERT_CLASS_FITS_IN_CELL(RegExpConstructor);
 
-const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::regExpConstructorTable };
+const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::regExpConstructorTable, CREATE_METHOD_TABLE(RegExpConstructor) };
 
 /* Source for RegExpConstructor.lut.h
 @begin regExpConstructorTable
 
 /* Source for RegExpConstructor.lut.h
 @begin regExpConstructorTable
@@ -97,10 +85,16 @@ const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_i
 @end
 */
 
 @end
 */
 
-RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, RegExpPrototype* regExpPrototype)
-    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, "RegExp"))
-    , d(adoptPtr(new RegExpConstructorPrivate))
+RegExpConstructor::RegExpConstructor(JSGlobalObject* globalObject, Structure* structure, RegExpPrototype* regExpPrototype)
+    : InternalFunction(globalObject, structure)
+    , m_cachedResult(globalObject->globalData(), this, regExpPrototype->regExp())
+    , m_multiline(false)
+{
+}
+
+void RegExpConstructor::finishCreation(ExecState* exec, RegExpPrototype* regExpPrototype)
 {
 {
+    Base::finishCreation(exec->globalData(), Identifier(exec, "RegExp"));
     ASSERT(inherits(&s_info));
 
     // ECMA 15.10.5.1 RegExp.prototype
     ASSERT(inherits(&s_info));
 
     // ECMA 15.10.5.1 RegExp.prototype
@@ -110,98 +104,66 @@ RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObje
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
 }
 
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
 }
 
-RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data)
-    : JSArray(exec->globalData(), exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1, CreateInitialized)
-{
-    RegExpConstructorPrivate* d = new RegExpConstructorPrivate;
-    d->input = data->lastInput;
-    d->lastInput = data->lastInput;
-    d->lastNumSubPatterns = data->lastNumSubPatterns;
-    unsigned offsetVectorSize = (data->lastNumSubPatterns + 1) * 2; // only copying the result part of the vector
-    d->lastOvector().resize(offsetVectorSize);
-    memcpy(d->lastOvector().data(), data->lastOvector().data(), offsetVectorSize * sizeof(int));
-    // d->multiline is not needed, and remains uninitialized
-
-    setSubclassData(d);
-}
-
-RegExpMatchesArray::~RegExpMatchesArray()
+void RegExpConstructor::destroy(JSCell* cell)
 {
 {
-    delete static_cast<RegExpConstructorPrivate*>(subclassData());
+    jsCast<RegExpConstructor*>(cell)->RegExpConstructor::~RegExpConstructor();
 }
 
 }
 
-void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
+void RegExpConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    RegExpConstructorPrivate* d = static_cast<RegExpConstructorPrivate*>(subclassData());
-    ASSERT(d);
+    RegExpConstructor* thisObject = jsCast<RegExpConstructor*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
 
 
-    unsigned lastNumSubpatterns = d->lastNumSubPatterns;
-
-    for (unsigned i = 0; i <= lastNumSubpatterns; ++i) {
-        int start = d->lastOvector()[2 * i];
-        if (start >= 0)
-            JSArray::put(exec, i, jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start));
-        else
-            JSArray::put(exec, i, jsUndefined());
-    }
-
-    PutPropertySlot 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;
-    setSubclassData(0);
+    Base::visitChildren(thisObject, visitor);
+    thisObject->m_cachedResult.visitChildren(visitor);
 }
 
 }
 
-JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const
+JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i)
 {
 {
-    return new (exec) RegExpMatchesArray(exec, d.get());
-}
+    RegExpMatchesArray* array = m_cachedResult.lastResult(exec, this);
 
 
-JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i) const
-{
-    if (!d->lastOvector().isEmpty() && i <= d->lastNumSubPatterns) {
-        int start = d->lastOvector()[2 * i];
-        if (start >= 0)
-            return jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start);
+    if (i < array->length()) {
+        JSValue result = JSValue(array).get(exec, i);
+        ASSERT(result.isString() || result.isUndefined());
+        if (!result.isUndefined())
+            return result;
     }
     return jsEmptyString(exec);
 }
 
     }
     return jsEmptyString(exec);
 }
 
-JSValue RegExpConstructor::getLastParen(ExecState* exec) const
+JSValue RegExpConstructor::getLastParen(ExecState* exec)
 {
 {
-    unsigned i = d->lastNumSubPatterns;
-    if (i > 0) {
-        ASSERT(!d->lastOvector().isEmpty());
-        int start = d->lastOvector()[2 * i];
-        if (start >= 0)
-            return jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start);
+    RegExpMatchesArray* array = m_cachedResult.lastResult(exec, this);
+    unsigned length = array->length();
+    if (length > 1) {
+        JSValue result = JSValue(array).get(exec, length - 1);
+        ASSERT(result.isString() || result.isUndefined());
+        if (!result.isUndefined())
+            return result;
     }
     return jsEmptyString(exec);
 }
 
     }
     return jsEmptyString(exec);
 }
 
-JSValue RegExpConstructor::getLeftContext(ExecState* exec) const
+JSValue RegExpConstructor::getLeftContext(ExecState* exec)
 {
 {
-    if (!d->lastOvector().isEmpty())
-        return jsSubstring(exec, d->lastInput, 0, d->lastOvector()[0]);
-    return jsEmptyString(exec);
+    return m_cachedResult.lastResult(exec, this)->leftContext(exec);
 }
 
 }
 
-JSValue RegExpConstructor::getRightContext(ExecState* exec) const
+JSValue RegExpConstructor::getRightContext(ExecState* exec)
 {
 {
-    if (!d->lastOvector().isEmpty())
-        return jsSubstring(exec, d->lastInput, d->lastOvector()[1], d->lastInput.length() - d->lastOvector()[1]);
-    return jsEmptyString(exec);
+    return m_cachedResult.lastResult(exec, this)->rightContext(exec);
 }
     
 }
     
-bool RegExpConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+bool RegExpConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
-    return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot);
+    return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), jsCast<RegExpConstructor*>(cell), propertyName, slot);
 }
 
 }
 
-bool RegExpConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool RegExpConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticValueDescriptor<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, descriptor);
+    return getStaticValueDescriptor<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), jsCast<RegExpConstructor*>(object), propertyName, descriptor);
 }
 
 JSValue regExpConstructorDollar1(ExecState* exec, JSValue slotBase, const Identifier&)
 }
 
 JSValue regExpConstructorDollar1(ExecState* exec, JSValue slotBase, const Identifier&)
@@ -249,9 +211,9 @@ JSValue regExpConstructorDollar9(ExecState* exec, JSValue slotBase, const Identi
     return asRegExpConstructor(slotBase)->getBackref(exec, 9);
 }
 
     return asRegExpConstructor(slotBase)->getBackref(exec, 9);
 }
 
-JSValue regExpConstructorInput(ExecState* exec, JSValue slotBase, const Identifier&)
+JSValue regExpConstructorInput(ExecState*, JSValue slotBase, const Identifier&)
 {
 {
-    return jsString(exec, asRegExpConstructor(slotBase)->input());
+    return asRegExpConstructor(slotBase)->input();
 }
 
 JSValue regExpConstructorMultiline(ExecState*, JSValue slotBase, const Identifier&)
 }
 
 JSValue regExpConstructorMultiline(ExecState*, JSValue slotBase, const Identifier&)
@@ -279,14 +241,14 @@ JSValue regExpConstructorRightContext(ExecState* exec, JSValue slotBase, const I
     return asRegExpConstructor(slotBase)->getRightContext(exec);
 }
 
     return asRegExpConstructor(slotBase)->getRightContext(exec);
 }
 
-void RegExpConstructor::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void RegExpConstructor::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
-    lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), this, slot);
+    lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), jsCast<RegExpConstructor*>(cell), slot);
 }
 
 void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue value)
 {
 }
 
 void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue value)
 {
-    asRegExpConstructor(baseObject)->setInput(value.toString(exec));
+    asRegExpConstructor(baseObject)->setInput(exec, value.toString(exec));
 }
 
 void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue value)
 }
 
 void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue value)
@@ -295,7 +257,7 @@ void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValu
 }
 
 // ECMA 15.10.4
 }
 
 // ECMA 15.10.4
-JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
+JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, bool callAsConstructor)
 {
     JSValue arg0 = args.at(0);
     JSValue arg1 = args.at(1);
 {
     JSValue arg0 = args.at(0);
     JSValue arg1 = args.at(1);
@@ -303,35 +265,40 @@ JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const A
     if (arg0.inherits(&RegExpObject::s_info)) {
         if (!arg1.isUndefined())
             return throwError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
     if (arg0.inherits(&RegExpObject::s_info)) {
         if (!arg1.isUndefined())
             return throwError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
+        // If called as a function, this just returns the first argument (see 15.10.3.1).
+        if (callAsConstructor) {
+            RegExp* regExp = static_cast<RegExpObject*>(asObject(arg0))->regExp();
+            return RegExpObject::create(exec, globalObject, globalObject->regExpStructure(), regExp);
+        }
         return asObject(arg0);
     }
 
         return asObject(arg0);
     }
 
-    UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec);
+    UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec)->value(exec);
     if (exec->hadException())
         return 0;
 
     RegExpFlags flags = NoFlags;
     if (!arg1.isUndefined()) {
     if (exec->hadException())
         return 0;
 
     RegExpFlags flags = NoFlags;
     if (!arg1.isUndefined()) {
-        flags = regExpFlags(arg1.toString(exec));
+        flags = regExpFlags(arg1.toString(exec)->value(exec));
         if (exec->hadException())
             return 0;
         if (flags == InvalidFlags)
             return throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
     }
 
         if (exec->hadException())
             return 0;
         if (flags == InvalidFlags)
             return throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
     }
 
-    RegExp* regExp = RegExp::create(&exec->globalData(), pattern, flags);
+    RegExp* regExp = RegExp::create(exec->globalData(), pattern, flags);
     if (!regExp->isValid())
         return throwError(exec, createSyntaxError(exec, regExp->errorMessage()));
     if (!regExp->isValid())
         return throwError(exec, createSyntaxError(exec, regExp->errorMessage()));
-    return new (exec) RegExpObject(exec->lexicalGlobalObject(), globalObject->regExpStructure(), regExp);
+    return RegExpObject::create(exec, exec->lexicalGlobalObject(), globalObject->regExpStructure(), regExp);
 }
 
 static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState* exec)
 {
     ArgList args(exec);
 }
 
 static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState* exec)
 {
     ArgList args(exec);
-    return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args));
+    return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args, true));
 }
 
 }
 
-ConstructType RegExpConstructor::getConstructData(ConstructData& constructData)
+ConstructType RegExpConstructor::getConstructData(JSCell*, ConstructData& constructData)
 {
     constructData.native.function = constructWithRegExpConstructor;
     return ConstructTypeHost;
 {
     constructData.native.function = constructWithRegExpConstructor;
     return ConstructTypeHost;
@@ -344,32 +311,10 @@ static EncodedJSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec)
     return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
     return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
-CallType RegExpConstructor::getCallData(CallData& callData)
+CallType RegExpConstructor::getCallData(JSCell*, CallData& callData)
 {
     callData.native.function = callRegExpConstructor;
     return CallTypeHost;
 }
 
 {
     callData.native.function = callRegExpConstructor;
     return CallTypeHost;
 }
 
-void RegExpConstructor::setInput(const UString& input)
-{
-    d->input = input;
-}
-
-const UString& RegExpConstructor::input() const
-{
-    // Can detect a distinct initial state that is invisible to JavaScript, by checking for null
-    // state (since jsString turns null strings to empty strings).
-    return d->input;
-}
-
-void RegExpConstructor::setMultiline(bool multiline)
-{
-    d->multiline = multiline;
-}
-
-bool RegExpConstructor::multiline() const
-{
-    return d->multiline;
-}
-
 } // namespace JSC
 } // namespace JSC
index 1d02e6ff7cfc4155457931a11e925d164edb580b..0093f9484d9ffb2088526995b7490aed50f77501 100644 (file)
 
 #include "InternalFunction.h"
 #include "RegExp.h"
 
 #include "InternalFunction.h"
 #include "RegExp.h"
+#include "RegExpCachedResult.h"
+#include "RegExpObject.h"
 #include <wtf/OwnPtr.h>
 
 #include <wtf/OwnPtr.h>
 
+
 namespace JSC {
 
 namespace JSC {
 
-    class RegExp;
     class RegExpPrototype;
     class RegExpPrototype;
-    struct RegExpConstructorPrivate;
 
 
-    struct RegExpConstructorPrivate {
-        WTF_MAKE_FAST_ALLOCATED;
+    class RegExpConstructor : public InternalFunction {
     public:
     public:
-        // Global search cache / settings
-        RegExpConstructorPrivate()
-            : lastNumSubPatterns(0)
-            , multiline(false)
-            , lastOvectorIndex(0)
+        typedef InternalFunction Base;
+
+        static RegExpConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, RegExpPrototype* regExpPrototype)
         {
         {
+            RegExpConstructor* constructor = new (NotNull, allocateCell<RegExpConstructor>(*exec->heap())) RegExpConstructor(globalObject, structure, regExpPrototype);
+            constructor->finishCreation(exec, regExpPrototype);
+            return constructor;
         }
 
         }
 
-        const Vector<int, 32>& lastOvector() const { return ovector[lastOvectorIndex]; }
-        Vector<int, 32>& lastOvector() { return ovector[lastOvectorIndex]; }
-        Vector<int, 32>& tempOvector() { return ovector[lastOvectorIndex ? 0 : 1]; }
-        void changeLastOvector() { lastOvectorIndex = lastOvectorIndex ? 0 : 1; }
-
-        UString input;
-        UString lastInput;
-        Vector<int, 32> ovector[2];
-        unsigned lastNumSubPatterns : 30;
-        bool multiline : 1;
-        unsigned lastOvectorIndex : 1;
-    };
-
-    class RegExpConstructor : public InternalFunction {
-    public:
-        RegExpConstructor(ExecState*, JSGlobalObject*, Structure*, RegExpPrototype*);
-
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
         }
 
-        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
         static const ClassInfo s_info;
 
 
         static const ClassInfo s_info;
 
-        void performMatch(JSGlobalData&, RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0);
-        JSObject* arrayOfMatches(ExecState*) const;
+        MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset, int** ovector);
+        MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset);
+
+        void setMultiline(bool multiline) { m_multiline = multiline; }
+        bool multiline() const { return m_multiline; }
 
 
-        void setInput(const UString&);
-        const UString& input() const;
+        JSValue getBackref(ExecState*, unsigned);
+        JSValue getLastParen(ExecState*);
+        JSValue getLeftContext(ExecState*);
+        JSValue getRightContext(ExecState*);
 
 
-        void setMultiline(bool);
-        bool multiline() const;
+        void setInput(ExecState* exec, JSString* string) { m_cachedResult.setInput(exec, this, string); }
+        JSString* input() { return m_cachedResult.input(); }
 
 
-        JSValue getBackref(ExecState*, unsigned) const;
-        JSValue getLastParen(ExecState*) const;
-        JSValue getLeftContext(ExecState*) const;
-        JSValue getRightContext(ExecState*) const;
+        static void visitChildren(JSCell*, SlotVisitor&);
 
     protected:
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | InternalFunction::StructureFlags;
+        void finishCreation(ExecState*, RegExpPrototype*);
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | Base::StructureFlags;
 
     private:
 
     private:
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
-
-        OwnPtr<RegExpConstructorPrivate> d;
+        RegExpConstructor(JSGlobalObject*, Structure*, RegExpPrototype*);
+        static void destroy(JSCell*);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
+
+        RegExpCachedResult m_cachedResult;
+        bool m_multiline;
+        Vector<int, 32> m_ovector;
     };
 
     RegExpConstructor* asRegExpConstructor(JSValue);
 
     };
 
     RegExpConstructor* asRegExpConstructor(JSValue);
 
-    JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&);
+    JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&, bool callAsConstructor = false);
 
     inline RegExpConstructor* asRegExpConstructor(JSValue value)
     {
 
     inline RegExpConstructor* asRegExpConstructor(JSValue value)
     {
@@ -109,23 +101,31 @@ 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.
     */
-    ALWAYS_INLINE void RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
+    ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const UString& input, int startOffset, int** ovector)
     {
     {
-        position = r->match(globalData, s, startOffset, &d->tempOvector());
+        int position = regExp->match(globalData, input, startOffset, m_ovector);
 
         if (ovector)
 
         if (ovector)
-            *ovector = d->tempOvector().data();
+            *ovector = m_ovector.data();
 
 
-        if (position != -1) {
-            ASSERT(!d->tempOvector().isEmpty());
+        if (position == -1)
+            return MatchResult::failed();
 
 
-            length = d->tempOvector()[1] - d->tempOvector()[0];
+        ASSERT(!m_ovector.isEmpty());
+        ASSERT(m_ovector[0] == position);
+        ASSERT(m_ovector[1] >= position);
+        size_t end = m_ovector[1];
 
 
-            d->input = s;
-            d->lastInput = s;
-            d->changeLastOvector();
-            d->lastNumSubPatterns = r->numSubpatterns();
-        }
+        m_cachedResult.record(globalData, this, regExp, string, MatchResult(position, end));
+
+        return MatchResult(position, end);
+    }
+    ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const UString& input, int startOffset)
+    {
+        MatchResult result = regExp->match(globalData, input, startOffset);
+        if (result)
+            m_cachedResult.record(globalData, this, regExp, string, result);
+        return result;
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
diff --git a/runtime/RegExpMatchesArray.cpp b/runtime/RegExpMatchesArray.cpp
new file mode 100644 (file)
index 0000000..80f1068
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "RegExpMatchesArray.h"
+
+namespace JSC {
+
+ASSERT_CLASS_FITS_IN_CELL(RegExpMatchesArray);
+
+const ClassInfo RegExpMatchesArray::s_info = {"Array", &JSArray::s_info, 0, 0, CREATE_METHOD_TABLE(RegExpMatchesArray)};
+
+void RegExpMatchesArray::finishCreation(JSGlobalData& globalData)
+{
+    Base::finishCreation(globalData, m_regExp->numSubpatterns() + 1);
+}
+
+void RegExpMatchesArray::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+
+    Base::visitChildren(thisObject, visitor);
+    visitor.append(&thisObject->m_input);
+    visitor.append(&thisObject->m_regExp);
+}
+
+void RegExpMatchesArray::reifyAllProperties(ExecState* exec)
+{
+    ASSERT(m_state != ReifiedAll);
+    ASSERT(m_result);
+    reifyMatchPropertyIfNecessary(exec);
+
+    if (unsigned numSubpatterns = m_regExp->numSubpatterns()) {
+        Vector<int, 32> subpatternResults;
+        int position = m_regExp->match(exec->globalData(), m_input->value(exec), m_result.start, subpatternResults);
+        ASSERT_UNUSED(position, position >= 0 && static_cast<size_t>(position) == m_result.start);
+        ASSERT(m_result.start == static_cast<size_t>(subpatternResults[0]));
+        ASSERT(m_result.end == static_cast<size_t>(subpatternResults[1]));
+
+        for (unsigned i = 1; i <= numSubpatterns; ++i) {
+            int start = subpatternResults[2 * i];
+            if (start >= 0)
+                putDirectIndex(exec, i, jsSubstring(exec, m_input.get(), start, subpatternResults[2 * i + 1] - start), false);
+            else
+                putDirectIndex(exec, i, jsUndefined(), false);
+        }
+    }
+
+    PutPropertySlot slot;
+    JSArray::put(this, exec, exec->propertyNames().index, jsNumber(m_result.start), slot);
+    JSArray::put(this, exec, exec->propertyNames().input, m_input.get(), slot);
+
+    m_state = ReifiedAll;
+}
+
+void RegExpMatchesArray::reifyMatchProperty(ExecState* exec)
+{
+    ASSERT(m_state == ReifiedNone);
+    ASSERT(m_result);
+    putDirectIndex(exec, 0, jsSubstring(exec, m_input.get(), m_result.start, m_result.end - m_result.start), false);
+    m_state = ReifiedMatch;
+}
+
+JSString* RegExpMatchesArray::leftContext(ExecState* exec)
+{
+    if (!m_result.start)
+        return jsEmptyString(exec);
+    return jsSubstring(exec, m_input.get(), 0, m_result.start);
+}
+
+JSString* RegExpMatchesArray::rightContext(ExecState* exec)
+{
+    unsigned length = m_input->length();
+    if (m_result.end == length)
+        return jsEmptyString(exec);
+    return jsSubstring(exec, m_input.get(), m_result.end, length - m_result.end);
+}
+
+} // namespace JSC
index b82362156350d3031622edf2c3ea822024ebbb18..595457bca16d221e79d575db124a61cb97cd3c1a 100644 (file)
 #define RegExpMatchesArray_h
 
 #include "JSArray.h"
 #define RegExpMatchesArray_h
 
 #include "JSArray.h"
+#include "JSGlobalObject.h"
+#include "RegExpObject.h"
 
 namespace JSC {
 
     class RegExpMatchesArray : public JSArray {
 
 namespace JSC {
 
     class RegExpMatchesArray : public JSArray {
+    private:
+        RegExpMatchesArray(JSGlobalData& globalData, JSGlobalObject* globalObject, JSString* input, RegExp* regExp, MatchResult result)
+            : JSArray(globalData, globalObject->regExpMatchesArrayStructure())
+            , m_result(result)
+            , m_state(ReifiedNone)
+        {
+            m_input.set(globalData, this, input);
+            m_regExp.set(globalData, this, regExp);
+        }
+
+        enum ReifiedState { ReifiedNone, ReifiedMatch, ReifiedAll };
+
     public:
     public:
-        RegExpMatchesArray(ExecState*, RegExpConstructorPrivate*);
-        virtual ~RegExpMatchesArray();
+        typedef JSArray Base;
+
+        static RegExpMatchesArray* create(ExecState* exec, JSString* input, RegExp* regExp, MatchResult result)
+        {
+            ASSERT(result);
+            JSGlobalData& globalData = exec->globalData();
+            RegExpMatchesArray* array = new (NotNull, allocateCell<RegExpMatchesArray>(globalData.heap)) RegExpMatchesArray(globalData, exec->lexicalGlobalObject(), input, regExp, result);
+            array->finishCreation(globalData);
+            return array;
+        }
+
+        JSString* leftContext(ExecState*);
+        JSString* rightContext(ExecState*);
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+        {
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
+        }
+
+        static void visitChildren(JSCell*, SlotVisitor&);
+
+    protected:
+        void finishCreation(JSGlobalData&);
+
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
 
     private:
 
     private:
-        virtual bool getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+        ALWAYS_INLINE void reifyAllPropertiesIfNecessary(ExecState* exec)
+        {
+            if (m_state != ReifiedAll)
+                reifyAllProperties(exec);
+        }
+
+        ALWAYS_INLINE void reifyMatchPropertyIfNecessary(ExecState* exec)
         {
         {
-            if (subclassData())
-                fillArrayInstance(exec);
-            return JSArray::getOwnPropertySlot(exec, propertyName, slot);
+            if (m_state == ReifiedNone)
+                reifyMatchProperty(exec);
         }
 
         }
 
-        virtual bool getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+        static bool getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
         {
         {
-            if (subclassData())
-                fillArrayInstance(exec);
-            return JSArray::getOwnPropertySlot(exec, propertyName, slot);
+            RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
+            thisObject->reifyAllPropertiesIfNecessary(exec);
+            return JSArray::getOwnPropertySlot(thisObject, exec, propertyName, slot);
         }
 
         }
 
-        virtual bool getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+        static bool getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)
         {
         {
-            if (subclassData())
-                fillArrayInstance(exec);
-            return JSArray::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+            RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
+            if (propertyName)
+                thisObject->reifyAllPropertiesIfNecessary(exec);
+            else
+                thisObject->reifyMatchPropertyIfNecessary(exec);
+            return JSArray::getOwnPropertySlotByIndex(thisObject, exec, propertyName, slot);
         }
 
         }
 
-        virtual void put(ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot)
+        static bool getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
         {
         {
-            if (subclassData())
-                fillArrayInstance(exec);
-            JSArray::put(exec, propertyName, v, slot);
+            RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object);
+            thisObject->reifyAllPropertiesIfNecessary(exec);
+            return JSArray::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
         }
 
         }
 
-        virtual void put(ExecState* exec, unsigned propertyName, JSValue v)
+        static void put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot)
         {
         {
-            if (subclassData())
-                fillArrayInstance(exec);
-            JSArray::put(exec, propertyName, v);
+            RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
+            thisObject->reifyAllPropertiesIfNecessary(exec);
+            JSArray::put(thisObject, exec, propertyName, v, slot);
+        }
+        
+        static void putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue v, bool shouldThrow)
+        {
+            RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
+            thisObject->reifyAllPropertiesIfNecessary(exec);
+            JSArray::putByIndex(thisObject, exec, propertyName, v, shouldThrow);
+        }
+
+        static bool deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
+        {
+            RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
+            thisObject->reifyAllPropertiesIfNecessary(exec);
+            return JSArray::deleteProperty(thisObject, exec, propertyName);
         }
 
         }
 
-        virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName)
+        static bool deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName)
         {
         {
-            if (subclassData())
-                fillArrayInstance(exec);
-            return JSArray::deleteProperty(exec, propertyName);
+            RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
+            thisObject->reifyAllPropertiesIfNecessary(exec);
+            return JSArray::deletePropertyByIndex(thisObject, exec, propertyName);
         }
 
         }
 
-        virtual bool deleteProperty(ExecState* exec, unsigned propertyName)
+        static void getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& arr, EnumerationMode mode = ExcludeDontEnumProperties)
         {
         {
-            if (subclassData())
-                fillArrayInstance(exec);
-            return JSArray::deleteProperty(exec, propertyName);
+            RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object);
+            thisObject->reifyAllPropertiesIfNecessary(exec);
+            JSArray::getOwnPropertyNames(thisObject, exec, arr, mode);
         }
 
         }
 
-        virtual void getOwnPropertyNames(ExecState* exec, PropertyNameArray& arr, EnumerationMode mode = ExcludeDontEnumProperties)
+        static bool defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
         {
         {
-            if (subclassData())
-                fillArrayInstance(exec);
-            JSArray::getOwnPropertyNames(exec, arr, mode);
+            RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object);
+            thisObject->reifyAllPropertiesIfNecessary(exec);
+            return JSArray::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
         }
 
         }
 
-        void fillArrayInstance(ExecState*);
+        void reifyAllProperties(ExecState*);
+        void reifyMatchProperty(ExecState*);
+
+        WriteBarrier<JSString> m_input;
+        WriteBarrier<RegExp> m_regExp;
+        MatchResult m_result;
+        ReifiedState m_state;
 };
 
 }
 };
 
 }
index fc3b2058c48f80de1ad30818cf99ff45484f1dad..5e10a1c9e0db78c3d5bf16172fac25691aaff746 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, 2012 Apple Inc. All Rights Reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU 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 "JSArray.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
 #include "JSArray.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
+#include "Lexer.h"
 #include "Lookup.h"
 #include "RegExpConstructor.h"
 #include "Lookup.h"
 #include "RegExpConstructor.h"
+#include "RegExpMatchesArray.h"
 #include "RegExpPrototype.h"
 #include "RegExpPrototype.h"
+#include "UStringBuilder.h"
 #include "UStringConcatenate.h"
 #include <wtf/PassOwnPtr.h>
 
 #include "UStringConcatenate.h"
 #include <wtf/PassOwnPtr.h>
 
@@ -40,8 +43,6 @@ static JSValue regExpObjectGlobal(ExecState*, JSValue, const Identifier&);
 static JSValue regExpObjectIgnoreCase(ExecState*, JSValue, const Identifier&);
 static JSValue regExpObjectMultiline(ExecState*, JSValue, const Identifier&);
 static JSValue regExpObjectSource(ExecState*, JSValue, const Identifier&);
 static JSValue regExpObjectIgnoreCase(ExecState*, JSValue, const Identifier&);
 static JSValue regExpObjectMultiline(ExecState*, JSValue, const Identifier&);
 static JSValue regExpObjectSource(ExecState*, JSValue, const Identifier&);
-static JSValue regExpObjectLastIndex(ExecState*, JSValue, const Identifier&);
-static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue);
 
 } // namespace JSC
 
 
 } // namespace JSC
 
@@ -51,7 +52,7 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(RegExpObject);
 
 
 ASSERT_CLASS_FITS_IN_CELL(RegExpObject);
 
-const ClassInfo RegExpObject::s_info = { "RegExp", &JSObjectWithGlobalObject::s_info, 0, ExecState::regExpTable };
+const ClassInfo RegExpObject::s_info = { "RegExp", &JSNonFinalObject::s_info, 0, ExecState::regExpTable, CREATE_METHOD_TABLE(RegExpObject) };
 
 /* Source for RegExpObject.lut.h
 @begin regExpTable
 
 /* Source for RegExpObject.lut.h
 @begin regExpTable
@@ -59,41 +60,109 @@ const ClassInfo RegExpObject::s_info = { "RegExp", &JSObjectWithGlobalObject::s_
     ignoreCase    regExpObjectIgnoreCase   DontDelete|ReadOnly|DontEnum
     multiline     regExpObjectMultiline    DontDelete|ReadOnly|DontEnum
     source        regExpObjectSource       DontDelete|ReadOnly|DontEnum
     ignoreCase    regExpObjectIgnoreCase   DontDelete|ReadOnly|DontEnum
     multiline     regExpObjectMultiline    DontDelete|ReadOnly|DontEnum
     source        regExpObjectSource       DontDelete|ReadOnly|DontEnum
-    lastIndex     regExpObjectLastIndex    DontDelete|DontEnum
 @end
 */
 
 RegExpObject::RegExpObject(JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
 @end
 */
 
 RegExpObject::RegExpObject(JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
-    : JSObjectWithGlobalObject(globalObject, structure)
-    , d(adoptPtr(new RegExpObjectData(globalObject->globalData(), this, regExp)))
+    : JSNonFinalObject(globalObject->globalData(), structure)
+    , m_regExp(globalObject->globalData(), this, regExp)
+    , m_lastIndexIsWritable(true)
 {
 {
-    ASSERT(inherits(&s_info));
+    m_lastIndex.setWithoutWriteBarrier(jsNumber(0));
 }
 
 }
 
-RegExpObject::~RegExpObject()
+void RegExpObject::finishCreation(JSGlobalObject* globalObject)
 {
 {
+    Base::finishCreation(globalObject->globalData());
+    ASSERT(inherits(&s_info));
 }
 
 }
 
-void RegExpObject::visitChildren(SlotVisitor& visitor)
+void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    RegExpObject* thisObject = jsCast<RegExpObject*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     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);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    Base::visitChildren(thisObject, visitor);
+    if (thisObject->m_regExp)
+        visitor.append(&thisObject->m_regExp);
+    if (UNLIKELY(!thisObject->m_lastIndex.get().isInt32()))
+        visitor.append(&thisObject->m_lastIndex);
+}
+
+bool RegExpObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+    if (propertyName == exec->propertyNames().lastIndex) {
+        RegExpObject* regExp = asRegExpObject(cell);
+        slot.setValue(regExp, regExp->getLastIndex());
+        return true;
+    }
+    return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), propertyName, slot);
 }
 
 }
 
-bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+bool RegExpObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
+    if (propertyName == exec->propertyNames().lastIndex) {
+        RegExpObject* regExp = asRegExpObject(object);
+        descriptor.setDescriptor(regExp->getLastIndex(), regExp->m_lastIndexIsWritable ? DontDelete | DontEnum : DontDelete | DontEnum | ReadOnly);
+        return true;
+    }
+    return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(object), propertyName, descriptor);
+}
+
+bool RegExpObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
+{
+    if (propertyName == exec->propertyNames().lastIndex)
+        return false;
+    return Base::deleteProperty(cell, exec, propertyName);
 }
 
 }
 
-bool RegExpObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+void RegExpObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
-    return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, descriptor);
+    if (mode == IncludeDontEnumProperties)
+        propertyNames.add(exec->propertyNames().lastIndex);
+    Base::getOwnPropertyNames(object, exec, propertyNames, mode);
+}
+
+void RegExpObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    if (mode == IncludeDontEnumProperties)
+        propertyNames.add(exec->propertyNames().lastIndex);
+    Base::getPropertyNames(object, exec, propertyNames, mode);
+}
+
+static bool reject(ExecState* exec, bool throwException, const char* message)
+{
+    if (throwException)
+        throwTypeError(exec, message);
+    return false;
+}
+
+bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
+{
+    if (propertyName == exec->propertyNames().lastIndex) {
+        RegExpObject* regExp = asRegExpObject(object);
+        if (descriptor.configurablePresent() && descriptor.configurable())
+            return reject(exec, shouldThrow, "Attempting to change configurable attribute of unconfigurable property.");
+        if (descriptor.enumerablePresent() && descriptor.enumerable())
+            return reject(exec, shouldThrow, "Attempting to change enumerable attribute of unconfigurable property.");
+        if (descriptor.isAccessorDescriptor())
+            return reject(exec, shouldThrow, "Attempting to change access mechanism for an unconfigurable property.");
+        if (!regExp->m_lastIndexIsWritable) {
+            if (descriptor.writablePresent() && descriptor.writable())
+                return reject(exec, shouldThrow, "Attempting to change writable attribute of unconfigurable property.");
+            if (!sameValue(exec, regExp->getLastIndex(), descriptor.value()))
+                return reject(exec, shouldThrow, "Attempting to change value of a readonly property.");
+            return true;
+        }
+        if (descriptor.writablePresent() && !descriptor.writable())
+            regExp->m_lastIndexIsWritable = false;
+        if (descriptor.value())
+            regExp->setLastIndex(exec, descriptor.value(), false);
+        return true;
+    }
+
+    return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
 }
 
 JSValue regExpObjectGlobal(ExecState*, JSValue slotBase, const Identifier&)
 }
 
 JSValue regExpObjectGlobal(ExecState*, JSValue slotBase, const Identifier&)
@@ -113,76 +182,140 @@ JSValue regExpObjectMultiline(ExecState*, JSValue slotBase, const Identifier&)
 
 JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
 {
 
 JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
 {
-    return jsString(exec, asRegExpObject(slotBase)->regExp()->pattern());
-}
+    UString pattern = asRegExpObject(slotBase)->regExp()->pattern();
+    unsigned length = pattern.length();
+    const UChar* characters = pattern.characters();
+    bool previousCharacterWasBackslash = false;
+    bool inBrackets = false;
+    bool shouldEscape = false;
 
 
-JSValue regExpObjectLastIndex(ExecState*, JSValue slotBase, const Identifier&)
-{
-    return asRegExpObject(slotBase)->getLastIndex();
-}
+    // 15.10.6.4 specifies that RegExp.prototype.toString must return '/' + source + '/',
+    // and also states that the result must be a valid RegularExpressionLiteral. '//' is
+    // not a valid RegularExpressionLiteral (since it is a single line comment), and hence
+    // source cannot ever validly be "". If the source is empty, return a different Pattern
+    // that would match the same thing.
+    if (!length)
+        return jsString(exec, "(?:)");
 
 
-void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
-{
-    lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this, slot);
-}
+    // early return for strings that don't contain a forwards slash and LineTerminator
+    for (unsigned i = 0; i < length; ++i) {
+        UChar ch = characters[i];
+        if (!previousCharacterWasBackslash) {
+            if (inBrackets) {
+                if (ch == ']')
+                    inBrackets = false;
+            } else {
+                if (ch == '/') {
+                    shouldEscape = true;
+                    break;
+                }
+                if (ch == '[')
+                    inBrackets = true;
+            }
+        }
 
 
-void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value)
-{
-    asRegExpObject(baseObject)->setLastIndex(exec->globalData(), value);
+        if (Lexer<UChar>::isLineTerminator(ch)) {
+            shouldEscape = true;
+            break;
+        }
+
+        if (previousCharacterWasBackslash)
+            previousCharacterWasBackslash = false;
+        else
+            previousCharacterWasBackslash = ch == '\\';
+    }
+
+    if (!shouldEscape)
+        return jsString(exec, pattern);
+
+    previousCharacterWasBackslash = false;
+    inBrackets = false;
+    UStringBuilder result;
+    for (unsigned i = 0; i < length; ++i) {
+        UChar ch = characters[i];
+        if (!previousCharacterWasBackslash) {
+            if (inBrackets) {
+                if (ch == ']')
+                    inBrackets = false;
+            } else {
+                if (ch == '/')
+                    result.append('\\');
+                else if (ch == '[')
+                    inBrackets = true;
+            }
+        }
+
+        // escape LineTerminator
+        if (Lexer<UChar>::isLineTerminator(ch)) {
+            if (!previousCharacterWasBackslash)
+                result.append('\\');
+
+            if (ch == '\n')
+                result.append('n');
+            else if (ch == '\r')
+                result.append('r');
+            else if (ch == 0x2028)
+                result.append("u2028");
+            else
+                result.append("u2029");
+        } else
+            result.append(ch);
+
+        if (previousCharacterWasBackslash)
+            previousCharacterWasBackslash = false;
+        else
+            previousCharacterWasBackslash = ch == '\\';
+    }
+
+    return jsString(exec, result.toUString());
 }
 
 }
 
-JSValue RegExpObject::test(ExecState* exec)
+void RegExpObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
-    return jsBoolean(match(exec));
+    if (propertyName == exec->propertyNames().lastIndex) {
+        asRegExpObject(cell)->setLastIndex(exec, value, slot.isStrictMode());
+        return;
+    }
+    lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), slot);
 }
 
 }
 
-JSValue RegExpObject::exec(ExecState* exec)
+JSValue RegExpObject::exec(ExecState* exec, JSString* string)
 {
 {
-    if (match(exec))
-        return exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec);
+    if (MatchResult result = match(exec, string))
+        return RegExpMatchesArray::create(exec, string, regExp(), result);
     return jsNull();
 }
 
 // Shared implementation used by test and exec.
     return jsNull();
 }
 
 // Shared implementation used by test and exec.
-bool RegExpObject::match(ExecState* exec)
+MatchResult RegExpObject::match(ExecState* exec, JSString* string)
 {
 {
+    RegExp* regExp = this->regExp();
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
-    UString input = exec->argument(0).toString(exec);
-    JSGlobalData* globalData = &exec->globalData();
-    if (!regExp()->global()) {
-        int position;
-        int length;
-        regExpConstructor->performMatch(*globalData, d->regExp.get(), input, 0, position, length);
-        return position >= 0;
-    }
+    UString input = string->value(exec);
+    JSGlobalData& globalData = exec->globalData();
+    if (!regExp->global())
+        return regExpConstructor->performMatch(globalData, regExp, string, input, 0);
 
     JSValue jsLastIndex = getLastIndex();
     unsigned lastIndex;
     if (LIKELY(jsLastIndex.isUInt32())) {
         lastIndex = jsLastIndex.asUInt32();
         if (lastIndex > input.length()) {
 
     JSValue jsLastIndex = getLastIndex();
     unsigned lastIndex;
     if (LIKELY(jsLastIndex.isUInt32())) {
         lastIndex = jsLastIndex.asUInt32();
         if (lastIndex > input.length()) {
-            setLastIndex(0);
-            return false;
+            setLastIndex(exec, 0);
+            return MatchResult::failed();
         }
     } else {
         double doubleLastIndex = jsLastIndex.toInteger(exec);
         if (doubleLastIndex < 0 || doubleLastIndex > input.length()) {
         }
     } else {
         double doubleLastIndex = jsLastIndex.toInteger(exec);
         if (doubleLastIndex < 0 || doubleLastIndex > input.length()) {
-            setLastIndex(0);
-            return false;
+            setLastIndex(exec, 0);
+            return MatchResult::failed();
         }
         lastIndex = static_cast<unsigned>(doubleLastIndex);
     }
 
         }
         lastIndex = static_cast<unsigned>(doubleLastIndex);
     }
 
-    int position;
-    int length = 0;
-    regExpConstructor->performMatch(*globalData, d->regExp.get(), input, lastIndex, position, length);
-    if (position < 0) {
-        setLastIndex(0);
-        return false;
-    }
-
-    setLastIndex(position + length);
-    return true;
+    MatchResult result = regExpConstructor->performMatch(globalData, regExp, string, input, lastIndex);
+    setLastIndex(exec, result.end);
+    return result;
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 6fc6cb9a72f298527c3a654ef55b8248e7eb0740..a7dd5470512676dc043d499972adf16a41335bf7 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, 2012 Apple Inc. All Rights Reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU 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
 #ifndef RegExpObject_h
 #define RegExpObject_h
 
 #ifndef RegExpObject_h
 #define RegExpObject_h
 
-#include "JSObjectWithGlobalObject.h"
+#include "JSObject.h"
 #include "RegExp.h"
 
 namespace JSC {
     
 #include "RegExp.h"
 
 namespace JSC {
     
-    class RegExpObject : public JSObjectWithGlobalObject {
+    class RegExpObject : public JSNonFinalObject {
     public:
     public:
-        typedef JSObjectWithGlobalObject Base;
+        typedef JSNonFinalObject Base;
 
 
-        RegExpObject(JSGlobalObject*, Structure*, RegExp*);
-        virtual ~RegExpObject();
+        static RegExpObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
+        {
+            RegExpObject* object = new (NotNull, allocateCell<RegExpObject>(*exec->heap())) RegExpObject(globalObject, structure, regExp);
+            object->finishCreation(globalObject);
+            return object;
+        }
+        
+        static RegExpObject* create(JSGlobalData& globalData, JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
+        {
+            RegExpObject* object = new (NotNull, allocateCell<RegExpObject>(globalData.heap)) RegExpObject(globalObject, structure, regExp);
+            object->finishCreation(globalObject);
+            return object;
+        }
 
 
-        void setRegExp(JSGlobalData& globalData, RegExp* r) { d->regExp.set(globalData, this, r); }
-        RegExp* regExp() const { return d->regExp.get(); }
+        void setRegExp(JSGlobalData& globalData, RegExp* r) { m_regExp.set(globalData, this, r); }
+        RegExp* regExp() const { return m_regExp.get(); }
 
 
-        void setLastIndex(size_t lastIndex)
+        void setLastIndex(ExecState* exec, size_t lastIndex)
         {
         {
-            d->lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
+            m_lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
+            if (LIKELY(m_lastIndexIsWritable))
+                m_lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
+            else
+                throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
         }
         }
-        void setLastIndex(JSGlobalData& globalData, JSValue lastIndex)
+        void setLastIndex(ExecState* exec, JSValue lastIndex, bool shouldThrow)
         {
         {
-            d->lastIndex.set(globalData, this, lastIndex);
+            if (LIKELY(m_lastIndexIsWritable))
+                m_lastIndex.set(exec->globalData(), this, lastIndex);
+            else if (shouldThrow)
+                throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
         }
         JSValue getLastIndex() const
         {
         }
         JSValue getLastIndex() const
         {
-            return d->lastIndex.get();
+            return m_lastIndex.get();
         }
 
         }
 
-        JSValue test(ExecState*);
-        JSValue exec(ExecState*);
+        bool test(ExecState* exec, JSString* string) { return match(exec, string); }
+        JSValue exec(ExecState*, JSString*);
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
-        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+        static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
 
         static JS_EXPORTDATA const ClassInfo s_info;
 
 
         static JS_EXPORTDATA const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
-        static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | JSObjectWithGlobalObject::StructureFlags;
+        JS_EXPORT_PRIVATE RegExpObject(JSGlobalObject*, Structure*, RegExp*);
+        JS_EXPORT_PRIVATE void finishCreation(JSGlobalObject*);
+
+        static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | Base::StructureFlags;
+
+        static void visitChildren(JSCell*, SlotVisitor&);
+
+        JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
+        JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+        JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+        JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
 
     private:
 
     private:
-        virtual void visitChildren(SlotVisitor&);
-
-        bool match(ExecState*);
-
-        struct RegExpObjectData {
-            WTF_MAKE_FAST_ALLOCATED;
-        public:
-            RegExpObjectData(JSGlobalData& globalData, RegExpObject* owner, RegExp* regExp)
-                : regExp(globalData, owner, regExp)
-            {
-                lastIndex.setWithoutWriteBarrier(jsNumber(0));
-            }
-
-            WriteBarrier<RegExp> regExp;
-            WriteBarrier<Unknown> lastIndex;
-        };
-#if COMPILER(MSVC)
-        friend void WTF::deleteOwnedPtr<RegExpObjectData>(RegExpObjectData*);
-#endif
-        OwnPtr<RegExpObjectData> d;
+        MatchResult match(ExecState*, JSString*);
+
+        WriteBarrier<RegExp> m_regExp;
+        WriteBarrier<Unknown> m_lastIndex;
+        bool m_lastIndexIsWritable;
     };
 
     RegExpObject* asRegExpObject(JSValue);
     };
 
     RegExpObject* asRegExpObject(JSValue);
index 26f62330a0d5ec225e1538769ceb7a25e38870c1..fba4de2b4b1a42fcf4ed86b8ed68df3503e1bff6 100644 (file)
@@ -49,7 +49,7 @@ static EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*);
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo RegExpPrototype::s_info = { "RegExp", &RegExpObject::s_info, 0, ExecState::regExpPrototypeTable };
+const ClassInfo RegExpPrototype::s_info = { "RegExp", &RegExpObject::s_info, 0, ExecState::regExpPrototypeTable, CREATE_METHOD_TABLE(RegExpPrototype) };
 
 /* Source for RegExpPrototype.lut.h
 @begin regExpPrototypeTable
 
 /* Source for RegExpPrototype.lut.h
 @begin regExpPrototypeTable
@@ -62,19 +62,19 @@ const ClassInfo RegExpPrototype::s_info = { "RegExp", &RegExpObject::s_info, 0,
 
 ASSERT_CLASS_FITS_IN_CELL(RegExpPrototype);
 
 
 ASSERT_CLASS_FITS_IN_CELL(RegExpPrototype);
 
-RegExpPrototype::RegExpPrototype(ExecState*, JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
+RegExpPrototype::RegExpPrototype(JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
     : RegExpObject(globalObject, structure, regExp)
 {
 }
 
     : RegExpObject(globalObject, structure, regExp)
 {
 }
 
-bool RegExpPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+bool RegExpPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 {
-    return getStaticFunctionSlot<RegExpObject>(exec, ExecState::regExpPrototypeTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<RegExpObject>(exec, ExecState::regExpPrototypeTable(exec), jsCast<RegExpPrototype*>(cell), propertyName, slot);
 }
 
 }
 
-bool RegExpPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool RegExpPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<RegExpObject>(exec, ExecState::regExpPrototypeTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<RegExpObject>(exec, ExecState::regExpPrototypeTable(exec), jsCast<RegExpPrototype*>(object), propertyName, descriptor);
 }
 
 // ------------------------------ Functions ---------------------------
 }
 
 // ------------------------------ Functions ---------------------------
@@ -84,7 +84,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (!thisValue.inherits(&RegExpObject::s_info))
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (!thisValue.inherits(&RegExpObject::s_info))
         return throwVMTypeError(exec);
-    return JSValue::encode(asRegExpObject(thisValue)->test(exec));
+    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->test(exec, exec->argument(0).toString(exec))));
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec)
@@ -92,7 +92,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (!thisValue.inherits(&RegExpObject::s_info))
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (!thisValue.inherits(&RegExpObject::s_info))
         return throwVMTypeError(exec);
-    return JSValue::encode(asRegExpObject(thisValue)->exec(exec));
+    return JSValue::encode(asRegExpObject(thisValue)->exec(exec, exec->argument(0).toString(exec)));
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
@@ -110,43 +110,40 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
             return throwVMError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
         regExp = asRegExpObject(arg0)->regExp();
     } else {
             return throwVMError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
         regExp = asRegExpObject(arg0)->regExp();
     } else {
-        UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec);
+        UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec)->value(exec);
         if (exec->hadException())
             return JSValue::encode(jsUndefined());
 
         RegExpFlags flags = NoFlags;
         if (!arg1.isUndefined()) {
         if (exec->hadException())
             return JSValue::encode(jsUndefined());
 
         RegExpFlags flags = NoFlags;
         if (!arg1.isUndefined()) {
-            flags = regExpFlags(arg1.toString(exec));
+            flags = regExpFlags(arg1.toString(exec)->value(exec));
             if (exec->hadException())
                 return JSValue::encode(jsUndefined());
             if (flags == InvalidFlags)
                 return throwVMError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
         }
             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);
+        regExp = RegExp::create(exec->globalData(), pattern, flags);
     }
 
     if (!regExp->isValid())
         return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
 
     asRegExpObject(thisValue)->setRegExp(exec->globalData(), regExp);
     }
 
     if (!regExp->isValid())
         return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
 
     asRegExpObject(thisValue)->setRegExp(exec->globalData(), regExp);
-    asRegExpObject(thisValue)->setLastIndex(0);
+    asRegExpObject(thisValue)->setLastIndex(exec, 0);
     return JSValue::encode(jsUndefined());
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     return JSValue::encode(jsUndefined());
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    if (!thisValue.inherits(&RegExpObject::s_info)) {
-        if (thisValue.inherits(&RegExpPrototype::s_info))
-            return JSValue::encode(jsNontrivialString(exec, "//"));
+    if (!thisValue.inherits(&RegExpObject::s_info))
         return throwVMTypeError(exec);
         return throwVMTypeError(exec);
-    }
 
     RegExpObject* thisObject = asRegExpObject(thisValue);
 
     StringRecursionChecker checker(exec, thisObject);
 
     RegExpObject* thisObject = asRegExpObject(thisValue);
 
     StringRecursionChecker checker(exec, thisObject);
-    if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
-        return earlyReturnValue;
+    if (JSValue earlyReturnValue = checker.earlyReturnValue())
+        return JSValue::encode(earlyReturnValue);
 
     char postfix[5] = { '/', 0, 0, 0, 0 };
     int index = 1;
 
     char postfix[5] = { '/', 0, 0, 0, 0 };
     int index = 1;
@@ -156,9 +153,9 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec)
         postfix[index++] = 'i';
     if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean(exec))
         postfix[index] = 'm';
         postfix[index++] = 'i';
     if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean(exec))
         postfix[index] = 'm';
-    UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec);
+    UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec)->value(exec);
     // If source is empty, use "/(?:)/" to avoid colliding with comment syntax
     // If source is empty, use "/(?:)/" to avoid colliding with comment syntax
-    return JSValue::encode(jsMakeNontrivialString(exec, "/", source.length() ? source : UString("(?:)"), postfix));
+    return JSValue::encode(jsMakeNontrivialString(exec, "/", source, postfix));
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 83e75be0252912d4d349cffab61492cd8abf5f5a..6702592fd3d2719a120ba4df86b4cc2399a6b3ad 100644 (file)
@@ -28,21 +28,29 @@ namespace JSC {
 
     class RegExpPrototype : public RegExpObject {
     public:
 
     class RegExpPrototype : public RegExpObject {
     public:
-        RegExpPrototype(ExecState*, JSGlobalObject*, Structure*, RegExp*);
+        typedef RegExpObject Base;
 
 
+        static RegExpPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
+        {
+            RegExpPrototype* prototype = new (NotNull, allocateCell<RegExpPrototype>(*exec->heap())) RegExpPrototype(globalObject, structure, regExp);
+            prototype->finishCreation(globalObject);
+            return prototype;
+        }
+        
         static const ClassInfo s_info;
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
+        RegExpPrototype(JSGlobalObject*, Structure*, RegExp*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | RegExpObject::StructureFlags;
 
     private:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | RegExpObject::StructureFlags;
 
     private:
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
diff --git a/runtime/RopeImpl.cpp b/runtime/RopeImpl.cpp
deleted file mode 100644 (file)
index 09c24a9..0000000
+++ /dev/null
@@ -1,62 +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 "RopeImpl.h"
-
-namespace JSC {
-
-void RopeImpl::derefFibersNonRecursive(Vector<RopeImpl*, 32>& workQueue)
-{
-    unsigned fiberCount = this->fiberCount();
-    for (unsigned i = 0; i < fiberCount; ++i) {
-        Fiber& fiber = m_fibers[i];
-        if (isRope(fiber)) {
-            RopeImpl* nextRope = static_cast<RopeImpl*>(fiber);
-            if (nextRope->hasOneRef())
-                workQueue.append(nextRope);
-            else
-                nextRope->deref();
-        } else
-            static_cast<StringImpl*>(fiber)->deref();
-    }
-}
-
-void RopeImpl::destructNonRecursive()
-{
-    Vector<RopeImpl*, 32> workQueue;
-
-    derefFibersNonRecursive(workQueue);
-    delete this;
-
-    while (!workQueue.isEmpty()) {
-        RopeImpl* rope = workQueue.last();
-        workQueue.removeLast();
-        rope->derefFibersNonRecursive(workQueue);
-        delete rope;
-    }
-}
-
-} // namespace JSC
diff --git a/runtime/RopeImpl.h b/runtime/RopeImpl.h
deleted file mode 100644 (file)
index dfacbf5..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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 RopeImpl_h
-#define RopeImpl_h
-
-#include <wtf/text/StringImpl.h>
-
-namespace JSC {
-
-class RopeImpl : public StringImplBase {
-public:
-    // A RopeImpl is composed from a set of smaller strings called Fibers.
-    // Each Fiber in a rope is either StringImpl or another RopeImpl.
-    typedef StringImplBase* Fiber;
-
-    // Creates a RopeImpl comprising of 'fiberCount' Fibers.
-    // The RopeImpl is constructed in an uninitialized state - initialize must be called for each Fiber in the RopeImpl.
-    static PassRefPtr<RopeImpl> tryCreateUninitialized(unsigned fiberCount)
-    {
-        void* allocation;
-        if (tryFastMalloc(sizeof(RopeImpl) + (fiberCount - 1) * sizeof(Fiber)).getValue(allocation))
-            return adoptRef(new (allocation) RopeImpl(fiberCount));
-        return 0;
-    }
-
-    static bool isRope(Fiber fiber)
-    {
-        return !fiber->isStringImpl();
-    }
-
-    static void deref(Fiber fiber)
-    {
-        if (isRope(fiber))
-            static_cast<RopeImpl*>(fiber)->deref();
-        else
-            static_cast<StringImpl*>(fiber)->deref();
-    }
-
-    void initializeFiber(unsigned &index, Fiber fiber)
-    {
-        m_fibers[index++] = fiber;
-        fiber->ref();
-        m_length += fiber->length();
-    }
-
-    unsigned fiberCount() { return m_size; }
-    Fiber* fibers() { return m_fibers; }
-
-    ALWAYS_INLINE void deref()
-    {
-        m_refCountAndFlags -= s_refCountIncrement;
-        if (!(m_refCountAndFlags & s_refCountMask))
-            destructNonRecursive();
-    }
-
-private:
-    RopeImpl(unsigned fiberCount)
-        : StringImplBase(ConstructNonStringImpl)
-        , m_size(fiberCount)
-    {
-    }
-
-    void destructNonRecursive();
-    void derefFibersNonRecursive(Vector<RopeImpl*, 32>& workQueue);
-
-    bool hasOneRef() { return (m_refCountAndFlags & s_refCountMask) == s_refCountIncrement; }
-
-    unsigned m_size;
-    Fiber m_fibers[1];
-};
-
-}
-
-#endif
diff --git a/runtime/SamplingCounter.cpp b/runtime/SamplingCounter.cpp
new file mode 100644 (file)
index 0000000..abed763
--- /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.
+ * 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 "SamplingCounter.h"
+
+namespace JSC {
+
+void AbstractSamplingCounter::dump()
+{
+#if ENABLE(SAMPLING_COUNTERS)
+    if (s_abstractSamplingCounterChain != &s_abstractSamplingCounterChainEnd) {
+        dataLog("\nSampling Counter Values:\n");
+        for (AbstractSamplingCounter* currCounter = s_abstractSamplingCounterChain; (currCounter != &s_abstractSamplingCounterChainEnd); currCounter = currCounter->m_next)
+            dataLog("\t%s\t: %lld\n", currCounter->m_name, currCounter->m_counter);
+        dataLog("\n\n");
+    }
+    s_completed = true;
+#endif
+}
+
+AbstractSamplingCounter AbstractSamplingCounter::s_abstractSamplingCounterChainEnd;
+AbstractSamplingCounter* AbstractSamplingCounter::s_abstractSamplingCounterChain = &s_abstractSamplingCounterChainEnd;
+bool AbstractSamplingCounter::s_completed = false;
+
+} // namespace JSC
+
diff --git a/runtime/SamplingCounter.h b/runtime/SamplingCounter.h
new file mode 100644 (file)
index 0000000..8413b54
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * 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 SamplingCounter_h
+#define SamplingCounter_h
+
+#include <stdint.h>
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+// 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 DeletableSamplingCounter;
+public:
+    void count(uint32_t count = 1)
+    {
+        m_counter += count;
+    }
+
+    JS_EXPORT_PRIVATE 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)
+    {
+        m_counter = 0;
+        m_name = name;
+
+        // Set m_next to point to the head of the chain, and inform whatever is
+        // currently at the head that this node will now hold the pointer to it.
+        m_next = s_abstractSamplingCounterChain;
+        s_abstractSamplingCounterChain->m_referer = &m_next;
+        // Add this node to the head of the list.
+        s_abstractSamplingCounterChain = this;
+        m_referer = &s_abstractSamplingCounterChain;
+    }
+
+    int64_t m_counter;
+    const char* m_name;
+    AbstractSamplingCounter* m_next;
+    // This is a pointer to the pointer to this node in the chain; used to
+    // allow fast linked list deletion.
+    AbstractSamplingCounter** m_referer;
+    // Null object used to detect end of static chain.
+    static AbstractSamplingCounter s_abstractSamplingCounterChainEnd;
+    JS_EXPORTDATA static AbstractSamplingCounter* s_abstractSamplingCounterChain;
+    static bool s_completed;
+};
+
+#if ENABLE(SAMPLING_COUNTERS)
+// SamplingCounter:
+//
+// This class is suitable and (hopefully!) convenient for cases where a counter is
+// required within the scope of a single function. It can be instantiated as a
+// static variable since it contains a constructor but not a destructor (static
+// variables in WebKit cannot have destructors).
+//
+// For example:
+//
+// void someFunction()
+// {
+//     static SamplingCounter countMe("This is my counter. There are many like it, but this one is mine.");
+//     countMe.count();
+//     // ...
+// }
+//
+class SamplingCounter : public AbstractSamplingCounter {
+public:
+    SamplingCounter(const char* name) { init(name); }
+};
+
+// GlobalSamplingCounter:
+//
+// This class is suitable for use where a counter is to be declared globally,
+// since it contains neither a constructor nor destructor. Instead, ensure
+// that 'name()' is called to provide the counter with a name (and also to
+// allow it to be printed out on exit).
+//
+// GlobalSamplingCounter globalCounter;
+//
+// void firstFunction()
+// {
+//     // Put this within a function that is definitely called!
+//     // (Or alternatively alongside all calls to 'count()').
+//     globalCounter.name("I Name You Destroyer.");
+//     globalCounter.count();
+//     // ...
+// }
+//
+// void secondFunction()
+// {
+//     globalCounter.count();
+//     // ...
+// }
+//
+class GlobalSamplingCounter : public AbstractSamplingCounter {
+public:
+    void name(const char* name)
+    {
+        // Global objects should be mapped in zero filled memory, so this should
+        // be a safe (albeit not necessarily threadsafe) check for 'first call'.
+        if (!m_next)
+            init(name);
+    }
+};
+
+// DeletableSamplingCounter:
+//
+// The above classes (SamplingCounter, GlobalSamplingCounter), are intended for
+// use within a global or static scope, and as such cannot have a destructor.
+// This means there is no convenient way for them to remove themselves from the
+// static list of counters, and should an instance of either class be freed
+// before 'dump()' has walked over the list it will potentially walk over an
+// invalid pointer.
+//
+// This class is intended for use where the counter may possibly be deleted before
+// the program exits. Should this occur, the counter will print it's value to
+// stderr, and remove itself from the static list. Example:
+//
+// DeletableSamplingCounter* counter = new DeletableSamplingCounter("The Counter With No Name");
+// counter->count();
+// delete counter;
+//
+class DeletableSamplingCounter : public AbstractSamplingCounter {
+public:
+    DeletableSamplingCounter(const char* name) { init(name); }
+
+    ~DeletableSamplingCounter()
+    {
+        if (!s_completed)
+            dataFile("DeletableSamplingCounter \"%s\" deleted early (with count %lld)\n", m_name, m_counter);
+        // Our m_referer pointer should know where the pointer to this node is,
+        // and m_next should know that this node is the previous node in the list.
+        ASSERT(*m_referer == this);
+        ASSERT(m_next->m_referer == &m_next);
+        // Remove this node from the list, and inform m_next that we have done so.
+        m_next->m_referer = m_referer;
+        *m_referer = m_next;
+    }
+};
+#endif
+
+} // namespace JSC
+
+#endif // SamplingCounter_h
+
+
index df4da41c021394270654c051c6f7c8e52885ec65..e7ea07508385dd2288c049ac317d8423b2e255af 100644 (file)
@@ -29,6 +29,8 @@
 
 namespace JSC {
 
 
 namespace JSC {
 
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ScopeChainNode);
+
 #ifndef NDEBUG
 
 void ScopeChainNode::print()
 #ifndef NDEBUG
 
 void ScopeChainNode::print()
@@ -37,21 +39,21 @@ void ScopeChainNode::print()
     for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
         JSObject* o = scopeIter->get();
         PropertyNameArray propertyNames(globalObject->globalExec());
     for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
         JSObject* o = scopeIter->get();
         PropertyNameArray propertyNames(globalObject->globalExec());
-        o->getPropertyNames(globalObject->globalExec(), propertyNames);
+        o->methodTable()->getPropertyNames(o, globalObject->globalExec(), propertyNames, ExcludeDontEnumProperties);
         PropertyNameArray::const_iterator propEnd = propertyNames.end();
 
         PropertyNameArray::const_iterator propEnd = propertyNames.end();
 
-        fprintf(stderr, "----- [scope %p] -----\n", o);
+        dataLog("----- [scope %p] -----\n", o);
         for (PropertyNameArray::const_iterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) {
             Identifier name = *propIter;
         for (PropertyNameArray::const_iterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) {
             Identifier name = *propIter;
-            fprintf(stderr, "%s, ", name.ustring().utf8().data());
+            dataLog("%s, ", name.ustring().utf8().data());
         }
         }
-        fprintf(stderr, "\n");
+        dataLog("\n");
     }
 }
 
 #endif
 
     }
 }
 
 #endif
 
-const ClassInfo ScopeChainNode::s_info = { "ScopeChainNode", 0, 0, 0 };
+const ClassInfo ScopeChainNode::s_info = { "ScopeChainNode", 0, 0, 0, CREATE_METHOD_TABLE(ScopeChainNode) };
 
 int ScopeChainNode::localDepth()
 {
 
 int ScopeChainNode::localDepth()
 {
@@ -67,16 +69,17 @@ int ScopeChainNode::localDepth()
     return scopeDepth;
 }
 
     return scopeDepth;
 }
 
-void ScopeChainNode::visitChildren(SlotVisitor& visitor)
+void ScopeChainNode::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    ScopeChainNode* thisObject = jsCast<ScopeChainNode*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
-    if (next)
-        visitor.append(&next);
-    visitor.append(&object);
-    visitor.append(&globalObject);
-    visitor.append(&globalThis);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    if (thisObject->next)
+        visitor.append(&thisObject->next);
+    visitor.append(&thisObject->object);
+    visitor.append(&thisObject->globalObject);
+    visitor.append(&thisObject->globalThis);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 7fbb888e3b4ae62114f9b9271e1e2cf2071167e3..c382008f11587428e96ac8790642756a6072bb74 100644 (file)
@@ -30,12 +30,12 @@ namespace JSC {
     class JSGlobalData;
     class JSGlobalObject;
     class JSObject;
     class JSGlobalData;
     class JSGlobalObject;
     class JSObject;
-    class MarkStack;
+    class LLIntOffsetsExtractor;
     class ScopeChainIterator;
     class ScopeChainIterator;
-    typedef MarkStack SlotVisitor;
+    class SlotVisitor;
     
     class ScopeChainNode : public JSCell {
     
     class ScopeChainNode : public JSCell {
-    public:
+    private:
         ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
             : JSCell(*globalData, globalData->scopeChainNodeStructure.get())
             , globalData(globalData)
         ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
             : JSCell(*globalData, globalData->scopeChainNodeStructure.get())
             , globalData(globalData)
@@ -44,10 +44,31 @@ namespace JSC {
             , globalObject(*globalData, this, globalObject)
             , globalThis(*globalData, this, globalThis)
         {
             , globalObject(*globalData, this, globalObject)
             , globalThis(*globalData, this, globalThis)
         {
-            ASSERT(globalData);
-            ASSERT(globalObject);
         }
 
         }
 
+    protected:
+        void finishCreation(JSGlobalData* globalData, JSGlobalObject* globalObject)
+        {
+            Base::finishCreation(*globalData);
+            ASSERT_UNUSED(globalObject, globalObject);
+        }
+
+    public:
+        typedef JSCell Base;
+
+        static ScopeChainNode* create(ExecState* exec, ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
+        {
+            ScopeChainNode* node = new (NotNull, allocateCell<ScopeChainNode>(*exec->heap())) ScopeChainNode(next, object, globalData, globalObject, globalThis);
+            node->finishCreation(globalData, globalObject);
+            return node;
+        }
+        static ScopeChainNode* create(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
+        {
+            ScopeChainNode* node = new (NotNull, allocateCell<ScopeChainNode>(globalData->heap)) ScopeChainNode(next, object, globalData, globalObject, globalThis);
+            node->finishCreation(globalData, globalObject);
+            return node;
+        }
+        
         JSGlobalData* globalData;
         WriteBarrier<ScopeChainNode> next;
         WriteBarrier<JSObject> object;
         JSGlobalData* globalData;
         WriteBarrier<ScopeChainNode> next;
         WriteBarrier<JSObject> object;
@@ -66,18 +87,20 @@ namespace JSC {
         void print();
 #endif
         
         void print();
 #endif
         
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); }
-        virtual void visitChildren(SlotVisitor&);
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
+        static void visitChildren(JSCell*, SlotVisitor&);
         static JS_EXPORTDATA const ClassInfo s_info;
 
     private:
         static JS_EXPORTDATA const ClassInfo s_info;
 
     private:
+        friend class LLIntOffsetsExtractor;
+        
         static const unsigned StructureFlags = OverridesVisitChildren;
     };
 
     inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
     {
         ASSERT(o);
         static const unsigned StructureFlags = OverridesVisitChildren;
     };
 
     inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
     {
         ASSERT(o);
-        return new (globalData) ScopeChainNode(this, o, globalData, globalObject.get(), globalThis.get());
+        return ScopeChainNode::create(this, o, globalData, globalObject.get(), globalThis.get());
     }
 
     inline ScopeChainNode* ScopeChainNode::pop()
     }
 
     inline ScopeChainNode* ScopeChainNode::pop()
index 8741e9bd29a53220d916f9971c20278fb04de1e4..f50f73d27c7c030fae2a3dfb666f5a4faab5c22e 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "SmallStrings.h"
 
 #include "config.h"
 #include "SmallStrings.h"
 
+#include "HeapRootVisitor.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
 #include <wtf/Noncopyable.h>
 #include "JSGlobalObject.h"
 #include "JSString.h"
 #include <wtf/Noncopyable.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
-static inline bool isMarked(JSCell* string)
+static inline void finalize(JSString*& string)
 {
 {
-    return string && Heap::isMarked(string);
+    if (!string || Heap::isMarked(string))
+        return;
+    string = 0;
 }
 
 class SmallStringsStorage {
 }
 
 class SmallStringsStorage {
@@ -56,7 +59,7 @@ private:
 
 SmallStringsStorage::SmallStringsStorage()
 {
 
 SmallStringsStorage::SmallStringsStorage()
 {
-    UChar* characterBuffer = 0;
+    LChar* characterBuffer = 0;
     RefPtr<StringImpl> baseString = StringImpl::createUninitialized(singleCharacterStringCount, characterBuffer);
     for (unsigned i = 0; i < singleCharacterStringCount; ++i) {
         characterBuffer[i] = i;
     RefPtr<StringImpl> baseString = StringImpl::createUninitialized(singleCharacterStringCount, characterBuffer);
     for (unsigned i = 0; i < singleCharacterStringCount; ++i) {
         characterBuffer[i] = i;
@@ -65,67 +68,35 @@ SmallStringsStorage::SmallStringsStorage()
 }
 
 SmallStrings::SmallStrings()
 }
 
 SmallStrings::SmallStrings()
+    : m_emptyString(0)
+#define JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE(name) , m_##name(0)
+    JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE)
+#undef JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE
 {
     COMPILE_ASSERT(singleCharacterStringCount == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
 {
     COMPILE_ASSERT(singleCharacterStringCount == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
-    clear();
-}
 
 
-SmallStrings::~SmallStrings()
-{
+    for (unsigned i = 0; i < singleCharacterStringCount; ++i)
+        m_singleCharacterStrings[i] = 0;
 }
 
 }
 
-void SmallStrings::visitChildren(HeapRootVisitor& heapRootMarker)
+SmallStrings::~SmallStrings()
 {
 {
-    /*
-       Our hypothesis is that small strings are very common. So, we cache them
-       to avoid GC churn. However, in cases where this hypothesis turns out to
-       be false -- including the degenerate case where all JavaScript execution
-       has terminated -- we don't want to waste memory.
-
-       To test our hypothesis, we check if any small string has been marked. If
-       so, it's probably reasonable to mark the rest. If not, we clear the cache.
-     */
-
-    bool isAnyStringMarked = isMarked(m_emptyString);
-    for (unsigned i = 0; i < singleCharacterStringCount && !isAnyStringMarked; ++i)
-        isAnyStringMarked = isMarked(m_singleCharacterStrings[i]);
-    
-    if (!isAnyStringMarked) {
-        clear();
-        return;
-    }
-    
-    if (m_emptyString)
-        heapRootMarker.mark(&m_emptyString);
-    for (unsigned i = 0; i < singleCharacterStringCount; ++i) {
-        if (m_singleCharacterStrings[i])
-            heapRootMarker.mark(&m_singleCharacterStrings[i]);
-    }
 }
 
 }
 
-void SmallStrings::clear()
+void SmallStrings::finalizeSmallStrings()
 {
 {
-    m_emptyString = 0;
+    finalize(m_emptyString);
     for (unsigned i = 0; i < singleCharacterStringCount; ++i)
     for (unsigned i = 0; i < singleCharacterStringCount; ++i)
-        m_singleCharacterStrings[i] = 0;
-}
-
-unsigned SmallStrings::count() const
-{
-    unsigned count = 0;
-    if (m_emptyString)
-        ++count;
-    for (unsigned i = 0; i < singleCharacterStringCount; ++i) {
-        if (m_singleCharacterStrings[i])
-            ++count;
-    }
-    return count;
+        finalize(m_singleCharacterStrings[i]);
+#define JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE(name) finalize(m_##name);
+    JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE)
+#undef JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE
 }
 
 void SmallStrings::createEmptyString(JSGlobalData* globalData)
 {
     ASSERT(!m_emptyString);
 }
 
 void SmallStrings::createEmptyString(JSGlobalData* globalData)
 {
     ASSERT(!m_emptyString);
-    m_emptyString = new (globalData) JSString(globalData, "", JSString::HasOtherOwner);
+    m_emptyString = JSString::createHasOtherOwner(*globalData, StringImpl::empty());
 }
 
 void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigned char character)
 }
 
 void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigned char character)
@@ -133,7 +104,7 @@ void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigne
     if (!m_storage)
         m_storage = adoptPtr(new SmallStringsStorage);
     ASSERT(!m_singleCharacterStrings[character]);
     if (!m_storage)
         m_storage = adoptPtr(new SmallStringsStorage);
     ASSERT(!m_singleCharacterStrings[character]);
-    m_singleCharacterStrings[character] = new (globalData) JSString(globalData, PassRefPtr<StringImpl>(m_storage->rep(character)), JSString::HasOtherOwner);
+    m_singleCharacterStrings[character] = JSString::createHasOtherOwner(*globalData, PassRefPtr<StringImpl>(m_storage->rep(character)));
 }
 
 StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character)
 }
 
 StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character)
@@ -143,4 +114,9 @@ StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character)
     return m_storage->rep(character);
 }
 
     return m_storage->rep(character);
 }
 
+void SmallStrings::initialize(JSGlobalData* globalData, JSString*& string, const char* value) const
+{
+    string = JSString::create(*globalData, StringImpl::create(value));
+}
+
 } // namespace JSC
 } // namespace JSC
index e762e1f365c88c38d02cce2d775bd192e6c996c1..e609c509221c6ab00d6d578a9f334d1674ed1b1e 100644 (file)
 #include <wtf/FixedArray.h>
 #include <wtf/OwnPtr.h>
 
 #include <wtf/FixedArray.h>
 #include <wtf/OwnPtr.h>
 
+#define JSC_COMMON_STRINGS_EACH_NAME(macro) \
+    macro(boolean) \
+    macro(false) \
+    macro(function) \
+    macro(number) \
+    macro(null) \
+    macro(object) \
+    macro(undefined) \
+    macro(string) \
+    macro(true)
+
 namespace JSC {
 
     class HeapRootVisitor;
     class JSGlobalData;
     class JSString;
 namespace JSC {
 
     class HeapRootVisitor;
     class JSGlobalData;
     class JSString;
-    class MarkStack;
     class SmallStringsStorage;
     class SmallStringsStorage;
-    typedef MarkStack SlotVisitor;
+    class SlotVisitor;
 
     static const unsigned maxSingleCharacterString = 0xFF;
 
 
     static const unsigned maxSingleCharacterString = 0xFF;
 
@@ -61,22 +71,34 @@ namespace JSC {
             return m_singleCharacterStrings[character];
         }
 
             return m_singleCharacterStrings[character];
         }
 
-        StringImpl* singleCharacterStringRep(unsigned char character);
-
-        void visitChildren(HeapRootVisitor&);
-        void clear();
+        JS_EXPORT_PRIVATE StringImpl* singleCharacterStringRep(unsigned char character);
 
 
-        unsigned count() const;
+        void finalizeSmallStrings();
 
         JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; }
 
 
         JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; }
 
+#define JSC_COMMON_STRINGS_ACCESSOR_DEFINITION(name) \
+        JSString* name##String(JSGlobalData* globalData) const \
+        { \
+            if (!m_##name) \
+                initialize(globalData, m_##name, #name); \
+            return m_##name; \
+        }
+        JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ACCESSOR_DEFINITION)
+#undef JSC_COMMON_STRINGS_ACCESSOR_DEFINITION
+
     private:
         static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
 
     private:
         static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
 
-        void createEmptyString(JSGlobalData*);
-        void createSingleCharacterString(JSGlobalData*, unsigned char);
+        JS_EXPORT_PRIVATE void createEmptyString(JSGlobalData*);
+        JS_EXPORT_PRIVATE void createSingleCharacterString(JSGlobalData*, unsigned char);
+
+        void initialize(JSGlobalData* globalData, JSString*& string, const char* value) const;
 
         JSString* m_emptyString;
 
         JSString* m_emptyString;
+#define JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION(name) mutable JSString* m_##name;
+        JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION)
+#undef JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION
         JSString* m_singleCharacterStrings[singleCharacterStringCount];
         OwnPtr<SmallStringsStorage> m_storage;
     };
         JSString* m_singleCharacterStrings[singleCharacterStringCount];
         OwnPtr<SmallStringsStorage> m_storage;
     };
diff --git a/runtime/StorageBarrier.h b/runtime/StorageBarrier.h
new file mode 100644 (file)
index 0000000..2a0c842
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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 StorageBarrier_h
+#define StorageBarrier_h
+
+#include "JSGlobalData.h"
+#include "WriteBarrier.h"
+
+namespace JSC {
+
+typedef WriteBarrierBase<Unknown>* PropertyStorage;
+typedef const WriteBarrierBase<Unknown>* ConstPropertyStorage;
+
+class StorageBarrier {
+public:
+    enum UncheckedTag { Unchecked };
+    StorageBarrier(JSGlobalData& globalData, JSCell* owner, PropertyStorage storage)
+    {
+        set(globalData, owner, storage);
+    }
+    
+    StorageBarrier(PropertyStorage storage, UncheckedTag)
+    {
+        set(storage, Unchecked);
+    }
+    
+    void set(JSGlobalData&, JSCell*, PropertyStorage newStorage)
+    {
+        m_storage = newStorage;
+    }
+    
+    void set(PropertyStorage newStorage, UncheckedTag)
+    {
+        m_storage = newStorage;
+    }
+    
+    WriteBarrierBase<Unknown>* operator->() const { return m_storage; }
+    WriteBarrierBase<Unknown>* operator->() { return m_storage; }
+    WriteBarrierBase<Unknown> operator*() const { return *m_storage; }
+    WriteBarrierBase<Unknown> operator*() { return *m_storage; }
+    const WriteBarrierBase<Unknown>& operator[](size_t i) const { return m_storage[i]; }
+    WriteBarrierBase<Unknown>& operator[](size_t i) { return m_storage[i]; }
+    
+    ConstPropertyStorage get() const { return m_storage; }
+    PropertyStorage get() { return m_storage; }
+    
+private:
+    PropertyStorage m_storage;
+};
+
+}
+
+#endif
index e666dee15792b7fbe897e60d2c503d623b76fd83..fbd9d5fbd97cc03bb4d76eb20cda49b8cd257edc 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(StrictEvalActivation);
+
+const ClassInfo StrictEvalActivation::s_info = { "Object", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(StrictEvalActivation) };
+
 StrictEvalActivation::StrictEvalActivation(ExecState* exec)
     : JSNonFinalObject(exec->globalData(), exec->globalData().strictEvalActivationStructure.get())
 {
 }
 
 StrictEvalActivation::StrictEvalActivation(ExecState* exec)
     : JSNonFinalObject(exec->globalData(), exec->globalData().strictEvalActivationStructure.get())
 {
 }
 
-bool StrictEvalActivation::deleteProperty(ExecState*, const Identifier&)
+bool StrictEvalActivation::deleteProperty(JSCell*, ExecState*, const Identifier&)
 {
     return false;
 }
 
 {
     return false;
 }
 
-JSObject* StrictEvalActivation::toThisObject(ExecState* exec) const
+JSObject* StrictEvalActivation::toThisObject(JSCell*, ExecState* exec)
 {
     return exec->globalThisValue();
 }
 
 {
     return exec->globalThisValue();
 }
 
-JSValue StrictEvalActivation::toStrictThisObject(ExecState*) const
-{
-    return jsNull();
-}
-
 }
 }
index e2885cc0c65685a9b83da42701986a69547c44d4..a7b6d3e96458a498b293852f4440e3a1c5822578 100644 (file)
@@ -32,10 +32,30 @@ namespace JSC {
 
 class StrictEvalActivation : public JSNonFinalObject {
 public:
 
 class StrictEvalActivation : public JSNonFinalObject {
 public:
+    typedef JSNonFinalObject Base;
+
+    static StrictEvalActivation* create(ExecState* exec)
+    {
+        StrictEvalActivation* activation = new (NotNull, allocateCell<StrictEvalActivation>(*exec->heap())) StrictEvalActivation(exec);
+        activation->finishCreation(exec->globalData());
+        return activation;
+    }
+
+    static bool deleteProperty(JSCell*, ExecState*, const Identifier&);
+    static JSObject* toThisObject(JSCell*, ExecState*);
+
+    static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
+    }
+    
+    static const ClassInfo s_info;
+
+protected:
+    static const unsigned StructureFlags = IsEnvironmentRecord | JSNonFinalObject::StructureFlags;
+
+private:
     StrictEvalActivation(ExecState*);
     StrictEvalActivation(ExecState*);
-    virtual bool deleteProperty(ExecState*, const Identifier&);
-    virtual JSObject* toThisObject(ExecState*) const;
-    virtual JSValue toStrictThisObject(ExecState*) const;
 };
 
 } // namespace JSC
 };
 
 } // namespace JSC
index ea6e12853e776820cdef9df6fbdb604a50eff564..e03a87f03e467561f183c7475b07652c5b3ed8aa 100644 (file)
@@ -37,7 +37,7 @@ static EncodedJSValue JSC_HOST_CALL stringFromCharCode(ExecState*);
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo StringConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::stringConstructorTable };
+const ClassInfo StringConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::stringConstructorTable, CREATE_METHOD_TABLE(StringConstructor) };
 
 /* Source for StringConstructor.lut.h
 @begin stringConstructorTable
 
 /* Source for StringConstructor.lut.h
 @begin stringConstructorTable
@@ -46,22 +46,28 @@ const ClassInfo StringConstructor::s_info = { "Function", &InternalFunction::s_i
 */
 
 ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
 */
 
 ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(StringConstructor);
 
 
-StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, StringPrototype* stringPrototype)
-    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, stringPrototype->classInfo()->className))
+StringConstructor::StringConstructor(JSGlobalObject* globalObject, Structure* structure)
+    : InternalFunction(globalObject, structure)
 {
 {
+}
+
+void StringConstructor::finishCreation(ExecState* exec, StringPrototype* stringPrototype)
+{
+    Base::finishCreation(exec->globalData(), Identifier(exec, stringPrototype->classInfo()->className));
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete);
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
 
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete);
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
 
-bool StringConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+bool StringConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 {
-    return getStaticFunctionSlot<InternalFunction>(exec, ExecState::stringConstructorTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<InternalFunction>(exec, ExecState::stringConstructorTable(exec), jsCast<StringConstructor*>(cell), propertyName, slot);
 }
 
 }
 
-bool StringConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool StringConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<InternalFunction>(exec, ExecState::stringConstructorTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<InternalFunction>(exec, ExecState::stringConstructorTable(exec), jsCast<StringConstructor*>(object), propertyName, descriptor);
 }
 
 // ------------------------------ Functions --------------------------------
 }
 
 // ------------------------------ Functions --------------------------------
@@ -87,11 +93,12 @@ static EncodedJSValue JSC_HOST_CALL constructWithStringConstructor(ExecState* ex
 {
     JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
     if (!exec->argumentCount())
 {
     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)));
+        return JSValue::encode(StringObject::create(exec, globalObject->stringObjectStructure()));
+    
+    return JSValue::encode(StringObject::create(exec, globalObject->stringObjectStructure(), exec->argument(0).toString(exec)));
 }
 
 }
 
-ConstructType StringConstructor::getConstructData(ConstructData& constructData)
+ConstructType StringConstructor::getConstructData(JSCell*, ConstructData& constructData)
 {
     constructData.native.function = constructWithStringConstructor;
     return ConstructTypeHost;
 {
     constructData.native.function = constructWithStringConstructor;
     return ConstructTypeHost;
@@ -101,10 +108,10 @@ static EncodedJSValue JSC_HOST_CALL callStringConstructor(ExecState* exec)
 {
     if (!exec->argumentCount())
         return JSValue::encode(jsEmptyString(exec));
 {
     if (!exec->argumentCount())
         return JSValue::encode(jsEmptyString(exec));
-    return JSValue::encode(jsString(exec, exec->argument(0).toString(exec)));
+    return JSValue::encode(exec->argument(0).toString(exec));
 }
 
 }
 
-CallType StringConstructor::getCallData(CallData& callData)
+CallType StringConstructor::getCallData(JSCell*, CallData& callData)
 {
     callData.native.function = callStringConstructor;
     return CallTypeHost;
 {
     callData.native.function = callStringConstructor;
     return CallTypeHost;
index b2e3be60949d7c3d9ad2a662ac53530988f2af2f..6f553cdbb58bf7e5892fccbd6388115d6cbac213 100644 (file)
@@ -29,24 +29,33 @@ namespace JSC {
 
     class StringConstructor : public InternalFunction {
     public:
 
     class StringConstructor : public InternalFunction {
     public:
-        StringConstructor(ExecState*, JSGlobalObject*, Structure*, StringPrototype*);
+        typedef InternalFunction Base;
+
+        static StringConstructor* create(ExecState* exec, JSGlobalObject* globalObject , Structure* structure, StringPrototype* stringPrototype)
+        {
+            StringConstructor* constructor = new (NotNull, allocateCell<StringConstructor>(*exec->heap())) StringConstructor(globalObject, structure);
+            constructor->finishCreation(exec, stringPrototype);
+            return constructor;
+        }
 
         static const ClassInfo s_info;
 
 
         static const ClassInfo s_info;
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
 
     private:
         }
 
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
 
     private:
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
+        StringConstructor(JSGlobalObject*, Structure*);
+        void finishCreation(ExecState*, StringPrototype*);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 67dc291b09ecf7d7eba88aaf296fa5348ec22cf9..d7e1c8a17b89dd134188b96492524e475e0818ef 100644 (file)
 #include "config.h"
 #include "StringObject.h"
 
 #include "config.h"
 #include "StringObject.h"
 
+#include "Error.h"
 #include "PropertyNameArray.h"
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(StringObject);
 #include "PropertyNameArray.h"
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(StringObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(StringObject);
 
 
-const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0 };
+const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(StringObject) };
 
 
-StringObject::StringObject(ExecState* exec, Structure* structure)
-    : JSWrapperObject(exec->globalData(), structure)
-{
-    ASSERT(inherits(&s_info));
-    setInternalValue(exec->globalData(), jsEmptyString(exec));
-}
-
-StringObject::StringObject(JSGlobalData& globalData, Structure* structure, JSString* string)
+StringObject::StringObject(JSGlobalData& globalData, Structure* structure)
     : JSWrapperObject(globalData, structure)
 {
     : JSWrapperObject(globalData, structure)
 {
-    ASSERT(inherits(&s_info));
-    setInternalValue(globalData, string);
 }
 
 }
 
-StringObject::StringObject(ExecState* exec, Structure* structure, const UString& string)
-    : JSWrapperObject(exec->globalData(), structure)
+void StringObject::finishCreation(JSGlobalData& globalData, JSString* string)
 {
 {
+    Base::finishCreation(globalData);
     ASSERT(inherits(&s_info));
     ASSERT(inherits(&s_info));
-    setInternalValue(exec->globalData(), jsString(exec, string));
+    setInternalValue(globalData, string);
 }
 
 }
 
-bool StringObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+bool StringObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
 {
-    if (internalValue()->getStringPropertySlot(exec, propertyName, slot))
+    StringObject* thisObject = jsCast<StringObject*>(cell);
+    if (thisObject->internalValue()->getStringPropertySlot(exec, propertyName, slot))
         return true;
         return true;
-    return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+    return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
 }
     
 }
     
-bool StringObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+bool StringObject::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)
 {
 {
-    if (internalValue()->getStringPropertySlot(exec, propertyName, slot))
+    StringObject* thisObject = jsCast<StringObject*>(cell);
+    if (thisObject->internalValue()->getStringPropertySlot(exec, propertyName, slot))
         return true;    
         return true;    
-    return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
+    return JSObject::getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot);
 }
 
 }
 
-bool StringObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool StringObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    if (internalValue()->getStringPropertyDescriptor(exec, propertyName, descriptor))
+    StringObject* thisObject = jsCast<StringObject*>(object);
+    if (thisObject->internalValue()->getStringPropertyDescriptor(exec, propertyName, descriptor))
         return true;    
         return true;    
-    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    return JSObject::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
 }
 
 }
 
-void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void StringObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
 {
-    if (propertyName == exec->propertyNames().length)
+    if (propertyName == exec->propertyNames().length) {
+        if (slot.isStrictMode())
+            throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
         return;
         return;
-    JSObject::put(exec, propertyName, value, slot);
+    }
+    JSObject::put(cell, exec, propertyName, value, slot);
+}
+
+bool StringObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
+{
+    StringObject* thisObject = jsCast<StringObject*>(object);
+
+    if (propertyName == exec->propertyNames().length) {
+        if (!object->isExtensible()) {
+            if (throwException)
+                throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible."));
+            return false;
+        }
+        if (descriptor.configurablePresent() && descriptor.configurable()) {
+            if (throwException)
+                throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property."));
+            return false;
+        }
+        if (descriptor.enumerablePresent() && descriptor.enumerable()) {
+            if (throwException)
+                throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property."));
+            return false;
+        }
+        if (descriptor.isAccessorDescriptor()) {
+            if (throwException)
+                throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
+            return false;
+        }
+        if (descriptor.writablePresent() && descriptor.writable()) {
+            if (throwException)
+                throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property."));
+            return false;
+        }
+        if (!descriptor.value())
+            return true;
+        if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->internalValue()->length())))
+            return true;
+        if (throwException)
+            throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
+        return false;
+    }
+
+    return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
 }
 
 }
 
-bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
+bool StringObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
 {
 {
+    StringObject* thisObject = jsCast<StringObject*>(cell);
     if (propertyName == exec->propertyNames().length)
         return false;
     bool isStrictUInt32;
     unsigned i = propertyName.toUInt32(isStrictUInt32);
     if (propertyName == exec->propertyNames().length)
         return false;
     bool isStrictUInt32;
     unsigned i = propertyName.toUInt32(isStrictUInt32);
-    if (isStrictUInt32 && internalValue()->canGetIndex(i))
+    if (isStrictUInt32 && thisObject->internalValue()->canGetIndex(i))
         return false;
         return false;
-    return JSObject::deleteProperty(exec, propertyName);
+    return JSObject::deleteProperty(thisObject, exec, propertyName);
 }
 
 }
 
-void StringObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void StringObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
 {
-    int size = internalValue()->length();
+    StringObject* thisObject = jsCast<StringObject*>(object);
+    int size = thisObject->internalValue()->length();
     for (int i = 0; i < size; ++i)
         propertyNames.add(Identifier(exec, UString::number(i)));
     if (mode == IncludeDontEnumProperties)
         propertyNames.add(exec->propertyNames().length);
     for (int i = 0; i < size; ++i)
         propertyNames.add(Identifier(exec, UString::number(i)));
     if (mode == IncludeDontEnumProperties)
         propertyNames.add(exec->propertyNames().length);
-    return JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+    return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 4c16044fba698574ced732a22ccf6fc66d247bf1..bad5595c3eea5225a3c8773bfbe2c927dcee549c 100644 (file)
@@ -28,31 +28,46 @@ namespace JSC {
 
     class StringObject : public JSWrapperObject {
     public:
 
     class StringObject : public JSWrapperObject {
     public:
-        StringObject(ExecState*, Structure*);
-        StringObject(ExecState*, Structure*, const UString&);
+        typedef JSWrapperObject Base;
 
 
+        static StringObject* create(ExecState* exec, Structure* structure)
+        {
+            JSString* string = jsEmptyString(exec);
+            StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->globalData(), structure);  
+            object->finishCreation(exec->globalData(), string);
+            return object;
+        }
+        static StringObject* create(ExecState* exec, Structure* structure, JSString* string)
+        {
+            StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->globalData(), structure);
+            object->finishCreation(exec->globalData(), string);
+            return object;
+        }
         static StringObject* create(ExecState*, JSGlobalObject*, JSString*);
 
         static StringObject* create(ExecState*, JSGlobalObject*, JSString*);
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
-        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
+        static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+
+        static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
 
 
-        virtual void put(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&);
-        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
-        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+        static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
+        static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+        static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
 
         static const JS_EXPORTDATA ClassInfo s_info;
 
         JSString* internalValue() const { return asString(JSWrapperObject::internalValue());}
 
 
         static const JS_EXPORTDATA ClassInfo s_info;
 
         JSString* internalValue() const { return asString(JSWrapperObject::internalValue());}
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
     protected:
         }
 
     protected:
+        JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, JSString*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSWrapperObject::StructureFlags;
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSWrapperObject::StructureFlags;
-        StringObject(JSGlobalData&, Structure*, JSString*);
+        JS_EXPORT_PRIVATE StringObject(JSGlobalData&, Structure*);
     };
 
     StringObject* asStringObject(JSValue);
     };
 
     StringObject* asStringObject(JSValue);
diff --git a/runtime/StringObjectThatMasqueradesAsUndefined.h b/runtime/StringObjectThatMasqueradesAsUndefined.h
deleted file mode 100644 (file)
index 3133944..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 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 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 StringObjectThatMasqueradesAsUndefined_h
-#define StringObjectThatMasqueradesAsUndefined_h
-
-#include "JSGlobalObject.h"
-#include "StringObject.h"
-#include "UString.h"
-
-namespace JSC {
-
-    // WebCore uses this to make style.filter undetectable
-    class StringObjectThatMasqueradesAsUndefined : public StringObject {
-    public:
-        static StringObjectThatMasqueradesAsUndefined* create(ExecState* exec, const UString& string)
-        {
-            return new (exec) StringObjectThatMasqueradesAsUndefined(exec,
-                createStructure(exec->globalData(), exec->lexicalGlobalObject()->stringPrototype()), string);
-        }
-
-    private:
-        StringObjectThatMasqueradesAsUndefined(ExecState* exec, Structure* structure, const UString& string)
-            : StringObject(exec, structure, string)
-        {
-        }
-
-        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
-        { 
-            return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
-        }
-
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | MasqueradesAsUndefined | OverridesGetPropertyNames | StringObject::StructureFlags;
-
-        virtual bool toBoolean(ExecState*) const { return false; }
-    };
-} // namespace JSC
-
-#endif // StringObjectThatMasqueradesAsUndefined_h
index ce88a465e5eec752bf2411aa909ca1934c2ec0df..81129f2a21595398bc2c0911926e45781e262d55 100644 (file)
@@ -35,6 +35,7 @@
 #include "PropertyNameArray.h"
 #include "RegExpCache.h"
 #include "RegExpConstructor.h"
 #include "PropertyNameArray.h"
 #include "RegExpCache.h"
 #include "RegExpConstructor.h"
+#include "RegExpMatchesArray.h"
 #include "RegExpObject.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/MathExtras.h>
 #include "RegExpObject.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/MathExtras.h>
@@ -45,6 +46,7 @@ using namespace WTF;
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(StringPrototype);
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(StringPrototype);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(StringPrototype);
 
 static EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState*);
 static EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState*);
 
 static EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState*);
 static EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState*);
@@ -85,7 +87,7 @@ static EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState*);
 
 namespace JSC {
 
 
 namespace JSC {
 
-const ClassInfo StringPrototype::s_info = { "String", &StringObject::s_info, 0, ExecState::stringTable };
+const ClassInfo StringPrototype::s_info = { "String", &StringObject::s_info, 0, ExecState::stringTable, CREATE_METHOD_TABLE(StringPrototype) };
 
 /* Source for StringPrototype.lut.h
 @begin stringTable 26
 
 /* Source for StringPrototype.lut.h
 @begin stringTable 26
@@ -131,31 +133,48 @@ const ClassInfo StringPrototype::s_info = { "String", &StringObject::s_info, 0,
 */
 
 // ECMA 15.5.4
 */
 
 // ECMA 15.5.4
-StringPrototype::StringPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
-    : StringObject(exec, structure)
+StringPrototype::StringPrototype(ExecState* exec, Structure* structure)
+    : StringObject(exec->globalData(), structure)
 {
 {
+}
+
+void StringPrototype::finishCreation(ExecState* exec, JSGlobalObject*, JSString* nameAndMessage)
+{
+    Base::finishCreation(exec->globalData(), nameAndMessage);
     ASSERT(inherits(&s_info));
 
     ASSERT(inherits(&s_info));
 
-    putAnonymousValue(exec->globalData(), 0, globalObject);
     // The constructor will be added later, after StringConstructor has been built
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
 }
 
     // The constructor will be added later, after StringConstructor has been built
     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
 }
 
-bool StringPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+bool StringPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
 {
-    return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), jsCast<StringPrototype*>(cell), propertyName, slot);
 }
 
 }
 
-bool StringPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool StringPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 {
-    return getStaticFunctionDescriptor<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<StringObject>(exec, ExecState::stringTable(exec), jsCast<StringPrototype*>(object), propertyName, descriptor);
 }
 
 // ------------------------------ Functions --------------------------
 
 }
 
 // ------------------------------ Functions --------------------------
 
+// Helper for producing a JSString for 'string', where 'string' was been produced by
+// calling ToString on 'originalValue'. In cases where 'originalValue' already was a
+// string primitive we can just use this, otherwise we need to allocate a new JSString.
+static inline JSString* jsStringWithReuse(ExecState* exec, JSValue originalValue, const UString& string)
+{
+    if (originalValue.isString()) {
+        ASSERT(asString(originalValue)->value(exec) == string);
+        return asString(originalValue);
+    }
+    return jsString(exec, string);
+}
+
+template <typename CharType>
 static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacement, const UString& source, const int* ovector, RegExp* reg, size_t i)
 {
 static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacement, const UString& source, const int* ovector, RegExp* reg, size_t i)
 {
-    Vector<UChar> substitutedReplacement;
+    Vector<CharType> substitutedReplacement;
     int offset = 0;
     do {
         if (i + 1 == replacement.length())
     int offset = 0;
     do {
         if (i + 1 == replacement.length())
@@ -165,7 +184,7 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem
         if (ref == '$') {
             // "$$" -> "$"
             ++i;
         if (ref == '$') {
             // "$$" -> "$"
             ++i;
-            substitutedReplacement.append(replacement.characters() + offset, i - offset);
+            substitutedReplacement.append(replacement.getCharacters<CharType>() + offset, i - offset);
             offset = i + 1;
             continue;
         }
             offset = i + 1;
             continue;
         }
@@ -205,15 +224,15 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem
             continue;
 
         if (i - offset)
             continue;
 
         if (i - offset)
-            substitutedReplacement.append(replacement.characters() + offset, i - offset);
+            substitutedReplacement.append(replacement.getCharacters<CharType>() + offset, i - offset);
         i += 1 + advance;
         offset = i + 1;
         if (backrefStart >= 0)
         i += 1 + advance;
         offset = i + 1;
         if (backrefStart >= 0)
-            substitutedReplacement.append(source.characters() + backrefStart, backrefLength);
+            substitutedReplacement.append(source.getCharacters<CharType>() + backrefStart, backrefLength);
     } while ((i = replacement.find('$', i + 1)) != notFound);
 
     if (replacement.length() - offset)
     } while ((i = replacement.find('$', i + 1)) != notFound);
 
     if (replacement.length() - offset)
-        substitutedReplacement.append(replacement.characters() + offset, replacement.length() - offset);
+        substitutedReplacement.append(replacement.getCharacters<CharType>() + offset, replacement.length() - offset);
 
     substitutedReplacement.shrinkToFit();
     return UString::adopt(substitutedReplacement);
 
     substitutedReplacement.shrinkToFit();
     return UString::adopt(substitutedReplacement);
@@ -221,9 +240,12 @@ 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)
 {
-    size_t i = replacement.find('$', 0);
-    if (UNLIKELY(i != notFound))
-        return substituteBackreferencesSlow(replacement, source, ovector, reg, i);
+    size_t i = replacement.find('$');
+    if (UNLIKELY(i != notFound)) {
+        if (replacement.is8Bit() && source.is8Bit())
+            return substituteBackreferencesSlow<LChar>(replacement, source, ovector, reg, i);
+        return substituteBackreferencesSlow<UChar>(replacement, source, ovector, reg, i);
+    }
     return replacement;
 }
 
     return replacement;
 }
 
@@ -248,6 +270,61 @@ public:
     int length;
 };
 
     int length;
 };
 
+static ALWAYS_INLINE JSValue jsSpliceSubstrings(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount)
+{
+    if (rangeCount == 1) {
+        int sourceSize = source.length();
+        int position = substringRanges[0].position;
+        int length = substringRanges[0].length;
+        if (position <= 0 && length >= sourceSize)
+            return sourceVal;
+        // We could call UString::substr, but this would result in redundant checks
+        return jsString(exec, StringImpl::create(source.impl(), max(0, position), min(sourceSize, length)));
+    }
+
+    int totalLength = 0;
+    for (int i = 0; i < rangeCount; i++)
+        totalLength += substringRanges[i].length;
+
+    if (!totalLength)
+        return jsString(exec, "");
+
+    if (source.is8Bit()) {
+        LChar* buffer;
+        const LChar* sourceData = source.characters8();
+        RefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
+        if (!impl)
+            return throwOutOfMemoryError(exec);
+
+        int bufferPos = 0;
+        for (int i = 0; i < rangeCount; i++) {
+            if (int srcLen = substringRanges[i].length) {
+                StringImpl::copyChars(buffer + bufferPos, sourceData + substringRanges[i].position, srcLen);
+                bufferPos += srcLen;
+            }
+        }
+
+        return jsString(exec, impl.release());
+    }
+
+    UChar* buffer;
+    const UChar* sourceData = source.characters16();
+
+    RefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
+    if (!impl)
+        return throwOutOfMemoryError(exec);
+
+    int bufferPos = 0;
+    for (int i = 0; i < rangeCount; i++) {
+        if (int srcLen = substringRanges[i].length) {
+            StringImpl::copyChars(buffer + bufferPos, sourceData + substringRanges[i].position, srcLen);
+            bufferPos += srcLen;
+        }
+    }
+
+    return jsString(exec, impl.release());
+}
+
 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) {
 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) {
@@ -261,16 +338,48 @@ static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, J
     }
 
     int totalLength = 0;
     }
 
     int totalLength = 0;
+    bool allSeperators8Bit = true;
     for (int i = 0; i < rangeCount; i++)
         totalLength += substringRanges[i].length;
     for (int i = 0; i < rangeCount; i++)
         totalLength += substringRanges[i].length;
-    for (int i = 0; i < separatorCount; i++)
+    for (int i = 0; i < separatorCount; i++) {
         totalLength += separators[i].length();
         totalLength += separators[i].length();
+        if (separators[i].length() && !separators[i].is8Bit())
+            allSeperators8Bit = false;
+    }
 
 
-    if (totalLength == 0)
+    if (!totalLength)
         return jsString(exec, "");
 
         return jsString(exec, "");
 
+    if (source.is8Bit() && allSeperators8Bit) {
+        LChar* buffer;
+        const LChar* sourceData = source.characters8();
+
+        RefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
+        if (!impl)
+            return throwOutOfMemoryError(exec);
+
+        int maxCount = max(rangeCount, separatorCount);
+        int bufferPos = 0;
+        for (int i = 0; i < maxCount; i++) {
+            if (i < rangeCount) {
+                if (int srcLen = substringRanges[i].length) {
+                    StringImpl::copyChars(buffer + bufferPos, sourceData + substringRanges[i].position, srcLen);
+                    bufferPos += srcLen;
+                }
+            }
+            if (i < separatorCount) {
+                if (int sepLen = separators[i].length()) {
+                    StringImpl::copyChars(buffer + bufferPos, separators[i].characters8(), sepLen);
+                    bufferPos += sepLen;
+                }
+            }
+        }        
+
+        return jsString(exec, impl.release());
+    }
+
     UChar* buffer;
     UChar* buffer;
-    PassRefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
+    RefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
     if (!impl)
         return throwOutOfMemoryError(exec);
 
     if (!impl)
         return throwOutOfMemoryError(exec);
 
@@ -291,181 +400,284 @@ static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, J
         }
     }
 
         }
     }
 
-    return jsString(exec, impl);
+    return jsString(exec, impl.release());
 }
 
 }
 
-EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec)
+static NEVER_INLINE EncodedJSValue removeUsingRegExpSearch(ExecState* exec, JSString* string, const UString& source, RegExp* regExp)
 {
 {
-    JSValue thisValue = exec->hostThisValue();
-    JSString* sourceVal = thisValue.toThisJSString(exec);
-    JSValue pattern = exec->argument(0);
-    JSValue replacement = exec->argument(1);
+    size_t lastIndex = 0;
+    unsigned startPosition = 0;
+
+    Vector<StringRange, 16> sourceRanges;
     JSGlobalData* globalData = &exec->globalData();
     JSGlobalData* globalData = &exec->globalData();
+    RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
+    unsigned sourceLen = source.length();
+
+    while (true) {
+        MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition);
+        if (!result)
+            break;
+
+        if (lastIndex < result.start)
+            sourceRanges.append(StringRange(lastIndex, result.start - lastIndex));
+
+        lastIndex = result.end;
+        startPosition = lastIndex;
 
 
+        // special case of empty match
+        if (result.empty()) {
+            startPosition++;
+            if (startPosition > sourceLen)
+                break;
+        }
+    }
+
+    if (!lastIndex)
+        return JSValue::encode(string);
+
+    if (static_cast<unsigned>(lastIndex) < sourceLen)
+        sourceRanges.append(StringRange(lastIndex, sourceLen - lastIndex));
+
+    return JSValue::encode(jsSpliceSubstrings(exec, string, source, sourceRanges.data(), sourceRanges.size()));
+}
+
+static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSString* string, JSValue searchValue)
+{
+    JSValue replaceValue = exec->argument(1);
     UString replacementString;
     CallData callData;
     UString replacementString;
     CallData callData;
-    CallType callType = getCallData(replacement, callData);
+    CallType callType = getCallData(replaceValue, callData);
     if (callType == CallTypeNone)
     if (callType == CallTypeNone)
-        replacementString = replacement.toString(exec);
-
-    if (pattern.inherits(&RegExpObject::s_info)) {
-        const UString& source = sourceVal->value(exec);
-        unsigned sourceLen = source.length();
+        replacementString = replaceValue.toString(exec)->value(exec);
+
+    const UString& source = string->value(exec);
+    unsigned sourceLen = source.length();
+    if (exec->hadException())
+        return JSValue::encode(JSValue());
+    RegExpObject* regExpObject = asRegExpObject(searchValue);
+    RegExp* regExp = regExpObject->regExp();
+    bool global = regExp->global();
+
+    if (global) {
+        // ES5.1 15.5.4.10 step 8.a.
+        regExpObject->setLastIndex(exec, 0);
         if (exec->hadException())
             return JSValue::encode(JSValue());
         if (exec->hadException())
             return JSValue::encode(JSValue());
-        RegExp* reg = asRegExpObject(pattern)->regExp();
-        bool global = reg->global();
 
 
-        RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
+        if (callType == CallTypeNone && !replacementString.length())
+            return removeUsingRegExpSearch(exec, string, source, regExp);
+    }
+
+    RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
 
 
-        int lastIndex = 0;
-        unsigned startPosition = 0;
+    size_t lastIndex = 0;
+    unsigned startPosition = 0;
 
 
-        Vector<StringRange, 16> sourceRanges;
-        Vector<UString, 16> replacements;
+    Vector<StringRange, 16> sourceRanges;
+    Vector<UString, 16> replacements;
 
 
-        // This is either a loop (if global is set) or a one-way (if not).
-        if (global && callType == CallTypeJS) {
-            // 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);
-            if (exec->hadException())
-                return JSValue::encode(jsNull());
+    // This is either a loop (if global is set) or a one-way (if not).
+    if (global && callType == CallTypeJS) {
+        // regExp->numSubpatterns() + 1 for pattern args, + 2 for match start and string
+        int argCount = regExp->numSubpatterns() + 1 + 2;
+        JSFunction* func = jsCast<JSFunction*>(replaceValue);
+        CachedCall cachedCall(exec, func, argCount);
+        if (exec->hadException())
+            return JSValue::encode(jsNull());
+        JSGlobalData* globalData = &exec->globalData();
+        if (source.is8Bit()) {
             while (true) {
             while (true) {
-                int matchIndex;
-                int matchLen = 0;
                 int* ovector;
                 int* ovector;
-                regExpConstructor->performMatch(*globalData, reg, source, startPosition, matchIndex, matchLen, &ovector);
-                if (matchIndex < 0)
+                MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition, &ovector);
+                if (!result)
                     break;
 
                     break;
 
-                sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
+                sourceRanges.append(StringRange(lastIndex, result.start - lastIndex));
 
 
-                int completeMatchStart = ovector[0];
                 unsigned i = 0;
                 unsigned i = 0;
-                for (; i < reg->numSubpatterns() + 1; ++i) {
+                for (; i < regExp->numSubpatterns() + 1; ++i) {
                     int matchStart = ovector[i * 2];
                     int matchLen = ovector[i * 2 + 1] - matchStart;
 
                     if (matchStart < 0)
                         cachedCall.setArgument(i, jsUndefined());
                     else
                     int matchStart = ovector[i * 2];
                     int matchLen = ovector[i * 2 + 1] - matchStart;
 
                     if (matchStart < 0)
                         cachedCall.setArgument(i, jsUndefined());
                     else
-                        cachedCall.setArgument(i, jsSubstring(exec, source, matchStart, matchLen));
+                        cachedCall.setArgument(i, jsSubstring8(globalData, source, matchStart, matchLen));
                 }
 
                 }
 
-                cachedCall.setArgument(i++, jsNumber(completeMatchStart));
-                cachedCall.setArgument(i++, sourceVal);
+                cachedCall.setArgument(i++, jsNumber(result.start));
+                cachedCall.setArgument(i++, string);
 
 
-                cachedCall.setThis(exec->globalThisValue());
-                JSValue result = cachedCall.call();
-                if (LIKELY(result.isString()))
-                    replacements.append(asString(result)->value(exec));
-                else
-                    replacements.append(result.toString(cachedCall.newCallFrame(exec)));
+                cachedCall.setThis(jsUndefined());
+                JSValue jsResult = cachedCall.call();
+                replacements.append(jsResult.toString(cachedCall.newCallFrame(exec))->value(exec));
                 if (exec->hadException())
                     break;
 
                 if (exec->hadException())
                     break;
 
-                lastIndex = matchIndex + matchLen;
+                lastIndex = result.end;
                 startPosition = lastIndex;
 
                 // special case of empty match
                 startPosition = lastIndex;
 
                 // special case of empty match
-                if (matchLen == 0) {
+                if (result.empty()) {
                     startPosition++;
                     if (startPosition > sourceLen)
                         break;
                 }
             }
         } else {
                     startPosition++;
                     if (startPosition > sourceLen)
                         break;
                 }
             }
         } else {
-            do {
-                int matchIndex;
-                int matchLen = 0;
+            while (true) {
                 int* ovector;
                 int* ovector;
-                regExpConstructor->performMatch(*globalData, reg, source, startPosition, matchIndex, matchLen, &ovector);
-                if (matchIndex < 0)
+                MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition, &ovector);
+                if (!result)
                     break;
 
                     break;
 
-                if (callType != CallTypeNone) {
-                    sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
+                sourceRanges.append(StringRange(lastIndex, result.start - lastIndex));
 
 
-                    int completeMatchStart = ovector[0];
-                    MarkedArgumentBuffer args;
+                unsigned i = 0;
+                for (; i < regExp->numSubpatterns() + 1; ++i) {
+                    int matchStart = ovector[i * 2];
+                    int matchLen = ovector[i * 2 + 1] - matchStart;
 
 
-                    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)
+                        cachedCall.setArgument(i, jsUndefined());
+                    else
+                        cachedCall.setArgument(i, jsSubstring(globalData, source, matchStart, matchLen));
+                }
 
 
-                    args.append(jsNumber(completeMatchStart));
-                    args.append(sourceVal);
+                cachedCall.setArgument(i++, jsNumber(result.start));
+                cachedCall.setArgument(i++, string);
 
 
-                    replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec));
-                    if (exec->hadException())
-                        break;
-                } 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());
-                    }
-                }
+                cachedCall.setThis(jsUndefined());
+                JSValue jsResult = cachedCall.call();
+                replacements.append(jsResult.toString(cachedCall.newCallFrame(exec))->value(exec));
+                if (exec->hadException())
+                    break;
 
 
-                lastIndex = matchIndex + matchLen;
+                lastIndex = result.end;
                 startPosition = lastIndex;
 
                 // special case of empty match
                 startPosition = lastIndex;
 
                 // special case of empty match
-                if (matchLen == 0) {
+                if (result.empty()) {
                     startPosition++;
                     if (startPosition > sourceLen)
                         break;
                 }
                     startPosition++;
                     if (startPosition > sourceLen)
                         break;
                 }
-            } while (global);
+            }
         }
         }
+    } else {
+        JSGlobalData* globalData = &exec->globalData();
+        do {
+            int* ovector;
+            MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition, &ovector);
+            if (!result)
+                break;
+
+            if (callType != CallTypeNone) {
+                sourceRanges.append(StringRange(lastIndex, result.start - lastIndex));
+
+                MarkedArgumentBuffer args;
+
+                for (unsigned i = 0; i < regExp->numSubpatterns() + 1; ++i) {
+                    int matchStart = ovector[i * 2];
+                    int matchLen = ovector[i * 2 + 1] - matchStart;
 
 
-        if (!lastIndex && replacements.isEmpty())
-            return JSValue::encode(sourceVal);
+                    if (matchStart < 0)
+                        args.append(jsUndefined());
+                    else
+                        args.append(jsSubstring(exec, source, matchStart, matchLen));
+                }
+
+                args.append(jsNumber(result.start));
+                args.append(string);
+
+                replacements.append(call(exec, replaceValue, callType, callData, jsUndefined(), args).toString(exec)->value(exec));
+                if (exec->hadException())
+                    break;
+            } else {
+                int replLen = replacementString.length();
+                if (lastIndex < result.start || replLen) {
+                    sourceRanges.append(StringRange(lastIndex, result.start - lastIndex));
+
+                    if (replLen)
+                        replacements.append(substituteBackreferences(replacementString, source, ovector, regExp));
+                    else
+                        replacements.append(UString());
+                }
+            }
 
 
-        if (static_cast<unsigned>(lastIndex) < sourceLen)
-            sourceRanges.append(StringRange(lastIndex, sourceLen - lastIndex));
+            lastIndex = result.end;
+            startPosition = lastIndex;
 
 
-        return JSValue::encode(jsSpliceSubstringsWithSeparators(exec, sourceVal, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size()));
+            // special case of empty match
+            if (result.empty()) {
+                startPosition++;
+                if (startPosition > sourceLen)
+                    break;
+            }
+        } while (global);
     }
 
     }
 
-    // Not a regular expression, so treat the pattern as a string.
+    if (!lastIndex && replacements.isEmpty())
+        return JSValue::encode(string);
 
 
-    UString patternString = pattern.toString(exec);
-    // 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));
+    if (static_cast<unsigned>(lastIndex) < sourceLen)
+        sourceRanges.append(StringRange(lastIndex, sourceLen - lastIndex));
 
 
-    const UString& source = sourceVal->value(exec);
-    size_t matchPos = source.find(patternString);
+    return JSValue::encode(jsSpliceSubstringsWithSeparators(exec, string, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size()));
+}
+
+static inline EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSString* jsString, JSValue searchValue)
+{
+    const UString& string = jsString->value(exec);
+    UString searchString = searchValue.toUString(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
 
-    if (matchPos == notFound)
-        return JSValue::encode(sourceVal);
+    size_t matchStart = string.find(searchString);
 
 
-    int matchLen = patternString.length();
+    if (matchStart == notFound)
+        return JSValue::encode(jsString);
+
+    JSValue replaceValue = exec->argument(1);
+    CallData callData;
+    CallType callType = getCallData(replaceValue, callData);
     if (callType != CallTypeNone) {
         MarkedArgumentBuffer args;
     if (callType != CallTypeNone) {
         MarkedArgumentBuffer args;
-        args.append(jsSubstring(exec, source, matchPos, matchLen));
-        args.append(jsNumber(matchPos));
-        args.append(sourceVal);
-
-        replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec);
+        args.append(jsSubstring(exec, string, matchStart, searchString.impl()->length()));
+        args.append(jsNumber(matchStart));
+        args.append(jsString);
+        replaceValue = call(exec, replaceValue, callType, callData, jsUndefined(), args);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
     }
     }
-    
-    size_t matchEnd = matchPos + matchLen;
-    int ovector[2] = { matchPos, matchEnd };
-    return JSValue::encode(jsString(exec, source.substringSharingImpl(0, matchPos), substituteBackreferences(replacementString, source, ovector, 0), source.substringSharingImpl(matchEnd)));
+
+    UString replaceString = replaceValue.toUString(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    StringImpl* stringImpl = string.impl();
+    UString leftPart(StringImpl::create(stringImpl, 0, matchStart));
+
+    size_t matchEnd = matchStart + searchString.impl()->length();
+    int ovector[2] = { matchStart,  matchEnd};
+    UString middlePart = substituteBackreferences(replaceString, string, ovector, 0);
+
+    size_t leftLength = stringImpl->length() - matchEnd;
+    UString rightPart(StringImpl::create(stringImpl, matchEnd, leftLength));
+    return JSValue::encode(JSC::jsString(exec, leftPart, middlePart, rightPart));
+}
+
+EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec)
+{
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    JSString* string = thisValue.toString(exec);
+    JSValue searchValue = exec->argument(0);
+
+    if (searchValue.inherits(&RegExpObject::s_info))
+        return replaceUsingRegExpSearch(exec, string, searchValue);
+    return replaceUsingStringSearch(exec, string, searchValue);
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec)
@@ -487,7 +699,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toThisString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     unsigned len = s.length();
     JSValue a0 = exec->argument(0);
     if (a0.isUInt32()) {
     unsigned len = s.length();
     JSValue a0 = exec->argument(0);
     if (a0.isUInt32()) {
@@ -507,13 +719,16 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toThisString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     unsigned len = s.length();
     JSValue a0 = exec->argument(0);
     if (a0.isUInt32()) {
         uint32_t i = a0.asUInt32();
     unsigned len = s.length();
     JSValue a0 = exec->argument(0);
     if (a0.isUInt32()) {
         uint32_t i = a0.asUInt32();
-        if (i < len)
-            return JSValue::encode(jsNumber(s.characters()[i]));
+        if (i < len) {
+            if (s.is8Bit())
+                return JSValue::encode(jsNumber(s.characters8()[i]));
+            return JSValue::encode(jsNumber(s.characters16()[i]));
+        }
         return JSValue::encode(jsNaN());
     }
     double dpos = a0.toInteger(exec);
         return JSValue::encode(jsNaN());
     }
     double dpos = a0.toInteger(exec);
@@ -525,15 +740,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec)
 EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    if (thisValue.isString() && (exec->argumentCount() == 1)) {
-        JSValue v = exec->argument(0);
-        return JSValue::encode(v.isString()
-            ? jsString(exec, asString(thisValue), asString(v))
-            : jsString(exec, asString(thisValue), v.toString(exec)));
-    }
+    if (thisValue.isString() && (exec->argumentCount() == 1))
+        return JSValue::encode(jsString(exec, asString(thisValue), exec->argument(0).toString(exec)));
+
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    return JSValue::encode(jsString(exec, thisValue));
+    return JSValue::encode(jsStringFromArguments(exec, thisValue));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec)
@@ -541,27 +753,31 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toThisString(exec);
-    int len = s.length();
+    UString s = thisValue.toString(exec)->value(exec);
 
     JSValue a0 = exec->argument(0);
     JSValue a1 = exec->argument(1);
 
     JSValue a0 = exec->argument(0);
     JSValue a1 = exec->argument(1);
-    UString u2 = a0.toString(exec);
-    int pos;
+    UString u2 = a0.toString(exec)->value(exec);
+
+    size_t result;
     if (a1.isUndefined())
     if (a1.isUndefined())
-        pos = 0;
-    else if (a1.isUInt32())
-        pos = min<uint32_t>(a1.asUInt32(), len);
+        result = s.find(u2);
     else {
     else {
-        double dpos = a1.toInteger(exec);
-        if (dpos < 0)
-            dpos = 0;
-        else if (dpos > len)
-            dpos = len;
-        pos = static_cast<int>(dpos);
+        unsigned pos;
+        int len = s.length();
+        if (a1.isUInt32())
+            pos = min<uint32_t>(a1.asUInt32(), len);
+        else {
+            double dpos = a1.toInteger(exec);
+            if (dpos < 0)
+                dpos = 0;
+            else if (dpos > len)
+                dpos = len;
+            pos = static_cast<unsigned>(dpos);
+        }
+        result = s.find(u2, pos);
     }
 
     }
 
-    size_t result = s.find(u2, pos);
     if (result == notFound)
         return JSValue::encode(jsNumber(-1));
     return JSValue::encode(jsNumber(result));
     if (result == notFound)
         return JSValue::encode(jsNumber(-1));
     return JSValue::encode(jsNumber(result));
@@ -572,23 +788,18 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toThisString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     int len = s.length();
 
     JSValue a0 = exec->argument(0);
     JSValue a1 = exec->argument(1);
 
     int len = s.length();
 
     JSValue a0 = exec->argument(0);
     JSValue a1 = exec->argument(1);
 
-    UString u2 = a0.toString(exec);
+    UString u2 = a0.toString(exec)->value(exec);
     double dpos = a1.toIntegerPreserveNaN(exec);
     if (dpos < 0)
         dpos = 0;
     else if (!(dpos <= len)) // true for NaN
         dpos = len;
     double dpos = a1.toIntegerPreserveNaN(exec);
     if (dpos < 0)
         dpos = 0;
     else if (!(dpos <= len)) // true for NaN
         dpos = len;
-#if OS(SYMBIAN)
-    // Work around for broken NaN compare operator
-    else if (isnan(dpos))
-        dpos = len;
-#endif
 
     size_t result = s.reverseFind(u2, static_cast<unsigned>(dpos));
     if (result == notFound)
 
     size_t result = s.reverseFind(u2, static_cast<unsigned>(dpos));
     if (result == notFound)
@@ -601,39 +812,49 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toThisString(exec);
+    JSString* string = thisValue.toString(exec);
+    UString s = string->value(exec);
     JSGlobalData* globalData = &exec->globalData();
 
     JSValue a0 = exec->argument(0);
 
     JSGlobalData* globalData = &exec->globalData();
 
     JSValue a0 = exec->argument(0);
 
-    RegExp* reg;
-    if (a0.inherits(&RegExpObject::s_info))
-        reg = asRegExpObject(a0)->regExp();
-    else {
+    RegExp* regExp;
+    bool global = false;
+    if (a0.inherits(&RegExpObject::s_info)) {
+        RegExpObject* regExpObject = asRegExpObject(a0);
+        regExp = regExpObject->regExp();
+        if ((global = regExp->global())) {
+            // ES5.1 15.5.4.10 step 8.a.
+            regExpObject->setLastIndex(exec, 0);
+            if (exec->hadException())
+                return JSValue::encode(JSValue());
+        }
+    } else {
         /*
          *  ECMA 15.5.4.12 String.prototype.search (regexp)
          *  If regexp is not an object whose [[Class]] property is "RegExp", it is
          *  replaced with the result of the expression new RegExp(regexp).
         /*
          *  ECMA 15.5.4.12 String.prototype.search (regexp)
          *  If regexp is not an object whose [[Class]] property is "RegExp", it is
          *  replaced with the result of the expression new RegExp(regexp).
+         *  Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string.
          */
          */
-        reg = RegExp::create(&exec->globalData(), a0.toString(exec), NoFlags);
+        regExp = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec)->value(exec), NoFlags);
+        if (!regExp->isValid())
+            return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
     }
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
     }
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
-    int pos;
-    int matchLength = 0;
-    regExpConstructor->performMatch(*globalData, reg, s, 0, pos, matchLength);
-    if (!(reg->global())) {
-        // case without 'g' flag is handled like RegExp.prototype.exec
-        if (pos < 0)
-            return JSValue::encode(jsNull());
-        return JSValue::encode(regExpConstructor->arrayOfMatches(exec));
-    }
+    MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, s, 0);
+    // case without 'g' flag is handled like RegExp.prototype.exec
+    if (!global)
+        return JSValue::encode(result ? RegExpMatchesArray::create(exec, string, regExp, result) : jsNull());
 
     // return array of matches
     MarkedArgumentBuffer list;
 
     // return array of matches
     MarkedArgumentBuffer list;
-    while (pos >= 0) {
-        list.append(jsSubstring(exec, s, pos, matchLength));
-        pos += matchLength == 0 ? 1 : matchLength;
-        regExpConstructor->performMatch(*globalData, reg, s, pos, pos, matchLength);
+    while (result) {
+        size_t end = result.end;
+        size_t length = end - result.start;
+        list.append(jsSubstring(exec, s, result.start, length));
+        if (!length)
+            ++end;
+        result = regExpConstructor->performMatch(*globalData, regExp, string, s, end);
     }
     if (list.isEmpty()) {
         // if there are no matches at all, it's important to return
     }
     if (list.isEmpty()) {
         // if there are no matches at all, it's important to return
@@ -650,7 +871,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toThisString(exec);
+    JSString* string = thisValue.toString(exec);
+    UString s = string->value(exec);
     JSGlobalData* globalData = &exec->globalData();
 
     JSValue a0 = exec->argument(0);
     JSGlobalData* globalData = &exec->globalData();
 
     JSValue a0 = exec->argument(0);
@@ -663,14 +885,15 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
          *  ECMA 15.5.4.12 String.prototype.search (regexp)
          *  If regexp is not an object whose [[Class]] property is "RegExp", it is
          *  replaced with the result of the expression new RegExp(regexp).
          *  ECMA 15.5.4.12 String.prototype.search (regexp)
          *  If regexp is not an object whose [[Class]] property is "RegExp", it is
          *  replaced with the result of the expression new RegExp(regexp).
+         *  Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string.
          */
          */
-        reg = RegExp::create(&exec->globalData(), a0.toString(exec), NoFlags);
+        reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec)->value(exec), NoFlags);
+        if (!reg->isValid())
+            return throwVMError(exec, createSyntaxError(exec, reg->errorMessage()));
     }
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
     }
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
-    int pos;
-    int matchLength = 0;
-    regExpConstructor->performMatch(*globalData, reg, s, 0, pos, matchLength);
-    return JSValue::encode(jsNumber(pos));
+    MatchResult result = regExpConstructor->performMatch(*globalData, reg, string, s, 0);
+    return JSValue::encode(result ? jsNumber(result.start) : jsNumber(-1));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec)
@@ -678,7 +901,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    UString s = thisValue.toThisString(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     int len = s.length();
 
     JSValue a0 = exec->argument(0);
     int len = s.length();
 
     JSValue a0 = exec->argument(0);
@@ -700,85 +923,261 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec)
     return JSValue::encode(jsEmptyString(exec));
 }
 
     return JSValue::encode(jsEmptyString(exec));
 }
 
+// Return true in case of early return (resultLength got to limitLength).
+template<typename CharacterType>
+static ALWAYS_INLINE bool splitStringByOneCharacterImpl(ExecState* exec, JSArray* result, const UString& input, StringImpl* string, UChar separatorCharacter, size_t& position, unsigned& resultLength, unsigned limitLength)
+{
+    // 12. Let q = p.
+    size_t matchPosition;
+    const CharacterType* characters = string->getCharacters<CharacterType>();
+    // 13. Repeat, while q != s
+    //   a. Call SplitMatch(S, q, R) and let z be its MatchResult result.
+    //   b. If z is failure, then let q = q+1.
+    //   c. Else, z is not failure
+    while ((matchPosition = WTF::find(characters, string->length(), separatorCharacter, position)) != notFound) {
+        // 1. Let T be a String value equal to the substring of S consisting of the characters at positions p (inclusive)
+        //    through q (exclusive).
+        // 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA),
+        //    Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+        result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false);
+        // 3. Increment lengthA by 1.
+        // 4. If lengthA == lim, return A.
+        if (++resultLength == limitLength)
+            return true;
+
+        // 5. Let p = e.
+        // 8. Let q = p.
+        position = matchPosition + 1;
+    }
+    return false;
+}
+
+// ES 5.1 - 15.5.4.14 String.prototype.split (separator, limit)
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
 {
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
 {
+    // 1. Call CheckObjectCoercible passing the this value as its argument.
     JSValue thisValue = exec->hostThisValue();
     JSValue thisValue = exec->hostThisValue();
-    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+    if (thisValue.isUndefinedOrNull())
         return throwVMTypeError(exec);
         return throwVMTypeError(exec);
-    UString s = thisValue.toThisString(exec);
-    JSGlobalData* globalData = &exec->globalData();
 
 
-    JSValue a0 = exec->argument(0);
-    JSValue a1 = exec->argument(1);
+    // 2. Let S be the result of calling ToString, giving it the this value as its argument.
+    // 6. Let s be the number of characters in S.
+    UString input = thisValue.toString(exec)->value(exec);
 
 
+    // 3. Let A be a new array created as if by the expression new Array()
+    //    where Array is the standard built-in constructor with that name.
     JSArray* result = constructEmptyArray(exec);
     JSArray* result = constructEmptyArray(exec);
-    unsigned i = 0;
-    unsigned p0 = 0;
-    unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec);
-    if (a0.inherits(&RegExpObject::s_info)) {
-        RegExp* reg = asRegExpObject(a0)->regExp();
-        if (s.isEmpty() && reg->match(*globalData, s, 0) >= 0) {
-            // empty string matched by regexp -> empty array
+
+    // 4. Let lengthA be 0.
+    unsigned resultLength = 0;
+
+    // 5. If limit is undefined, let lim = 2^32-1; else let lim = ToUint32(limit).
+    JSValue limitValue = exec->argument(1);
+    unsigned limit = limitValue.isUndefined() ? 0xFFFFFFFFu : limitValue.toUInt32(exec);
+
+    // 7. Let p = 0.
+    size_t position = 0;
+
+    // 8. If separator is a RegExp object (its [[Class]] is "RegExp"), let R = separator;
+    //    otherwise let R = ToString(separator).
+    JSValue separatorValue = exec->argument(0);
+    if (separatorValue.inherits(&RegExpObject::s_info)) {
+        JSGlobalData* globalData = &exec->globalData();
+        RegExp* reg = asRegExpObject(separatorValue)->regExp();
+
+        // 9. If lim == 0, return A.
+        if (!limit)
+            return JSValue::encode(result);
+
+        // 10. If separator is undefined, then
+        if (separatorValue.isUndefined()) {
+            // a. Call the [[DefineOwnProperty]] internal method of A with arguments "0",
+            //    Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+            result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
+            // b. Return A.
             return JSValue::encode(result);
         }
             return JSValue::encode(result);
         }
-        unsigned pos = 0;
-        while (i != limit && pos < s.length()) {
+
+        // 11. If s == 0, then
+        if (input.isEmpty()) {
+            // a. Call SplitMatch(S, 0, R) and let z be its MatchResult result.
+            // b. If z is not failure, return A.
+            // c. Call the [[DefineOwnProperty]] internal method of A with arguments "0",
+            //    Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+            // d. Return A.
+            if (!reg->match(*globalData, input, 0))
+                result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
+            return JSValue::encode(result);
+        }
+
+        // 12. Let q = p.
+        size_t matchPosition = 0;
+        // 13. Repeat, while q != s
+        while (matchPosition < input.length()) {
+            // a. Call SplitMatch(S, q, R) and let z be its MatchResult result.
             Vector<int, 32> ovector;
             Vector<int, 32> ovector;
-            int mpos = reg->match(*globalData, s, pos, &ovector);
+            int mpos = reg->match(*globalData, input, matchPosition, ovector);
+            // b. If z is failure, then let q = q + 1.
             if (mpos < 0)
                 break;
             if (mpos < 0)
                 break;
-            int mlen = ovector[1] - ovector[0];
-            pos = mpos + (mlen == 0 ? 1 : mlen);
-            if (static_cast<unsigned>(mpos) != p0 || mlen) {
-                result->put(exec, i++, jsSubstring(exec, s, p0, mpos - p0));
-                p0 = mpos + mlen;
+            matchPosition = mpos;
+
+            // c. Else, z is not failure
+            // i. z must be a State. Let e be z's endIndex and let cap be z's captures array.
+            size_t matchEnd = ovector[1];
+
+            // ii. If e == p, then let q = q + 1.
+            if (matchEnd == position) {
+                ++matchPosition;
+                continue;
             }
             }
-            for (unsigned si = 1; si <= reg->numSubpatterns(); ++si) {
-                int spos = ovector[si * 2];
-                if (spos < 0)
-                    result->put(exec, i++, jsUndefined());
-                else
-                    result->put(exec, i++, jsSubstring(exec, s, spos, ovector[si * 2 + 1] - spos));
+            // iii. Else, e != p
+
+            // 1. Let T be a String value equal to the substring of S consisting of the characters at positions p (inclusive)
+            //    through q (exclusive).
+            // 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA),
+            //    Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+            result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false);
+            // 3. Increment lengthA by 1.
+            // 4. If lengthA == lim, return A.
+            if (++resultLength == limit)
+                return JSValue::encode(result);
+
+            // 5. Let p = e.
+            // 8. Let q = p.
+            position = matchEnd;
+            matchPosition = matchEnd;
+
+            // 6. Let i = 0.
+            // 7. Repeat, while i is not equal to the number of elements in cap.
+            //  a Let i = i + 1.
+            for (unsigned i = 1; i <= reg->numSubpatterns(); ++i) {
+                // b Call the [[DefineOwnProperty]] internal method of A with arguments
+                //   ToString(lengthA), Property Descriptor {[[Value]]: cap[i], [[Writable]]:
+                //   true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+                int sub = ovector[i * 2];
+                result->putDirectIndex(exec, resultLength, sub < 0 ? jsUndefined() : jsSubstring(exec, input, sub, ovector[i * 2 + 1] - sub), false);
+                // c Increment lengthA by 1.
+                // d If lengthA == lim, return A.
+                if (++resultLength == limit)
+                    return JSValue::encode(result);
             }
         }
     } else {
             }
         }
     } else {
-        UString u2 = a0.toString(exec);
-        if (u2.isEmpty()) {
-            if (s.isEmpty()) {
-                // empty separator matches empty string -> empty array
-                return JSValue::encode(result);
+        UString separator = separatorValue.toString(exec)->value(exec);
+
+        // 9. If lim == 0, return A.
+        if (!limit)
+            return JSValue::encode(result);
+
+        // 10. If separator is undefined, then
+        JSValue separatorValue = exec->argument(0);
+        if (separatorValue.isUndefined()) {
+            // a.  Call the [[DefineOwnProperty]] internal method of A with arguments "0",
+            //     Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+            result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
+            // b.  Return A.
+            return JSValue::encode(result);
+        }
+
+        // 11. If s == 0, then
+        if (input.isEmpty()) {
+            // a. Call SplitMatch(S, 0, R) and let z be its MatchResult result.
+            // b. If z is not failure, return A.
+            // c. Call the [[DefineOwnProperty]] internal method of A with arguments "0",
+            //    Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+            // d. Return A.
+            if (!separator.isEmpty())
+                result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
+            return JSValue::encode(result);
+        }
+
+        // Optimized case for splitting on the empty string.
+        if (separator.isEmpty()) {
+            limit = std::min(limit, input.length());
+            // Zero limt/input length handled in steps 9/11 respectively, above.
+            ASSERT(limit);
+
+            do {
+                result->putDirectIndex(exec, position, jsSingleCharacterSubstring(exec, input, position), false);
+            } while (++position < limit);
+
+            return JSValue::encode(result);
+        }
+
+        // 3 cases:
+        // -separator length == 1, 8 bits
+        // -separator length == 1, 16 bits
+        // -separator length > 1
+        StringImpl* stringImpl = input.impl();
+        StringImpl* separatorImpl = separator.impl();
+        size_t separatorLength = separatorImpl->length();
+
+        if (separatorLength == 1) {
+            UChar separatorCharacter;
+            if (separatorImpl->is8Bit())
+                separatorCharacter = separatorImpl->characters8()[0];
+            else
+                separatorCharacter = separatorImpl->characters16()[0];
+
+            if (stringImpl->is8Bit()) {
+                if (splitStringByOneCharacterImpl<LChar>(exec, result, input, stringImpl, separatorCharacter, position, resultLength, limit))
+                    return JSValue::encode(result);
+            } else {
+                if (splitStringByOneCharacterImpl<UChar>(exec, result, input, stringImpl, separatorCharacter, position, resultLength, limit))
+                    return JSValue::encode(result);
             }
             }
-            while (i != limit && p0 < s.length() - 1)
-                result->put(exec, i++, jsSingleCharacterSubstring(exec, s, p0++));
         } else {
         } else {
-            size_t pos;
-            while (i != limit && (pos = s.find(u2, p0)) != notFound) {
-                result->put(exec, i++, jsSubstring(exec, s, p0, pos - p0));
-                p0 = pos + u2.length();
+            // 12. Let q = p.
+            size_t matchPosition;
+            // 13. Repeat, while q != s
+            //   a. Call SplitMatch(S, q, R) and let z be its MatchResult result.
+            //   b. If z is failure, then let q = q+1.
+            //   c. Else, z is not failure
+            while ((matchPosition = stringImpl->find(separatorImpl, position)) != notFound) {
+                // 1. Let T be a String value equal to the substring of S consisting of the characters at positions p (inclusive)
+                //    through q (exclusive).
+                // 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA),
+                //    Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+                result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false);
+                // 3. Increment lengthA by 1.
+                // 4. If lengthA == lim, return A.
+                if (++resultLength == limit)
+                    return JSValue::encode(result);
+
+                // 5. Let p = e.
+                // 8. Let q = p.
+                position = matchPosition + separator.length();
             }
         }
     }
 
             }
         }
     }
 
-    // add remaining string
-    if (i != limit)
-        result->put(exec, i++, jsSubstring(exec, s, p0, s.length() - p0));
+    // 14. Let T be a String value equal to the substring of S consisting of the characters at positions p (inclusive)
+    //     through s (exclusive).
+    // 15. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA), Property Descriptor
+    //     {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+    result->putDirectIndex(exec, resultLength++, jsSubstring(exec, input, position, input.length() - position), false);
 
 
+    // 16. Return A.
     return JSValue::encode(result);
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     return JSValue::encode(result);
 }
 
 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()) {
     unsigned len;
     JSString* jsString = 0;
     UString uString;
     if (thisValue.isString()) {
-        jsString = static_cast<JSString*>(thisValue.asCell());
+        jsString = jsCast<JSString*>(thisValue.asCell());
         len = jsString->length();
         len = jsString->length();
+    } else if (thisValue.isUndefinedOrNull()) {
+        // CheckObjectCoercible
+        return throwVMTypeError(exec);
     } else {
     } else {
-        uString = thisValue.toThisObject(exec)->toString(exec);
+        uString = thisValue.toString(exec)->value(exec);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
         len = uString.length();
     }
 
         len = uString.length();
     }
 
@@ -808,19 +1207,14 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    int len;
-    JSString* jsString = 0;
-    UString uString;
-    if (thisValue.isString()) {
-        jsString = static_cast<JSString*>(thisValue.asCell());
-        len = jsString->length();
-    } else {
-        uString = thisValue.toThisObject(exec)->toString(exec);
-        len = uString.length();
-    }
+
+    JSString* jsString = thisValue.toString(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
     JSValue a0 = exec->argument(0);
     JSValue a1 = exec->argument(1);
 
     JSValue a0 = exec->argument(0);
     JSValue a1 = exec->argument(1);
+    int len = jsString->length();
 
     double start = a0.toNumber(exec);
     double end;
 
     double start = a0.toNumber(exec);
     double end;
@@ -844,9 +1238,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec)
     }
     unsigned substringStart = static_cast<unsigned>(start);
     unsigned substringLength = static_cast<unsigned>(end) - substringStart;
     }
     unsigned substringStart = static_cast<unsigned>(start);
     unsigned substringLength = static_cast<unsigned>(end) - substringStart;
-    if (jsString)
-        return JSValue::encode(jsSubstring(exec, jsString, substringStart, substringLength));
-    return JSValue::encode(jsSubstring(exec, uString, substringStart, substringLength));
+    return JSValue::encode(jsSubstring(exec, jsString, substringStart, substringLength));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec)
@@ -854,39 +1246,18 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    JSString* sVal = thisValue.toThisJSString(exec);
+    JSString* sVal = thisValue.toString(exec);
     const UString& s = sVal->value(exec);
 
     int sSize = s.length();
     if (!sSize)
         return JSValue::encode(sVal);
 
     const UString& s = sVal->value(exec);
 
     int sSize = s.length();
     if (!sSize)
         return JSValue::encode(sVal);
 
-    const UChar* sData = s.characters();
-    Vector<UChar> buffer(sSize);
-
-    UChar ored = 0;
-    for (int i = 0; i < sSize; i++) {
-        UChar c = sData[i];
-        ored |= c;
-        buffer[i] = toASCIILower(c);
-    }
-    if (!(ored & ~0x7f))
-        return JSValue::encode(jsString(exec, UString::adopt(buffer)));
-
-    bool error;
-    int length = Unicode::toLower(buffer.data(), sSize, sData, sSize, &error);
-    if (error) {
-        buffer.resize(length);
-        length = Unicode::toLower(buffer.data(), length, sData, sSize, &error);
-        if (error)
-            return JSValue::encode(sVal);
-    }
-    if (length == sSize) {
-        if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
-            return JSValue::encode(sVal);
-    } else
-        buffer.resize(length);
-    return JSValue::encode(jsString(exec, UString::adopt(buffer)));
+    StringImpl* ourImpl = s.impl();
+    RefPtr<StringImpl> lower = ourImpl->lower();
+    if (ourImpl == lower)
+        return JSValue::encode(sVal);
+    return JSValue::encode(jsString(exec, UString(lower.release())));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec)
@@ -894,39 +1265,18 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
-    JSString* sVal = thisValue.toThisJSString(exec);
+    JSString* sVal = thisValue.toString(exec);
     const UString& s = sVal->value(exec);
 
     int sSize = s.length();
     if (!sSize)
         return JSValue::encode(sVal);
 
     const UString& s = sVal->value(exec);
 
     int sSize = s.length();
     if (!sSize)
         return JSValue::encode(sVal);
 
-    const UChar* sData = s.characters();
-    Vector<UChar> buffer(sSize);
-
-    UChar ored = 0;
-    for (int i = 0; i < sSize; i++) {
-        UChar c = sData[i];
-        ored |= c;
-        buffer[i] = toASCIIUpper(c);
-    }
-    if (!(ored & ~0x7f))
-        return JSValue::encode(jsString(exec, UString::adopt(buffer)));
-
-    bool error;
-    int length = Unicode::toUpper(buffer.data(), sSize, sData, sSize, &error);
-    if (error) {
-        buffer.resize(length);
-        length = Unicode::toUpper(buffer.data(), length, sData, sSize, &error);
-        if (error)
-            return JSValue::encode(sVal);
-    }
-    if (length == sSize) {
-        if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
-            return JSValue::encode(sVal);
-    } else
-        buffer.resize(length);
-    return JSValue::encode(jsString(exec, UString::adopt(buffer)));
+    StringImpl* sImpl = s.impl();
+    RefPtr<StringImpl> upper = sImpl->upper();
+    if (sImpl == upper)
+        return JSValue::encode(sVal);
+    return JSValue::encode(jsString(exec, UString(upper.release())));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec)
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec)
@@ -937,87 +1287,109 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
 
 
-    UString s = thisValue.toThisString(exec);
     JSValue a0 = exec->argument(0);
     JSValue a0 = exec->argument(0);
-    return JSValue::encode(jsNumber(localeCompare(s, a0.toString(exec))));
+    return JSValue::encode(jsNumber(localeCompare(s, a0.toString(exec)->value(exec))));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<big>", s, "</big>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     return JSValue::encode(jsMakeNontrivialString(exec, "<big>", s, "</big>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<small>", s, "</small>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     return JSValue::encode(jsMakeNontrivialString(exec, "<small>", s, "</small>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<blink>", s, "</blink>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     return JSValue::encode(jsMakeNontrivialString(exec, "<blink>", s, "</blink>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<b>", s, "</b>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     return JSValue::encode(jsMakeNontrivialString(exec, "<b>", s, "</b>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<tt>", s, "</tt>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     return JSValue::encode(jsMakeNontrivialString(exec, "<tt>", s, "</tt>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<i>", s, "</i>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     return JSValue::encode(jsMakeNontrivialString(exec, "<i>", s, "</i>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<strike>", s, "</strike>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     return JSValue::encode(jsMakeNontrivialString(exec, "<strike>", s, "</strike>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<sub>", s, "</sub>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     return JSValue::encode(jsMakeNontrivialString(exec, "<sub>", s, "</sub>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     return JSValue::encode(jsMakeNontrivialString(exec, "<sup>", s, "</sup>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
     return JSValue::encode(jsMakeNontrivialString(exec, "<sup>", s, "</sup>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     JSValue a0 = exec->argument(0);
     JSValue a0 = exec->argument(0);
-    return JSValue::encode(jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec), "\">", s, "</font>"));
+    return JSValue::encode(jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec)->value(exec), "\">", s, "</font>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     JSValue a0 = exec->argument(0);
 
     uint32_t smallInteger;
     JSValue a0 = exec->argument(0);
 
     uint32_t smallInteger;
@@ -1054,23 +1426,27 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec)
         return JSValue::encode(jsNontrivialString(exec, impl));
     }
 
         return JSValue::encode(jsNontrivialString(exec, impl));
     }
 
-    return JSValue::encode(jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec), "\">", s, "</font>"));
+    return JSValue::encode(jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec)->value(exec), "\">", s, "</font>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     JSValue a0 = exec->argument(0);
     JSValue a0 = exec->argument(0);
-    return JSValue::encode(jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec), "\">", s, "</a>"));
+    return JSValue::encode(jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec)->value(exec), "\">", s, "</a>"));
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
 }
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec)
 {
     JSValue thisValue = exec->hostThisValue();
-    UString s = thisValue.toThisString(exec);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    UString s = thisValue.toString(exec)->value(exec);
     JSValue a0 = exec->argument(0);
     JSValue a0 = exec->argument(0);
-    UString linkText = a0.toString(exec);
+    UString linkText = a0.toString(exec)->value(exec);
 
     unsigned linkTextSize = linkText.length();
     unsigned stringSize = s.length();
 
     unsigned linkTextSize = linkText.length();
     unsigned stringSize = s.length();
@@ -1113,7 +1489,7 @@ static inline JSValue trimString(ExecState* exec, JSValue thisValue, int trimKin
 {
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwTypeError(exec);
 {
     if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
         return throwTypeError(exec);
-    UString str = thisValue.toThisString(exec);
+    UString str = thisValue.toString(exec)->value(exec);
     unsigned left = 0;
     if (trimKind & TrimLeft) {
         while (left < str.length() && isTrimWhitespace(str[left]))
     unsigned left = 0;
     if (trimKind & TrimLeft) {
         while (left < str.length() && isTrimWhitespace(str[left]))
index 6c4b4756413ac270f9f7ea3248013a87e8e1f2a0..113f21f2addefccd73fc93bbe0a30e1d05cec817 100644 (file)
@@ -28,24 +28,34 @@ namespace JSC {
     class ObjectPrototype;
 
     class StringPrototype : public StringObject {
     class ObjectPrototype;
 
     class StringPrototype : public StringObject {
+    private:
+        StringPrototype(ExecState*, Structure*);
+
     public:
     public:
-        StringPrototype(ExecState*, JSGlobalObject*, Structure*);
+        typedef StringObject Base;
+
+        static StringPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+        {
+            JSString* empty = jsEmptyString(exec);
+            StringPrototype* prototype = new (NotNull, allocateCell<StringPrototype>(*exec->heap())) StringPrototype(exec, structure);
+            prototype->finishCreation(exec, globalObject, empty);
+            return prototype;
+        }
 
 
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
-        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
         {
-            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
         }
 
         static const ClassInfo s_info;
         
     protected:
         }
 
         static const ClassInfo s_info;
         
     protected:
+        void finishCreation(ExecState*, JSGlobalObject*, JSString*);
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | StringObject::StructureFlags;
 
         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
index 4e747351b0be3698cfc2c7ddb96398078c248cf7..22b7367bccc8b61040fa941265c29c392da5133b 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-EncodedJSValue StringRecursionChecker::throwStackOverflowError()
+JSValue StringRecursionChecker::throwStackOverflowError()
 {
 {
-    return throwVMError(m_exec, createStackOverflowError(m_exec));
+    return throwError(m_exec, createStackOverflowError(m_exec));
 }
 
 }
 
-EncodedJSValue StringRecursionChecker::emptyString()
+JSValue StringRecursionChecker::emptyString()
 {
 {
-    return JSValue::encode(jsEmptyString(m_exec));
+    return jsEmptyString(m_exec);
 }
 
 }
 }
 
 }
index 314f14eeb833b77266405580e25ab196ae6f4b2e..127d028e0f542f29b9a80caa8b711f266b49a582 100644 (file)
@@ -31,27 +31,27 @@ public:
     StringRecursionChecker(ExecState*, JSObject* thisObject);
     ~StringRecursionChecker();
 
     StringRecursionChecker(ExecState*, JSObject* thisObject);
     ~StringRecursionChecker();
 
-    EncodedJSValue earlyReturnValue() const; // 0 if everything is OK, value to return for failure cases
+    JSValue earlyReturnValue() const; // 0 if everything is OK, value to return for failure cases
 
 private:
 
 private:
-    EncodedJSValue throwStackOverflowError();
-    EncodedJSValue emptyString();
-    EncodedJSValue performCheck();
+    JSValue throwStackOverflowError();
+    JSValue emptyString();
+    JSValue performCheck();
 
     ExecState* m_exec;
     JSObject* m_thisObject;
 
     ExecState* m_exec;
     JSObject* m_thisObject;
-    EncodedJSValue m_earlyReturnValue;
+    JSValue m_earlyReturnValue;
 };
 
 };
 
-inline EncodedJSValue StringRecursionChecker::performCheck()
+inline JSValue StringRecursionChecker::performCheck()
 {
     int size = m_exec->globalData().stringRecursionCheckVisitedObjects.size();
     if (size >= MaxSmallThreadReentryDepth && size >= m_exec->globalData().maxReentryDepth)
         return throwStackOverflowError();
 {
     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;
+    bool alreadyVisited = !m_exec->globalData().stringRecursionCheckVisitedObjects.add(m_thisObject).isNewEntry;
     if (alreadyVisited)
         return emptyString(); // Return empty string to avoid infinite recursion.
     if (alreadyVisited)
         return emptyString(); // Return empty string to avoid infinite recursion.
-    return 0; // Indicate success.
+    return JSValue(); // Indicate success.
 }
 
 inline StringRecursionChecker::StringRecursionChecker(ExecState* exec, JSObject* thisObject)
 }
 
 inline StringRecursionChecker::StringRecursionChecker(ExecState* exec, JSObject* thisObject)
@@ -61,7 +61,7 @@ inline StringRecursionChecker::StringRecursionChecker(ExecState* exec, JSObject*
 {
 }
 
 {
 }
 
-inline EncodedJSValue StringRecursionChecker::earlyReturnValue() const
+inline JSValue StringRecursionChecker::earlyReturnValue() const
 {
     return m_earlyReturnValue;
 }
 {
     return m_earlyReturnValue;
 }
index a3fda547fddb7f850929b2a1229fe6071b3637d0..074c8b3544f7bc0f92d210eb31e0676918eea2ff 100644 (file)
 #include "StructureChain.h"
 #include <wtf/RefCountedLeakCounter.h>
 #include <wtf/RefPtr.h>
 #include "StructureChain.h"
 #include <wtf/RefCountedLeakCounter.h>
 #include <wtf/RefPtr.h>
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
 #include <wtf/Threading.h>
 #include <wtf/Threading.h>
-#endif
 
 #define DUMP_STRUCTURE_ID_STATISTICS 0
 
 
 #define DUMP_STRUCTURE_ID_STATISTICS 0
 
@@ -83,29 +80,6 @@ inline Structure* StructureTransitionTable::get(StringImpl* rep, unsigned attrib
     return map()->get(make_pair(rep, attributes));
 }
 
     return map()->get(make_pair(rep, attributes));
 }
 
-inline void StructureTransitionTable::remove(Structure* structure)
-{
-    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);
-    }
-}
-
 inline void StructureTransitionTable::add(JSGlobalData& globalData, Structure* structure)
 {
     if (isUsingSingleSlot()) {
 inline void StructureTransitionTable::add(JSGlobalData& globalData, Structure* structure)
 {
     if (isUsingSingleSlot()) {
@@ -128,12 +102,12 @@ inline void StructureTransitionTable::add(JSGlobalData& globalData, Structure* s
     // 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
     // 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) {
+    TransitionMap::AddResult result = map()->add(globalData, make_pair(structure->m_nameInPrevious, +structure->m_attributesInPrevious), structure);
+    if (!result.isNewEntry) {
         // There already is an entry! - we should only hit this when despecifying.
         // There already is an entry! - we should only hit this when despecifying.
-        ASSERT(result.first.get().second->m_specificValueInPrevious);
+        ASSERT(result.iterator.get().second->m_specificValueInPrevious);
         ASSERT(!structure->m_specificValueInPrevious);
         ASSERT(!structure->m_specificValueInPrevious);
-        map()->set(result.first, structure);
+        map()->set(globalData, result.iterator.get().first, structure);
     }
 }
 
     }
 }
 
@@ -168,45 +142,45 @@ void Structure::dumpStatistics()
         }
     }
 
         }
     }
 
-    printf("Number of live Structures: %d\n", liveStructureSet.size());
-    printf("Number of Structures using the single item optimization for transition map: %d\n", numberUsingSingleSlot);
-    printf("Number of Structures that are leaf nodes: %d\n", numberLeaf);
-    printf("Number of Structures that singletons: %d\n", numberSingletons);
-    printf("Number of Structures with PropertyMaps: %d\n", numberWithPropertyMaps);
+    dataLog("Number of live Structures: %d\n", liveStructureSet.size());
+    dataLog("Number of Structures using the single item optimization for transition map: %d\n", numberUsingSingleSlot);
+    dataLog("Number of Structures that are leaf nodes: %d\n", numberLeaf);
+    dataLog("Number of Structures that singletons: %d\n", numberSingletons);
+    dataLog("Number of Structures with PropertyMaps: %d\n", numberWithPropertyMaps);
 
 
-    printf("Size of a single Structures: %d\n", static_cast<unsigned>(sizeof(Structure)));
-    printf("Size of sum of all property maps: %d\n", totalPropertyMapsSize);
-    printf("Size of average of all property maps: %f\n", static_cast<double>(totalPropertyMapsSize) / static_cast<double>(liveStructureSet.size()));
+    dataLog("Size of a single Structures: %d\n", static_cast<unsigned>(sizeof(Structure)));
+    dataLog("Size of sum of all property maps: %d\n", totalPropertyMapsSize);
+    dataLog("Size of average of all property maps: %f\n", static_cast<double>(totalPropertyMapsSize) / static_cast<double>(liveStructureSet.size()));
 #else
 #else
-    printf("Dumping Structure statistics is not enabled.\n");
+    dataLog("Dumping Structure statistics is not enabled.\n");
 #endif
 }
 
 #endif
 }
 
-Structure::Structure(JSGlobalData& globalData, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo)
+Structure::Structure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo)
     : JSCell(globalData, globalData.structureStructure.get())
     , m_typeInfo(typeInfo)
     : JSCell(globalData, globalData.structureStructure.get())
     , m_typeInfo(typeInfo)
+    , m_globalObject(globalData, this, globalObject, WriteBarrier<JSGlobalObject>::MayBeNull)
     , m_prototype(globalData, this, prototype)
     , m_classInfo(classInfo)
     , m_prototype(globalData, this, prototype)
     , m_classInfo(classInfo)
-    , m_propertyStorageCapacity(typeInfo.isFinal() ? JSFinalObject_inlineStorageCapacity : JSNonFinalObject_inlineStorageCapacity)
+    , m_propertyStorageCapacity(typeInfo.isFinalObject() ? 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_hasReadOnlyOrGetterSetterPropertiesExcludingProto(false)
     , m_hasNonEnumerableProperties(false)
     , m_attributesInPrevious(0)
     , m_specificFunctionThrashCount(0)
     , m_hasNonEnumerableProperties(false)
     , m_attributesInPrevious(0)
     , m_specificFunctionThrashCount(0)
-    , m_anonymousSlotCount(anonymousSlotCount)
     , m_preventExtensions(false)
     , m_didTransition(false)
     , m_preventExtensions(false)
     , m_didTransition(false)
+    , m_staticFunctionReified(false)
 {
 {
-    ASSERT(m_prototype);
-    ASSERT(m_prototype.isObject() || m_prototype.isNull());
 }
 
 }
 
-const ClassInfo Structure::s_info = { "Structure", 0, 0, 0 };
+const ClassInfo Structure::s_info = { "Structure", 0, 0, 0, CREATE_METHOD_TABLE(Structure) };
 
 Structure::Structure(JSGlobalData& globalData)
 
 Structure::Structure(JSGlobalData& globalData)
-    : JSCell(globalData, this, CreatingEarlyCell)
+    : JSCell(CreatingEarlyCell)
     , m_typeInfo(CompoundType, OverridesVisitChildren)
     , m_prototype(globalData, this, jsNull())
     , m_classInfo(&s_info)
     , m_typeInfo(CompoundType, OverridesVisitChildren)
     , m_prototype(globalData, this, jsNull())
     , m_classInfo(&s_info)
@@ -215,16 +189,14 @@ Structure::Structure(JSGlobalData& globalData)
     , m_dictionaryKind(NoneDictionaryKind)
     , m_isPinnedPropertyTable(false)
     , m_hasGetterSetterProperties(false)
     , m_dictionaryKind(NoneDictionaryKind)
     , m_isPinnedPropertyTable(false)
     , m_hasGetterSetterProperties(false)
+    , m_hasReadOnlyOrGetterSetterPropertiesExcludingProto(false)
     , m_hasNonEnumerableProperties(false)
     , m_attributesInPrevious(0)
     , m_specificFunctionThrashCount(0)
     , m_hasNonEnumerableProperties(false)
     , m_attributesInPrevious(0)
     , m_specificFunctionThrashCount(0)
-    , m_anonymousSlotCount(0)
     , m_preventExtensions(false)
     , m_didTransition(false)
     , m_preventExtensions(false)
     , m_didTransition(false)
+    , m_staticFunctionReified(false)
 {
 {
-    ASSERT(m_prototype);
-    ASSERT(m_prototype.isNull());
-    ASSERT(!globalData.structureStructure);
 }
 
 Structure::Structure(JSGlobalData& globalData, const Structure* previous)
 }
 
 Structure::Structure(JSGlobalData& globalData, const Structure* previous)
@@ -234,22 +206,24 @@ Structure::Structure(JSGlobalData& globalData, const Structure* previous)
     , m_classInfo(previous->m_classInfo)
     , m_propertyStorageCapacity(previous->m_propertyStorageCapacity)
     , m_offset(noOffset)
     , m_classInfo(previous->m_classInfo)
     , m_propertyStorageCapacity(previous->m_propertyStorageCapacity)
     , m_offset(noOffset)
-    , m_dictionaryKind(NoneDictionaryKind)
+    , m_dictionaryKind(previous->m_dictionaryKind)
     , m_isPinnedPropertyTable(false)
     , m_hasGetterSetterProperties(previous->m_hasGetterSetterProperties)
     , m_isPinnedPropertyTable(false)
     , m_hasGetterSetterProperties(previous->m_hasGetterSetterProperties)
+    , m_hasReadOnlyOrGetterSetterPropertiesExcludingProto(previous->m_hasReadOnlyOrGetterSetterPropertiesExcludingProto)
     , m_hasNonEnumerableProperties(previous->m_hasNonEnumerableProperties)
     , m_attributesInPrevious(0)
     , m_specificFunctionThrashCount(previous->m_specificFunctionThrashCount)
     , 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)
     , m_preventExtensions(previous->m_preventExtensions)
     , m_didTransition(true)
+    , m_staticFunctionReified(previous->m_staticFunctionReified)
 {
 {
-    ASSERT(m_prototype);
-    ASSERT(m_prototype.isObject() || m_prototype.isNull());
+    if (previous->m_globalObject)
+        m_globalObject.set(globalData, this, previous->m_globalObject.get());
 }
 
 }
 
-Structure::~Structure()
+void Structure::destroy(JSCell* cell)
 {
 {
+    jsCast<Structure*>(cell)->Structure::~Structure();
 }
 
 void Structure::materializePropertyMap(JSGlobalData& globalData)
 }
 
 void Structure::materializePropertyMap(JSGlobalData& globalData)
@@ -280,7 +254,7 @@ void Structure::materializePropertyMap(JSGlobalData& globalData)
 
     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];
-        PropertyMapEntry entry(globalData, this, structure->m_nameInPrevious.get(), m_anonymousSlotCount + structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious.get());
+        PropertyMapEntry entry(globalData, this, structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious.get());
         m_propertyTable->add(entry);
     }
 }
         m_propertyTable->add(entry);
     }
 }
@@ -293,6 +267,13 @@ void Structure::growPropertyStorageCapacity()
         m_propertyStorageCapacity *= 2;
 }
 
         m_propertyStorageCapacity *= 2;
 }
 
+size_t Structure::suggestedNewPropertyStorageSize()
+{
+    if (isUsingInlineStorage())
+        return JSObject::baseExternalStorageCapacity;
+    return m_propertyStorageCapacity * 2;
+}
+
 void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, const Identifier& propertyName)
 {
     StringImpl* rep = propertyName.impl();
 void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, const Identifier& propertyName)
 {
     StringImpl* rep = propertyName.impl();
@@ -310,16 +291,14 @@ void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, const Iden
 Structure* Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
 {
     ASSERT(!structure->isDictionary());
 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->isObject());
 
     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);
 
     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(structure->m_anonymousSlotCount == existingTransition->m_anonymousSlotCount);
+        offset = existingTransition->m_offset;
         return existingTransition;
     }
 
         return existingTransition;
     }
 
@@ -339,7 +318,7 @@ Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure*
         specificValue = 0;
 
     ASSERT(!structure->isDictionary());
         specificValue = 0;
 
     ASSERT(!structure->isDictionary());
-    ASSERT(structure->typeInfo().type() == ObjectType);
+    ASSERT(structure->isObject());
     ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
     
     if (structure->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
     ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
     
     if (structure->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
@@ -349,13 +328,11 @@ Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure*
         Structure* transition = toCacheableDictionaryTransition(globalData, structure);
         ASSERT(structure != transition);
         offset = transition->putSpecificValue(globalData, propertyName, attributes, specificValue);
         Structure* transition = toCacheableDictionaryTransition(globalData, structure);
         ASSERT(structure != transition);
         offset = transition->putSpecificValue(globalData, propertyName, attributes, specificValue);
-        ASSERT(offset >= structure->m_anonymousSlotCount);
-        ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
         if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
             transition->growPropertyStorageCapacity();
         return transition;
     }
         if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
             transition->growPropertyStorageCapacity();
         return transition;
     }
-
+    
     Structure* transition = create(globalData, structure);
 
     transition->m_cachedPrototypeChain.setMayBeNull(globalData, transition, structure->m_cachedPrototypeChain.get());
     Structure* transition = create(globalData, structure);
 
     transition->m_cachedPrototypeChain.setMayBeNull(globalData, transition, structure->m_cachedPrototypeChain.get());
@@ -366,7 +343,7 @@ Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure*
 
     if (structure->m_propertyTable) {
         if (structure->m_isPinnedPropertyTable)
 
     if (structure->m_propertyTable) {
         if (structure->m_isPinnedPropertyTable)
-            transition->m_propertyTable = structure->m_propertyTable->copy(globalData, 0, structure->m_propertyTable->size() + 1);
+            transition->m_propertyTable = structure->m_propertyTable->copy(globalData, transition, structure->m_propertyTable->size() + 1);
         else
             transition->m_propertyTable = structure->m_propertyTable.release();
     } else {
         else
             transition->m_propertyTable = structure->m_propertyTable.release();
     } else {
@@ -377,13 +354,10 @@ Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure*
     }
 
     offset = transition->putSpecificValue(globalData, 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();
 
     if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
         transition->growPropertyStorageCapacity();
 
-    transition->m_offset = offset - structure->m_anonymousSlotCount;
-    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
+    transition->m_offset = offset;
     structure->m_transitionTable.add(globalData, transition);
     return transition;
 }
     structure->m_transitionTable.add(globalData, transition);
     return transition;
 }
@@ -395,8 +369,6 @@ Structure* Structure::removePropertyTransition(JSGlobalData& globalData, Structu
     Structure* transition = toUncacheableDictionaryTransition(globalData, structure);
 
     offset = transition->remove(propertyName);
     Structure* transition = toUncacheableDictionaryTransition(globalData, structure);
 
     offset = transition->remove(propertyName);
-    ASSERT(offset >= structure->m_anonymousSlotCount);
-    ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
 
     return transition;
 }
 
     return transition;
 }
@@ -410,10 +382,9 @@ Structure* Structure::changePrototypeTransition(JSGlobalData& globalData, Struct
     // Don't set m_offset, as one can not transition to this.
 
     structure->materializePropertyMapIfNecessary(globalData);
     // 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;
-    
-    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
+    transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
+    transition->pin();
+
     return transition;
 }
 
     return transition;
 }
 
@@ -427,8 +398,8 @@ Structure* Structure::despecifyFunctionTransition(JSGlobalData& globalData, Stru
     // Don't set m_offset, as one can not transition to this.
 
     structure->materializePropertyMapIfNecessary(globalData);
     // 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_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
+    transition->pin();
 
     if (transition->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
         transition->despecifyAllFunctions(globalData);
 
     if (transition->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
         transition->despecifyAllFunctions(globalData);
@@ -436,23 +407,30 @@ Structure* Structure::despecifyFunctionTransition(JSGlobalData& globalData, Stru
         bool removed = transition->despecifyFunction(globalData, replaceFunction);
         ASSERT_UNUSED(removed, removed);
     }
         bool removed = transition->despecifyFunction(globalData, replaceFunction);
         ASSERT_UNUSED(removed, removed);
     }
-    
-    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
+
     return transition;
 }
 
     return transition;
 }
 
-Structure* Structure::getterSetterTransition(JSGlobalData& globalData, Structure* structure)
+Structure* Structure::attributeChangeTransition(JSGlobalData& globalData, Structure* structure, const Identifier& propertyName, unsigned attributes)
 {
 {
-    Structure* transition = create(globalData, structure);
+    if (!structure->isUncacheableDictionary()) {
+        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(globalData);
-    transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
-    transition->m_isPinnedPropertyTable = true;
-    
-    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
-    return transition;
+        structure->materializePropertyMapIfNecessary(globalData);
+        transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
+        transition->pin();
+        
+        structure = transition;
+    }
+
+    ASSERT(structure->m_propertyTable);
+    PropertyMapEntry* entry = structure->m_propertyTable->find(propertyName.impl()).first;
+    ASSERT(entry);
+    entry->attributes = attributes;
+
+    return structure;
 }
 
 Structure* Structure::toDictionaryTransition(JSGlobalData& globalData, Structure* structure, DictionaryKind kind)
 }
 
 Structure* Structure::toDictionaryTransition(JSGlobalData& globalData, Structure* structure, DictionaryKind kind)
@@ -462,11 +440,10 @@ Structure* Structure::toDictionaryTransition(JSGlobalData& globalData, Structure
     Structure* transition = create(globalData, structure);
 
     structure->materializePropertyMapIfNecessary(globalData);
     Structure* transition = create(globalData, structure);
 
     structure->materializePropertyMapIfNecessary(globalData);
-    transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
-    transition->m_isPinnedPropertyTable = true;
+    transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
     transition->m_dictionaryKind = kind;
     transition->m_dictionaryKind = kind;
-    
-    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
+    transition->pin();
+
     return transition;
 }
 
     return transition;
 }
 
@@ -500,9 +477,12 @@ Structure* Structure::freezeTransition(JSGlobalData& globalData, Structure* stru
     Structure* transition = preventExtensionsTransition(globalData, structure);
 
     if (transition->m_propertyTable) {
     Structure* transition = preventExtensionsTransition(globalData, structure);
 
     if (transition->m_propertyTable) {
+        PropertyTable::iterator iter = transition->m_propertyTable->begin();
         PropertyTable::iterator end = transition->m_propertyTable->end();
         PropertyTable::iterator end = transition->m_propertyTable->end();
-        for (PropertyTable::iterator iter = transition->m_propertyTable->begin(); iter != end; ++iter)
-            iter->attributes |= (DontDelete | ReadOnly);
+        if (iter != end)
+            transition->m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
+        for (; iter != end; ++iter)
+            iter->attributes |= iter->attributes & Accessor ? DontDelete : (DontDelete | ReadOnly);
     }
 
     return transition;
     }
 
     return transition;
@@ -516,11 +496,10 @@ Structure* Structure::preventExtensionsTransition(JSGlobalData& globalData, Stru
     // Don't set m_offset, as one can not transition to this.
 
     structure->materializePropertyMapIfNecessary(globalData);
     // 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_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
     transition->m_preventExtensions = true;
     transition->m_preventExtensions = true;
+    transition->pin();
 
 
-    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
     return transition;
 }
 
     return transition;
 }
 
@@ -554,7 +533,9 @@ bool Structure::isFrozen(JSGlobalData& globalData)
 
     PropertyTable::iterator end = m_propertyTable->end();
     for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
 
     PropertyTable::iterator end = m_propertyTable->end();
     for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
-        if ((iter->attributes & (DontDelete | ReadOnly)) != (DontDelete | ReadOnly))
+        if (!(iter->attributes & DontDelete))
+            return false;
+        if (!(iter->attributes & (ReadOnly | Accessor)))
             return false;
     }
     return true;
             return false;
     }
     return true;
@@ -566,7 +547,6 @@ Structure* Structure::flattenDictionaryStructure(JSGlobalData& globalData, JSObj
     if (isUncacheableDictionary()) {
         ASSERT(m_propertyTable);
 
     if (isUncacheableDictionary()) {
         ASSERT(m_propertyTable);
 
-        unsigned anonymousSlotCount = m_anonymousSlotCount;
         size_t propertyCount = m_propertyTable->size();
         Vector<JSValue> values(propertyCount);
 
         size_t propertyCount = m_propertyTable->size();
         Vector<JSValue> values(propertyCount);
 
@@ -575,12 +555,12 @@ Structure* Structure::flattenDictionaryStructure(JSGlobalData& globalData, JSObj
         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
         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
-            iter->offset = anonymousSlotCount + i;
+            iter->offset = 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(globalData, anonymousSlotCount + i, values[i]);
+            object->putDirectOffset(globalData, i, values[i]);
 
         m_propertyTable->clearDeletedOffsets();
     }
 
         m_propertyTable->clearDeletedOffsets();
     }
@@ -596,12 +576,11 @@ size_t Structure::addPropertyWithoutTransition(JSGlobalData& globalData, const I
     if (m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
         specificValue = 0;
 
     if (m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
         specificValue = 0;
 
-    materializePropertyMapIfNecessary(globalData);
-
-    m_isPinnedPropertyTable = true;
+    materializePropertyMapIfNecessaryForPinning(globalData);
+    
+    pin();
 
     size_t offset = putSpecificValue(globalData, propertyName, attributes, specificValue);
 
     size_t offset = putSpecificValue(globalData, propertyName, attributes, specificValue);
-    ASSERT(offset >= m_anonymousSlotCount);
     if (propertyStorageSize() > propertyStorageCapacity())
         growPropertyStorageCapacity();
     return offset;
     if (propertyStorageSize() > propertyStorageCapacity())
         growPropertyStorageCapacity();
     return offset;
@@ -612,14 +591,21 @@ size_t Structure::removePropertyWithoutTransition(JSGlobalData& globalData, cons
     ASSERT(isUncacheableDictionary());
     ASSERT(!m_enumerationCache);
 
     ASSERT(isUncacheableDictionary());
     ASSERT(!m_enumerationCache);
 
-    materializePropertyMapIfNecessary(globalData);
+    materializePropertyMapIfNecessaryForPinning(globalData);
 
 
-    m_isPinnedPropertyTable = true;
+    pin();
     size_t offset = remove(propertyName);
     size_t offset = remove(propertyName);
-    ASSERT(offset >= m_anonymousSlotCount);
     return offset;
 }
 
     return offset;
 }
 
+void Structure::pin()
+{
+    ASSERT(m_propertyTable);
+    m_isPinnedPropertyTable = true;
+    m_previous.clear();
+    m_nameInPrevious.clear();
+}
+
 #if DUMP_PROPERTYMAP_STATS
 
 struct PropertyMapStatisticsExitLogger {
 #if DUMP_PROPERTYMAP_STATS
 
 struct PropertyMapStatisticsExitLogger {
@@ -630,11 +616,11 @@ static PropertyMapStatisticsExitLogger logger;
 
 PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
 {
 
 PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
 {
-    printf("\nJSC::PropertyMap statistics\n\n");
-    printf("%d probes\n", numProbes);
-    printf("%d collisions (%.1f%%)\n", numCollisions, 100.0 * numCollisions / numProbes);
-    printf("%d rehashes\n", numRehashes);
-    printf("%d removes\n", numRemoves);
+    dataLog("\nJSC::PropertyMap statistics\n\n");
+    dataLog("%d probes\n", numProbes);
+    dataLog("%d collisions (%.1f%%)\n", numCollisions, 100.0 * numCollisions / numProbes);
+    dataLog("%d rehashes\n", numRehashes);
+    dataLog("%d removes\n", numRemoves);
 }
 
 #endif
 }
 
 #endif
@@ -652,6 +638,11 @@ PassOwnPtr<PropertyTable> Structure::copyPropertyTable(JSGlobalData& globalData,
     return adoptPtr(m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : 0);
 }
 
     return adoptPtr(m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : 0);
 }
 
+PassOwnPtr<PropertyTable> Structure::copyPropertyTableForPinning(JSGlobalData& globalData, Structure* owner)
+{
+    return adoptPtr(m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : new PropertyTable(m_offset == noOffset ? 0 : m_offset));
+}
+
 size_t Structure::get(JSGlobalData& globalData, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue)
 {
     materializePropertyMapIfNecessary(globalData);
 size_t Structure::get(JSGlobalData& globalData, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue)
 {
     materializePropertyMapIfNecessary(globalData);
@@ -664,7 +655,6 @@ size_t Structure::get(JSGlobalData& globalData, StringImpl* propertyName, unsign
 
     attributes = entry->attributes;
     specificValue = entry->specificValue.get();
 
     attributes = entry->attributes;
     specificValue = entry->specificValue.get();
-    ASSERT(entry->offset >= m_anonymousSlotCount);
     return entry->offset;
 }
 
     return entry->offset;
 }
 
@@ -714,8 +704,7 @@ size_t Structure::putSpecificValue(JSGlobalData& globalData, const Identifier& p
     if (m_propertyTable->hasDeletedOffset())
         newOffset = m_propertyTable->getDeletedOffset();
     else
     if (m_propertyTable->hasDeletedOffset())
         newOffset = m_propertyTable->getDeletedOffset();
     else
-        newOffset = m_propertyTable->size() + m_anonymousSlotCount;
-    ASSERT(newOffset >= m_anonymousSlotCount);
+        newOffset = m_propertyTable->size();
 
     m_propertyTable->add(PropertyMapEntry(globalData, this, rep, newOffset, attributes, specificValue));
 
 
     m_propertyTable->add(PropertyMapEntry(globalData, this, rep, newOffset, attributes, specificValue));
 
@@ -739,7 +728,6 @@ size_t Structure::remove(const Identifier& propertyName)
         return notFound;
 
     size_t offset = position.first->offset;
         return notFound;
 
     size_t offset = position.first->offset;
-    ASSERT(offset >= m_anonymousSlotCount);
 
     m_propertyTable->remove(position);
     m_propertyTable->addDeletedOffset(offset);
 
     m_propertyTable->remove(position);
     m_propertyTable->addDeletedOffset(offset);
@@ -757,7 +745,7 @@ void Structure::createPropertyMap(unsigned capacity)
     checkConsistency();
 }
 
     checkConsistency();
 }
 
-void Structure::getPropertyNames(JSGlobalData& globalData, PropertyNameArray& propertyNames, EnumerationMode mode)
+void Structure::getPropertyNamesFromStructure(JSGlobalData& globalData, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     materializePropertyMapIfNecessary(globalData);
     if (!m_propertyTable)
 {
     materializePropertyMapIfNecessary(globalData);
     if (!m_propertyTable)
@@ -777,28 +765,37 @@ void Structure::getPropertyNames(JSGlobalData& globalData, PropertyNameArray& pr
     }
 }
 
     }
 }
 
-void Structure::visitChildren(SlotVisitor& visitor)
-{
-    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) {
+void Structure::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    Structure* thisObject = jsCast<Structure*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+    JSCell::visitChildren(thisObject, visitor);
+    if (thisObject->m_globalObject)
+        visitor.append(&thisObject->m_globalObject);
+    if (!thisObject->isObject())
+        thisObject->m_cachedPrototypeChain.clear();
+    else {
+        if (thisObject->m_prototype)
+            visitor.append(&thisObject->m_prototype);
+        if (thisObject->m_cachedPrototypeChain)
+            visitor.append(&thisObject->m_cachedPrototypeChain);
+    }
+    if (thisObject->m_previous)
+        visitor.append(&thisObject->m_previous);
+    if (thisObject->m_specificValueInPrevious)
+        visitor.append(&thisObject->m_specificValueInPrevious);
+    if (thisObject->m_enumerationCache)
+        visitor.append(&thisObject->m_enumerationCache);
+    if (thisObject->m_propertyTable) {
+        PropertyTable::iterator end = thisObject->m_propertyTable->end();
+        for (PropertyTable::iterator ptr = thisObject->m_propertyTable->begin(); ptr != end; ++ptr) {
             if (ptr->specificValue)
                 visitor.append(&ptr->specificValue);
         }
     }
             if (ptr->specificValue)
                 visitor.append(&ptr->specificValue);
         }
     }
+    if (thisObject->m_objectToStringValue)
+        visitor.append(&thisObject->m_objectToStringValue);
 }
 
 #if DO_PROPERTYMAP_CONSTENCY_CHECK
 }
 
 #if DO_PROPERTYMAP_CONSTENCY_CHECK
@@ -869,7 +866,6 @@ void Structure::checkConsistency()
         PropertyTable::iterator end = m_propertyTable->end();
         for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
             ASSERT(!(iter->attributes & DontEnum));
         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);
         }
     }
 
         }
     }
 
index f71d23c12bc46bd6ff13a45b833f5ec26524b3fd..00bc761771e99c2a0fa059206b9a1d201e80811b 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef Structure_h
 #define Structure_h
 
 #ifndef Structure_h
 #define Structure_h
 
+#include "ClassInfo.h"
 #include "Identifier.h"
 #include "JSCell.h"
 #include "JSType.h"
 #include "Identifier.h"
 #include "JSCell.h"
 #include "JSType.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class MarkStack;
+    class LLIntOffsetsExtractor;
     class PropertyNameArray;
     class PropertyNameArrayData;
     class StructureChain;
     class PropertyNameArray;
     class PropertyNameArrayData;
     class StructureChain;
-    typedef MarkStack SlotVisitor;
-
-    struct ClassInfo;
-
-    enum EnumerationMode {
-        ExcludeDontEnumProperties,
-        IncludeDontEnumProperties
-    };
+    class SlotVisitor;
+    class JSString;
 
     class Structure : public JSCell {
     public:
         friend class StructureTransitionTable;
 
     class Structure : public JSCell {
     public:
         friend class StructureTransitionTable;
-        static Structure* create(JSGlobalData& globalData, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo)
+
+        typedef JSCell Base;
+
+        static Structure* create(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo)
         {
             ASSERT(globalData.structureStructure);
             ASSERT(classInfo);
         {
             ASSERT(globalData.structureStructure);
             ASSERT(classInfo);
-            return new (&globalData) Structure(globalData, prototype, typeInfo, anonymousSlotCount, classInfo);
+            Structure* structure = new (NotNull, allocateCell<Structure>(globalData.heap)) Structure(globalData, globalObject, prototype, typeInfo, classInfo);
+            structure->finishCreation(globalData);
+            return structure;
         }
 
         }
 
+    protected:
+        void finishCreation(JSGlobalData& globalData)
+        {
+            Base::finishCreation(globalData);
+            ASSERT(m_prototype);
+            ASSERT(m_prototype.isObject() || m_prototype.isNull());
+        }
+
+        void finishCreation(JSGlobalData& globalData, CreatingEarlyCellTag)
+        {
+            Base::finishCreation(globalData, this, CreatingEarlyCell);
+            ASSERT(m_prototype);
+            ASSERT(m_prototype.isNull());
+            ASSERT(!globalData.structureStructure);
+        }
+
+    public:
         static void dumpStatistics();
 
         static void dumpStatistics();
 
-        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);
+        JS_EXPORT_PRIVATE static Structure* addPropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
+        JS_EXPORT_PRIVATE 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* 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*);
+        JS_EXPORT_PRIVATE static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype);
+        JS_EXPORT_PRIVATE static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, const Identifier&);
+        static Structure* attributeChangeTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes);
         static Structure* toCacheableDictionaryTransition(JSGlobalData&, Structure*);
         static Structure* toUncacheableDictionaryTransition(JSGlobalData&, Structure*);
         static Structure* sealTransition(JSGlobalData&, Structure*);
         static Structure* toCacheableDictionaryTransition(JSGlobalData&, Structure*);
         static Structure* toUncacheableDictionaryTransition(JSGlobalData&, Structure*);
         static Structure* sealTransition(JSGlobalData&, Structure*);
@@ -85,35 +102,45 @@ namespace JSC {
         bool isFrozen(JSGlobalData&);
         bool isExtensible() const { return !m_preventExtensions; }
         bool didTransition() const { return m_didTransition; }
         bool isFrozen(JSGlobalData&);
         bool isExtensible() const { return !m_preventExtensions; }
         bool didTransition() const { return m_didTransition; }
+        bool shouldGrowPropertyStorage() { return propertyStorageCapacity() == propertyStorageSize(); }
+        JS_EXPORT_PRIVATE size_t suggestedNewPropertyStorageSize(); 
 
         Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);
 
 
         Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);
 
-        ~Structure();
+        static void destroy(JSCell*);
 
         // These should be used with caution.  
 
         // These should be used with caution.  
-        size_t addPropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
+        JS_EXPORT_PRIVATE 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; }
 
         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; }
 
+        // Type accessors.
         const TypeInfo& typeInfo() const { ASSERT(structure()->classInfo() == &s_info); return m_typeInfo; }
         const TypeInfo& typeInfo() const { ASSERT(structure()->classInfo() == &s_info); return m_typeInfo; }
+        bool isObject() const { return typeInfo().isObject(); }
 
 
+
+        JSGlobalObject* globalObject() const { return m_globalObject.get(); }
+        void setGlobalObject(JSGlobalData& globalData, JSGlobalObject* globalObject) { m_globalObject.set(globalData, this, globalObject); }
+        
         JSValue storedPrototype() const { return m_prototype.get(); }
         JSValue prototypeForLookup(ExecState*) const;
         StructureChain* prototypeChain(ExecState*) const;
         JSValue storedPrototype() const { return m_prototype.get(); }
         JSValue prototypeForLookup(ExecState*) const;
         StructureChain* prototypeChain(ExecState*) const;
-        void visitChildren(SlotVisitor&);
+        static void visitChildren(JSCell*, SlotVisitor&);
 
         Structure* previousID() const { ASSERT(structure()->classInfo() == &s_info); return m_previous.get(); }
 
         Structure* previousID() const { ASSERT(structure()->classInfo() == &s_info); return m_previous.get(); }
+        bool transitivelyTransitionedFrom(Structure* structureToFind);
 
         void growPropertyStorageCapacity();
         unsigned propertyStorageCapacity() const { ASSERT(structure()->classInfo() == &s_info); return m_propertyStorageCapacity; }
 
         void growPropertyStorageCapacity();
         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)); }
+        unsigned propertyStorageSize() const { ASSERT(structure()->classInfo() == &s_info); return (m_propertyTable ? m_propertyTable->propertyStorageSize() : static_cast<unsigned>(m_offset + 1)); }
         bool isUsingInlineStorage() const;
 
         size_t get(JSGlobalData&, const Identifier& propertyName);
         bool isUsingInlineStorage() const;
 
         size_t get(JSGlobalData&, const Identifier& propertyName);
-        size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue);
+        size_t get(JSGlobalData&, const UString& name);
+        JS_EXPORT_PRIVATE 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());
         size_t get(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
         {
             ASSERT(!propertyName.isNull());
@@ -122,21 +149,45 @@ namespace JSC {
         }
 
         bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
         }
 
         bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
-        void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
+        bool hasReadOnlyOrGetterSetterPropertiesExcludingProto() const { return m_hasReadOnlyOrGetterSetterPropertiesExcludingProto; }
+        void setHasGetterSetterProperties(bool is__proto__)
+        {
+            m_hasGetterSetterProperties = true;
+            if (!is__proto__)
+                m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
+        }
+        void setContainsReadOnlyProperties()
+        {
+            m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
+        }
 
         bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
 
         bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
-
-        bool hasAnonymousSlots() const { return !!m_anonymousSlotCount; }
-        unsigned anonymousSlotCount() const { return m_anonymousSlotCount; }
         
         bool isEmpty() const { return m_propertyTable ? m_propertyTable->isEmpty() : m_offset == noOffset; }
 
         
         bool isEmpty() const { return m_propertyTable ? m_propertyTable->isEmpty() : m_offset == noOffset; }
 
-        void despecifyDictionaryFunction(JSGlobalData&, const Identifier& propertyName);
+        JS_EXPORT_PRIVATE void despecifyDictionaryFunction(JSGlobalData&, const Identifier& propertyName);
         void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
 
         void setEnumerationCache(JSGlobalData&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
         JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
         void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
 
         void setEnumerationCache(JSGlobalData&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
         JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
-        void getPropertyNames(JSGlobalData&, PropertyNameArray&, EnumerationMode mode);
+        void getPropertyNamesFromStructure(JSGlobalData&, PropertyNameArray&, EnumerationMode);
+
+        JSString* objectToStringValue() { return m_objectToStringValue.get(); }
+
+        void setObjectToStringValue(JSGlobalData& globalData, const JSCell* owner, JSString* value)
+        {
+            m_objectToStringValue.set(globalData, owner, value);
+        }
+
+        bool staticFunctionsReified()
+        {
+            return m_staticFunctionReified;
+        }
+
+        void setStaticFunctionsReified()
+        {
+            m_staticFunctionReified = true;
+        }
 
         const ClassInfo* classInfo() const { return m_classInfo; }
 
 
         const ClassInfo* classInfo() const { return m_classInfo; }
 
@@ -158,20 +209,26 @@ namespace JSC {
         static Structure* createStructure(JSGlobalData& globalData)
         {
             ASSERT(!globalData.structureStructure);
         static Structure* createStructure(JSGlobalData& globalData)
         {
             ASSERT(!globalData.structureStructure);
-            return new (&globalData) Structure(globalData);
+            Structure* structure = new (NotNull, allocateCell<Structure>(globalData.heap)) Structure(globalData);
+            structure->finishCreation(globalData, CreatingEarlyCell);
+            return structure;
         }
         
         static JS_EXPORTDATA const ClassInfo s_info;
 
     private:
         }
         
         static JS_EXPORTDATA const ClassInfo s_info;
 
     private:
-        Structure(JSGlobalData&, JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount, const ClassInfo*);
+        friend class LLIntOffsetsExtractor;
+        
+        JS_EXPORT_PRIVATE Structure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*);
         Structure(JSGlobalData&);
         Structure(JSGlobalData&, const Structure*);
 
         static Structure* create(JSGlobalData& globalData, const Structure* structure)
         {
             ASSERT(globalData.structureStructure);
         Structure(JSGlobalData&);
         Structure(JSGlobalData&, const Structure*);
 
         static Structure* create(JSGlobalData& globalData, const Structure* structure)
         {
             ASSERT(globalData.structureStructure);
-            return new (&globalData) Structure(globalData, structure);
+            Structure* newStructure = new (NotNull, allocateCell<Structure>(globalData.heap)) Structure(globalData, structure);
+            newStructure->finishCreation(globalData);
+            return newStructure;
         }
         
         typedef enum { 
         }
         
         typedef enum { 
@@ -191,30 +248,40 @@ namespace JSC {
         void despecifyAllFunctions(JSGlobalData&);
 
         PassOwnPtr<PropertyTable> copyPropertyTable(JSGlobalData&, Structure* owner);
         void despecifyAllFunctions(JSGlobalData&);
 
         PassOwnPtr<PropertyTable> copyPropertyTable(JSGlobalData&, Structure* owner);
-        void materializePropertyMap(JSGlobalData&);
+        PassOwnPtr<PropertyTable> copyPropertyTableForPinning(JSGlobalData&, Structure* owner);
+        JS_EXPORT_PRIVATE void materializePropertyMap(JSGlobalData&);
         void materializePropertyMapIfNecessary(JSGlobalData& globalData)
         {
             ASSERT(structure()->classInfo() == &s_info);
             if (!m_propertyTable && m_previous)
                 materializePropertyMap(globalData);
         }
         void materializePropertyMapIfNecessary(JSGlobalData& globalData)
         {
             ASSERT(structure()->classInfo() == &s_info);
             if (!m_propertyTable && m_previous)
                 materializePropertyMap(globalData);
         }
+        void materializePropertyMapIfNecessaryForPinning(JSGlobalData& globalData)
+        {
+            ASSERT(structure()->classInfo() == &s_info);
+            if (!m_propertyTable)
+                materializePropertyMap(globalData);
+        }
 
 
-        signed char transitionCount() const
+        int transitionCount() const
         {
             // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
             return m_offset == noOffset ? 0 : m_offset + 1;
         }
 
         bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
         {
             // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
             return m_offset == noOffset ? 0 : m_offset + 1;
         }
 
         bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
+        
+        void pin();
 
 
-        static const signed char s_maxTransitionLength = 64;
+        static const int s_maxTransitionLength = 64;
 
 
-        static const signed char noOffset = -1;
+        static const int noOffset = -1;
 
         static const unsigned maxSpecificFunctionThrashCount = 3;
 
         TypeInfo m_typeInfo;
 
         static const unsigned maxSpecificFunctionThrashCount = 3;
 
         TypeInfo m_typeInfo;
-
+        
+        WriteBarrier<JSGlobalObject> m_globalObject;
         WriteBarrier<Unknown> m_prototype;
         mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
 
         WriteBarrier<Unknown> m_prototype;
         mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
 
@@ -232,26 +299,21 @@ namespace JSC {
 
         uint32_t m_propertyStorageCapacity;
 
 
         uint32_t m_propertyStorageCapacity;
 
+        WriteBarrier<JSString> m_objectToStringValue;
+
         // m_offset does not account for anonymous slots
         // m_offset does not account for anonymous slots
-        signed char m_offset;
+        int m_offset;
 
         unsigned m_dictionaryKind : 2;
         bool m_isPinnedPropertyTable : 1;
         bool m_hasGetterSetterProperties : 1;
 
         unsigned m_dictionaryKind : 2;
         bool m_isPinnedPropertyTable : 1;
         bool m_hasGetterSetterProperties : 1;
+        bool m_hasReadOnlyOrGetterSetterPropertiesExcludingProto : 1;
         bool m_hasNonEnumerableProperties : 1;
         bool m_hasNonEnumerableProperties : 1;
-#if COMPILER(WINSCW)
-        // Workaround for Symbian WINSCW compiler that cannot resolve unsigned type of the declared 
-        // bitfield, when used as argument in make_pair() function calls in structure.ccp.
-        // This bitfield optimization is insignificant for the Symbian emulator target.
-        unsigned m_attributesInPrevious;
-#else
         unsigned m_attributesInPrevious : 7;
         unsigned m_attributesInPrevious : 7;
-#endif
         unsigned m_specificFunctionThrashCount : 2;
         unsigned m_specificFunctionThrashCount : 2;
-        unsigned m_anonymousSlotCount : 5;
         unsigned m_preventExtensions : 1;
         unsigned m_didTransition : 1;
         unsigned m_preventExtensions : 1;
         unsigned m_didTransition : 1;
-        // 3 free bits
+        unsigned m_staticFunctionReified;
     };
 
     inline size_t Structure::get(JSGlobalData& globalData, const Identifier& propertyName)
     };
 
     inline size_t Structure::get(JSGlobalData& globalData, const Identifier& propertyName)
@@ -262,13 +324,23 @@ namespace JSC {
             return notFound;
 
         PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first;
             return notFound;
 
         PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first;
-        ASSERT(!entry || entry->offset >= m_anonymousSlotCount);
         return entry ? entry->offset : notFound;
     }
 
         return entry ? entry->offset : notFound;
     }
 
+    inline size_t Structure::get(JSGlobalData& globalData, const UString& name)
+    {
+        ASSERT(structure()->classInfo() == &s_info);
+        materializePropertyMapIfNecessary(globalData);
+        if (!m_propertyTable)
+            return notFound;
+
+        PropertyMapEntry* entry = m_propertyTable->findWithString(name.impl()).first;
+        return entry ? entry->offset : notFound;
+    }
+    
     inline bool JSCell::isObject() const
     {
     inline bool JSCell::isObject() const
     {
-        return m_structure->typeInfo().type() == ObjectType;
+        return m_structure->isObject();
     }
 
     inline bool JSCell::isString() const
     }
 
     inline bool JSCell::isString() const
@@ -276,35 +348,47 @@ namespace JSC {
         return m_structure->typeInfo().type() == StringType;
     }
 
         return m_structure->typeInfo().type() == StringType;
     }
 
-    inline const ClassInfo* JSCell::classInfo() const
+    inline bool JSCell::isGetterSetter() const
     {
     {
-#if ENABLE(GC_VALIDATION)
-        return m_structure.unvalidatedGet()->classInfo();
-#else
-        return m_structure->classInfo();
-#endif
+        return m_structure->typeInfo().type() == GetterSetterType;
     }
 
     }
 
-    inline Structure* JSCell::createDummyStructure(JSGlobalData& globalData)
+    inline bool JSCell::isAPIValueWrapper() const
     {
     {
-        return Structure::create(globalData, jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount, &s_dummyCellInfo);
+        return m_structure->typeInfo().type() == APIValueWrapperType;
     }
 
     }
 
-    inline bool JSValue::needsThisConversion() const
+    inline void JSCell::setStructure(JSGlobalData& globalData, Structure* structure)
     {
     {
-        if (UNLIKELY(!isCell()))
-            return true;
-        return asCell()->structure()->typeInfo().needsThisConversion();
+        ASSERT(structure->typeInfo().overridesVisitChildren() == this->structure()->typeInfo().overridesVisitChildren());
+        ASSERT(structure->classInfo() == m_structure->classInfo());
+        m_structure.set(globalData, this, structure);
+    }
+
+    inline const ClassInfo* JSCell::validatedClassInfo() const
+    {
+#if ENABLE(GC_VALIDATION)
+        ASSERT(m_structure.unvalidatedGet()->classInfo() == m_classInfo);
+#else
+        ASSERT(m_structure->classInfo() == m_classInfo);
+#endif
+        return m_classInfo;
     }
 
     ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell)
     {
         ASSERT(!m_isCheckingForDefaultMarkViolation);
     }
 
     ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell)
     {
         ASSERT(!m_isCheckingForDefaultMarkViolation);
-        ASSERT(cell);
-        if (Heap::testAndSetMarked(cell))
+#if ENABLE(GC_VALIDATION)
+        validate(cell);
+#endif
+        m_visitCount++;
+        if (Heap::testAndSetMarked(cell) || !cell->structure())
             return;
             return;
-        if (cell->structure() && cell->structure()->typeInfo().type() >= CompoundType)
-            m_values.append(cell);
+        
+        // Should never attempt to mark something that is zapped.
+        ASSERT(!cell->isZapped());
+        
+        m_stack.append(cell);
     }
 
     inline StructureTransitionTable::Hash::Key StructureTransitionTable::keyForWeakGCMapFinalizer(void*, Structure* structure)
     }
 
     inline StructureTransitionTable::Hash::Key StructureTransitionTable::keyForWeakGCMapFinalizer(void*, Structure* structure)
@@ -315,6 +399,34 @@ namespace JSC {
         return Hash::Key(structure->m_nameInPrevious.get(), +structure->m_attributesInPrevious);
     }
 
         return Hash::Key(structure->m_nameInPrevious.get(), +structure->m_attributesInPrevious);
     }
 
+    inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
+    {
+        for (Structure* current = this; current; current = current->previousID()) {
+            if (current == structureToFind)
+                return true;
+        }
+        return false;
+    }
+
+    inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure)
+        : m_classInfo(structure->classInfo())
+        , m_structure(globalData, this, structure)
+    {
+    }
+
+    inline void JSCell::finishCreation(JSGlobalData& globalData, Structure* structure, CreatingEarlyCellTag)
+    {
+#if ENABLE(GC_VALIDATION)
+        ASSERT(globalData.isInitializingObject());
+        globalData.setInitializingObjectClass(0);
+        if (structure)
+#endif
+            m_structure.setEarlyValue(globalData, this, structure);
+        m_classInfo = structure->classInfo();
+        // Very first set of allocations won't have a real structure.
+        ASSERT(m_structure || !globalData.structureStructure);
+    }
+
 } // namespace JSC
 
 #endif // Structure_h
 } // namespace JSC
 
 #endif // Structure_h
index 89a0ec0c2067b4696fa31e269b597d7c6b99baff..afb2d95018867f9db7f441f28c893b10e2a601c2 100644 (file)
 
 namespace JSC {
     
 
 namespace JSC {
     
-ClassInfo StructureChain::s_info = { "StructureChain", 0, 0, 0 };
+ClassInfo StructureChain::s_info = { "StructureChain", 0, 0, 0, CREATE_METHOD_TABLE(StructureChain) };
 
 
-StructureChain::StructureChain(JSGlobalData& globalData, Structure* structure, Structure* head)
+StructureChain::StructureChain(JSGlobalData& globalData, Structure* structure)
     : JSCell(globalData, structure)
 {
     : JSCell(globalData, structure)
 {
-    size_t size = 0;
-    for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
-        ++size;
-    
-    m_vector = adoptArrayPtr(new WriteBarrier<Structure>[size + 1]);
-
-    size_t i = 0;
-    for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
-        m_vector[i++].set(globalData, this, current);
-    m_vector[i].clear();
 }
 
 }
 
-StructureChain::~StructureChain()
+void StructureChain::destroy(JSCell* cell)
 {
 {
+    jsCast<StructureChain*>(cell)->StructureChain::~StructureChain();
 }
 
 }
 
-void StructureChain::visitChildren(SlotVisitor& visitor)
+void StructureChain::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
 {
-    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
-    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    StructureChain* thisObject = jsCast<StructureChain*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
     size_t i = 0;
     size_t i = 0;
-    while (m_vector[i])
-        visitor.append(&m_vector[i++]);
+    while (thisObject->m_vector[i])
+        visitor.append(&thisObject->m_vector[i++]);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index 4fc1212bc7a28eda127fcc939360b4000290fbb8..3b19d4cf16baf6ae63f4ab2e07e32a2f61312c46 100644 (file)
@@ -27,6 +27,7 @@
 #define StructureChain_h
 
 #include "JSCell.h"
 #define StructureChain_h
 
 #include "JSCell.h"
+#include "JSObject.h"
 #include "Structure.h"
 
 #include <wtf/OwnArrayPtr.h>
 #include "Structure.h"
 
 #include <wtf/OwnArrayPtr.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
+    class LLIntOffsetsExtractor;
     class Structure;
 
     class StructureChain : public JSCell {
         friend class JIT;
 
     public:
     class Structure;
 
     class StructureChain : public JSCell {
         friend class JIT;
 
     public:
-        static StructureChain* create(JSGlobalData& globalData, Structure* head) { return new (&globalData) StructureChain(globalData, globalData.structureChainStructure.get(), head); }
+        typedef JSCell Base;
+
+        static StructureChain* create(JSGlobalData& globalData, Structure* head)
+        { 
+            StructureChain* chain = new (NotNull, allocateCell<StructureChain>(globalData.heap)) StructureChain(globalData, globalData.structureChainStructure.get());
+            chain->finishCreation(globalData, head);
+            return chain;
+        }
         WriteBarrier<Structure>* head() { return m_vector.get(); }
         WriteBarrier<Structure>* head() { return m_vector.get(); }
-        void visitChildren(SlotVisitor&);
+        static void visitChildren(JSCell*, SlotVisitor&);
 
 
-        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesVisitChildren), 0, &s_info); }
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) { return Structure::create(globalData, globalObject, prototype, TypeInfo(CompoundType, OverridesVisitChildren), &s_info); }
         
         static ClassInfo s_info;
 
         
         static ClassInfo s_info;
 
+    protected:
+        void finishCreation(JSGlobalData& globalData, Structure* head)
+        {
+            Base::finishCreation(globalData);
+            size_t size = 0;
+            for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
+                ++size;
+    
+            m_vector = adoptArrayPtr(new WriteBarrier<Structure>[size + 1]);
+
+            size_t i = 0;
+            for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
+                m_vector[i++].set(globalData, this, current);
+        }
+
     private:
     private:
-        StructureChain(JSGlobalData&, Structure*, Structure* head);
-        ~StructureChain();
+        friend class LLIntOffsetsExtractor;
+        
+        StructureChain(JSGlobalData&, Structure*);
+        static void destroy(JSCell*);
         OwnArrayPtr<WriteBarrier<Structure> > m_vector;
     };
 
         OwnArrayPtr<WriteBarrier<Structure> > m_vector;
     };
 
index adebad28480c24db39a5015da6cdad4add0747d3..2067a899546f788a79a477e7d80dc7f0e21db260 100644 (file)
 #include "UString.h"
 #include "WeakGCMap.h"
 #include <wtf/HashFunctions.h>
 #include "UString.h"
 #include "WeakGCMap.h"
 #include <wtf/HashFunctions.h>
-#include <wtf/HashTraits.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/RefPtr.h>
 
 namespace JSC {
 
 #include <wtf/OwnPtr.h>
 #include <wtf/RefPtr.h>
 
 namespace JSC {
 
+class JSCell;
 class Structure;
 
 class StructureTransitionTable {
 class Structure;
 
 class StructureTransitionTable {
@@ -55,20 +55,6 @@ class StructureTransitionTable {
         static const bool safeToCompareToEmptyOrDeleted = true;
     };
 
         static const bool safeToCompareToEmptyOrDeleted = true;
     };
 
-    struct HashTraits {
-        typedef WTF::HashTraits<RefPtr<StringImpl> > FirstTraits;
-        typedef WTF::GenericHashTraits<unsigned> SecondTraits;
-        typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType;
-
-        static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
-        static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
-
-        static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
-
-        static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
-        static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
-    };
-
     struct WeakGCMapFinalizerCallback {
         static void* finalizerContextFor(Hash::Key)
         {
     struct WeakGCMapFinalizerCallback {
         static void* finalizerContextFor(Hash::Key)
         {
@@ -81,7 +67,7 @@ class StructureTransitionTable {
         }
     };
 
         }
     };
 
-    typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash, HashTraits> TransitionMap;
+    typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash> TransitionMap;
 
     static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*);
 
 
     static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*);
 
@@ -93,14 +79,18 @@ public:
 
     ~StructureTransitionTable()
     {
 
     ~StructureTransitionTable()
     {
-        if (!isUsingSingleSlot())
+        if (!isUsingSingleSlot()) {
             delete map();
             delete map();
-        else
-            clearSingleTransition();
+            return;
+        }
+
+        WeakImpl* impl = this->weakImpl();
+        if (!impl)
+            return;
+        WeakSet::deallocate(impl);
     }
 
     inline void add(JSGlobalData&, Structure*);
     }
 
     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;
 
     inline bool contains(StringImpl* rep, unsigned attributes) const;
     inline Structure* get(StringImpl* rep, unsigned attributes) const;
 
@@ -116,18 +106,18 @@ private:
         return reinterpret_cast<TransitionMap*>(m_data);
     }
 
         return reinterpret_cast<TransitionMap*>(m_data);
     }
 
-    HandleSlot slot() const
+    WeakImpl* weakImpl() const
     {
         ASSERT(isUsingSingleSlot());
     {
         ASSERT(isUsingSingleSlot());
-        return reinterpret_cast<HandleSlot>(m_data & ~UsingSingleSlotFlag);
+        return reinterpret_cast<WeakImpl*>(m_data & ~UsingSingleSlotFlag);
     }
 
     void setMap(TransitionMap* map)
     {
         ASSERT(isUsingSingleSlot());
         
     }
 
     void setMap(TransitionMap* map)
     {
         ASSERT(isUsingSingleSlot());
         
-        if (HandleSlot slot = this->slot())
-            HandleHeap::heapFor(slot)->deallocate(slot);
+        if (WeakImpl* impl = this->weakImpl())
+            WeakSet::deallocate(impl);
 
         // This implicitly clears the flag that indicates we're using a single transition
         m_data = reinterpret_cast<intptr_t>(map);
 
         // This implicitly clears the flag that indicates we're using a single transition
         m_data = reinterpret_cast<intptr_t>(map);
@@ -138,31 +128,20 @@ private:
     Structure* singleTransition() const
     {
         ASSERT(isUsingSingleSlot());
     Structure* singleTransition() const
     {
         ASSERT(isUsingSingleSlot());
-        if (HandleSlot slot = this->slot()) {
-            if (*slot)
-                return reinterpret_cast<Structure*>(slot->asCell());
+        if (WeakImpl* impl = this->weakImpl()) {
+            if (impl->state() == WeakImpl::Live)
+                return reinterpret_cast<Structure*>(impl->jsValue().asCell());
         }
         return 0;
     }
     
         }
         return 0;
     }
     
-    void clearSingleTransition()
-    {
-        ASSERT(isUsingSingleSlot());
-        if (HandleSlot slot = this->slot())
-            HandleHeap::heapFor(slot)->deallocate(slot);
-    }
-    
-    void setSingleTransition(JSGlobalData& globalData, Structure* structure)
+    void setSingleTransition(JSGlobalData&, Structure* structure)
     {
         ASSERT(isUsingSingleSlot());
     {
         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);
+        if (WeakImpl* impl = this->weakImpl())
+            WeakSet::deallocate(impl);
+        WeakImpl* impl = WeakSet::allocate(reinterpret_cast<JSCell*>(structure));
+        m_data = reinterpret_cast<intptr_t>(impl) | UsingSingleSlotFlag;
     }
 
     intptr_t m_data;
     }
 
     intptr_t m_data;
index 2635501e11eaa4b74b3b462ad1bc00a0498d21f7..f540a12c73ef1726f6c2fdaefed591e5ceea369d 100644 (file)
@@ -32,6 +32,7 @@
 #include "JSObject.h"
 #include "UString.h"
 #include <wtf/AlwaysInline.h>
 #include "JSObject.h"
 #include "UString.h"
 #include <wtf/AlwaysInline.h>
+#include <wtf/HashTraits.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -112,9 +113,7 @@ namespace JSC {
         int m_bits;
     };
 
         int m_bits;
     };
 
-    struct SymbolTableIndexHashTraits {
-        typedef SymbolTableEntry TraitType;
-        static SymbolTableEntry emptyValue() { return SymbolTableEntry(); }
+    struct SymbolTableIndexHashTraits : HashTraits<SymbolTableEntry> {
         static const bool emptyValueIsZero = true;
         static const bool needsDestruction = false;
     };
         static const bool emptyValueIsZero = true;
         static const bool needsDestruction = false;
     };
@@ -126,7 +125,7 @@ namespace JSC {
     public:
         static PassRefPtr<SharedSymbolTable> create() { return adoptRef(new SharedSymbolTable); }
     private:
     public:
         static PassRefPtr<SharedSymbolTable> create() { return adoptRef(new SharedSymbolTable); }
     private:
-        SharedSymbolTable() { }
+        SharedSymbolTable() { turnOffVerifier(); }
     };
     
 } // namespace JSC
     };
     
 } // namespace JSC
index 81a096aad2826ca963ed2442930bd8b6970adaee..2798dac399355043ddb3b15683c4d38edf182c34 100644 (file)
 #elif OS(WINDOWS)
 #include <windows.h>
 #else
 #elif OS(WINDOWS)
 #include <windows.h>
 #else
-#include "CurrentTime.h"
-#endif
-
-#if PLATFORM(BREWMP)
-#include <AEEStdLib.h>
+#include <wtf/CurrentTime.h>
 #endif
 
 using namespace std;
 #endif
 
 using namespace std;
@@ -84,18 +80,6 @@ static inline unsigned getCPUTime()
     GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
     
     return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
     GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
     
     return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
-#elif OS(SYMBIAN)
-    RThread current;
-    TTimeIntervalMicroSeconds cpuTime;
-
-    TInt err = current.GetCpuTime(cpuTime);
-    ASSERT_WITH_MESSAGE(err == KErrNone, "GetCpuTime failed with %d", err);
-    return cpuTime.Int64() / 1000;
-#elif PLATFORM(BREWMP)
-    // This function returns a continuously and linearly increasing millisecond
-    // timer from the time the device was powered on.
-    // There is only one thread in BREW, so this is enough.
-    return GETUPTIMEMS();
 #else
     // FIXME: We should return the time the current thread has spent executing.
 
 #else
     // FIXME: We should return the time the current thread has spent executing.
 
@@ -145,11 +129,11 @@ bool TimeoutChecker::didTimeOut(ExecState* exec)
     if (m_ticksUntilNextCheck == 0)
         m_ticksUntilNextCheck = ticksUntilFirstCheck;
     
     if (m_ticksUntilNextCheck == 0)
         m_ticksUntilNextCheck = ticksUntilFirstCheck;
     
-    if (exec->dynamicGlobalObject()->shouldInterruptScriptBeforeTimeout())
+    if (exec->dynamicGlobalObject()->globalObjectMethodTable()->shouldInterruptScriptBeforeTimeout(exec->dynamicGlobalObject()))
         return true;
 
     if (m_timeoutInterval && m_timeExecuting > m_timeoutInterval) {
         return true;
 
     if (m_timeoutInterval && m_timeExecuting > m_timeoutInterval) {
-        if (exec->dynamicGlobalObject()->shouldInterruptScript())
+        if (exec->dynamicGlobalObject()->globalObjectMethodTable()->shouldInterruptScript(exec->dynamicGlobalObject()))
             return true;
         
         reset();
             return true;
         
         reset();
index 5925641f80a366ad34061b562c74cd822e3cfe9b..89d6158ccdd647e236932f6d4c9c21e039b60ef8 100644 (file)
@@ -57,9 +57,9 @@ namespace JSC {
             --m_startCount;
         }
 
             --m_startCount;
         }
 
-        void reset();
+        JS_EXPORT_PRIVATE void reset();
 
 
-        bool didTimeOut(ExecState*);
+        JS_EXPORT_PRIVATE bool didTimeOut(ExecState*);
 
     private:
         unsigned m_timeoutInterval;
 
     private:
         unsigned m_timeoutInterval;
index b70d505ce60cb193d3540451a1718d0db8ce31e3..5b1e9a0e0b12a0a7aefc627192562ab43377d4dc 100644 (file)
 #include <stdlib.h>
 #include <wtf/ASCIICType.h>
 #include <wtf/Assertions.h>
 #include <stdlib.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/MathExtras.h>
 #include <wtf/StringExtras.h>
 #include <wtf/Vector.h>
+#include <wtf/dtoa.h>
 #include <wtf/unicode/UTF8.h>
 
 #if HAVE(STRINGS_H)
 #include <wtf/unicode/UTF8.h>
 
 #if HAVE(STRINGS_H)
@@ -51,9 +51,6 @@ using namespace std;
 
 namespace JSC {
 
 
 namespace JSC {
 
-extern const double NaN;
-extern const double Inf;
-
 COMPILE_ASSERT(sizeof(UString) == sizeof(void*), UString_should_stay_small);
 
 // Construct a string with UTF-16 data.
 COMPILE_ASSERT(sizeof(UString) == sizeof(void*), UString_should_stay_small);
 
 // Construct a string with UTF-16 data.
@@ -76,22 +73,32 @@ UString::UString(const UChar* characters)
 }
 
 // Construct a string with latin1 data.
 }
 
 // Construct a string with latin1 data.
-UString::UString(const char* characters, unsigned length)
+UString::UString(const LChar* characters, unsigned length)
     : m_impl(characters ? StringImpl::create(characters, length) : 0)
 {
 }
 
     : m_impl(characters ? StringImpl::create(characters, length) : 0)
 {
 }
 
+UString::UString(const char* characters, unsigned length)
+    : m_impl(characters ? StringImpl::create(reinterpret_cast<const LChar*>(characters), length) : 0)
+{
+}
+
 // Construct a string with latin1 data, from a null-terminated source.
 // Construct a string with latin1 data, from a null-terminated source.
-UString::UString(const char* characters)
+UString::UString(const LChar* characters)
     : m_impl(characters ? StringImpl::create(characters) : 0)
 {
 }
 
     : m_impl(characters ? StringImpl::create(characters) : 0)
 {
 }
 
+UString::UString(const char* characters)
+    : m_impl(characters ? StringImpl::create(reinterpret_cast<const LChar*>(characters)) : 0)
+{
+}
+
 UString UString::number(int i)
 {
 UString UString::number(int i)
 {
-    UChar buf[1 + sizeof(i) * 3];
-    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
-    UChar* p = end;
+    LChar buf[1 + sizeof(i) * 3];
+    LChar* end = buf + WTF_ARRAY_LENGTH(buf);
+    LChar* p = end;
 
     if (i == 0)
         *--p = '0';
 
     if (i == 0)
         *--p = '0';
@@ -118,9 +125,9 @@ UString UString::number(int i)
 
 UString UString::number(long long i)
 {
 
 UString UString::number(long long i)
 {
-    UChar buf[1 + sizeof(i) * 3];
-    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
-    UChar* p = end;
+    LChar buf[1 + sizeof(i) * 3];
+    LChar* end = buf + WTF_ARRAY_LENGTH(buf);
+    LChar* p = end;
 
     if (i == 0)
         *--p = '0';
 
     if (i == 0)
         *--p = '0';
@@ -151,9 +158,9 @@ UString UString::number(long long i)
 
 UString UString::number(unsigned u)
 {
 
 UString UString::number(unsigned u)
 {
-    UChar buf[sizeof(u) * 3];
-    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
-    UChar* p = end;
+    LChar buf[sizeof(u) * 3];
+    LChar* end = buf + WTF_ARRAY_LENGTH(buf);
+    LChar* p = end;
 
     if (u == 0)
         *--p = '0';
 
     if (u == 0)
         *--p = '0';
@@ -169,9 +176,9 @@ UString UString::number(unsigned u)
 
 UString UString::number(long l)
 {
 
 UString UString::number(long l)
 {
-    UChar buf[1 + sizeof(l) * 3];
-    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
-    UChar* p = end;
+    LChar buf[1 + sizeof(l) * 3];
+    LChar* end = buf + WTF_ARRAY_LENGTH(buf);
+    LChar* p = end;
 
     if (l == 0)
         *--p = '0';
 
     if (l == 0)
         *--p = '0';
@@ -199,8 +206,7 @@ UString UString::number(long l)
 UString UString::number(double d)
 {
     NumberToStringBuffer buffer;
 UString UString::number(double d)
 {
     NumberToStringBuffer buffer;
-    unsigned length = numberToString(d, buffer);
-    return UString(buffer, length);
+    return UString(numberToString(d, buffer));
 }
 
 UString UString::substringSharingImpl(unsigned offset, unsigned length) const
 }
 
 UString UString::substringSharingImpl(unsigned offset, unsigned length) const
@@ -218,19 +224,81 @@ UString UString::substringSharingImpl(unsigned offset, unsigned length) const
 
 bool operator==(const UString& s1, const char *s2)
 {
 
 bool operator==(const UString& s1, const char *s2)
 {
-    if (s2 == 0)
-        return s1.isEmpty();
-
-    const UChar* u = s1.characters();
-    const UChar* uend = u + s1.length();
-    while (u != uend && *s2) {
-        if (u[0] != (unsigned char)*s2)
-            return false;
-        s2++;
-        u++;
-    }
+    if (s1.isEmpty())
+        return !s2;
 
 
-    return u == uend && *s2 == 0;
+    return equal(s1.impl(), s2);
+}
+
+// This method assumes that all simple checks have been performed by
+// the inlined operator==() in the header file.
+bool equalSlowCase(const UString& s1, const UString& s2)
+{
+    StringImpl* rep1 = s1.impl();
+    StringImpl* rep2 = s2.impl();
+    unsigned size1 = rep1->length();
+
+    // At this point we know 
+    //   (a) that the strings are the same length and
+    //   (b) that they are greater than zero length.
+    bool s1Is8Bit = rep1->is8Bit();
+    bool s2Is8Bit = rep2->is8Bit();
+    
+    if (s1Is8Bit) {
+        const LChar* d1 = rep1->characters8();
+        if (s2Is8Bit) {
+            const LChar* d2 = rep2->characters8();
+            
+            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(LChar)));
+            }
+        }
+        
+        const UChar* d2 = rep2->characters16();
+        
+        for (unsigned i = 0; i < size1; i++) {
+            if (d1[i] != d2[i])
+                return false;
+        }
+        return true;
+    }
+    
+    if (s2Is8Bit) {
+        const UChar* d1 = rep1->characters16();
+        const LChar* d2 = rep2->characters8();
+        
+        for (unsigned i = 0; i < size1; i++) {
+            if (d1[i] != d2[i])
+                return false;
+        }
+        return true;
+        
+    }
+    
+    const UChar* d1 = rep1->characters16();
+    const UChar* d2 = rep2->characters16();
+    
+    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)));
+    }
 }
 
 bool operator<(const UString& s1, const UString& s2)
 }
 
 bool operator<(const UString& s1, const UString& s2)
@@ -238,15 +306,29 @@ bool operator<(const UString& s1, const UString& s2)
     const unsigned l1 = s1.length();
     const unsigned l2 = s2.length();
     const unsigned lmin = l1 < l2 ? l1 : l2;
     const unsigned l1 = s1.length();
     const unsigned l2 = s2.length();
     const unsigned lmin = l1 < l2 ? l1 : l2;
+    if (s1.is8Bit() && s2.is8Bit()) {
+        const LChar* c1 = s1.characters8();
+        const LChar* c2 = s2.characters8();
+        unsigned length = 0;
+        while (length < lmin && *c1 == *c2) {
+            c1++;
+            c2++;
+            length++;
+        }
+        if (length < lmin)
+            return (c1[0] < c2[0]);
+
+        return (l1 < l2);        
+    }
     const UChar* c1 = s1.characters();
     const UChar* c2 = s2.characters();
     const UChar* c1 = s1.characters();
     const UChar* c2 = s2.characters();
-    unsigned l = 0;
-    while (l < lmin && *c1 == *c2) {
+    unsigned length = 0;
+    while (length < lmin && *c1 == *c2) {
         c1++;
         c2++;
         c1++;
         c2++;
-        l++;
+        length++;
     }
     }
-    if (l < lmin)
+    if (length < lmin)
         return (c1[0] < c2[0]);
 
     return (l1 < l2);
         return (c1[0] < c2[0]);
 
     return (l1 < l2);
@@ -277,7 +359,22 @@ CString UString::ascii() const
     // preserved, characters outside of this range are converted to '?'.
 
     unsigned length = this->length();
     // preserved, characters outside of this range are converted to '?'.
 
     unsigned length = this->length();
-    const UChar* characters = this->characters();
+
+    if (this->is8Bit()) {
+        const LChar* characters = this->characters8();
+        
+        char* characterBuffer;
+        CString result = CString::newUninitialized(length, characterBuffer);
+        
+        for (unsigned i = 0; i < length; ++i) {
+            LChar ch = characters[i];
+            characterBuffer[i] = ch && (ch < 0x20 || ch > 0x7f) ? '?' : ch;
+        }
+        
+        return result;        
+    }
+
+    const UChar* characters = this->characters16();
 
     char* characterBuffer;
     CString result = CString::newUninitialized(length, characterBuffer);
 
     char* characterBuffer;
     CString result = CString::newUninitialized(length, characterBuffer);
@@ -321,7 +418,9 @@ static inline void putUTF8Triple(char*& buffer, UChar ch)
 CString UString::utf8(bool strict) const
 {
     unsigned length = this->length();
 CString UString::utf8(bool strict) const
 {
     unsigned length = this->length();
-    const UChar* characters = this->characters();
+
+    if (!length)
+        return CString("", 0);
 
     // Allocate a buffer big enough to hold all the characters
     // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes).
 
     // Allocate a buffer big enough to hold all the characters
     // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes).
@@ -335,29 +434,39 @@ CString UString::utf8(bool strict) const
     //    buffer without reallocing (say, 1.5 x length).
     if (length > numeric_limits<unsigned>::max() / 3)
         return CString();
     //    buffer without reallocing (say, 1.5 x length).
     if (length > numeric_limits<unsigned>::max() / 3)
         return CString();
-    Vector<char, 1024> bufferVector(length * 3);
 
 
+    Vector<char, 1024> bufferVector(length * 3);
     char* buffer = bufferVector.data();
     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();
+    if (is8Bit()) {
+        const LChar* characters = this->characters8();
 
 
-    // Check for an unconverted high surrogate.
-    if (result == sourceExhausted) {
-        if (strict)
+        ConversionResult result = convertLatin1ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size());
+        ASSERT_UNUSED(result, result != targetExhausted); // (length * 3) should be sufficient for any conversion
+    } else {
+        const UChar* characters = this->characters16();
+
+        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();
             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);
+
+        // 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(bufferVector.data(), buffer - bufferVector.data());
     }
 
     return CString(bufferVector.data(), buffer - bufferVector.data());
index b98e7b40d7f597244d248b1126cf244c6e71b591..7677161a36a5ce4942cd53a809f995957a4f7fc1 100644 (file)
@@ -33,16 +33,18 @@ public:
     UString() { }
 
     // Construct a string with UTF-16 data.
     UString() { }
 
     // Construct a string with UTF-16 data.
-    UString(const UChar* characters, unsigned length);
+    JS_EXPORT_PRIVATE UString(const UChar* characters, unsigned length);
 
     // Construct a string with UTF-16 data, from a null-terminated source.
 
     // Construct a string with UTF-16 data, from a null-terminated source.
-    UString(const UChar*);
+    JS_EXPORT_PRIVATE UString(const UChar*);
 
     // Construct a string with latin1 data.
 
     // Construct a string with latin1 data.
-    UString(const char* characters, unsigned length);
+    UString(const LChar* characters, unsigned length);
+    JS_EXPORT_PRIVATE UString(const char* characters, unsigned length);
 
     // Construct a string with latin1 data, from a null-terminated source.
 
     // Construct a string with latin1 data, from a null-terminated source.
-    UString(const char* characters);
+    UString(const LChar* characters);
+    JS_EXPORT_PRIVATE UString(const char* characters);
 
     // Construct a string referencing an existing StringImpl.
     UString(StringImpl* impl) : m_impl(impl) { }
 
     // Construct a string referencing an existing StringImpl.
     UString(StringImpl* impl) : m_impl(impl) { }
@@ -54,8 +56,8 @@ public:
 
     void swap(UString& o) { m_impl.swap(o.m_impl); }
 
 
     void swap(UString& o) { m_impl.swap(o.m_impl); }
 
-    template<size_t inlineCapacity>
-    static UString adopt(Vector<UChar, inlineCapacity>& vector) { return StringImpl::adopt(vector); }
+    template<typename CharType, size_t inlineCapacity>
+    static UString adopt(Vector<CharType, inlineCapacity>& vector) { return StringImpl::adopt(vector); }
 
     bool isNull() const { return !m_impl; }
     bool isEmpty() const { return !m_impl || !m_impl->length(); }
 
     bool isNull() const { return !m_impl; }
     bool isEmpty() const { return !m_impl || !m_impl->length(); }
@@ -76,29 +78,56 @@ public:
         return m_impl->characters();
     }
 
         return m_impl->characters();
     }
 
-    CString ascii() const;
+    const LChar* characters8() const
+    {
+        if (!m_impl)
+            return 0;
+        ASSERT(m_impl->is8Bit());
+        return m_impl->characters8();
+    }
+
+    const UChar* characters16() const
+    {
+        if (!m_impl)
+            return 0;
+        ASSERT(!m_impl->is8Bit());
+        return m_impl->characters16();
+    }
+
+    template <typename CharType>
+    inline const CharType* getCharacters() const;
+
+    bool is8Bit() const { return m_impl->is8Bit(); }
+
+    JS_EXPORT_PRIVATE CString ascii() const;
     CString latin1() const;
     CString latin1() const;
-    CString utf8(bool strict = false) const;
+    JS_EXPORT_PRIVATE CString utf8(bool strict = false) const;
 
     UChar operator[](unsigned index) const
     {
         if (!m_impl || index >= m_impl->length())
             return 0;
 
     UChar operator[](unsigned index) const
     {
         if (!m_impl || index >= m_impl->length())
             return 0;
-        return m_impl->characters()[index];
+        if (is8Bit())
+            return m_impl->characters8()[index];
+        return m_impl->characters16()[index];
     }
 
     }
 
-    static UString number(int);
-    static UString number(unsigned);
-    static UString number(long);
+    JS_EXPORT_PRIVATE static UString number(int);
+    JS_EXPORT_PRIVATE static UString number(unsigned);
+    JS_EXPORT_PRIVATE static UString number(long);
     static UString number(long long);
     static UString number(long long);
-    static UString number(double);
+    JS_EXPORT_PRIVATE 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; }
 
     // 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
+
+    size_t find(const UString& str) const
+        { return m_impl ? m_impl->find(str.impl()) : notFound; }
+    size_t find(const UString& str, unsigned start) const
         { return m_impl ? m_impl->find(str.impl(), start) : notFound; }
         { return m_impl ? m_impl->find(str.impl(), start) : notFound; }
-    size_t find(const char* str, unsigned start = 0) const
+
+    size_t find(const LChar* str, unsigned start = 0) const
         { return m_impl ? m_impl->find(str, start) : notFound; }
 
     // Find the last instance of a single character or string.
         { return m_impl ? m_impl->find(str, start) : notFound; }
 
     // Find the last instance of a single character or string.
@@ -107,52 +136,47 @@ public:
     size_t reverseFind(const UString& str, unsigned start = UINT_MAX) const
         { return m_impl ? m_impl->reverseFind(str.impl(), 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;
+    JS_EXPORT_PRIVATE UString substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const;
 
 private:
     RefPtr<StringImpl> m_impl;
 };
 
 
 private:
     RefPtr<StringImpl> m_impl;
 };
 
+template<>
+inline const LChar* UString::getCharacters<LChar>() const { return characters8(); }
+
+template<>
+inline const UChar* UString::getCharacters<UChar>() const { return characters(); }
+
+NEVER_INLINE bool equalSlowCase(const UString& s1, const UString& s2);
+
 ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2)
 {
     StringImpl* rep1 = s1.impl();
     StringImpl* rep2 = s2.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 == rep2) // If they're the same rep, they're equal.
         return true;
-    
+
+    unsigned size1 = 0;
+    unsigned size2 = 0;
+
     if (rep1)
         size1 = rep1->length();
     if (rep1)
         size1 = rep1->length();
-        
+
     if (rep2)
         size2 = rep2->length();
     if (rep2)
         size2 = rep2->length();
-        
+
     if (size1 != size2) // If the lengths are not the same, we're done.
         return false;
     if (size1 != size2) // If the lengths are not the same, we're done.
         return false;
-    
+
     if (!size1)
         return true;
     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;
-    }
+
+    if (size1 == 1)
+        return (*rep1)[0u] == (*rep2)[0u];
+
+    return equalSlowCase(s1, s2);
 }
 
 
 }
 
 
@@ -161,10 +185,10 @@ inline bool operator!=(const UString& s1, const UString& s2)
     return !JSC::operator==(s1, s2);
 }
 
     return !JSC::operator==(s1, s2);
 }
 
-bool operator<(const UString& s1, const UString& s2);
-bool operator>(const UString& s1, const UString& s2);
+JS_EXPORT_PRIVATE bool operator<(const UString& s1, const UString& s2);
+JS_EXPORT_PRIVATE bool operator>(const UString& s1, const UString& s2);
 
 
-bool operator==(const UString& s1, const char* s2);
+JS_EXPORT_PRIVATE bool operator==(const UString& s1, const char* s2);
 
 inline bool operator!=(const UString& s1, const char* s2)
 {
 
 inline bool operator!=(const UString& s1, const char* s2)
 {
@@ -202,7 +226,7 @@ struct UStringHash {
 
         // 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) || CPU(MIPS)
+#if CPU(ARM) || CPU(SH4) || CPU(MIPS) || CPU(SPARC)
         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) {
index 0990c7273ac1720889bbfaae2059d4097facc358..cbd4e60ca4b3a7ae54fcc7525ffaf20946bee2d2 100644 (file)
@@ -35,21 +35,37 @@ template<>
 class StringTypeAdapter<JSC::UString> {
 public:
     StringTypeAdapter<JSC::UString>(JSC::UString& string)
 class StringTypeAdapter<JSC::UString> {
 public:
     StringTypeAdapter<JSC::UString>(JSC::UString& string)
-        : m_data(string.characters())
+        : m_string(string)
         , m_length(string.length())
     {
     }
 
     unsigned length() { return m_length; }
 
         , m_length(string.length())
     {
     }
 
     unsigned length() { return m_length; }
 
-    void writeTo(UChar* destination)
+    bool is8Bit() { return m_string.isNull() || m_string.is8Bit(); }
+
+    void writeTo(LChar* destination)
     {
     {
+        const LChar* characters = m_string.characters8();
         for (unsigned i = 0; i < m_length; ++i)
         for (unsigned i = 0; i < m_length; ++i)
-            destination[i] = m_data[i];
+            destination[i] = characters[i];
+    }
+
+    void writeTo(UChar* destination)
+    {
+        if (is8Bit()) {
+            const LChar* characters = m_string.characters8();
+            for (unsigned i = 0; i < m_length; ++i)
+                destination[i] = characters[i];
+        } else {
+            const UChar* characters = m_string.characters16();
+            for (unsigned i = 0; i < m_length; ++i)
+                destination[i] = characters[i];
+        }
     }
 
 private:
     }
 
 private:
-    const UChar* m_data;
+    const JSC::UString& m_string;
     unsigned m_length;
 };
 
     unsigned m_length;
 };
 
diff --git a/runtime/Uint16WithFraction.h b/runtime/Uint16WithFraction.h
new file mode 100644 (file)
index 0000000..0e5c5f9
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * 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 Uint16WithFraction_h
+#define Uint16WithFraction_h
+
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+// Would be nice if this was a static const member, but the OS X linker
+// seems to want a symbol in the binary in that case...
+#define oneGreaterThanMaxUInt16 0x10000
+
+// A uint16_t with an infinite precision fraction. Upon overflowing
+// the uint16_t range, this class will clamp to oneGreaterThanMaxUInt16.
+// This is used in converting the fraction part of a number to a string.
+class Uint16WithFraction {
+public:
+    explicit Uint16WithFraction(double number, uint16_t divideByExponent = 0)
+    {
+        ASSERT(number && isfinite(number) && !signbit(number));
+
+        // Check for values out of uint16_t range.
+        if (number >= oneGreaterThanMaxUInt16) {
+            m_values.append(oneGreaterThanMaxUInt16);
+            m_leadingZeros = 0;
+            return;
+        }
+
+        // Append the units to m_values.
+        double integerPart = floor(number);
+        m_values.append(static_cast<uint32_t>(integerPart));
+
+        bool sign;
+        int32_t exponent;
+        uint64_t mantissa;
+        decomposeDouble(number - integerPart, sign, exponent, mantissa);
+        ASSERT(!sign && exponent < 0);
+        exponent -= divideByExponent;
+
+        int32_t zeroBits = -exponent;
+        --zeroBits;
+
+        // Append the append words for to m_values.
+        while (zeroBits >= 32) {
+            m_values.append(0);
+            zeroBits -= 32;
+        }
+
+        // Left align the 53 bits of the mantissa within 96 bits.
+        uint32_t values[3];
+        values[0] = static_cast<uint32_t>(mantissa >> 21);
+        values[1] = static_cast<uint32_t>(mantissa << 11);
+        values[2] = 0;
+        // Shift based on the remainder of the exponent.
+        if (zeroBits) {
+            values[2] = values[1] << (32 - zeroBits);
+            values[1] = (values[1] >> zeroBits) | (values[0] << (32 - zeroBits));
+            values[0] = (values[0] >> zeroBits);
+        }
+        m_values.append(values[0]);
+        m_values.append(values[1]);
+        m_values.append(values[2]);
+
+        // Canonicalize; remove any trailing zeros.
+        while (m_values.size() > 1 && !m_values.last())
+            m_values.removeLast();
+
+        // Count the number of leading zero, this is useful in optimizing multiplies.
+        m_leadingZeros = 0;
+        while (m_leadingZeros < m_values.size() && !m_values[m_leadingZeros])
+            ++m_leadingZeros;
+    }
+
+    Uint16WithFraction& operator*=(uint16_t multiplier)
+    {
+        ASSERT(checkConsistency());
+
+        // iteratate backwards over the fraction until we reach the leading zeros,
+        // passing the carry from one calculation into the next.
+        uint64_t accumulator = 0;
+        for (size_t i = m_values.size(); i > m_leadingZeros; ) {
+            --i;
+            accumulator += static_cast<uint64_t>(m_values[i]) * static_cast<uint64_t>(multiplier);
+            m_values[i] = static_cast<uint32_t>(accumulator);
+            accumulator >>= 32;
+        }
+
+        if (!m_leadingZeros) {
+            // With a multiplicand and multiplier in the uint16_t range, this cannot carry
+            // (even allowing for the infinity value).
+            ASSERT(!accumulator);
+            // Check for overflow & clamp to 'infinity'.
+            if (m_values[0] >= oneGreaterThanMaxUInt16) {
+                m_values.shrink(1);
+                m_values[0] = oneGreaterThanMaxUInt16;
+                m_leadingZeros = 0;
+                return *this;
+            }
+        } else if (accumulator) {
+            // Check for carry from the last multiply, if so overwrite last leading zero.
+            m_values[--m_leadingZeros] = static_cast<uint32_t>(accumulator);
+            // The limited range of the multiplier should mean that even if we carry into
+            // the units, we don't need to check for overflow of the uint16_t range.
+            ASSERT(m_values[0] < oneGreaterThanMaxUInt16);
+        }
+
+        // Multiplication by an even value may introduce trailing zeros; if so, clean them
+        // up. (Keeping the value in a normalized form makes some of the comparison operations
+        // more efficient).
+        while (m_values.size() > 1 && !m_values.last())
+            m_values.removeLast();
+        ASSERT(checkConsistency());
+        return *this;
+    }
+
+    bool operator<(const Uint16WithFraction& other)
+    {
+        ASSERT(checkConsistency());
+        ASSERT(other.checkConsistency());
+
+        // Iterate over the common lengths of arrays.
+        size_t minSize = std::min(m_values.size(), other.m_values.size());
+        for (size_t index = 0; index < minSize; ++index) {
+            // If we find a value that is not equal, compare and return.
+            uint32_t fromThis = m_values[index];
+            uint32_t fromOther = other.m_values[index];
+            if (fromThis != fromOther)
+                return fromThis < fromOther;
+        }
+        // If these numbers have the same lengths, they are equal,
+        // otherwise which ever number has a longer fraction in larger.
+        return other.m_values.size() > minSize;
+    }
+
+    // Return the floor (non-fractional portion) of the number, clearing this to zero,
+    // leaving the fractional part unchanged.
+    uint32_t floorAndSubtract()
+    {
+        // 'floor' is simple the integer portion of the value.
+        uint32_t floor = m_values[0];
+
+        // If floor is non-zero, 
+        if (floor) {
+            m_values[0] = 0;
+            m_leadingZeros = 1;
+            while (m_leadingZeros < m_values.size() && !m_values[m_leadingZeros])
+                ++m_leadingZeros;
+        }
+
+        return floor;
+    }
+
+    // Compare this value to 0.5, returns -1 for less than, 0 for equal, 1 for greater.
+    int comparePoint5()
+    {
+        ASSERT(checkConsistency());
+        // If units != 0, this is greater than 0.5.
+        if (m_values[0])
+            return 1;
+        // If size == 1 this value is 0, hence < 0.5.
+        if (m_values.size() == 1)
+            return -1;
+        // Compare to 0.5.
+        if (m_values[1] > 0x80000000ul)
+            return 1;
+        if (m_values[1] < 0x80000000ul)
+            return -1;
+        // Check for more words - since normalized numbers have no trailing zeros, if
+        // there are more that two digits we can assume at least one more is non-zero,
+        // and hence the value is > 0.5.
+        return m_values.size() > 2 ? 1 : 0;
+    }
+
+    // Return true if the sum of this plus addend would be greater than 1.
+    bool sumGreaterThanOne(const Uint16WithFraction& addend) 
+    {
+        ASSERT(checkConsistency());
+        ASSERT(addend.checkConsistency());
+
+        // First, sum the units. If the result is greater than one, return true.
+        // If equal to one, return true if either number has a fractional part.
+        uint32_t sum = m_values[0] + addend.m_values[0];
+        if (sum)
+            return sum > 1 || std::max(m_values.size(), addend.m_values.size()) > 1;
+
+        // We could still produce a result greater than zero if addition of the next
+        // word from the fraction were to carry, leaving a result > 0.
+
+        // Iterate over the common lengths of arrays.
+        size_t minSize = std::min(m_values.size(), addend.m_values.size());
+        for (size_t index = 1; index < minSize; ++index) {
+            // Sum the next word from this & the addend.
+            uint32_t fromThis = m_values[index];
+            uint32_t fromAddend = addend.m_values[index];
+            sum = fromThis + fromAddend;
+
+            // Check for overflow. If so, check whether the remaining result is non-zero,
+            // or if there are any further words in the fraction.
+            if (sum < fromThis)
+                return sum || (index + 1) < std::max(m_values.size(), addend.m_values.size());
+
+            // If the sum is uint32_t max, then we would carry a 1 if addition of the next
+            // digits in the number were to overflow.
+            if (sum != 0xFFFFFFFF)
+                return false;
+        }
+        return false;
+    }
+
+private:
+    bool checkConsistency() const
+    {
+        // All values should have at least one value.
+        return (m_values.size())
+            // The units value must be a uint16_t, or the value is the overflow value.
+            && (m_values[0] < oneGreaterThanMaxUInt16 || (m_values[0] == oneGreaterThanMaxUInt16 && m_values.size() == 1))
+            // There should be no trailing zeros (unless this value is zero!).
+            && (m_values.last() || m_values.size() == 1);
+    }
+
+    // The internal storage of the number. This vector is always at least one entry in size,
+    // with the first entry holding the portion of the number greater than zero. The first
+    // value always hold a value in the uint16_t range, or holds the value oneGreaterThanMaxUInt16 to
+    // indicate the value has overflowed to >= 0x10000. If the units value is oneGreaterThanMaxUInt16,
+    // there can be no fraction (size must be 1).
+    //
+    // Subsequent values in the array represent portions of the fractional part of this number.
+    // The total value of the number is the sum of (m_values[i] / pow(2^32, i)), for each i
+    // in the array. The vector should contain no trailing zeros, except for the value '0',
+    // represented by a vector contianing a single zero value. These constraints are checked
+    // by 'checkConsistency()', above.
+    //
+    // The inline capacity of the vector is set to be able to contain any IEEE double (1 for
+    // the units column, 32 for zeros introduced due to an exponent up to -3FE, and 2 for
+    // bits taken from the mantissa).
+    Vector<uint32_t, 36> m_values;
+
+    // Cache a count of the number of leading zeros in m_values. We can use this to optimize
+    // methods that would otherwise need visit all words in the vector, e.g. multiplication.
+    size_t m_leadingZeros;
+};
+
+}
+
+#endif
+
index 5ad1c62a3e97298d24047f649878d197259e22f6..e7e9447ab5d2fb53b95c4462f103a54a9dce437b 100644 (file)
@@ -51,7 +51,7 @@ class WeakGCMap : private WeakHandleOwner {
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(WeakGCMap);
 
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(WeakGCMap);
 
-    typedef HashMap<KeyType, HandleSlot, HashArg, KeyTraitsArg> MapType;
+    typedef HashMap<KeyType, WeakImpl*, HashArg, KeyTraitsArg> MapType;
     typedef typename HandleTypes<MappedType>::ExternalType ExternalType;
     typedef typename MapType::iterator map_iterator;
 
     typedef typename HandleTypes<MappedType>::ExternalType ExternalType;
     typedef typename MapType::iterator map_iterator;
 
@@ -64,8 +64,7 @@ public:
         {
         }
         
         {
         }
         
-        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; }
+        std::pair<KeyType, ExternalType> get() const { return std::make_pair(m_iterator->first, HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&m_iterator->second->jsValue()))); }
         
         iterator& operator++() { ++m_iterator; return *this; }
         
         
         iterator& operator++() { ++m_iterator; return *this; }
         
@@ -79,6 +78,8 @@ public:
         map_iterator m_iterator;
     };
 
         map_iterator m_iterator;
     };
 
+    typedef WTF::HashTableAddResult<iterator> AddResult;
+
     WeakGCMap()
     {
     }
     WeakGCMap()
     {
     }
@@ -88,7 +89,7 @@ public:
     {
         map_iterator end = m_map.end();
         for (map_iterator ptr = m_map.begin(); ptr != end; ++ptr)
     {
         map_iterator end = m_map.end();
         for (map_iterator ptr = m_map.begin(); ptr != end; ++ptr)
-            HandleHeap::heapFor(ptr->second)->deallocate(ptr->second);
+            WeakSet::deallocate(ptr->second);
         m_map.clear();
     }
 
         m_map.clear();
     }
 
@@ -105,63 +106,43 @@ public:
     void remove(iterator iter)
     {
         ASSERT(iter.m_iterator != m_map.end());
     void remove(iterator iter)
     {
         ASSERT(iter.m_iterator != m_map.end());
-        HandleSlot slot = iter.m_iterator->second;
-        ASSERT(slot);
-        HandleHeap::heapFor(slot)->deallocate(slot);
+        WeakImpl* impl = iter.m_iterator->second;
+        ASSERT(impl);
+        WeakSet::deallocate(impl);
         m_map.remove(iter.m_iterator);
     }
 
     ExternalType get(const KeyType& key) const
     {
         m_map.remove(iter.m_iterator);
     }
 
     ExternalType get(const KeyType& key) const
     {
-        return HandleTypes<MappedType>::getFromSlot(m_map.get(key));
+        return HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&m_map.get(key)->jsValue()));
     }
 
     }
 
-    HandleSlot getSlot(const KeyType& key) const
+    AddResult add(JSGlobalData&, const KeyType& key, ExternalType value)
     {
     {
-        return m_map.get(key);
-    }
+        typename MapType::AddResult result = m_map.add(key, 0);
+        if (result.isNewEntry)
+            result.iterator->second = WeakSet::allocate(value, this, FinalizerCallback::finalizerContextFor(key));
 
 
-    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;
+        // WeakGCMap exposes a different iterator, so we need to wrap it and create our own AddResult.
+        return AddResult(iterator(result.iterator), result.isNewEntry);
     }
 
     void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)
     {
     }
 
     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;
+        ASSERT_UNUSED(globalData, globalData.apiLock().currentThreadIsHoldingLock());
+        typename MapType::AddResult result = m_map.add(key, 0);
+        if (!result.isNewEntry)
+            WeakSet::deallocate(result.iterator->second);
+        result.iterator->second = WeakSet::allocate(value, this, FinalizerCallback::finalizerContextFor(key));
     }
 
     ExternalType take(const KeyType& key)
     {
     }
 
     ExternalType take(const KeyType& key)
     {
-        HandleSlot slot = m_map.take(key);
-        if (!slot)
+        WeakImpl* impl = m_map.take(key);
+        if (!impl)
             return HashTraits<ExternalType>::emptyValue();
             return HashTraits<ExternalType>::emptyValue();
-        ExternalType result = HandleTypes<MappedType>::getFromSlot(slot);
-        HandleHeap::heapFor(slot)->deallocate(slot);
+        ExternalType result = HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&impl->jsValue()));
+        WeakSet::deallocate(impl);
         return result;
     }
 
         return result;
     }
 
@@ -178,9 +159,9 @@ public:
 private:
     virtual void finalize(Handle<Unknown> handle, void* context)
     {
 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);
+        WeakImpl* impl = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes<MappedType>::getFromSlot(handle.slot())));
+        ASSERT(impl);
+        WeakSet::deallocate(impl);
     }
 
     MapType m_map;
     }
 
     MapType m_map;
index 89989479529c003e9d6d1b9764317106aa5d08b1..05f3bc5bba93eecf046ba5e3d870d098563bc0a4 100644 (file)
 #ifndef WriteBarrier_h
 #define WriteBarrier_h
 
 #ifndef WriteBarrier_h
 #define WriteBarrier_h
 
+#include "GCAssertions.h"
 #include "HandleTypes.h"
 #include "Heap.h"
 #include "HandleTypes.h"
 #include "Heap.h"
-#include "TypeTraits.h"
+#include "SamplingCounter.h"
+#include <wtf/TypeTraits.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -39,8 +41,8 @@ class JSGlobalObject;
 template<class T> class WriteBarrierBase;
 template<> class WriteBarrierBase<JSValue>;
 
 template<class T> class WriteBarrierBase;
 template<> class WriteBarrierBase<JSValue>;
 
-void slowValidateCell(JSCell*);
-void slowValidateCell(JSGlobalObject*);
+JS_EXPORT_PRIVATE void slowValidateCell(JSCell*);
+JS_EXPORT_PRIVATE void slowValidateCell(JSGlobalObject*);
     
 #if ENABLE(GC_VALIDATION)
 template<class T> inline void validateCell(T cell)
     
 #if ENABLE(GC_VALIDATION)
 template<class T> inline void validateCell(T cell)
@@ -72,6 +74,13 @@ public:
         validateCell(value);
         setEarlyValue(globalData, owner, value);
     }
         validateCell(value);
         setEarlyValue(globalData, owner, value);
     }
+    
+    // This is meant to be used like operator=, but is called copyFrom instead, in
+    // order to kindly inform the C++ compiler that its advice is not appreciated.
+    void copyFrom(const WriteBarrierBase<T>& other)
+    {
+        m_cell = other.m_cell;
+    }
 
     void setMayBeNull(JSGlobalData& globalData, const JSCell* owner, T* value)
     {
 
     void setMayBeNull(JSGlobalData& globalData, const JSCell* owner, T* value)
     {
@@ -86,25 +95,18 @@ public:
     {
         this->m_cell = reinterpret_cast<JSCell*>(value);
         Heap::writeBarrier(owner, this->m_cell);
     {
         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);
     }
     
     T* get() const
     {
         if (m_cell)
             validateCell(m_cell);
-        return reinterpret_cast<T*>(m_cell);
+        return reinterpret_cast<T*>(static_cast<void*>(m_cell));
     }
 
     T* operator*() const
     {
         ASSERT(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);
     }
         validateCell<T>(static_cast<T*>(m_cell));
         return static_cast<T*>(m_cell);
     }
@@ -127,14 +129,14 @@ public:
 
     void setWithoutWriteBarrier(T* value)
     {
 
     void setWithoutWriteBarrier(T* value)
     {
-        this->m_cell = reinterpret_cast<JSCell*>(value);
-#if ENABLE(JSC_ZOMBIES)
-        ASSERT(!m_cell || !isZombie(m_cell));
+#if ENABLE(WRITE_BARRIER_PROFILING)
+        WriteBarrierCounters::usesWithoutBarrierFromCpp.count();
 #endif
 #endif
+        this->m_cell = reinterpret_cast<JSCell*>(value);
     }
 
 #if ENABLE(GC_VALIDATION)
     }
 
 #if ENABLE(GC_VALIDATION)
-    T* unvalidatedGet() const { return reinterpret_cast<T*>(m_cell); }
+    T* unvalidatedGet() const { return reinterpret_cast<T*>(static_cast<void*>(m_cell)); }
 #endif
 
 private:
 #endif
 
 private:
@@ -145,19 +147,12 @@ template <> class WriteBarrierBase<Unknown> {
 public:
     void set(JSGlobalData&, const JSCell* owner, JSValue value)
     {
 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)
     {
         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);
     }
 
         m_value = JSValue::encode(value);
     }
 
@@ -234,14 +229,9 @@ template<typename T> inline void MarkStack::append(WriteBarrierBase<T>* slot)
     internalAppend(*slot->slot());
 }
 
     internalAppend(*slot->slot());
 }
 
-inline void MarkStack::appendValues(WriteBarrierBase<Unknown>* barriers, size_t count, MarkSetProperties properties)
+ALWAYS_INLINE void MarkStack::appendValues(WriteBarrierBase<Unknown>* barriers, size_t count)
 {
 {
-    JSValue* values = barriers->slot();
-#if ENABLE(GC_VALIDATION)
-    validateSet(values, count);
-#endif
-    if (count)
-        m_markSets.append(MarkSet(values, values + count, properties));
+    append(barriers->slot(), count);
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC
index a3272048b16700e85e3153e2066c2b1f40218085..85ad89a885255ea80266415416b052fa9e766fd3 100644 (file)
@@ -1,25 +1,28 @@
-SET(JSC_HEADERS
-)
-
 SET(JSC_SOURCES
     ../jsc.cpp
 )
 
 SET(JSC_LIBRARIES
 SET(JSC_SOURCES
     ../jsc.cpp
 )
 
 SET(JSC_LIBRARIES
+    ${WTF_LIBRARY_NAME}
     ${JavaScriptCore_LIBRARY_NAME}
 )
 
     ${JavaScriptCore_LIBRARY_NAME}
 )
 
-INCLUDE_IF_EXISTS(${JAVASCRIPTCORE_DIR}/shell/CMakeLists${PORT}.txt)
+WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS()
 
 WEBKIT_WRAP_SOURCELIST(${JSC_SOURCES})
 INCLUDE_DIRECTORIES(./ ${JavaScriptCore_INCLUDE_DIRECTORIES})
 
 WEBKIT_WRAP_SOURCELIST(${JSC_SOURCES})
 INCLUDE_DIRECTORIES(./ ${JavaScriptCore_INCLUDE_DIRECTORIES})
-ADD_EXECUTABLE(${JSC_EXECUTABLE_NAME} ${JSC_HEADERS} ${JSC_SOURCES})
+ADD_EXECUTABLE(${JSC_EXECUTABLE_NAME} ${JSC_SOURCES})
 TARGET_LINK_LIBRARIES(${JSC_EXECUTABLE_NAME} ${JSC_LIBRARIES})
 TARGET_LINK_LIBRARIES(${JSC_EXECUTABLE_NAME} ${JSC_LIBRARIES})
+SET_TARGET_PROPERTIES(${JSC_EXECUTABLE_NAME} PROPERTIES FOLDER "JavaScriptCore")
 
 IF (JSC_LINK_FLAGS)
     ADD_TARGET_PROPERTIES(${JSC_EXECUTABLE_NAME} LINK_FLAGS "${JSC_LINK_FLAGS}")
 ENDIF ()
 
 
 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})
+IF ("${PORT}" STREQUAL "Efl")
+    SET_TARGET_PROPERTIES(${JSC_EXECUTABLE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
+ENDIF ()
+
+IF (SHOULD_INSTALL_JS_SHELL)
+    INSTALL(TARGETS ${JSC_EXECUTABLE_NAME} DESTINATION bin)
 ENDIF ()
 ENDIF ()
diff --git a/shell/CMakeListsEfl.txt b/shell/CMakeListsEfl.txt
deleted file mode 100644 (file)
index 58d44f4..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-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
deleted file mode 100644 (file)
index 0b7a3bf..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-LIST(APPEND JSC_SOURCES
-    ../os-win32/WinMain.cpp
-)
diff --git a/shell/PlatformBlackBerry.cmake b/shell/PlatformBlackBerry.cmake
new file mode 100644 (file)
index 0000000..4271148
--- /dev/null
@@ -0,0 +1,15 @@
+LIST(APPEND JSC_LIBRARIES
+    ${ICUI18N_LIBRARY}
+    ${ICUUC_LIBRARY}
+    ${INTL_LIBRARY} # Required for x86 builds
+    ${M_LIBRARY}
+    ${Screen_LIBRARY}
+    ${Skia_QNX_LIBRARY}
+    ${WebKitPlatform_LIBRARY}
+)
+
+IF (PROFILING)
+    LIST(APPEND JSC_LIBRARIES
+        ${PROFILING_LIBRARY}
+    )
+ENDIF ()
diff --git a/shell/PlatformEfl.cmake b/shell/PlatformEfl.cmake
new file mode 100644 (file)
index 0000000..c35af2d
--- /dev/null
@@ -0,0 +1,9 @@
+LIST(APPEND JSC_LIBRARIES
+    ${Glib_LIBRARIES}
+    ${ECORE_LIBRARIES}
+    ${CMAKE_DL_LIBS}
+)
+
+LIST(APPEND JSC_LINK_FLAGS
+    ${ECORE_LDFLAGS}
+)
diff --git a/shell/PlatformWinCE.cmake b/shell/PlatformWinCE.cmake
new file mode 100644 (file)
index 0000000..0b7a3bf
--- /dev/null
@@ -0,0 +1,3 @@
+LIST(APPEND JSC_SOURCES
+    ../os-win32/WinMain.cpp
+)
diff --git a/testRegExp.cpp b/testRegExp.cpp
new file mode 100644 (file)
index 0000000..61c21c3
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ *  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 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 "RegExp.h"
+
+#include <wtf/CurrentTime.h>
+#include "InitializeThreading.h"
+#include "JSGlobalObject.h"
+#include "UStringBuilder.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !OS(WINDOWS)
+#include <unistd.h>
+#endif
+
+#if HAVE(SYS_TIME_H)
+#include <sys/time.h>
+#endif
+
+#if COMPILER(MSVC) && !OS(WINCE)
+#include <crtdbg.h>
+#include <mmsystem.h>
+#include <windows.h>
+#endif
+
+#if PLATFORM(QT)
+#include <QCoreApplication>
+#include <QDateTime>
+#endif
+
+const int MaxLineLength = 100 * 1024;
+
+using namespace JSC;
+using namespace WTF;
+
+struct CommandLine {
+    CommandLine()
+        : interactive(false)
+        , verbose(false)
+    {
+    }
+
+    bool interactive;
+    bool verbose;
+    Vector<UString> arguments;
+    Vector<UString> files;
+};
+
+class StopWatch {
+public:
+    void start();
+    void stop();
+    long getElapsedMS(); // call stop() first
+
+private:
+    double m_startTime;
+    double m_stopTime;
+};
+
+void StopWatch::start()
+{
+    m_startTime = currentTime();
+}
+
+void StopWatch::stop()
+{
+    m_stopTime = currentTime();
+}
+
+long StopWatch::getElapsedMS()
+{
+    return static_cast<long>((m_stopTime - m_startTime) * 1000);
+}
+
+struct RegExpTest {
+    RegExpTest()
+        : offset(0)
+        , result(0)
+    {
+    }
+
+    UString subject;
+    int offset;
+    int result;
+    Vector<int, 32> expectVector;
+};
+
+class GlobalObject : public JSGlobalObject {
+private:
+    GlobalObject(JSGlobalData&, Structure*, const Vector<UString>& arguments);
+
+public:
+    typedef JSGlobalObject Base;
+
+    static GlobalObject* create(JSGlobalData& globalData, Structure* structure, const Vector<UString>& arguments)
+    {
+        return new (NotNull, allocateCell<GlobalObject>(globalData.heap)) GlobalObject(globalData, structure, arguments);
+    }
+
+    static const ClassInfo s_info;
+
+    static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+    {
+        return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
+    }
+
+protected:
+    void finishCreation(JSGlobalData& globalData, const Vector<UString>& arguments)
+    {
+        Base::finishCreation(globalData);
+        UNUSED_PARAM(arguments);
+    }
+};
+
+COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
+ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
+
+const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
+
+GlobalObject::GlobalObject(JSGlobalData& globalData, Structure* structure, const Vector<UString>& arguments)
+    : JSGlobalObject(globalData, structure)
+{
+    finishCreation(globalData, arguments);
+}
+
+// Use SEH for Release builds only to get rid of the crash report dialog
+// (luckily the same tests fail in Release and Debug builds so far). Need to
+// be in a separate main function because the realMain function requires object
+// unwinding.
+
+#if COMPILER(MSVC) && !COMPILER(INTEL) && !defined(_DEBUG) && !OS(WINCE)
+#define TRY       __try {
+#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
+#else
+#define TRY
+#define EXCEPT(x)
+#endif
+
+int realMain(int argc, char** argv);
+
+int main(int argc, char** argv)
+{
+#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);
+    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
+    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
+#endif
+
+    timeBeginPeriod(1);
+#endif
+
+#if PLATFORM(QT)
+    QCoreApplication app(argc, argv);
+#endif
+
+    // Initialize JSC before getting JSGlobalData.
+    JSC::initializeThreading();
+
+    // We can't use destructors in the following code because it uses Windows
+    // Structured Exception Handling
+    int res = 0;
+    TRY
+        res = realMain(argc, argv);
+    EXCEPT(res = 3)
+    return res;
+}
+
+static bool testOneRegExp(JSGlobalData& globalData, RegExp* regexp, RegExpTest* regExpTest, bool verbose, unsigned int lineNumber)
+{
+    bool result = true;
+    Vector<int, 32> outVector;
+    outVector.resize(regExpTest->expectVector.size());
+    int matchResult = regexp->match(globalData, regExpTest->subject, regExpTest->offset, outVector);
+
+    if (matchResult != regExpTest->result) {
+        result = false;
+        if (verbose)
+            printf("Line %d: results mismatch - expected %d got %d\n", lineNumber, regExpTest->result, matchResult);
+    } else if (matchResult != -1) {
+        if (outVector.size() != regExpTest->expectVector.size()) {
+            result = false;
+            if (verbose)
+                printf("Line %d: output vector size mismatch - expected %lu got %lu\n", lineNumber, regExpTest->expectVector.size(), outVector.size());
+        } else if (outVector.size() % 2) {
+            result = false;
+            if (verbose)
+                printf("Line %d: output vector size is odd (%lu), should be even\n", lineNumber, outVector.size());
+        } else {
+            // Check in pairs since the first value of the pair could be -1 in which case the second doesn't matter.
+            size_t pairCount = outVector.size() / 2;
+            for (size_t i = 0; i < pairCount; ++i) {
+                size_t startIndex = i*2;
+                if (outVector[startIndex] != regExpTest->expectVector[startIndex]) {
+                    result = false;
+                    if (verbose)
+                        printf("Line %d: output vector mismatch at index %lu - expected %d got %d\n", lineNumber, startIndex, regExpTest->expectVector[startIndex], outVector[startIndex]);
+                }
+                if ((i > 0) && (regExpTest->expectVector[startIndex] != -1) && (outVector[startIndex+1] != regExpTest->expectVector[startIndex+1])) {
+                    result = false;
+                    if (verbose)
+                        printf("Line %d: output vector mismatch at index %lu - expected %d got %d\n", lineNumber, startIndex+1, regExpTest->expectVector[startIndex+1], outVector[startIndex+1]);
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+static int scanString(char* buffer, int bufferLength, UStringBuilder& builder, char termChar)
+{
+    bool escape = false;
+    
+    for (int i = 0; i < bufferLength; ++i) {
+        UChar c = buffer[i];
+        
+        if (escape) {
+            switch (c) {
+            case '0':
+                c = '\0';
+                break;
+            case 'a':
+                c = '\a';
+                break;
+            case 'b':
+                c = '\b';
+                break;
+            case 'f':
+                c = '\f';
+                break;
+            case 'n':
+                c = '\n';
+                break;
+            case 'r':
+                c = '\r';
+                break;
+            case 't':
+                c = '\t';
+                break;
+            case 'v':
+                c = '\v';
+                break;
+            case '\\':
+                c = '\\';
+                break;
+            case '?':
+                c = '\?';
+                break;
+            case 'u':
+                if ((i + 4) >= bufferLength)
+                    return -1;
+                unsigned int charValue;
+                if (sscanf(buffer+i+1, "%04x", &charValue) != 1)
+                    return -1;
+                c = static_cast<UChar>(charValue);
+                i += 4;
+                break;
+            }
+            
+            builder.append(c);
+            escape = false;
+        } else {
+            if (c == termChar)
+                return i;
+
+            if (c == '\\')
+                escape = true;
+            else
+                builder.append(c);
+        }
+    }
+
+    return -1;
+}
+
+static RegExp* parseRegExpLine(JSGlobalData& globalData, char* line, int lineLength)
+{
+    UStringBuilder pattern;
+    
+    if (line[0] != '/')
+        return 0;
+
+    int i = scanString(line + 1, lineLength - 1, pattern, '/') + 1;
+
+    if ((i >= lineLength) || (line[i] != '/'))
+        return 0;
+
+    ++i;
+
+    return RegExp::create(globalData, pattern.toUString(), regExpFlags(line + i));
+}
+
+static RegExpTest* parseTestLine(char* line, int lineLength)
+{
+    UStringBuilder subjectString;
+    
+    if ((line[0] != ' ') || (line[1] != '"'))
+        return 0;
+
+    int i = scanString(line + 2, lineLength - 2, subjectString, '"') + 2;
+
+    if ((i >= (lineLength - 2)) || (line[i] != '"') || (line[i+1] != ',') || (line[i+2] != ' '))
+        return 0;
+
+    i += 3;
+    
+    int offset;
+    
+    if (sscanf(line + i, "%d, ", &offset) != 1)
+        return 0;
+
+    while (line[i] && line[i] != ' ')
+        ++i;
+
+    ++i;
+    
+    int matchResult;
+    
+    if (sscanf(line + i, "%d, ", &matchResult) != 1)
+        return 0;
+    
+    while (line[i] && line[i] != ' ')
+        ++i;
+    
+    ++i;
+    
+    if (line[i++] != '(')
+        return 0;
+
+    int start, end;
+    
+    RegExpTest* result = new RegExpTest();
+    
+    result->subject = subjectString.toUString();
+    result->offset = offset;
+    result->result = matchResult;
+
+    while (line[i] && line[i] != ')') {
+        if (sscanf(line + i, "%d, %d", &start, &end) != 2) {
+            delete result;
+            return 0;
+        }
+
+        result->expectVector.append(start);
+        result->expectVector.append(end);
+
+        while (line[i] && (line[i] != ',') && (line[i] != ')'))
+            i++;
+        i++;
+        while (line[i] && (line[i] != ',') && (line[i] != ')'))
+            i++;
+
+        if (line[i] == ')')
+            break;
+        if (!line[i] || (line[i] != ',')) {
+            delete result;
+            return 0;
+        }
+        i++;
+    }
+
+    return result;
+}
+
+static bool runFromFiles(GlobalObject* globalObject, const Vector<UString>& files, bool verbose)
+{
+    UString script;
+    UString fileName;
+    Vector<char> scriptBuffer;
+    unsigned tests = 0;
+    unsigned failures = 0;
+    char* lineBuffer = new char[MaxLineLength + 1];
+
+    JSGlobalData& globalData = globalObject->globalData();
+
+    bool success = true;
+    for (size_t i = 0; i < files.size(); i++) {
+        FILE* testCasesFile = fopen(files[i].utf8().data(), "rb");
+
+        if (!testCasesFile) {
+            printf("Unable to open test data file \"%s\"\n", files[i].utf8().data());
+            continue;
+        }
+            
+        RegExp* regexp = 0;
+        size_t lineLength = 0;
+        char* linePtr = 0;
+        unsigned int lineNumber = 0;
+
+        while ((linePtr = fgets(&lineBuffer[0], MaxLineLength, testCasesFile))) {
+            lineLength = strlen(linePtr);
+            if (linePtr[lineLength - 1] == '\n') {
+                linePtr[lineLength - 1] = '\0';
+                --lineLength;
+            }
+            ++lineNumber;
+
+            if (linePtr[0] == '#')
+                continue;
+
+            if (linePtr[0] == '/') {
+                regexp = parseRegExpLine(globalData, linePtr, lineLength);
+            } else if (linePtr[0] == ' ') {
+                RegExpTest* regExpTest = parseTestLine(linePtr, lineLength);
+                
+                if (regexp && regExpTest) {
+                    ++tests;
+                    if (!testOneRegExp(globalData, regexp, regExpTest, verbose, lineNumber)) {
+                        failures++;
+                        printf("Failure on line %u\n", lineNumber);
+                    }
+                }
+                
+                if (regExpTest)
+                    delete regExpTest;
+            }
+        }
+        
+        fclose(testCasesFile);
+    }
+
+    if (failures)
+        printf("%u tests run, %u failures\n", tests, failures);
+    else
+        printf("%u tests passed\n", tests);
+
+    delete[] lineBuffer;
+
+    globalData.dumpSampleData(globalObject->globalExec());
+#if ENABLE(REGEXP_TRACING)
+    globalData.dumpRegExpTrace();
+#endif
+    return success;
+}
+
+#define RUNNING_FROM_XCODE 0
+
+static NO_RETURN void printUsageStatement(bool help = false)
+{
+    fprintf(stderr, "Usage: regexp_test [options] file\n");
+    fprintf(stderr, "  -h|--help  Prints this help message\n");
+    fprintf(stderr, "  -v|--verbose  Verbose output\n");
+
+    exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+static void parseArguments(int argc, char** argv, CommandLine& options)
+{
+    int i = 1;
+    for (; i < argc; ++i) {
+        const char* arg = argv[i];
+        if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
+            printUsageStatement(true);
+        if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose"))
+            options.verbose = true;
+        else
+            options.files.append(argv[i]);
+    }
+
+    for (; i < argc; ++i)
+        options.arguments.append(argv[i]);
+}
+
+int realMain(int argc, char** argv)
+{
+    RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap);
+    JSLockHolder lock(globalData.get());
+
+    CommandLine options;
+    parseArguments(argc, argv, options);
+
+    GlobalObject* globalObject = GlobalObject::create(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.arguments);
+    bool success = runFromFiles(globalObject, options.files, options.verbose);
+
+    return success ? 0 : 3;
+}
index e57408b0394f30c21cbcb31c55a7443b61c99e78..71a45e66e116eb24d5ded9482f9610b9ec0e45f6 100644 (file)
@@ -104,6 +104,8 @@ function getTestCases() {
 
 
     for ( var i = 0X0020, TEST_STRING = "var A = new Array( " ; i < 0x00ff; i++ ) {
 
 
     for ( var i = 0X0020, TEST_STRING = "var A = new Array( " ; i < 0x00ff; i++ ) {
+        if ( i === 0x58 || i === 0x78 ) // x or X - skip testing invalid hex escapes.
+            continue;
         TEST_STRING += "\'\\"+ String.fromCharCode( i ) +"\'";
         if ( i < 0x00FF - 1   ) {
             TEST_STRING += ",";
         TEST_STRING += "\'\\"+ String.fromCharCode( i ) +"\'";
         if ( i < 0x00FF - 1   ) {
             TEST_STRING += ",";
@@ -112,7 +114,7 @@ function getTestCases() {
         }
     }
 
         }
     }
 
-    var LENGTH = 0x00ff - 0x0020;
+    var LENGTH = 0x00ff - 0x0020 - 2; // x & X
 
     array[item++] = new TestCase(   SECTION,
                                     TEST_STRING +" A[150] = 'hello'; A[150]",
 
     array[item++] = new TestCase(   SECTION,
                                     TEST_STRING +" A[150] = 'hello'; A[150]",
index ae0a263f34314298055aacde3e176a551ef24d67..38ff1df722edfc853a6660c8f1e1bbc915cdabfe 100644 (file)
@@ -69,6 +69,8 @@ function getTestCases() {
 
     array[item++] = new TestCase( SECTION,    "var VAR = true ? , : 'FAILED'", "PASSED",           (VAR = true ? "PASSED" : "FAILED") );
 
 
     array[item++] = new TestCase( SECTION,    "var VAR = true ? , : 'FAILED'", "PASSED",           (VAR = true ? "PASSED" : "FAILED") );
 
+    array[item++] = new TestCase( SECTION,    "item = " + item +"; VAR = (item < -2147483648) ? 'FAILED' : 'PASSED'", "PASSED",           (VAR = (item < -2147483648) ? "FAILED" : "PASSED") );
+
     return ( array );
 }
 function test() {
     return ( array );
 }
 function test() {
index 422109dadbe589a7c817579be943f8cecc6390a8..5d3904644fc7d1dbf894f614547e32fa805ae86f 100644 (file)
@@ -206,20 +206,19 @@ function getTestCases() {
         HEX_VALUE -= Math.pow(16,POWER)*15;
     }
 
         HEX_VALUE -= Math.pow(16,POWER)*15;
     }
 
-    //  let us do some octal tests.  numbers that start with 0 and do not provid a radix should
-    //  default to using "0" as a radix.
+    //  let us do some 'octal' tests - ES5 does not permit octal, these must be treated as decimal.
 
     var OCT_STRING = "0";
     var OCT_VALUE = 0;
 
     for ( OCT_STRING = "0", OCT_VALUE = 0, POWER = 0; POWER < 15; POWER++, OCT_STRING = OCT_STRING +"7" ) {
         array[item++] = new TestCase( SECTION, "parseInt("+OCT_STRING+")",    OCT_VALUE,  parseInt(OCT_STRING) );
 
     var OCT_STRING = "0";
     var OCT_VALUE = 0;
 
     for ( OCT_STRING = "0", OCT_VALUE = 0, POWER = 0; POWER < 15; POWER++, OCT_STRING = OCT_STRING +"7" ) {
         array[item++] = new TestCase( SECTION, "parseInt("+OCT_STRING+")",    OCT_VALUE,  parseInt(OCT_STRING) );
-        OCT_VALUE += Math.pow(8,POWER)*7;
+        OCT_VALUE += Math.pow(10,POWER)*7;
     }
 
     for ( OCT_STRING = "-0", OCT_VALUE = 0, POWER = 0; POWER < 15; POWER++, OCT_STRING = OCT_STRING +"7" ) {
         array[item++] = new TestCase( SECTION, "parseInt("+OCT_STRING+")",    OCT_VALUE,  parseInt(OCT_STRING) );
     }
 
     for ( OCT_STRING = "-0", OCT_VALUE = 0, POWER = 0; POWER < 15; POWER++, OCT_STRING = OCT_STRING +"7" ) {
         array[item++] = new TestCase( SECTION, "parseInt("+OCT_STRING+")",    OCT_VALUE,  parseInt(OCT_STRING) );
-        OCT_VALUE -= Math.pow(8,POWER)*7;
+        OCT_VALUE -= Math.pow(10,POWER)*7;
     }
 
     // should get the same results as above if we provid the radix of 8 (or 010)
     }
 
     // should get the same results as above if we provid the radix of 8 (or 010)
index 27d31be0ec078cbe904dd226ac6364b286fea1ca..ad48fac985882880c0f92cd69c4c18b07ddb874a 100644 (file)
@@ -138,7 +138,7 @@ testcases[tc++] = new TestCase( SECTION,
 
 testcases[tc++] = new TestCase( SECTION,
     'parseInt("0022")',
 
 testcases[tc++] = new TestCase( SECTION,
     'parseInt("0022")',
-    18,
+    22,
     parseInt("0022"));
 
 testcases[tc++] = new TestCase( SECTION,
     parseInt("0022"));
 
 testcases[tc++] = new TestCase( SECTION,
index 769b81989788a08c84a5aa8df38a12d70f418a3d..d8e26afd5458a378a22af05f8fe232173a9198b7 100644 (file)
@@ -170,9 +170,9 @@ function getTestCases() {
     array[item++] = new TestCase( SECTION, "\\x0F0",      String.fromCharCode(15)+"0",         "\x0F0" );
 
     // G is out of hex range
     array[item++] = new TestCase( SECTION, "\\x0F0",      String.fromCharCode(15)+"0",         "\x0F0" );
 
     // G is out of hex range
-
-    array[item++] = new TestCase( SECTION, "\\xG",        "xG",                                 "\xG" );
-    array[item++] = new TestCase( SECTION, "\\xCG",       "xCG",                               "\xCG" );
+// Invalid hex escapes are syntax error; these are covered in the sputnik test suite.
+//    array[item++] = new TestCase( SECTION, "\\xG",        "xG",                                 "\xG" );
+//    array[item++] = new TestCase( SECTION, "\\xCG",       "xCG",                                     "\xCG" );
 
     // DoubleStringCharacter::EscapeSequence::CharacterEscapeSequence::\ NonEscapeCharacter
     array[item++] = new TestCase( SECTION, "\\a",    "a",        "\a" );
 
     // DoubleStringCharacter::EscapeSequence::CharacterEscapeSequence::\ NonEscapeCharacter
     array[item++] = new TestCase( SECTION, "\\a",    "a",        "\a" );
@@ -193,7 +193,8 @@ function getTestCases() {
     array[item++] = new TestCase( SECTION, "\\u",    "u",        "\u" );
 
     array[item++] = new TestCase( SECTION, "\\w",    "w",        "\w" );
     array[item++] = new TestCase( SECTION, "\\u",    "u",        "\u" );
 
     array[item++] = new TestCase( SECTION, "\\w",    "w",        "\w" );
-    array[item++] = new TestCase( SECTION, "\\x",    "x",        "\x" );
+// Invalid hex escapes are syntax error; these are covered in the sputnik test suite.
+//    array[item++] = new TestCase( SECTION, "\\x",    "x",        "\x" );
     array[item++] = new TestCase( SECTION, "\\y",    "y",        "\y" );
     array[item++] = new TestCase( SECTION, "\\z",    "z",        "\z" );
     array[item++] = new TestCase( SECTION, "\\9",    "9",        "\9" );
     array[item++] = new TestCase( SECTION, "\\y",    "y",        "\y" );
     array[item++] = new TestCase( SECTION, "\\z",    "z",        "\z" );
     array[item++] = new TestCase( SECTION, "\\9",    "9",        "\9" );
index b75f3e8d65fc0c36cfeb51b520f97e4f040a2f8d..b224ffa83ee01394c2e491d943da5b5ffc9de8bd 100644 (file)
@@ -84,7 +84,7 @@ function getTestCases() {
     // Georgian
     // Range: U+10A0 to U+10FF
     for ( var i = 0x10A0; i <= 0x10FF; i++ ) {
     // Georgian
     // Range: U+10A0 to U+10FF
     for ( var i = 0x10A0; i <= 0x10FF; i++ ) {
-        var U = new Array(new Unicode( i, 4 ), new Unicode( i, 5 ));
+        var U = new Array(new Unicode( i, 4 ), new Unicode( i, 5 ), new Unicode( i, 6.1));
 
 /*
         array[item++] = new TestCase(   SECTION,
 
 /*
         array[item++] = new TestCase(   SECTION,
@@ -92,7 +92,7 @@ function getTestCases() {
                                         String.fromCharCode(U.lower),
                                         eval("var s = new String( String.fromCharCode("+i+") ); s.toLowerCase()") );
 */
                                         String.fromCharCode(U.lower),
                                         eval("var s = new String( String.fromCharCode("+i+") ); s.toLowerCase()") );
 */
-        array[item++] = new TestCaseDualExpected(   SECTION,
+        array[item++] = new TestCaseMultiExpected(   SECTION,
                                         "var s = new String( String.fromCharCode("+i+") ); s.toLowerCase().charCodeAt(0)",
                                         U,
                                         eval("var s = new String( String.fromCharCode(i) ); s.toLowerCase().charCodeAt(0)") );
                                         "var s = new String( String.fromCharCode("+i+") ); s.toLowerCase().charCodeAt(0)",
                                         U,
                                         eval("var s = new String( String.fromCharCode(i) ); s.toLowerCase().charCodeAt(0)") );
@@ -106,7 +106,7 @@ function getTestCases() {
  *
  */
 
  *
  */
 
-function TestCaseDualExpected( n, d, e, a ) {
+function TestCaseMultiExpected( n, d, e, a ) {
     this.name        = n;
     this.description = d;
     this.expect      = e;
     this.name        = n;
     this.description = d;
     this.expect      = e;
@@ -115,26 +115,27 @@ function TestCaseDualExpected( n, d, e, a ) {
     this.reason      = "";
     this.bugnumber   = BUGNUMBER;
 
     this.reason      = "";
     this.bugnumber   = BUGNUMBER;
 
-    this.passed = getTestCaseResultDualExpected( this.expect, this.actual );
+    this.passed = getTestCaseResultMultiExpected( this.expect, this.actual );
     if ( DEBUG ) {
         writeLineToLog( "added " + this.description );
     }
 }
 
 // Added so that either Unicode 4.0 or 5.0 results will be considered correct.
     if ( DEBUG ) {
         writeLineToLog( "added " + this.description );
     }
 }
 
 // Added so that either Unicode 4.0 or 5.0 results will be considered correct.
-function writeTestCaseResultDualExpected( expect, actual, string ) {
-        var passed = getTestCaseResultDualExpected( expect, actual );
+function writeTestCaseResultMultiExpected( expect, actual, string ) {
+        var passed = getTestCaseResultMultiExpected( expect, actual );
         writeFormattedResult( expect[1].lower, actual, string, passed );
         return passed;
 }
 /*
         writeFormattedResult( expect[1].lower, actual, string, passed );
         return passed;
 }
 /*
- * Added so that either Unicode 4.0 or 5.0 results will be considered correct.
+ * Added so that either Unicode 4.0, 5.0 or 6.1 results will be considered correct.
  * Compare expected result to the actual result and figure out whether
  * the test case passed.
  */
  * Compare expected result to the actual result and figure out whether
  * the test case passed.
  */
-function getTestCaseResultDualExpected( expect, actual ) {
+function getTestCaseResultMultiExpected( expect, actual ) {
     expectedU4 = expect[0].lower;
     expectedU5 = expect[1].lower;
     expectedU4 = expect[0].lower;
     expectedU5 = expect[1].lower;
+    expectedU6_1 = expect[2].lower;
     //  because ( NaN == NaN ) always returns false, need to do
     //  a special compare to see if we got the right result.
         if ( actual != actual ) {
     //  because ( NaN == NaN ) always returns false, need to do
     //  a special compare to see if we got the right result.
         if ( actual != actual ) {
@@ -159,22 +160,30 @@ function getTestCaseResultDualExpected( expect, actual ) {
                 expectedU5 = "NaN number";
             }
         }
                 expectedU5 = "NaN number";
             }
         }
+        if ( expectedU6_1 != expectedU6_1 )   {
+            if ( typeof expectedU6_1 == "object" ) {
+                expectedU6_1 = "NaN object";
+            } else {
+                expectedU6_1 = "NaN number";
+            }
+        }
 
 
-        var passed = ( expectedU4 == actual || expectedU5 == actual ) ? true : false;
+        var passed = ( expectedU4 == actual || expectedU5 == actual || expectedU6_1 == actual ) ? true : false;
         
         //  if both objects are numbers
         // need to replace w/ IEEE standard for rounding
         if ( !passed &&
              typeof(actual) == "number" &&
             (typeof(expectedU4) == "number" ||
         
         //  if both objects are numbers
         // need to replace w/ IEEE standard for rounding
         if ( !passed &&
              typeof(actual) == "number" &&
             (typeof(expectedU4) == "number" ||
-             typeof(expectedU5) == "number")) {
-            if (( Math.abs(actual-expectedU4) < 0.0000001 ) || ( Math.abs(actual-expectedU5) < 0.0000001 )) {
+             typeof(expectedU5) == "number" ||
+             typeof(expectedU6_1) == "number")) {
+            if (( Math.abs(actual-expectedU4) < 0.0000001 ) || ( Math.abs(actual-expectedU5) < 0.0000001 ) || ( Math.abs(actual-expectedU6_1) < 0.0000001 )) {
                 passed = true;
             }
         }
 
         //  verify type is the same
                 passed = true;
             }
         }
 
         //  verify type is the same
-        if ( typeof(expectedU4) != typeof(actual) && typeof(expectedU5) != typeof(actual) )   {
+        if ( typeof(expectedU4) != typeof(actual) && typeof(expectedU5) != typeof(actual) && typeof(expectedU6_1) != typeof(actual) )   {
             passed = false;
         }
 
             passed = false;
         }
 
@@ -183,7 +192,7 @@ function getTestCaseResultDualExpected( expect, actual ) {
 
 function test() {
     for ( tc=0; tc < testcases.length; tc++ ) {
 
 function test() {
     for ( tc=0; tc < testcases.length; tc++ ) {
-        testcases[tc].passed = writeTestCaseResultDualExpected(
+        testcases[tc].passed = writeTestCaseResultMultiExpected(
                             testcases[tc].expect,
                             testcases[tc].actual,
                             testcases[tc].description +" = "+ testcases[tc].actual );
                             testcases[tc].expect,
                             testcases[tc].actual,
                             testcases[tc].description +" = "+ testcases[tc].actual );
@@ -438,7 +447,12 @@ function GetUnicodeValues( c, version ) {
 
     // Georgian
     // Range: U+10A0 to U+10F0
 
     // Georgian
     // Range: U+10A0 to U+10F0
-    if ( version == 5 ) {
+    if ( version >= 5 ) {
+        if ( version >= 6.1 && ( c == 0x10c7 || c == 0x10cd ) ) {
+            u[0] = c;
+            u[1] = c + 7264; //48;
+            return u;
+        }
         if ( c >= 0x10A0 && c <= 0x10C5 ) {
             u[0] = c;
             u[1] = c + 7264; //48;
         if ( c >= 0x10A0 && c <= 0x10C5 ) {
             u[0] = c;
             u[1] = c + 7264; //48;
@@ -630,4 +644,4 @@ function DecimalToHexString( n ) {
     }
 
     return h;
     }
 
     return h;
-}
\ No newline at end of file
+}
index 6054a51ff3e72dabf2beccd6e99418fdda8205c6..bd1be63ec9330aa23109903d2e29467f94c2ae47 100644 (file)
@@ -184,10 +184,11 @@ function getTestCases() {
                                   2,
                                   eval("var obj = new Object(); obj.indexOf = String.prototype.indexOf; obj.indexOf('bject')") );
 
                                   2,
                                   eval("var obj = new Object(); obj.indexOf = String.prototype.indexOf; obj.indexOf('bject')") );
 
-    array[item++] = new TestCase( SECTION,
-                                  "var f = new Object( String.prototype.indexOf ); f('"+GLOBAL+"')",
-                                  0,
-                                  eval("var f = new Object( String.prototype.indexOf ); f('"+GLOBAL+"')") );
+// This correctly throws, due to ES5 15.5.4.7 step 1
+//    array[item++] = new TestCase( SECTION,
+//                                  "var f = new Object( String.prototype.indexOf ); f('"+GLOBAL+"')",
+//                                  0,
+//                                  eval("var f = new Object( String.prototype.indexOf ); f('"+GLOBAL+"')") );
 
     array[item++] = new TestCase( SECTION,
                                   "var f = new Function(); f.toString = Object.prototype.toString; f.indexOf = String.prototype.indexOf; f.indexOf('[object Function]')",
 
     array[item++] = new TestCase( SECTION,
                                   "var f = new Function(); f.toString = Object.prototype.toString; f.indexOf = String.prototype.indexOf; f.indexOf('[object Function]')",
index 18e41cd6a21b9ee68bcc50f82e4988a84c566623..59a730cd4994fd5441583354542f771fe1171297 100644 (file)
@@ -107,11 +107,11 @@ function getTestCases() {
                                     eval("var s = new String( TEST_STRING ); s.split('')["+i+"]") );
     }
 
                                     eval("var s = new String( TEST_STRING ); s.split('')["+i+"]") );
     }
 
-    // case where the value of the separator is undefined.  in this case. the value of the separator
-    // should be ToString( separator ), or "undefined".
+    // Case where the value of the separator is undefined.
+    // Per ES5 15.5.4.14 step 10 this returns the input (unless limit is non-zero).
 
     var TEST_STRING = "thisundefinedisundefinedaundefinedstringundefinedobject";
 
     var TEST_STRING = "thisundefinedisundefinedaundefinedstringundefinedobject";
-    var EXPECT_STRING = new Array( "this", "is", "a", "string", "object" );
+    var EXPECT_STRING = new Array( "thisundefinedisundefinedaundefinedstringundefinedobject" );
 
     array[item++] = new TestCase(   SECTION,
                                     "var s = new String( "+ TEST_STRING +" ); s.split(void 0).length",
 
     array[item++] = new TestCase(   SECTION,
                                     "var s = new String( "+ TEST_STRING +" ); s.split(void 0).length",
index 69407fb5f70c93d743232416893d44da9317883e..083226e5d753c5c28fe59ce140e5a9c09da0837e 100644 (file)
@@ -82,7 +82,7 @@ testcases[tc++] = new TestCase( SECTION,
 
 testcases[tc++] = new TestCase( SECTION,
     '- "-0x123456789abcde8"',
 
 testcases[tc++] = new TestCase( SECTION,
     '- "-0x123456789abcde8"',
-    81985529216486880,
+    NaN,
     - "-0x123456789abcde8" );
 
 // Convert some large numbers to string
     - "-0x123456789abcde8" );
 
 // Convert some large numbers to string
@@ -474,7 +474,7 @@ testcases[tc++] = new TestCase( SECTION,
 
 testcases[tc++] = new TestCase( SECTION,
                                 "parseInt(\"0022\")",
 
 testcases[tc++] = new TestCase( SECTION,
                                 "parseInt(\"0022\")",
-                                18,
+                                22,
                                 parseInt("0022") );
 
 testcases[tc++] = new TestCase( SECTION,
                                 parseInt("0022") );
 
 testcases[tc++] = new TestCase( SECTION,
@@ -664,7 +664,7 @@ testcases[tc++] = new TestCase( SECTION,
 
 testcases[tc++] = new TestCase( SECTION,
                                 "- \"-0x123456789abcde8\"",
 
 testcases[tc++] = new TestCase( SECTION,
                                 "- \"-0x123456789abcde8\"",
-                                81985529216486880,
+                                NaN,
                                 - "-0x123456789abcde8" );
 
 // the following two tests are not strictly ECMA 1.0
                                 - "-0x123456789abcde8" );
 
 // the following two tests are not strictly ECMA 1.0
index be904e576231ef5330083f9ac781fea25d28aaa2..ceaa39d3ddc457214cae5634ac0aa223ece4d5b1 100644 (file)
@@ -40,7 +40,7 @@
 
     AddTestCase(
         "(new RegExp()).source",
 
     AddTestCase(
         "(new RegExp()).source",
-        "",
+        "(?:)",
         re.source );
 
     AddTestCase(
         re.source );
 
     AddTestCase(
index 67c4f21d493d0eb1cddb98065e8970c7acb5dc95..96c3ccfdc7cf95bd5772e4e87ed08ad485d26584 100644 (file)
@@ -40,7 +40,7 @@
 
     AddTestCase(
         "(new RegExp()).source",
 
     AddTestCase(
         "(new RegExp()).source",
-        "",
+        "(?:)",
         re.source );
 
     AddTestCase(
         re.source );
 
     AddTestCase(
index 122d59cd3dfca56a2a1471c0b95f71c70ae980c7..4a04e944d5d7529d667470b229a77bb3d6c6dd49 100644 (file)
@@ -16,7 +16,8 @@
 
     AddRegExpCases( new RegExp("\x41"),  "new RegExp('\\x41')",  "A",  "A", 1, 0, ["A"] );
     AddRegExpCases( new RegExp("\x412"),"new RegExp('\\x412')", "A2", "A2", 1, 0, ["A2"] );
 
     AddRegExpCases( new RegExp("\x41"),  "new RegExp('\\x41')",  "A",  "A", 1, 0, ["A"] );
     AddRegExpCases( new RegExp("\x412"),"new RegExp('\\x412')", "A2", "A2", 1, 0, ["A2"] );
-    AddRegExpCases( new RegExp("\x1g"), "new RegExp('\\x1g')",  "x1g","x1g", 1, 0, ["x1g"] );
+// Invalid hex escapes are syntax error; these are covered in the sputnik test suite.
+//    AddRegExpCases( new RegExp("\x1g"), "new RegExp('\\x1g')",  "x1g","x1g", 1, 0, ["x1g"] );
 
     AddRegExpCases( new RegExp("A"),  "new RegExp('A')",  "\x41",  "\\x41",  1, 0, ["A"] );
     AddRegExpCases( new RegExp("A"),  "new RegExp('A')",  "\x412", "\\x412", 1, 0, ["A"] );
 
     AddRegExpCases( new RegExp("A"),  "new RegExp('A')",  "\x41",  "\\x41",  1, 0, ["A"] );
     AddRegExpCases( new RegExp("A"),  "new RegExp('A')",  "\x412", "\\x412", 1, 0, ["A"] );
index 3eb51cbcdfdfa77ceff6d2ac2454a678c2063b63..122b94171678419244c1b6c607a1bbf9fcd67c03 100644 (file)
@@ -52,10 +52,6 @@ function AddRegExpCases( re, s, g, i, m, l ) {
 
     // properties
 
 
     // properties
 
-    AddTestCase( re + ".source",
-                 s,
-                 re.source );
-
 /*
  * http://bugzilla.mozilla.org/show_bug.cgi?id=225550 changed
  * the behavior of toString() and toSource() on empty regexps.
 /*
  * http://bugzilla.mozilla.org/show_bug.cgi?id=225550 changed
  * the behavior of toString() and toSource() on empty regexps.
@@ -63,6 +59,10 @@ function AddRegExpCases( re, s, g, i, m, l ) {
  */
     var S = s? s : '(?:)';
 
  */
     var S = s? s : '(?:)';
 
+    AddTestCase( re + ".source",
+                 S,
+                 re.source );
+
     AddTestCase( re + ".toString()",
                  "/" + S +"/" + (g?"g":"") + (i?"i":"") +(m?"m":""),
                  re.toString() );
     AddTestCase( re + ".toString()",
                  "/" + S +"/" + (g?"g":"") + (i?"i":"") +(m?"m":""),
                  re.toString() );
index 7dd958b9814d3265eb69a63b6c0f6c65470aa4a0..2283f77b516c3164e47d893eea481375f510cc5e 100644 (file)
@@ -6,90 +6,83 @@
 <h2>Test results, squirrelfish</h2><br>
 <p class='results_summary'>
 Test List: All tests<br>
 <h2>Test results, squirrelfish</h2><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, 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>
+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, ecma/Date/15.9.5.14.js, ecma/Date/15.9.5.31-1.js, ecma/Date/15.9.5.34-1.js<br>
+1124 test(s) selected, 1116 test(s) completed, 46 failures reported (4.12% failed)<br>
+Engine command line: "/Volumes/Big/ggaren/webkit/WebKitBuild/Debug/jsc" <br>
+OS type: Darwin garen.apple.com 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 18:47:41 PST 2012; root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64<br>
+Testcase execution time: 1 minutes, 8 seconds.<br>
+Tests completed on Tue Apr  3 22:31:56 2012.<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>
 <h2>Failure Details</h2><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>
 <h2>Failure Details</h2><br>
-<dl><a name='failure1'></a><dd><b>Testcase <a target='other_window' href='./ecma/TypeConversion/9.3.1-3.js'>ecma/TypeConversion/9.3.1-3.js</a> failed</b> <br>
+<dl><a name='failure1'></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='#failure2'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
  [ <a href='#failure2'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
-- "-0x123456789abcde8" = NaN FAILED! expected: 81985529216486880<br>
-- "-0x123456789abcde8" = NaN FAILED! expected: 81985529216486880<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>
-Failure messages were:<br>
 eval("function f(){}function g(){}") (threw no exception thrown = fail FAILED! expected: pass<br>
 </tt><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_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 name='failure2'></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='#failure1'>Previous Failure</a> | <a href='#failure3'>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>
 <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>
+<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 href='#failure2'>Previous Failure</a> | <a href='#failure4'>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='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 name='failure4'></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='#failure3'>Previous Failure</a> | <a href='#failure5'>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='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>
+<a name='failure5'></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='#failure4'>Previous Failure</a> | <a href='#failure6'>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='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>
+<a name='failure6'></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='#failure5'>Previous Failure</a> | <a href='#failure7'>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>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 JS1_2 Object.toString()<br>
 </tt><br>
-<a name='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>
+<a name='failure7'></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='#failure6'>Previous Failure</a> | <a href='#failure8'>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='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>
+<a name='failure8'></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='#failure7'>Previous Failure</a> | <a href='#failure9'>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='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>
+<a name='failure9'></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='#failure8'>Previous Failure</a> | <a href='#failure10'>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>
 <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>
+<a name='failure10'></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='#failure9'>Previous Failure</a> | <a href='#failure11'>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>
@@ -98,8 +91,8 @@ Failure messages were:<br>
 } FAILED! expected: <br>
 } FAILED! expected: <br>
 </tt><br>
 } FAILED! expected: <br>
 } FAILED! expected: <br>
 </tt><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>
+<a name='failure11'></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='#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>
@@ -112,76 +105,44 @@ 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/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>
+<a name='failure12'></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='#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>
 (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='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>
+<a name='failure13'></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='#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>
 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='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>
-(multiline == true) 'a11\na22\na23\na24'.match(/^a../g) = a11 FAILED! expected: a11,a22,a23,a24<br>
-(multiline == true) '123\n456'.match(/.3$/) = null FAILED! expected: 23<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='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>
-(['$*'] == true) 'a11\na22\na23\na24'.match(/^a../g) = a11 FAILED! expected: a11,a22,a23,a24<br>
-(['$*'] == true) '123\n456'.match(/.3$/) = null FAILED! expected: 23<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='failure17'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/beginLine.js'>js1_2/regexp/beginLine.js</a> failed</b> <br>
- [ <a href='#failure16'>Previous Failure</a> | <a href='#failure18'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
-<tt><br>
-Failure messages were:<br>
-123xyz'.match(new RegExp('^\d+')) = null FAILED! expected: 123<br>
-</tt><br>
-<a name='failure18'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/endLine.js'>js1_2/regexp/endLine.js</a> failed</b> <br>
- [ <a href='#failure17'>Previous Failure</a> | <a href='#failure19'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
-<tt><br>
-Failure messages were:<br>
-xyz'.match(new RegExp('\d+$')) = null FAILED! expected: 890<br>
-</tt><br>
-<a name='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>
+<a name='failure14'></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='#failure13'>Previous Failure</a> | <a href='#failure15'>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>
 <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 name='failure15'></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='#failure14'>Previous Failure</a> | <a href='#failure16'>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>
 <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>
+<a name='failure16'></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='#failure15'>Previous Failure</a> | <a href='#failure17'>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>
 <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>
+<a name='failure17'></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='#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>
 'abc'.split(/[a-z]/) = ,,, FAILED! expected: ,,<br>
 <tt><br>
 Failure messages were:<br>
 'abc'.split(/[a-z]/) = ,,, FAILED! expected: ,,<br>
@@ -189,22 +150,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='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>
+<a name='failure18'></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='#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>
 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='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>
+<a name='failure19'></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='#failure18'>Previous Failure</a> | <a href='#failure20'>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='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>
+<a name='failure20'></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='#failure19'>Previous Failure</a> | <a href='#failure21'>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>
@@ -212,15 +173,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='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>
+<a name='failure21'></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='#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>
 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='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>
+<a name='failure22'></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='#failure21'>Previous Failure</a> | <a href='#failure23'>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>
@@ -228,90 +189,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='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>
+<a name='failure23'></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='#failure22'>Previous Failure</a> | <a href='#failure24'>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/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>
+<a name='failure24'></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='#failure23'>Previous Failure</a> | <a href='#failure25'>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/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>
+<a name='failure25'></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='#failure24'>Previous Failure</a> | <a href='#failure26'>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='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>
+<a name='failure26'></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='#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>
 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/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>
+<a name='failure27'></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='#failure26'>Previous Failure</a> | <a href='#failure28'>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='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>
+<a name='failure28'></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='#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='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>
+<a name='failure29'></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='#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='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>
+<a name='failure30'></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='#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='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>
+<a name='failure31'></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='#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='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>
+<a name='failure32'></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='#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>
 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/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>
+<a name='failure33'></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='#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='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>
+<a name='failure34'></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='#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='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>
+<a name='failure35'></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='#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>
 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='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>
+<a name='failure36'></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='#failure35'>Previous Failure</a> | <a href='#failure37'>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>
@@ -321,26 +282,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='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>
+<a name='failure37'></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='#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='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>
+<a name='failure38'></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='#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='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>
+<a name='failure39'></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='#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='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>
+<a name='failure40'></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='#failure39'>Previous Failure</a> | <a href='#failure41'>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>
@@ -390,14 +351,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='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>
+<a name='failure41'></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='#failure40'>Previous Failure</a> | <a href='#failure42'>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='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>
+<a name='failure42'></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='#failure41'>Previous Failure</a> | <a href='#failure43'>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>
@@ -408,8 +369,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='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>
+<a name='failure43'></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='#failure42'>Previous Failure</a> | <a href='#failure44'>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>
@@ -419,20 +380,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='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>
+<a name='failure44'></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='#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='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>
+<a name='failure45'></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='#failure44'>Previous Failure</a> | <a href='#failure46'>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='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>
+<a name='failure46'></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='#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>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
@@ -446,10 +407,9 @@ 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 Wed Jan 19 13:26:57 2011.
+# Retest List, squirrelfish, generated Tue Apr  3 22:31:56 2012.
 # Original test base was: All tests.
 # Original test base was: All tests.
-# 1119 of 1127 test(s) were completed, 51 failures reported.
-ecma/TypeConversion/9.3.1-3.js
+# 1116 of 1124 test(s) were completed, 46 failures reported.
 ecma_2/Exceptions/function-001.js
 ecma_2/RegExp/regress-001.js
 ecma_3/FunExpr/fe-001.js
 ecma_2/Exceptions/function-001.js
 ecma_2/RegExp/regress-001.js
 ecma_3/FunExpr/fe-001.js
@@ -463,10 +423,6 @@ js1_2/function/tostring-1.js
 js1_2/function/tostring-2.js
 js1_2/operator/equality.js
 js1_2/regexp/RegExp_lastIndex.js
 js1_2/function/tostring-2.js
 js1_2/operator/equality.js
 js1_2/regexp/RegExp_lastIndex.js
-js1_2/regexp/RegExp_multiline.js
-js1_2/regexp/RegExp_multiline_as_array.js
-js1_2/regexp/beginLine.js
-js1_2/regexp/endLine.js
 js1_2/regexp/regress-6359.js
 js1_2/regexp/regress-9141.js
 js1_2/regexp/simple_form.js
 js1_2/regexp/regress-6359.js
 js1_2/regexp/regress-9141.js
 js1_2/regexp/simple_form.js
index be222614707264aa1d58ba46c9f417abff135a9e..de22876c1a5e3ff144223b3a4cf2aa9fdbbc22fb 100644 (file)
     // **Now we do the tests with RegExp.multiline set to true
     // RegExp.multiline = true; RegExp.multiline
     RegExp.multiline = true;
     // **Now we do the tests with RegExp.multiline set to true
     // RegExp.multiline = true; RegExp.multiline
     RegExp.multiline = true;
-       testcases[count++] = new TestCase ( SECTION, "RegExp.multiline = true; RegExp.multiline",
+    testcases[count++] = new TestCase ( SECTION, "RegExp.multiline = true; RegExp.multiline",
                                            true, RegExp.multiline);
 
     // (multiline == true) '123\n456'.match(/^4../)
                                            true, RegExp.multiline);
 
     // (multiline == true) '123\n456'.match(/^4../)
-       testcases[count++] = new TestCase ( SECTION, "(multiline == true) '123\\n456'.match(/^4../)",
-                                           String(['456']), String('123\n456'.match(/^4../)));
+    testcases[count++] = new TestCase ( SECTION, "(multiline == true) '123\\n456'.match(/^4../m)",
+                                        String(['456']), String('123\n456'.match(/^4../m)));
 
     // (multiline == true) 'a11\na22\na23\na24'.match(/^a../g)
 
     // (multiline == true) 'a11\na22\na23\na24'.match(/^a../g)
-       testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(/^a../g)",
-                                           String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/^a../g)));
+    testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(/^a../gm)",
+                                        String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/^a../gm)));
 
     // (multiline == true) 'a11\na22'.match(/^.+^./)
        //testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\na22'.match(/^.+^./)",
        //                                    String(['a11\na']), String('a11\na22'.match(/^.+^./)));
 
     // (multiline == true) '123\n456'.match(/.3$/)
 
     // (multiline == true) 'a11\na22'.match(/^.+^./)
        //testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\na22'.match(/^.+^./)",
        //                                    String(['a11\na']), String('a11\na22'.match(/^.+^./)));
 
     // (multiline == true) '123\n456'.match(/.3$/)
-       testcases[count++] = new TestCase ( SECTION, "(multiline == true) '123\\n456'.match(/.3$/)",
-                                           String(['23']), String('123\n456'.match(/.3$/)));
+    testcases[count++] = new TestCase ( SECTION, "(multiline == true) '123\\n456'.match(/.3$/m)",
+                                        String(['23']), String('123\n456'.match(/.3$/m)));
 
     // (multiline == true) 'a11\na22\na23\na24'.match(/a..$/g)
 
     // (multiline == true) 'a11\na22\na23\na24'.match(/a..$/g)
-       testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(/a..$/g)",
-                                           String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/a..$/g)));
+    testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(/a..$/gm)",
+                                        String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/a..$/gm)));
 
     // (multiline == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g'))
 
     // (multiline == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g'))
-       testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(new RegExp('a..$','g'))",
-                                           String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(new RegExp('a..$','g'))));
+    testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(new RegExp('a..$','gm'))",
+                                        String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(new RegExp('a..$','gm'))));
 
     // (multiline == true) 'abc\ndef'.match(/c$....$/)
        //testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'abc\ndef'.match(/c$.+$/)",
 
     // (multiline == true) 'abc\ndef'.match(/c$....$/)
        //testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'abc\ndef'.match(/c$.+$/)",
index 690653f93b8267faa2949b6852f45491dca140b2..01734f5e7bde86314254c193b6ee536233dbe001 100644 (file)
                                            true, RegExp['$*']);
 
     // (['$*'] == true) '123\n456'.match(/^4../)
                                            true, RegExp['$*']);
 
     // (['$*'] == true) '123\n456'.match(/^4../)
-       testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) '123\\n456'.match(/^4../)",
-                                           String(['456']), String('123\n456'.match(/^4../)));
+    testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) '123\\n456'.match(/^4../m)",
+                                        String(['456']), String('123\n456'.match(/^4../m)));
 
     // (['$*'] == true) 'a11\na22\na23\na24'.match(/^a../g)
 
     // (['$*'] == true) 'a11\na22\na23\na24'.match(/^a../g)
-       testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(/^a../g)",
-                                           String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/^a../g)));
+    testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(/^a../gm)",
+                                        String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/^a../gm)));
 
     // (['$*'] == true) 'a11\na22'.match(/^.+^./)
        //testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\na22'.match(/^.+^./)",
        //                                    String(['a11\na']), String('a11\na22'.match(/^.+^./)));
 
     // (['$*'] == true) '123\n456'.match(/.3$/)
 
     // (['$*'] == true) 'a11\na22'.match(/^.+^./)
        //testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\na22'.match(/^.+^./)",
        //                                    String(['a11\na']), String('a11\na22'.match(/^.+^./)));
 
     // (['$*'] == true) '123\n456'.match(/.3$/)
-       testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) '123\\n456'.match(/.3$/)",
-                                           String(['23']), String('123\n456'.match(/.3$/)));
+    testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) '123\\n456'.match(/.3$/m)",
+                                        String(['23']), String('123\n456'.match(/.3$/m)));
 
     // (['$*'] == true) 'a11\na22\na23\na24'.match(/a..$/g)
 
     // (['$*'] == true) 'a11\na22\na23\na24'.match(/a..$/g)
-       testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(/a..$/g)",
-                                           String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/a..$/g)));
+    testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(/a..$/gm)",
+                                        String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/a..$/gm)));
 
     // (['$*'] == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g'))
 
     // (['$*'] == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g'))
-       testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(new RegExp('a..$','g'))",
-                                           String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(new RegExp('a..$','g'))));
+    testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(new RegExp('a..$','gm'))",
+                                        String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(new RegExp('a..$','gm'))));
 
     // (['$*'] == true) 'abc\ndef'.match(/c$....$/)
        //testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'abc\ndef'.match(/c$.+$/)",
 
     // (['$*'] == true) 'abc\ndef'.match(/c$....$/)
        //testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'abc\ndef'.match(/c$.+$/)",
index c5ccbdc293594623ac19478cfc6f1872af1948b3..686092a69c65ded9e2c2ad8ca51ab36defcc14aa 100644 (file)
@@ -60,8 +60,8 @@
 
     RegExp.multiline = true;
     // 'abc\n123xyz'.match(new RegExp('^\d+')) <multiline==true>
 
     RegExp.multiline = true;
     // 'abc\n123xyz'.match(new RegExp('^\d+')) <multiline==true>
-       testcases[count++] = new TestCase ( SECTION, "'abc\n123xyz'.match(new RegExp('^\\d+'))",
-                                           String(['123']), String('abc\n123xyz'.match(new RegExp('^\\d+'))));
+    testcases[count++] = new TestCase ( SECTION, "'abc\n123xyz'.match(new RegExp('^\\d+','m'))",
+                                        String(['123']), String('abc\n123xyz'.match(new RegExp('^\\d+','m'))));
 
        function test()
        {
 
        function test()
        {
index 655d6ec69c85bd4498bc4040858df5c2ebf9a5f2..e6d588cf91e2c97dfb052105a0f0989194bb0076 100644 (file)
@@ -60,8 +60,8 @@
 
     RegExp.multiline = true;
     // 'abc\n123xyz890\nxyz'.match(new RegExp('\d+$')) <multiline==true>
 
     RegExp.multiline = true;
     // 'abc\n123xyz890\nxyz'.match(new RegExp('\d+$')) <multiline==true>
-       testcases[count++] = new TestCase ( SECTION, "'abc\n123xyz890\nxyz'.match(new RegExp('\\d+$'))",
-                                           String(['890']), String('abc\n123xyz890\nxyz'.match(new RegExp('\\d+$'))));
+    testcases[count++] = new TestCase ( SECTION, "'abc\n123xyz890\nxyz'.match(new RegExp('\\d+$','m'))",
+                                        String(['890']), String('abc\n123xyz890\nxyz'.match(new RegExp('\\d+$','m'))));
 
        function test()
        {
 
        function test()
        {
index 8f68c9ab9b9f322263ff12f3a847da8e549cdb72..14e555869ab6d399db9cfbfe6a2f7b86351dfa33 100644 (file)
@@ -30,7 +30,7 @@
        var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"';
        var VERSION = 'no version';
     startTest();
        var SECTION = 'As described in Netscape doc "Whats new in JavaScript 1.2"';
        var VERSION = 'no version';
     startTest();
-       var TITLE   = 'RegExp: \x# (hex) ';
+       var TITLE   = 'RegExp: \\x# (hex) ';
 
        writeHeaderToLog('Executing script: hexadecimal.js');
        writeHeaderToLog( SECTION + " "+ TITLE);
 
        writeHeaderToLog('Executing script: hexadecimal.js');
        writeHeaderToLog( SECTION + " "+ TITLE);
index 5cab4a75dbc3c0328049023adda6a6a6fea277ae..fb751e555b0054b7b84c0dd063584fb1fe3fd593 100644 (file)
@@ -100,7 +100,7 @@ reportCompare('abc', value, summary + ': push');
 
 // pop
 value  = 'abc';
 
 // pop
 value  = 'abc';
-expect = 'c';
+expect = 'TypeError: Unable to delete property.';
 try
 {
   actual = Array.prototype.pop.call(value);
 try
 {
   actual = Array.prototype.pop.call(value);
@@ -128,7 +128,7 @@ reportCompare('def', value, summary + ': unshift');
 
 // shift
 value  = 'abc';
 
 // shift
 value  = 'abc';
-expect = 'a';
+expect = 'TypeError: Unable to delete property.';
 try
 {
   actual = Array.prototype.shift.call(value);
 try
 {
   actual = Array.prototype.shift.call(value);
@@ -142,7 +142,7 @@ reportCompare('abc', value, summary + ': shift');
 
 // splice
 value  = 'abc';
 
 // splice
 value  = 'abc';
-expect = 'b';
+expect = 'TypeError: Unable to delete property.';
 try
 {
   actual = Array.prototype.splice.call(value, 1, 1) + '';
 try
 {
   actual = Array.prototype.splice.call(value, 1, 1) + '';
diff --git a/tests/regexp/RegExpTest.data b/tests/regexp/RegExpTest.data
new file mode 100644 (file)
index 0000000..3a77e0b
--- /dev/null
@@ -0,0 +1,1040 @@
+# Test data file for JavaScriptCore::RegExp functional test.
+# The format of this file is:
+# # comment line
+# /{pattern}/{flags}
+#  "{string}", {offset}, {return-value}, {match-offset-vector}
+# Both the pattern and string accept backslash escapes.
+#
+/A/
+ "A", 0, 0, (0, 1)
+ "A2", 0, 0, (0, 1)
+/A2/
+ "A2", 0, 0, (0, 2)
+/\\u0041/
+ "A", 0, 0, (0, 1)
+/\\u00412/
+ "A2", 0, 0, (0, 2)
+/abc/
+ "abc", 0, 0, (0, 3)
+ "xabcy", 0, 1, (1, 4)
+ "ababc", 0, 2, (2, 5)
+ "xbc", 0, -1, (-1, -1)
+ "axc", 0, -1, (-1, -1)
+ "abx", 0, -1, (-1, -1)
+ "b", 0, -1, (-1, -1)
+/a|ab/
+ "abc", 0, 0, (0, 1)
+/(a|d|q|)x/i
+ "bcaDxqy", 0, 3, (3, 5, 3, 4)
+/(a|(e|q))(x|y)/
+ "bcaddxqy", 0, 6, (6, 8, 6, 7, 6, 7, 7, 8)
+/a*b/
+ "aaadaabaaa", 0, 4, (4, 7)
+ "xxx", 0, -1, (4, 4)
+/[^abc]def[abc]+/
+ "abxdefbb", 0, 2, (2, 8)
+/(a*)baa/
+ "ccdaaabaxaabaa", 0, 9, (9, 14, 9, 11)
+ "aabaa", 0, 0, (0, 5, 0, 2)
+/q(a|b)*q/
+ "xxqababqyy", 0, 2, (2, 8, 6, 7)
+/(a(.|[^d])c)*/
+ "adcaxc", 0, 0, (0, 6, 3, 6, 4, 5)
+/(a*)b\\1/
+ "abaaaxaabaayy", 0, 0, (0, 3, 0, 1)
+ "cccdaaabaxaabaayy", 0, 6, (6, 9, 6, 7)
+ "cccdaaabqxaabaayy", 0, 7, (7, 8, 7, 7)
+/x1g/
+ "x1g", 0, 0, (0, 3)
+/^x/
+ "x412", 0, 0, (0, 1)
+/\\u001g/
+ "u001g", 0, 0, (0, 5)
+/34/g
+ "343443444", 0, 0, (0, 2)
+ "343443444", 2, 2, (2, 4)
+ "343443444", 4, 5, (5, 7)
+ "343443444", 7, -1, (-1, -1)
+/\\d{1}/g
+ "123456abcde7890", 0, 0, (0, 1)
+ "123456abcde7890", 1, 1, (1, 2)
+ "123456abcde7890", 2, 2, (2, 3)
+ "123456abcde7890", 3, 3, (3, 4)
+ "123456abcde7890", 4, 4, (4, 5)
+ "123456abcde7890", 5, 5, (5, 6)
+ "123456abcde7890", 6, 11, (11, 12)
+ "123456abcde7890", 12, 12, (12, 13)
+ "123456abcde7890", 13, 13, (13, 14)
+ "123456abcde7890", 14, 14, (14, 15)
+ "123456abcde7890", 15, -1, (-1, -1)
+/\\d{2}/g
+ "123456abcde7890", 0, 0, (0, 2)
+ "123456abcde7890", 2, 2, (2, 4)
+ "123456abcde7890", 4, 4, (4, 6)
+ "123456abcde7890", 6, 11, (11, 13)
+ "123456abcde7890", 13, 13, (13, 15)
+ "123456abcde7890", 15, -1, (-1, -1)
+/\\D{2}/g
+ "123456abcde7890", 0, 6, (6, 8)
+ "123456abcde7890", 8, 8, (8, 10)
+ "123456abcde7890", 10, -1, (-1, -1)
+/([\\d]{5})([-\\ ]?[\\d]{4})?$/
+ "Boston, Mass. 02134", 0, 14, (14, 19, 14, 19, -1, -1)
+/l/
+ "hello", 0, 2, (2, 3)
+ "hello", 3, 3, (3, 4)
+ "hello", 4, -1, (-1, -1)
+/\\s/g
+ "x, x, x, x", 0, 2, (2, 3)
+ "x, x, x, x", 3, 5, (5, 6)
+ "x, x, x, x", 6, 8, (8, 9)
+ "x, x, x, x", 9, -1, (-1, -1)
+/((a)|(ab))((c)|(bc))/
+ "abc", 0, 0, (0, 3, 0, 1, 0, 1, -1, -1, 1, 3, -1, -1, 1, 3)
+/a[a-z]{2,4}/
+ "abcdefghi", 0, 0, (0, 5)
+/a[a-z]{2,4}?/
+ "abcdefghi", 0, 0, (0, 3)
+/(aa|aabaac|ba|b|c)*/
+ "aabaac", 0, 0, (0, 4, 2, 4)
+/^(a+)\\1*,\\1+$/
+ "aaaaaaaaaa,aaaaaaaaaaaaaaa", 0, 0, (0, 26, 0, 5)
+/(z)((a+)?(b+)?(c))*/
+ "zaacbbbcac", 0, 0, (0, 10, 0, 1, 8, 10, 8, 9, -1, -1, 9, 10)
+/(a*)*/
+ "b", 0, 0, (0, 0, -1, -1)
+ "ab", 0, 0, (0, 1, 0, 1)
+/(a*)b\\1+/
+ "baaaac", 0, 0, (0, 1, 0, 0)
+/(?=(a+))/
+ "baaabac", 0, 1, (1, 1, 1, 4)
+/(?=(a+))a*b\\1/
+ "baaabac", 0, 3, (3, 6, 3, 4)
+/(.*?)a(?!(a+)b\\2c)\\2(.*)/
+ "baaabaac", 0, 0, (0, 8, 0, 2, -1, -1, 3, 8)
+/\\w\\s\\w/g
+ "a b c d e", 0, 0, (0, 3)
+ "a b c d e", 3, 4, (4, 7)
+ "a b c d e", 7, -1, (-1, -1)
+/\\d\\d\\d/g
+ "12345678", 0, 0, (0, 3)
+ "12345678", 3, 3, (3, 6)
+ "12345678", 6, -1, (-1, -1)
+/abc/gi
+ "AbcaBcabC", 0, 0, (0, 3)
+ "AbcaBcabC", 3, 3, (3, 6)
+ "AbcaBcabC", 6, 6, (6, 9)
+ "AbcaBcabC", 9, -1, (-1, -1)
+/abc/i
+ "AbcaBcabC", 0, 0, (0, 3)
+ "ABC", 0, 0, (0, 3)
+ "XABCY", 0, 1, (1, 4)
+ "ABABC", 0, 2, (2, 5)
+ "XBC", 0, -1, (-1, -1)
+ "AXC", 0, -1, (-1, -1)
+ "ABX", 0, -1, (-1, -1)
+ "aaxabxbaxbbx", 0, -1, (-1, -1)
+/ab*c/
+ "abc", 0, 0, (0, 3)
+/ab*bc/
+ "abc", 0, 0, (0, 3)
+ "abbc", 0, 0, (0, 4)
+ "abbbbc", 0, 0, (0, 6)
+/.{1}/
+ "abbbbc", 0, 0, (0, 1)
+/.{3,4}/
+ "abbbbc", 0, 0, (0, 4)
+/ab{0,}bc/
+ "abbbbc", 0, 0, (0, 6)
+/ab+bc/
+ "abbc", 0, 0, (0, 4)
+ "abbbbc", 0, 0, (0, 6)
+ "abc", 0, -1, (0, 9)
+ "abq", 0, -1, (0, 9)
+ "abc", 0, -1, (0, -1)
+ "abq", 0, -1, (0, -1)
+/ab{1,}bc/
+ "abbbbc", 0, 0, (0, 6)
+ "abq", 0, -1, (0, 9)
+/ab{1,3}bc/
+ "abbbbc", 0, 0, (0, 6)
+ "abbbc", 0, 0, (0, 5)
+ "abbc", 0, 0, (0, 4)
+ "abc", 0, -1, (0, -1)
+ "abbbbbc", 0, -1, (4, -1)
+/ab{3,4}bc/
+ "abbbbc", 0, 0, (0, 6)
+/ab?bc/
+ "abbc", 0, 0, (0, 4)
+ "abc", 0, 0, (0, 3)
+ "abbbbc", 0, -1, (4, 9)
+/ab{0,1}bc/
+ "abc", 0, 0, (0, 3)
+/ab?c/
+ "abc", 0, 0, (0, 3)
+/ab{0,1}c/
+ "abc", 0, 0, (0, 3)
+/^abc$/
+ "abc", 0, 0, (0, 3)
+ "abcc", 0, -1, (-1, -1)
+ "aabc", 0, -1, (-1, -1)
+ "abbbbc", 0, -1, (-1, -1)
+ "qqq\nabc", 0, -1, (-1, -1)
+ "abc\nzzz", 0, -1, (-1, -1)
+ "qqq\nabc\nzzz", 0, -1, (-1, -1)
+/^abc/
+ "abcc", 0, 0, (0, 3)
+ "abcdefghi", 0, 0, (0, 3)
+ "abc", 0, 0, (0, 3)
+ "xyzabc", 0, -1, (-1, -1)
+/abc$/
+ "aabc", 0, 1, (1, 4)
+ "aabcd", 0, -1, (-1, -1)
+ "abc", 0, 0, (0, 3)
+ "abc\n", 0, -1, (-1, -1)
+ "abc\ndef", 0, -1, (-1, -1)
+/^/
+ "abc", 0, 0, (0, 0)
+ "test", 0, 0, (0, 0)
+/$/
+ "abc", 0, 3, (3, 3)
+ "a\nb\n", 0, 4, (4, 4)
+ "b\na\n", 0, 4, (4, 4)
+ "b\na", 0, 3, (3, 3)
+ "xxx", 0, 3, (3, 3)
+ "xxxx", 0, 4, (4, 4)
+/a.c/
+ "abc", 0, 0, (0, 3)
+ "axc", 0, 0, (0, 3)
+/a.*c/
+ "axyzc", 0, 0, (0, 5)
+ "axyzd", 0, -1, (4, 10)
+/a[bc]d/
+ "abd", 0, 0, (0, 3)
+ "abc", 0, -1, (-1, -1)
+ "axyzd", 0, -1, (-1, -1)
+/a[b-d]e/
+ "ace", 0, 0, (0, 3)
+ "abd", 0, -1, (-1, -1)
+/a[b-d]/
+ "aac", 0, 1, (1, 3)
+/a[-b]/
+ "a-", 0, 0, (0, 2)
+/a[b-]/
+ "a-", 0, 0, (0, 2)
+/a]/
+ "a]", 0, 0, (0, 2)
+/a[^bc]d/
+ "aed", 0, 0, (0, 3)
+ "abd", 0, -1, (-1, -1)
+/a[^-b]c/
+ "adc", 0, 0, (0, 3)
+ "a-c", 0, -1, (-1, -1)
+/\\ba\\b/
+ "a-", 0, 0, (0, 1)
+ "-a", 0, 1, (1, 2)
+ "-a-", 0, 1, (1, 2)
+/\\By\\b/
+ "xy", 0, 1, (1, 2)
+/\\by\\B/
+ "yz", 0, 0, (0, 1)
+/\\By\\B/
+ "xyz", 0, 1, (1, 2)
+/a\\Sb/
+ "a-b", 0, 0, (0, 3)
+ "a\tb a b a-b", 0, 8, (8, 11)
+ "a b", 0, -1, (-1, -1)
+/\\d/
+ "1", 0, 0, (0, 1)
+ "-", 0, -1, (-1, -1)
+ "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\f\n\r\t\v~`!@#$%^&*()-+={[}]|\\:;'<,>./? \"", 0, -1, (-1, -1)
+ "ab1cd", 0, 2, (2, 3)
+ "ab2cd", 0, 2, (2, 3)
+ "ab3cd", 0, 2, (2, 3)
+ "ab4cd", 0, 2, (2, 3)
+ "ab5cd", 0, 2, (2, 3)
+ "ab6cd", 0, 2, (2, 3)
+ "ab7cd", 0, 2, (2, 3)
+ "ab8cd", 0, 2, (2, 3)
+ "ab9cd", 0, 2, (2, 3)
+ "ab0cd", 0, 2, (2, 3)
+ "\u01003", 0, 1, (1, 2)
+/\\D/
+ "-", 0, 0, (0, 1)
+ "1", 0, -1, (-1, -1)
+ "1234567890", 0, -1, (-1, -1)
+ "12_34", 0, 2, (2, 3)
+ "12a34", 0, 2, (2, 3)
+ "12b34", 0, 2, (2, 3)
+ "1X2", 0, 1, (1, 2)
+ "1\u01002", 0, 1, (1, 2)
+/[\\w]/
+ "a", 0, 0, (0, 1)
+ "-", 0, -1, (-1, -1)
+/[\\W]/
+ "-", 0, 0, (0, 1)
+ "a", 0, -1, (-1, -1)
+/a[\\S]b/
+ "a-b", 0, 0, (0, 3)
+ "a b", 0, -1, (-1, -1)
+/[\\d]/
+ "1", 0, 0, (0, 1)
+ "-", 0, -1, (-1, -1)
+/[\\D]/
+ "-", 0, 0, (0, 1)
+ "1", 0, -1, (-1, -1)
+/ab|cd/
+ "abc", 0, 0, (0, 2)
+ "abcd", 0, 0, (0, 2)
+/()ef/
+ "def", 0, 1, (1, 3, 1, 1)
+/a\\(b/
+ "a(b", 0, 0, (0, 3)
+/a\\(*b/
+ "ab", 0, 0, (0, 2)
+ "a((b", 0, 0, (0, 4)
+/a\\\\b/
+ "a\\b", 0, 0, (0, 3)
+ "a\b", 0, -1, (-1, -1)
+/((a))/
+ "abc", 0, 0, (0, 1, 0, 1, 0, 1)
+/(a)b(c)/
+ "abc", 0, 0, (0, 3, 0, 1, 2, 3)
+/a+b+c/
+ "aabbabc", 0, 4, (4, 7)
+/a{1,}b{1,}c/
+ "aabbabc", 0, 4, (4, 7)
+/a.+?c/
+ "abcabc", 0, 0, (0, 3)
+/(a+|b)*/
+ "ab", 0, 0, (0, 2, 1, 2)
+/(a+|b){0,}/
+ "ab", 0, 0, (0, 2, 1, 2)
+/(a+|b)+/
+ "ab", 0, 0, (0, 2, 1, 2)
+/(a+|b){1,}/
+ "ab", 0, 0, (0, 2, 1, 2)
+/(a+|b)?/
+ "ab", 0, 0, (0, 1, 0, 1)
+/(a+|b){0,1}/
+ "ab", 0, 0, (0, 1, 0, 1)
+/[^ab]*/
+ "cde", 0, 0, (0, 3)
+/([abc])*d/
+ "abbbcd", 0, 0, (0, 6, 4, 5)
+/([abc])*bcd/
+ "abcd", 0, 0, (0, 4, 0, 1)
+/a|b|c|d|e/
+ "e", 0, 0, (0, 1)
+/(a|b|c|d|e)f/
+ "ef", 0, 0, (0, 2, 0, 1)
+/abcd*efg/
+ "abcdefg", 0, 0, (0, 7)
+/ab*/
+ "xabyabbbz", 0, 1, (1, 3)
+ "xayabbbz", 0, 1, (1, 2)
+/(ab|cd)e/
+ "abcde", 0, 2, (2, 5, 2, 4)
+/[abhgefdc]ij/
+ "hij", 0, 0, (0, 3)
+/(abc|)ef/
+ "abcdef", 0, 4, (4, 6, 4, 4)
+/(a|b)c*d/
+ "abcd", 0, 1, (1, 4, 1, 2)
+/(ab|ab*)bc/
+ "abc", 0, 0, (0, 3, 0, 1)
+/a([bc]*)c*/
+ "abc", 0, 0, (0, 3, 1, 3)
+/a([bc]*)(c*d)/
+ "abcd", 0, 0, (0, 4, 1, 3, 3, 4)
+/a([bc]+)(c*d)/
+ "abcd", 0, 0, (0, 4, 1, 3, 3, 4)
+/a([bc]*)(c+d)/
+ "abcd", 0, 0, (0, 4, 1, 2, 2, 4)
+/a[bcd]*dcdcde/
+ "adcdcde", 0, 0, (0, 7)
+/(ab|a)b*c/
+ "abc", 0, 0, (0, 3, 0, 2)
+/((a)(b)c)(d)/
+ "abcd", 0, 0, (0, 4, 0, 3, 0, 1, 1, 2, 3, 4)
+/[a-zA-Z_][a-zA-Z0-9_]*/
+ "alpha", 0, 0, (0, 5)
+/^a(bc+|b[eh])g|.h$/
+ "abh", 0, 1, (1, 3, -1, -1)
+/(bc+d$|ef*g.|h?i(j|k))/
+ "effgz", 0, 0, (0, 5, 0, 5, -1, -1)
+ "ij", 0, 0, (0, 2, 0, 2, 1, 2)
+ "reffgz", 0, 1, (1, 6, 1, 6, -1, -1)
+ "effg", 0, -1, (3, 10, -1, -1, -1, -1)
+ "bcdd", 0, -1, (3, 10, -1, -1, -1, -1)
+ "effg", 0, -1, (3, -1, -1, -1, -1, -1)
+ "bcdd", 0, -1, (3, -1, -1, -1, -1, -1)
+/((((((((((a))))))))))/
+ "a", 0, 0, (0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
+ "a!", 0, 0, (0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
+/((((((((((a))))))))))\\10/
+ "aa", 0, 0, (0, 2, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
+/(((((((((a)))))))))/
+ "a", 0, 0, (0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
+/(.*)c(.*)/
+ "abcde", 0, 0, (0, 5, 0, 2, 3, 5)
+/abcd/
+ "abcd", 0, 0, (0, 4)
+/a(bc)d/
+ "abcd", 0, 0, (0, 4, 1, 3)
+/a[-]?c/
+ "ac", 0, 0, (0, 2)
+/(abc)\\1/
+ "abcabc", 0, 0, (0, 6, 0, 3)
+/([a-c]*)\\1/
+ "abcabc", 0, 0, (0, 6, 0, 3)
+/(a)|\\1/
+ "a", 0, 0, (0, 1, 0, 1)
+ "x", 0, 0, (0, 0, -1, -1)
+ "ab", 0, 0, (0, 1, 0, 1)
+/(([a-c])b*?\\2)*/
+ "ababbbcbc", 0, 0, (0, 5, 3, 5, 3, 4)
+/(([a-c])b*?\\2){3}/
+ "ababbbcbc", 0, 0, (0, 9, 6, 9, 6, 7)
+/ab*c/i
+ "ABC", 0, 0, (0, 3)
+/ab*bc/i
+ "ABC", 0, 0, (0, 3)
+ "ABBC", 0, 0, (0, 4)
+/ab*?bc/i
+ "ABBBBC", 0, 0, (0, 6)
+/ab{0,}?bc/i
+ "ABBBBC", 0, 0, (0, 6)
+/ab+?bc/i
+ "ABBC", 0, 0, (0, 4)
+/ab+bc/i
+ "ABBBBC", 0, 0, (0, 6)
+ "ABC", 0, -1, (0, 10)
+ "ABQ", 0, -1, (0, 10)
+ "ABC", 0, -1, (0, -1)
+ "ABQ", 0, -1, (0, -1)
+/ab{1,}?bc/i
+ "ABBBBC", 0, 0, (0, 6)
+/ab{1,3}?bc/i
+ "ABBBBC", 0, 0, (0, 6)
+/ab{3,4}?bc/i
+ "ABBBBC", 0, 0, (0, 6)
+/ab??bc/i
+ "ABBC", 0, 0, (0, 4)
+ "ABC", 0, 0, (0, 3)
+ "ABBBBC", 0, -1, (4, 10)
+/ab{0,1}?bc/i
+ "ABC", 0, 0, (0, 3)
+/ab??c/i
+ "ABC", 0, 0, (0, 3)
+/ab{0,1}?c/i
+ "ABC", 0, 0, (0, 3)
+/^abc$/i
+ "ABC", 0, 0, (0, 3)
+ "ABCC", 0, -1, (-1, -1)
+ "AABC", 0, -1, (-1, -1)
+ "ABBBBC", 0, -1, (-1, -1)
+/^abc/i
+ "ABCC", 0, 0, (0, 3)
+/abc$/i
+ "AABC", 0, 1, (1, 4)
+/^/i
+ "ABC", 0, 0, (0, 0)
+/$/i
+ "ABC", 0, 3, (3, 3)
+/a.c/i
+ "ABC", 0, 0, (0, 3)
+ "AXC", 0, 0, (0, 3)
+/a.*?c/i
+ "AXYZC", 0, 0, (0, 5)
+ "ABCABC", 0, 0, (0, 3)
+/a[bc]d/i
+ "ABD", 0, 0, (0, 3)
+ "ABC", 0, -1, (-1, -1)
+/a[b-d]e/i
+ "ACE", 0, 0, (0, 3)
+ "ABD", 0, -1, (-1, -1)
+ "ABC", 0, -1, (-1, -1)
+/a[b-d]/i
+ "AAC", 0, 1, (1, 3)
+/a[-b]/i
+ "A-", 0, 0, (0, 2)
+/a[b-]/i
+ "A-", 0, 0, (0, 2)
+/a]/i
+ "A]", 0, 0, (0, 2)
+/a[^bc]d/i
+ "AED", 0, 0, (0, 3)
+ "ABD", 0, -1, (-1, -1)
+/a[^-b]c/i
+ "ADC", 0, 0, (0, 3)
+ "A-C", 0, -1, (-1, -1)
+ "ABD", 0, -1, (-1, -1)
+/ab|cd/i
+ "ABC", 0, 0, (0, 2)
+ "ABCD", 0, 0, (0, 2)
+/()ef/i
+ "DEF", 0, 1, (1, 3, 1, 1)
+/a\\(b/i
+ "A(B", 0, 0, (0, 3)
+/a\\(*b/i
+ "AB", 0, 0, (0, 2)
+ "A((B", 0, 0, (0, 4)
+/a\\\\b/i
+ "A\\B", 0, 0, (0, 3)
+ "AB", 0, -1, (-1, -1)
+/((a))/i
+ "ABC", 0, 0, (0, 1, 0, 1, 0, 1)
+/(a)b(c)/i
+ "ABC", 0, 0, (0, 3, 0, 1, 2, 3)
+/a+b+c/i
+ "AABBABC", 0, 4, (4, 7)
+/a{1,}b{1,}c/i
+ "AABBABC", 0, 4, (4, 7)
+/a.+?c/i
+ "ABCABC", 0, 0, (0, 3)
+/a.{0,5}?c/i
+ "ABCABC", 0, 0, (0, 3)
+/(a+|b)*/i
+ "AB", 0, 0, (0, 2, 1, 2)
+/(a+|b){0,}/i
+ "AB", 0, 0, (0, 2, 1, 2)
+/(a+|b)+/i
+ "AB", 0, 0, (0, 2, 1, 2)
+/(a+|b){1,}/i
+ "AB", 0, 0, (0, 2, 1, 2)
+/(a+|b)?/i
+ "AB", 0, 0, (0, 1, 0, 1)
+/(a+|b){0,1}/i
+ "AB", 0, 0, (0, 1, 0, 1)
+/(a+|b){0,1}?/i
+ "AB", 0, 0, (0, 0, -1, -1)
+/[^ab]*/i
+ "CDE", 0, 0, (0, 3)
+/([abc])*d/i
+ "ABBBCD", 0, 0, (0, 6, 4, 5)
+/([abc])*bcd/i
+ "ABCD", 0, 0, (0, 4, 0, 1)
+/a|b|c|d|e/i
+ "E", 0, 0, (0, 1)
+/(a|b|c|d|e)f/i
+ "EF", 0, 0, (0, 2, 0, 1)
+/abcd*efg/i
+ "ABCDEFG", 0, 0, (0, 7)
+/ab*/i
+ "XABYABBBZ", 0, 1, (1, 3)
+ "XAYABBBZ", 0, 1, (1, 2)
+/(ab|cd)e/i
+ "ABCDE", 0, 2, (2, 5, 2, 4)
+/[abhgefdc]ij/i
+ "HIJ", 0, 0, (0, 3)
+/(abc|)ef/i
+ "ABCDEF", 0, 4, (4, 6, 4, 4)
+/(a|b)c*d/i
+ "ABCD", 0, 1, (1, 4, 1, 2)
+/(ab|ab*)bc/i
+ "ABC", 0, 0, (0, 3, 0, 1)
+/a([bc]*)c*/i
+ "ABC", 0, 0, (0, 3, 1, 3)
+/a([bc]*)(c*d)/i
+ "ABCD", 0, 0, (0, 4, 1, 3, 3, 4)
+/a([bc]+)(c*d)/i
+ "ABCD", 0, 0, (0, 4, 1, 3, 3, 4)
+/a([bc]*)(c+d)/i
+ "ABCD", 0, 0, (0, 4, 1, 2, 2, 4)
+/a[bcd]*dcdcde/i
+ "ADCDCDE", 0, 0, (0, 7)
+/(ab|a)b*c/i
+ "ABC", 0, 0, (0, 3, 0, 2)
+/((a)(b)c)(d)/i
+ "ABCD", 0, 0, (0, 4, 0, 3, 0, 1, 1, 2, 3, 4)
+/[a-zA-Z_][a-zA-Z0-9_]*/i
+ "ALPHA", 0, 0, (0, 5)
+/^a(bc+|b[eh])g|.h$/i
+ "ABH", 0, 1, (1, 3, -1, -1)
+/(bc+d$|ef*g.|h?i(j|k))/i
+ "EFFGZ", 0, 0, (0, 5, 0, 5, -1, -1)
+ "IJ", 0, 0, (0, 2, 0, 2, 1, 2)
+ "REFFGZ", 0, 1, (1, 6, 1, 6, -1, -1)
+ "EFFG", 0, -1, (3, 10, -1, -1, -1, -1)
+ "BCDD", 0, -1, (3, 10, -1, -1, -1, -1)
+ "ADCDCDE", 0, -1, (6, -1, -1, -1, -1, -1)
+ "EFFG", 0, -1, (3, -1, -1, -1, -1, -1)
+ "BCDD", 0, -1, (3, -1, -1, -1, -1, -1)
+/((((((((((a))))))))))/i
+ "A", 0, 0, (0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
+ "A!", 0, 0, (0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
+/((((((((((a))))))))))\\10/i
+ "AA", 0, 0, (0, 2, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
+/(((((((((a)))))))))/i
+ "A", 0, 0, (0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
+/(?:(?:(?:(?:(?:(?:(?:(?:(?:(a))))))))))/i
+ "A", 0, 0, (0, 1, 0, 1)
+/(?:(?:(?:(?:(?:(?:(?:(?:(?:(a|b|c))))))))))/i
+ "C", 0, 0, (0, 1, 0, 1)
+/(.*)c(.*)/i
+ "ABCDE", 0, 0, (0, 5, 0, 2, 3, 5)
+/abcd/i
+ "ABCD", 0, 0, (0, 4)
+/a(bc)d/i
+ "ABCD", 0, 0, (0, 4, 1, 3)
+/a[-]?c/i
+ "AC", 0, 0, (0, 2)
+/(abc)\\1/i
+ "ABCABC", 0, 0, (0, 6, 0, 3)
+ "abcabc", 0, 0, (0, 6, 0, 3)
+ "ABCabc", 0, 0, (0, 6, 0, 3)
+ "abcABC", 0, 0, (0, 6, 0, 3)
+/([a-c]*)\\1/i
+ "ABCABC", 0, 0, (0, 6, 0, 3)
+/a(?!b)./
+ "abad", 0, 2, (2, 4)
+/a(?=d)./
+ "abad", 0, 2, (2, 4)
+/a(?=c|d)./
+ "abad", 0, 2, (2, 4)
+/a(?:b|c|d)(.)/
+ "ace", 0, 0, (0, 3, 2, 3)
+/a(?:b|c|d)*(.)/
+ "ace", 0, 0, (0, 3, 2, 3)
+/a(?:b|c|d)+?(.)/
+ "ace", 0, 0, (0, 3, 2, 3)
+ "acdbcdbe", 0, 0, (0, 3, 2, 3)
+/a(?:b|c|d)+(.)/
+ "acdbcdbe", 0, 0, (0, 8, 7, 8)
+/a(?:b|c|d){2}(.)/
+ "acdbcdbe", 0, 0, (0, 4, 3, 4)
+/a(?:b|c|d){4,5}(.)/
+ "acdbcdbe", 0, 0, (0, 7, 6, 7)
+/a(?:b|c|d){4,5}?(.)/
+ "acdbcdbe", 0, 0, (0, 6, 5, 6)
+/((foo)|(bar))*/
+ "foobar", 0, 0, (0, 6, 3, 6, -1, -1, 3, 6)
+/a(?:b|c|d){6,7}(.)/
+ "acdbcdbe", 0, 0, (0, 8, 7, 8)
+/a(?:b|c|d){6,7}?(.)/
+ "acdbcdbe", 0, 0, (0, 8, 7, 8)
+/a(?:b|c|d){5,6}(.)/
+ "acdbcdbe", 0, 0, (0, 8, 7, 8)
+/a(?:b|c|d){5,6}?(.)/
+ "acdbcdbe", 0, 0, (0, 7, 6, 7)
+/a(?:b|c|d){5,7}(.)/
+ "acdbcdbe", 0, 0, (0, 8, 7, 8)
+/a(?:b|c|d){5,7}?(.)/
+ "acdbcdbe", 0, 0, (0, 7, 6, 7)
+/a(?:b|(c|e){1,2}?|d)+?(.)/
+ "ace", 0, 0, (0, 3, 1, 2, 2, 3)
+/^(.+)?B/
+ "AB", 0, 0, (0, 2, 0, 1)
+/^([^a-z])|(\\^)$/
+ ".", 0, 0, (0, 1, 0, 1, -1, -1)
+/^[<>]&/
+ "<&OUT", 0, 0, (0, 2)
+/((a{4})+)/
+ "aaaaaaaaa", 0, 0, (0, 8, 0, 8, 4, 8)
+/(((aa){2})+)/
+ "aaaaaaaaaa", 0, 0, (0, 8, 0, 8, 4, 8, 6, 8)
+/(((a{2}){2})+)/
+ "aaaaaaaaaa", 0, 0, (0, 8, 0, 8, 4, 8, 6, 8)
+/(?:(f)(o)(o)|(b)(a)(r))*/
+ "foobar", 0, 0, (0, 6, -1, -1, -1, -1, -1, -1, 3, 4, 4, 5, 5, 6)
+/(?:..)*a/
+ "aba", 0, 0, (0, 3)
+/(?:..)*?a/
+ "aba", 0, 0, (0, 1)
+/^(?:b|a(?=(.)))*\\1/
+ "abc", 0, 0, (0, 2, -1, -1)
+/^(){3,5}/
+ "abc", 0, 0, (0, 0, 0, 0)
+/^(a+)*ax/
+ "aax", 0, 0, (0, 3, 0, 1)
+/^((a|b)+)*ax/
+ "aax", 0, 0, (0, 3, 0, 1, 0, 1)
+/^((a|bc)+)*ax/
+ "aax", 0, 0, (0, 3, 0, 1, 0, 1)
+/(a|x)*ab/
+ "cab", 0, 1, (1, 3, -1, -1)
+/(a)*ab/
+ "cab", 0, 1, (1, 3, -1, -1)
+/(?:c|d)(?:)(?:a(?:)(?:b)(?:b(?:))(?:b(?:)(?:b)))/
+ "cabbbb", 0, 0, (0, 6)
+/(?:c|d)(?:)(?:aaaaaaaa(?:)(?:bbbbbbbb)(?:bbbbbbbb(?:))(?:bbbbbbbb(?:)(?:bbbbbbbb)))/
+ "caaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 0, 0, (0, 41)
+/(ab)\\d\\1/i
+ "Ab4ab", 0, 0, (0, 5, 0, 2)
+ "ab4Ab", 0, 0, (0, 5, 0, 2)
+/foo\\w*\\d{4}baz/
+ "foobar1234baz", 0, 0, (0, 13)
+/x(~~)*(?:(?:F)?)?/
+ "x~~", 0, 0, (0, 3, 1, 3)
+/(?=(a+?))(\\1ab)/
+ "aaab", 0, 1, (1, 4, 1, 2, 1, 4)
+/(\\w+:)+/
+ "one:", 0, 0, (0, 4, 0, 4)
+/([\\w:]+::)?(\\w+)$/
+ "abcd", 0, 0, (0, 4, -1, -1, 0, 4)
+ "xy:z:::abcd", 0, 0, (0, 11, 0, 7, 7, 11)
+ "abcd:", 0, -1, (6, 11, -1, -1, -1, -1)
+ "abcd:", 0, -1, (6, -1, -1, -1, -1, -1)
+/^[^bcd]*(c+)/
+ "aexycd", 0, 0, (0, 5, 4, 5)
+/(a*)b+/
+ "caab", 0, 1, (1, 4, 1, 3)
+/([[:]+)/
+ "a:[b]:", 0, 1, (1, 3, 1, 3)
+/([[=]+)/
+ "a=[b]=", 0, 1, (1, 3, 1, 3)
+/([[.]+)/
+ "a.[b].", 0, 1, (1, 3, 1, 3)
+/$/m
+ "a\nb\n", 0, 1, (1, 1)
+ "b\na\n", 0, 1, (1, 1)
+ "b\na", 0, 1, (1, 1)
+/a$/
+ "b\na", 0, 2, (2, 3)
+ "a\nb\n", 0, -1, (-1, -1)
+ "aaab", 0, -1, (-1, -1)
+/a$/m
+ "a\nb\n", 0, 0, (0, 1)
+ "b\na\n", 0, 2, (2, 3)
+ "b\na", 0, 2, (2, 3)
+/aa$/
+ "b\naa", 0, 2, (2, 4)
+ "aa\nb\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/aa$/m
+ "aa\nb\n", 0, 0, (0, 2)
+ "b\naa\n", 0, 2, (2, 4)
+ "b\naa", 0, 2, (2, 4)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/ab$/
+ "b\nab", 0, 2, (2, 4)
+ "ab\nb\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/ab$/m
+ "ab\nb\n", 0, 0, (0, 2)
+ "b\nab\n", 0, 2, (2, 4)
+ "b\nab", 0, 2, (2, 4)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/abb$/
+ "b\nabb", 0, 2, (2, 5)
+ "abb\nb\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/abb$/m
+ "abb\nb\n", 0, 0, (0, 3)
+ "b\nabb\n", 0, 2, (2, 5)
+ "b\nabb", 0, 2, (2, 5)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/(^|x)(c)/
+ "ca", 0, 0, (0, 1, 0, 0, 0, 1)
+/foo.bart/
+ "foo.bart", 0, 0, (0, 8)
+/^d[x][x][x]/m
+ "abcd\ndxxx", 0, 5, (5, 9)
+/tt+$/
+ "xxxtt", 0, 3, (3, 5)
+/(\\d+\\.\\d+)/
+ "3.1415926", 0, 0, (0, 9, 0, 9)
+/\\.c(pp|xx|c)?$/i
+ "IO.c", 0, 2, (2, 4, -1, -1)
+ "Changes", 0, -1, (6, 11, -1, -1)
+/(\\.c(pp|xx|c)?$)/i
+ "IO.c", 0, 2, (2, 4, 2, 4, -1, -1)
+/(^|a)b/
+ "ab", 0, 0, (0, 2, 0, 1)
+/^([ab]*?)(b)?(c)$/
+ "abac", 0, 0, (0, 4, 0, 3, -1, -1, 3, 4)
+/^(?:.,){2}c/i
+ "a,b,c", 0, 0, (0, 5)
+/^(.,){2}c/i
+ "a,b,c", 0, 0, (0, 5, 2, 4)
+/^(?:[^,]*,){2}c/
+ "a,b,c", 0, 0, (0, 5)
+/^([^,]*,){2}c/
+ "a,b,c", 0, 0, (0, 5, 2, 4)
+/^([^,]*,){3}d/
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^([^,]*,){3,}d/
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^([^,]*,){0,3}d/
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^([^,]{1,3},){3}d/i
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^([^,]{1,3},){3,}d/
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^([^,]{1,3},){0,3}d/
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^([^,]{1,},){3}d/
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^([^,]{1,},){3,}d/
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^([^,]{1,},){0,3}d/
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^([^,]{0,3},){3}d/i
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^([^,]{0,3},){3,}d/
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^([^,]{0,3},){0,3}d/
+ "aaa,b,c,d", 0, 0, (0, 9, 6, 8)
+/^(a(b)?)+$/
+ "aba", 0, 0, (0, 3, 2, 3, -1, -1)
+/^(aa(bb)?)+$/
+ "aabbaa", 0, 0, (0, 6, 4, 6, -1, -1)
+/^.{9}abc.*\\n/m
+ "123\nabcabcabcabc\n", 0, 4, (4, 17)
+/^(a)?a$/
+ "a", 0, 0, (0, 1, -1, -1)
+/^(a\\1?)(a\\1?)(a\\2?)(a\\3?)$/
+ "aaaaaa", 0, 0, (0, 6, 0, 1, 1, 3, 3, 4, 4, 6)
+ "a", 0, -1, (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
+ "aa", 0, -1, (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
+ "aaa", 0, -1, (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
+ "aaaa", 0, 0, (0, 4, 0, 1, 1, 2, 2, 3, 3, 4)
+ "aaaaa", 0, 0, (0, 5, 0, 1, 1, 3, 3, 4, 4, 5)
+ "aaaaaaa", 0, 0, (0, 7, 0, 1, 1, 3, 3, 6, 6, 7)
+ "aaaaaaaa", 0, -1, (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
+ "aaaaaaaaa", 0, -1, (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
+ "aaaaaaaaaa", 0, 0, (0, 10, 0, 1, 1, 3, 3, 6, 6, 10)
+ "aaaaaaaaaaa", 0, -1, (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
+ "aaaaaaaaaaaa", 0, -1, (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
+ "aaaaaaaaaaaaa", 0, -1, (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
+ "aaaaaaaaaaaaaa", 0, -1, (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
+ "aaaaaaaaaaaaaaa", 0, -1, (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
+ "aaaaaaaaaaaaaaaa", 0, -1, (-1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
+/^(0+)?(?:x(1))?/
+ "x1", 0, 0, (0, 2, -1, -1, 1, 2)
+/^([0-9a-fA-F]+)(?:x([0-9a-fA-F]+)?)(?:x([0-9a-fA-F]+))?/
+ "012cxx0190", 0, 0, (0, 10, 0, 4, -1, -1, 6, 10)
+/^(b+?|a){1,2}c/
+ "bbbac", 0, 0, (0, 5, 3, 4)
+ "bbbbac", 0, 0, (0, 6, 4, 5)
+/((?:aaaa|bbbb)cccc)?/
+ "aaaacccc", 0, 0, (0, 8, 0, 8)
+ "bbbbcccc", 0, 0, (0, 8, 0, 8)
+/ab{4,5}bc/
+ "abbbbc", 0, -1, (0, 9)
+ "abq", 0, -1, (0, -1)
+ "abbbbc", 0, -1, (0, -1)
+/a[^]b]c/
+ "a]c", 0, -1, (-1, -1)
+/\\by\\b/
+ "xy", 0, -1, (-1, -1)
+ "yz", 0, -1, (-1, -1)
+ "xyz", 0, -1, (-1, -1)
+/\\Ba\\B/
+ "a-", 0, -1, (-1, -1)
+ "-a", 0, -1, (-1, -1)
+ "-a-", 0, -1, (-1, -1)
+/a\\sb/
+ "a-b", 0, -1, (-1, -1)
+ "a b", 0, 0, (0, 3)
+/a[\\s]b/
+ "a-b", 0, -1, (-1, -1)
+ "a b", 0, 0, (0, 3)
+/$b/
+ "b", 0, -1, (-1, -1)
+/^(ab|cd)e/
+ "abcde", 0, -1, (0, 10, -1, -1)
+/a[bcd]+dcdcde/
+ "adcdcde", 0, -1, (0, 10)
+ "abcde", 0, -1, (0, -1)
+ "adcdcde", 0, -1, (0, -1)
+/[k]/
+ "ab", 0, -1, (-1, -1)
+/((\\3|b)\\2(a)x)+/
+ "aaxabxbaxbbx", 0, 1, (1, 3, 1, 3, 1, 1, 1, 2)
+ "aaaxabaxbaaxbbax", 0, 2, (2, 4, 2, 4, 2, 2, 2, 3)
+/ab{1,}bc/i
+ "ABQ", 0, -1, (0, 10)
+/ab{4,5}?bc/i
+ "ABBBBC", 0, -1, (0, 10)
+ "ABQ", 0, -1, (0, -1)
+ "ABBBBC", 0, -1, (0, -1)
+/a.*c/i
+ "AXYZD", 0, -1, (4, 10)
+ "AABC", 0, 0, (0, 4)
+ "AXYZD", 0, -1, (4, -1)
+/a[^]b]c/i
+ "A]C", 0, -1, (-1, -1)
+/$b/i
+ "B", 0, -1, (-1, -1)
+ "A]C", 0, -1, (-1, -1)
+/^(ab|cd)e/i
+ "ABCDE", 0, -1, (0, 10, -1, -1)
+ "ABCDE", 0, -1, (0, -1, -1, -1)
+/a[bcd]+dcdcde/i
+ "ADCDCDE", 0, -1, (0, 10)
+/[k]/i
+ "AB", 0, -1, (-1, -1)
+/^(a\\1?){4}$/
+ "aaaaaaaaa", 0, -1, (-1, -1, -1, -1)
+ "aaaaaaaaaaa", 0, -1, (-1, -1, -1, -1)
+ "a", 0, -1, (-1, -1, -1, -1)
+ "aa", 0, -1, (-1, -1, -1, -1)
+ "aaa", 0, -1, (-1, -1, -1, -1)
+ "aaaa", 0, 0, (0, 4, 3, 4)
+ "aaaaa", 0, -1, (-1, -1, -1, -1)
+ "aaaaaaa", 0, -1, (-1, -1, -1, -1)
+ "aaaaaaaa", 0, -1, (-1, -1, -1, -1)
+ "aaaaaaaaaa", 0, -1, (-1, -1, -1, -1)
+ "aaaaaaaaaaaa", 0, -1, (-1, -1, -1, -1)
+ "aaaaaaaaaaaaa", 0, -1, (-1, -1, -1, -1)
+ "aaaaaaaaaaaaaa", 0, -1, (-1, -1, -1, -1)
+ "aaaaaaaaaaaaaaa", 0, -1, (-1, -1, -1, -1)
+ "aaaaaaaaaaaaaaaa", 0, -1, (-1, -1, -1, -1)
+ "AB", 0, -1, (-1, -1, -1, -1)
+/^(?:a?b?)*$/
+ "a--", 0, -1, (-1, -1)
+ "", 0, 0, (0, 0)
+ "a", 0, 0, (0, 1)
+ "ab", 0, 0, (0, 2)
+ "aaa", 0, 0, (0, 3)
+ "dbcb", 0, -1, (-1, -1)
+ "aa--", 0, -1, (-1, -1)
+/^b/
+ "a\nb\nc\n", 0, -1, (-1, -1)
+/()^b/
+ "a\nb\nc\n", 0, -1, (7, 10, -1, -1)
+ "a\nb\nc\n", 0, -1, (7, -1, -1, -1)
+/^(?=(a+?))\\1ab/
+ "aaab", 0, -1, (-1, -1, 0, 1)
+/(>a+)ab/
+ "aaab", 0, -1, (1, 11, -1, -1)
+/a\\Z/
+ "a\nb\n", 0, -1, (-1, -1)
+/a\\z/
+ "a\nb\n", 0, -1, (-1, -1)
+ "b\na\n", 0, -1, (-1, -1)
+ "az", 0, 0, (0, 2)
+/a\\z/m
+ "a\nb\n", 0, -1, (-1, -1)
+ "b\na\n", 0, -1, (-1, -1)
+/aa\\Z/
+ "aa\nb\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/aa\\z/
+ "aa\nb\n", 0, -1, (-1, -1)
+ "b\naa\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/aa\\z/m
+ "aa\nb\n", 0, -1, (-1, -1)
+ "b\naa\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/aa\\Z/m
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/ab\\Z/
+ "ab\nb\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/ab\\z/
+ "ab\nb\n", 0, -1, (-1, -1)
+ "b\nab\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/ab\\z/m
+ "ab\nb\n", 0, -1, (-1, -1)
+ "b\nab\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/ab\\Z/m
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/abb\\Z/
+ "abb\nb\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/abb\\z/
+ "abb\nb\n", 0, -1, (-1, -1)
+ "b\nabb\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/abb\\z/m
+ "abb\nb\n", 0, -1, (-1, -1)
+ "b\nabb\n", 0, -1, (-1, -1)
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
+/abb\\Z/m
+ "ac\nb\n", 0, -1, (-1, -1)
+ "b\nac\n", 0, -1, (-1, -1)
+ "b\nac", 0, -1, (-1, -1)
+ "ca\nb\n", 0, -1, (-1, -1)
+ "b\nca\n", 0, -1, (-1, -1)
+ "b\nca", 0, -1, (-1, -1)
diff --git a/tools/CodeProfile.cpp b/tools/CodeProfile.cpp
new file mode 100644 (file)
index 0000000..beed4b2
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "CodeProfile.h"
+
+#include "CodeBlock.h"
+#include "CodeProfiling.h"
+#include "LinkBuffer.h"
+#include "ProfileTreeNode.h"
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+#if PLATFORM(MAC)
+#include <cxxabi.h>
+#include <dlfcn.h>
+#include <execinfo.h>
+#endif
+
+namespace JSC {
+
+// Map from CodeType enum to a corresponding name.
+const char* CodeProfile::s_codeTypeNames[CodeProfile::NumberOfCodeTypes] = {
+    "[[EngineCode]]",
+    "[[GlobalThunk]]",
+    "[[RegExpCode]]",
+    "[[DFGJIT]]",
+    "[[BaselineOnly]]",
+    "[[BaselineProfile]]",
+    "[[BaselineOSR]]",
+    "[[EngineFrame]]"
+};
+
+// Helper function, find the symbol name for a pc in JSC.
+static const char* symbolName(void* address)
+{
+#if PLATFORM(MAC)
+    Dl_info info;
+    if (!dladdr(address, &info) || !info.dli_sname)
+        return "<unknown>";
+
+    const char* mangledName = info.dli_sname;
+    const char* cxaDemangled = abi::__cxa_demangle(mangledName, 0, 0, 0);
+    return cxaDemangled ? cxaDemangled : mangledName;
+#else
+    UNUSED_PARAM(address);
+    return "<unknown>";
+#endif
+}
+
+// Helper function, truncate traces to prune the output & make very verbose mode a little more readable.
+static bool truncateTrace(const char* symbolName)
+{
+    return !strcmp(symbolName, "JSC::BytecodeGenerator::generate()")
+        || !strcmp(symbolName, "JSC::Parser<JSC::Lexer<unsigned char> >::parseInner()")
+        || !strcmp(symbolName, "WTF::fastMalloc(unsigned long)")
+        || !strcmp(symbolName, "WTF::calculateUTCOffset()")
+        || !strcmp(symbolName, "JSC::DFG::ByteCodeParser::parseCodeBlock()");
+        
+}
+
+// Each trace consists of a sequence of zero or more 'EngineFrame' entries,
+// followed by a sample in JIT code, or one or more 'EngineFrame' entries,
+// followed by a 'EngineCode' terminator.
+void CodeProfile::sample(void* pc, void** framePointer)
+{
+    // Disallow traces containing only a 'EngineCode' terminator, without any 'EngineFrame' frames.
+    if (!framePointer)
+        return;
+
+    while (framePointer) {
+        CodeType type;
+
+#if ENABLE(JIT)
+        // Determine if this sample fell in JIT code, and if so, from which JIT & why.
+        void* ownerUID = CodeProfiling::getOwnerUIDForPC(pc);
+
+        if (!ownerUID)
+            type = EngineFrame;
+        else if (ownerUID == GLOBAL_THUNK_ID)
+            type = GlobalThunk;
+        else if (ownerUID == REGEXP_CODE_ID)
+            type = RegExpCode;
+        else {
+            CodeBlock* codeBlock = static_cast<CodeBlock*>(ownerUID);
+            if (codeBlock->getJITType() == JITCode::DFGJIT)
+                type = DFGJIT;
+            else if (codeBlock->canCompileWithDFGState() == CodeBlock::CompileWithDFGFalse)
+                type = BaselineOnly;
+            else if (codeBlock->replacement())
+                type = BaselineOSR;
+            else
+                type = BaselineProfile;
+        }
+#else
+        type = EngineFrame;
+#endif
+
+        // A sample in JIT code terminates the trace.
+        m_samples.append(CodeRecord(pc, type));
+        if (type != EngineFrame)
+            return;
+
+#if PLATFORM(MAC) && CPU(X86_64)
+        // Walk up the stack.
+        pc = framePointer[1];
+        framePointer = reinterpret_cast<void**>(*framePointer);
+#elif OS(LINUX) && CPU(X86)
+        // Don't unwind the stack as some dependent third party libraries
+        // may be compiled with -fomit-frame-pointer.
+        framePointer = 0;
+#else
+        // This platform is not yet supported!
+        ASSERT_NOT_REACHED();
+#endif
+    }
+
+    // If we get here, we walked the entire stack without finding any frames of JIT code.
+    m_samples.append(CodeRecord(0, EngineCode));
+}
+
+void CodeProfile::report()
+{
+    dataLog("<CodeProfiling %s:%d>\n", m_file.data(), m_lineNo);
+
+    // How many frames of C-code to print - 0, if not verbose, 1 if verbose, up to 1024 if very verbose.
+    unsigned recursionLimit = CodeProfiling::beVeryVerbose() ? 1024 : CodeProfiling::beVerbose();
+
+    ProfileTreeNode profile;
+
+    // Walk through the sample buffer.
+    size_t trace = 0;
+    while (trace < m_samples.size()) {
+
+        // All traces are zero or more 'EngineFrame's, followed by a non-'EngineFrame'.
+        // Scan to find the last sample in the trace.
+        size_t lastInTrace = trace;
+        while (m_samples[lastInTrace].type == EngineFrame)
+            ++lastInTrace;
+
+        // We use the last sample type to look up a name (used as a bucket in the profiler).
+        ProfileTreeNode* callbacks = profile.sampleChild(s_codeTypeNames[m_samples[lastInTrace].type]);
+
+        // If there are any samples in C-code, add up to recursionLimit of them into the profile tree.
+        size_t lastEngineFrame = lastInTrace;
+        for (unsigned count = 0; lastEngineFrame > trace && count < recursionLimit; ++count) {
+            --lastEngineFrame;
+            ASSERT(m_samples[lastEngineFrame].type == EngineFrame);
+            const char* name = symbolName(m_samples[lastEngineFrame].pc);
+            callbacks = callbacks->sampleChild(name);
+            if (truncateTrace(name))
+                break;
+        }
+
+        // Move on to the next trace.
+        trace = lastInTrace + 1;
+        ASSERT(trace <= m_samples.size());
+    }
+
+    // Output the profile tree.
+    dataLog("Total samples: %lld\n", static_cast<long long>(profile.childCount()));
+    profile.dump();
+    
+    for (size_t i = 0 ; i < m_children.size(); ++i)
+        m_children[i]->report();
+
+    dataLog("</CodeProfiling %s:%d>\n", m_file.data(), m_lineNo);
+}
+
+}
diff --git a/tools/CodeProfile.h b/tools/CodeProfile.h
new file mode 100644 (file)
index 0000000..ea360bc
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CodeProfile_h
+#define CodeProfile_h
+
+#include "SourceCode.h"
+#include "TieredMMapArray.h"
+#include <wtf/text/CString.h>
+
+namespace JSC {
+
+class CodeProfile {
+public:
+    CodeProfile(const SourceCode& source, CodeProfile* parent)
+        : m_file(source.provider()->url().utf8())
+        , m_lineNo(source.firstLine())
+        , m_parent(parent)
+    {
+        if (parent)
+            parent->addChild(this);
+    }
+
+    void sample(void* pc, void** framePointer);
+    void report();
+
+    CodeProfile* parent()
+    {
+        return m_parent;
+    }
+    
+    void addChild(CodeProfile* child)
+    {
+        m_children.append(adoptPtr(child));
+    }
+
+private:
+    enum CodeType {
+        EngineCode,
+        GlobalThunk,
+        RegExpCode,
+        DFGJIT,
+        BaselineOnly,
+        BaselineProfile,
+        BaselineOSR,
+        EngineFrame,
+        NumberOfCodeTypes
+    };
+    struct CodeRecord {
+        CodeRecord(void* pc, CodeType type)
+            : pc(pc)
+            , type(type)
+        {
+        }
+        void* pc;
+        CodeType type;
+    };
+
+    CString m_file;
+    unsigned m_lineNo;
+    CodeProfile* m_parent;
+    Vector< OwnPtr<CodeProfile> > m_children;
+    TieredMMapArray<CodeRecord> m_samples;
+
+    static const char* s_codeTypeNames[NumberOfCodeTypes];
+};
+
+}
+
+#endif // CodeProfile_h
+
diff --git a/tools/CodeProfiling.cpp b/tools/CodeProfiling.cpp
new file mode 100644 (file)
index 0000000..740595e
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "CodeProfiling.h"
+
+#include "CodeProfile.h"
+#include <wtf/MetaAllocator.h>
+
+#if HAVE(SIGNAL_H)
+#include <signal.h>
+#endif
+
+#if OS(LINUX)
+#include <sys/time.h>
+#endif
+
+namespace JSC {
+
+volatile CodeProfile* CodeProfiling::s_profileStack = 0;
+CodeProfiling::Mode CodeProfiling::s_mode = CodeProfiling::Disabled;
+WTF::MetaAllocatorTracker* CodeProfiling::s_tracker = 0;
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+#endif
+
+#if (PLATFORM(MAC) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))
+// Helper function to start & stop the timer.
+// Presently we're using the wall-clock timer, since this seems to give the best results.
+static void setProfileTimer(unsigned usec)
+{
+    itimerval timer;
+    timer.it_value.tv_sec = 0;
+    timer.it_value.tv_usec = usec;
+    timer.it_interval.tv_sec = 0;
+    timer.it_interval.tv_usec = usec;
+    setitimer(ITIMER_REAL, &timer, 0);
+}
+#endif
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+
+#if PLATFORM(MAC) && CPU(X86_64)
+static void profilingTimer(int, siginfo_t*, void* uap)
+{
+    mcontext_t context = static_cast<ucontext_t*>(uap)->uc_mcontext;
+    CodeProfiling::sample(reinterpret_cast<void*>(context->__ss.__rip),
+                          reinterpret_cast<void**>(context->__ss.__rbp));
+}
+#elif OS(LINUX) && CPU(X86)
+static void profilingTimer(int, siginfo_t*, void* uap)
+{
+    mcontext_t context = static_cast<ucontext_t*>(uap)->uc_mcontext;
+    CodeProfiling::sample(reinterpret_cast<void*>(context.gregs[REG_EIP]),
+                          reinterpret_cast<void**>(context.gregs[REG_EBP]));
+}
+#endif
+
+// Callback triggered when the timer is fired.
+void CodeProfiling::sample(void* pc, void** framePointer)
+{
+    CodeProfile* profileStack = const_cast<CodeProfile*>(s_profileStack);
+    if (profileStack)
+        profileStack->sample(pc, framePointer);
+}
+
+void CodeProfiling::notifyAllocator(WTF::MetaAllocator* allocator)
+{
+#if !OS(WINCE)
+    // Check for JSC_CODE_PROFILING.
+    const char* codeProfilingMode = getenv("JSC_CODE_PROFILING");
+    if (!codeProfilingMode)
+        return;
+
+    // Check for a valid mode, currently "1", "2", or "3".
+    if (!codeProfilingMode[0] || codeProfilingMode[1])
+        return;
+    switch (*codeProfilingMode) {
+    case '1':
+        s_mode = Enabled;
+        break;
+    case '2':
+        s_mode = Verbose;
+        break;
+    case '3':
+        s_mode = VeryVerbose;
+        break;
+    default:
+        return;
+    }
+
+    ASSERT(enabled());
+    ASSERT(!s_tracker);
+    s_tracker = new WTF::MetaAllocatorTracker();
+    allocator->trackAllocations(s_tracker);
+#endif
+}
+
+void* CodeProfiling::getOwnerUIDForPC(void* address)
+{
+    if (!s_tracker)
+        return 0;
+    WTF::MetaAllocatorHandle* handle = s_tracker->find(address);
+    if (!handle)
+        return 0;
+    return handle->ownerUID();
+}
+
+void CodeProfiling::begin(const SourceCode& source)
+{
+    // Push a new CodeProfile onto the stack for each script encountered.
+    CodeProfile* profileStack = const_cast<CodeProfile*>(s_profileStack);
+    bool alreadyProfiling = profileStack;
+    s_profileStack = profileStack = new CodeProfile(source, profileStack);
+
+    // Is the profiler already running - if so, the timer will already be set up.
+    if (alreadyProfiling)
+        return;
+
+#if (PLATFORM(MAC) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))
+    // Regsiter a signal handler & itimer.
+    struct sigaction action;
+    action.sa_sigaction = reinterpret_cast<void (*)(int, siginfo_t *, void *)>(profilingTimer);
+    sigfillset(&action.sa_mask);
+    action.sa_flags = SA_SIGINFO;
+    sigaction(SIGALRM, &action, 0);
+    setProfileTimer(100);
+#endif
+}
+
+void CodeProfiling::end()
+{
+    // Pop the current profiler off the stack.
+    CodeProfile* current = const_cast<CodeProfile*>(s_profileStack);
+    ASSERT(current);
+    s_profileStack = current->parent();
+
+    // Is this the outermost script being profiled? - if not, just return.
+    // We perform all output of profiles recursively from the outermost script,
+    // to minimize profiling overhead from skewing results.
+    if (s_profileStack)
+        return;
+
+#if (PLATFORM(MAC) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))
+    // Stop profiling
+    setProfileTimer(0);
+#endif
+
+    current->report();
+    delete current;
+}
+
+}
diff --git a/tools/CodeProfiling.h b/tools/CodeProfiling.h
new file mode 100644 (file)
index 0000000..9b0f5da
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CodeProfiling_h
+#define CodeProfiling_h
+
+namespace WTF {
+
+class MetaAllocator;
+class MetaAllocatorTracker;
+
+}
+
+namespace JSC {
+
+class CodeProfile;
+class SourceCode;
+
+class CodeProfiling {
+    enum Mode {
+        Disabled,
+        Enabled,
+        Verbose,
+        VeryVerbose
+    };
+
+public:
+    CodeProfiling(const SourceCode& source)
+        : m_active(enabled())
+    {
+        if (m_active)
+            begin(source);
+    }
+
+    ~CodeProfiling()
+    {
+        if (m_active)
+            end();
+    }
+
+    static bool enabled() { return s_mode != Disabled; }
+    static bool beVerbose() { return s_mode >= Verbose; }
+    static bool beVeryVerbose() { return s_mode >= VeryVerbose; }
+
+    static void notifyAllocator(WTF::MetaAllocator*);
+    static void* getOwnerUIDForPC(void*);
+    static void sample(void* pc, void** framePointer);
+
+private:
+    void begin(const SourceCode&);
+    void end();
+
+    bool m_active;
+
+    static Mode s_mode;
+    static WTF::MetaAllocatorTracker* s_tracker;
+    static volatile CodeProfile* s_profileStack;
+};
+
+}
+
+#endif // CodeProfiling_h
+
diff --git a/tools/ProfileTreeNode.h b/tools/ProfileTreeNode.h
new file mode 100644 (file)
index 0000000..9de39ad
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef ProfileTreeNode_h
+#define ProfileTreeNode_h
+
+namespace JSC {
+
+class ProfileTreeNode {
+    typedef HashMap<String, ProfileTreeNode> Map;
+    typedef std::pair<String, ProfileTreeNode> MapEntry;
+
+public:
+    ProfileTreeNode()
+        : m_count(0)
+        , m_children(0)
+    {
+    }
+
+    ~ProfileTreeNode()
+    {
+        delete m_children;
+    }
+
+    ProfileTreeNode* sampleChild(const char* name)
+    {
+        if (!m_children)
+            m_children = new Map();
+    
+        ProfileTreeNode newEntry;
+        Map::AddResult result = m_children->add(String(name), newEntry);
+        ProfileTreeNode* childInMap = &result.iterator->second;
+        ++childInMap->m_count;
+        return childInMap;
+    }
+
+    void dump()
+    {
+        dumpInternal(0);
+    }
+
+    uint64_t count()
+    {
+        return m_count;
+    }
+
+    uint64_t childCount()
+    {
+        if (!m_children)
+            return 0;
+        uint64_t childCount = 0;
+        for (Map::iterator it = m_children->begin(); it != m_children->end(); ++it)
+            childCount += it->second.count();
+        return childCount;
+    }
+    
+private:
+    void dumpInternal(unsigned indent)
+    {
+        if (!m_children)
+            return;
+
+        // Copy pointers to all children into a vector, and sort the vector by sample count.
+        Vector<MapEntry*> entries;
+        for (Map::iterator it = m_children->begin(); it != m_children->end(); ++it)
+            entries.append(&*it);
+        qsort(entries.begin(), entries.size(), sizeof(MapEntry*), compareEntries);
+
+        // Iterate over the children in sample-frequency order.
+        for (size_t e = 0; e < entries.size(); ++e) {
+            MapEntry* entry = entries[e];
+
+            // Print the number of samples, the name of this node, and the number of samples that are stack-top
+            // in this node (samples directly within this node, excluding samples in children.
+            for (unsigned i = 0; i < indent; ++i)
+                dataLog("    ");
+            dataLog("% 8lld: %s (%lld stack top)\n",
+                static_cast<long long>(entry->second.count()),
+                entry->first.utf8().data(),
+                static_cast<long long>(entry->second.count() - entry->second.childCount()));
+
+            // Recursively dump the child nodes.
+            entry->second.dumpInternal(indent + 1);
+        }
+    }
+
+    static int compareEntries(const void* a, const void* b)
+    {
+        uint64_t da = (*static_cast<MapEntry* const *>(a))->second.count();
+        uint64_t db = (*static_cast<MapEntry* const *>(b))->second.count();
+        return (da < db) - (da > db);
+    }
+
+    uint64_t m_count;
+    Map* m_children;
+};
+
+}
+
+#endif // ProfileTreeNode_h
+
diff --git a/tools/TieredMMapArray.h b/tools/TieredMMapArray.h
new file mode 100644 (file)
index 0000000..03d9df2
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef TieredMMapArray_h
+#define TieredMMapArray_h
+
+#include <wtf/OSAllocator.h>
+
+namespace JSC {
+
+// This class implements a simple array class that can be grown by appending items to the end.
+// This class is implemented purely in terms of system allocations, with no malloc/free, so that
+// it can safely be used from a secondary thread whilst the main thrad is paused (potentially
+// holding the fast malloc heap lock).
+template<typename T>
+class TieredMMapArray {
+    static const size_t entriesPerBlock = 4096;
+
+public:
+    TieredMMapArray()
+        : m_directoryCount(4096)
+        , m_directory(static_cast<T**>(OSAllocator::reserveAndCommit(m_directoryCount * sizeof(T*))))
+        , m_size(0)
+    {
+        for (size_t block = 0; block < m_directoryCount; ++block)
+            m_directory[block] = 0;
+    }
+
+    ~TieredMMapArray()
+    {
+        size_t usedCount = (m_size + (entriesPerBlock - 1)) / entriesPerBlock;
+        ASSERT(usedCount == m_directoryCount || !m_directory[usedCount]);
+
+        for (size_t block = 0; block < usedCount; ++block) {
+            ASSERT(m_directory[block]);
+            OSAllocator::decommitAndRelease(m_directory[block], entriesPerBlock * sizeof(T));
+        }
+
+        OSAllocator::decommitAndRelease(m_directory, m_directoryCount * sizeof(T*));
+    }
+
+    T& operator[](size_t index)
+    {
+        ASSERT(index < m_size);
+        size_t block = index / entriesPerBlock;
+        size_t offset = index % entriesPerBlock;
+
+        ASSERT(m_directory[block]);
+        return m_directory[block][offset];
+    }
+
+    void append(const T& value)
+    {
+        // Check if the array is completely full, if so create more capacity in the directory.
+        if (m_size == m_directoryCount * entriesPerBlock) {
+            // Reallocate the directory.
+            size_t oldDirectorySize = m_directoryCount * sizeof(T*);
+            size_t newDirectorySize = oldDirectorySize * 2;
+            if (newDirectorySize < oldDirectorySize)
+                CRASH();
+            m_directory = OSAllocator::reallocateCommitted(m_directory, oldDirectorySize, newDirectorySize);
+
+            // 
+            size_t newDirectoryCount = m_directoryCount * 2;
+            for (size_t block = m_directoryCount; block < newDirectoryCount; ++block)
+                m_directory[block] = 0;
+            m_directoryCount = newDirectoryCount;
+        }
+
+        size_t index = m_size;
+        size_t block = index / entriesPerBlock;
+        size_t offset = index % entriesPerBlock;
+
+        if (!offset) {
+            ASSERT(!m_directory[block]);
+            m_directory[block] = static_cast<T*>(OSAllocator::reserveAndCommit(entriesPerBlock * sizeof(T)));
+        }
+
+        ASSERT(m_directory[block]);
+        ++m_size;
+        m_directory[block][offset] = value;
+    }
+
+    size_t size() const { return m_size; }
+
+private:
+    size_t m_directoryCount;
+    T** m_directory;
+    size_t m_size;
+};
+
+}
+
+#endif // TieredMMapArray_h
+
diff --git a/wscript b/wscript
index 3df3ded546839691ffaddf95668c0b6996e5f414..4afb4d26a632787467b6bd822c841cbe285c4536 100644 (file)
--- a/wscript
+++ b/wscript
@@ -33,32 +33,40 @@ def build(bld):
 
     import Options
 
 
     import Options
 
-    jscore_excludes = ['jsc.cpp', 'ProfilerServer.mm', 'ExecutableAllocatorPosix.cpp']
-    jscore_excludes.extend(get_excludes(jscore_dir, ['*Brew.cpp', '*CF.cpp', '*Symbian.cpp']))
-
-    jscore_excludes.extend(get_excludes(jscore_dir, ['*None.cpp']))
+    jscore_excludes = ['jsc.cpp', 'ExecutableAllocatorPosix.cpp', 'LLIntOffsetsExtractor.cpp']
+    jscore_exclude_patterns = get_port_excludes(Options.options.port)
+    jscore_exclude_patterns.append('*None.cpp')
 
     sources = []
 
     if Options.options.port == "wx":
         if building_on_win32:
 
     sources = []
 
     if Options.options.port == "wx":
         if building_on_win32:
-            jscore_excludes += ['MarkStackPosix.cpp', 'OSAllocatorPosix.cpp', 'ThreadingPthreads.cpp']
-            sources += ['heap/MarkStackWin.cpp']
+            jscore_excludes += ['OSAllocatorPosix.cpp', 'ThreadingPthreads.cpp']
+            sources.extend(['../WTF/wtf/ThreadingWin.cpp', '../WTF/wtf/ThreadSpecificWin.cpp', '../WTF/wtf/OSAllocatorWin.cpp'])
         else:
             jscore_excludes.append('JSStringRefBSTR.cpp')
         else:
             jscore_excludes.append('JSStringRefBSTR.cpp')
-            jscore_excludes.extend(get_excludes(jscore_dir, ['*Win.cpp']))
 
 
+    if sys.platform.startswith('darwin'):
+        jscore_excludes.append('GCActivityCallback.cpp') # this is an empty impl.
+
+    bld.env.LIBDIR = output_dir
     full_dirs = get_dirs_for_features(jscore_dir, features=[Options.options.port.lower()], dirs=jscore_dirs)
     full_dirs = get_dirs_for_features(jscore_dir, features=[Options.options.port.lower()], dirs=jscore_dirs)
+    abs_dirs = []
+    for adir in full_dirs:
+        abs_dirs.append(os.path.join(jscore_dir, adir))
+
+    jscore_excludes.extend(get_excludes_in_dirs(abs_dirs, jscore_exclude_patterns))
 
 
-    includes = common_includes + full_dirs
+    includes = common_includes + full_dirs + [output_dir]
     if sys.platform.startswith('darwin'):
         includes.append(os.path.join(jscore_dir, 'icu'))
 
     # 1. A simple program
     jscore = bld.new_task_gen(
     if sys.platform.startswith('darwin'):
         includes.append(os.path.join(jscore_dir, 'icu'))
 
     # 1. A simple program
     jscore = bld.new_task_gen(
-        features = 'cxx cstaticlib',
-        includes = '. .. assembler DerivedSources ForwardingHeaders ' + ' '.join(includes),
+        features = 'cc cxx cshlib',
+        includes = '. .. assembler ../WTF ' + ' '.join(includes),
         source = sources,
         source = sources,
+        defines = ['BUILDING_JavaScriptCore'],
         target = 'jscore',
         uselib = 'WX ICU ' + get_config(),
         uselib_local = '',
         target = 'jscore',
         uselib = 'WX ICU ' + get_config(),
         uselib_local = '',
@@ -68,7 +76,7 @@ def build(bld):
     
     obj = bld.new_task_gen(
         features = 'cxx cprogram',
     
     obj = bld.new_task_gen(
         features = 'cxx cprogram',
-        includes = '. .. assembler DerivedSources ForwardingHeaders ' + ' '.join(includes),
+        includes = '. .. assembler ../WTF ' + ' '.join(includes),
         source = 'jsc.cpp',
         target = 'jsc',
         uselib = 'WX ICU ' + get_config(),
         source = 'jsc.cpp',
         target = 'jsc',
         uselib = 'WX ICU ' + get_config(),
@@ -82,4 +90,4 @@ def build(bld):
         myenv.CXXFLAGS.remove('/EHsc')
         obj.env = myenv
 
         myenv.CXXFLAGS.remove('/EHsc')
         obj.env = myenv
 
-    bld.install_files(os.path.join(output_dir, 'JavaScriptCore'), 'API/*.h')
+    bld.add_group()
diff --git a/wtf/ASCIICType.h b/wtf/ASCIICType.h
deleted file mode 100644 (file)
index 83f274b..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 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:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must 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_ASCIICType_h
-#define WTF_ASCIICType_h
-
-#include <wtf/Assertions.h>
-
-// The behavior of many of the functions in the <ctype.h> header is dependent
-// on the current locale. But in the WebKit project, all uses of those functions
-// are in code processing something that's not locale-specific. These equivalents
-// for some of the <ctype.h> functions are named more explicitly, not dependent
-// on the C library locale, and we should also optimize them as needed.
-
-// All functions return false or leave the character unchanged if passed a character
-// that is outside the range 0-7F. So they can be used on Unicode strings or
-// characters if the intent is to do processing only if the character is ASCII.
-
-namespace WTF {
-
-    inline bool isASCII(char c) { return !(c & ~0x7F); }
-    inline bool isASCII(unsigned short c) { return !(c & ~0x7F); }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    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'; }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    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'); }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    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'); }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    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'); }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    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'); }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    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'; }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    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'; }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    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:
-
-            character          count
-            ---------          -----
-            non-spaces         689383
-        20  space              294720
-        0A  \n                 89059
-        09  \t                 28320
-        0D  \r                 0
-        0C  \f                 0
-        0B  \v                 0
-    */
-    inline bool isASCIISpace(char c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
-    inline bool isASCIISpace(unsigned short c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    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); }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    inline wchar_t toASCIILower(wchar_t c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
-#endif
-    inline int toASCIILower(int c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
-    inline unsigned toASCIILower(unsigned c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
-
-    // FIXME: Why do these need static_cast?
-    inline char toASCIIUpper(char c) { return static_cast<char>(c & ~((c >= 'a' && c <= 'z') << 5)); }
-    inline unsigned short toASCIIUpper(unsigned short c) { return static_cast<unsigned short>(c & ~((c >= 'a' && c <= 'z') << 5)); }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    inline wchar_t toASCIIUpper(wchar_t c) { return static_cast<wchar_t>(c & ~((c >= 'a' && c <= 'z') << 5)); }
-#endif
-    inline int toASCIIUpper(int c) { return static_cast<int>(c & ~((c >= 'a' && c <= 'z') << 5)); }
-    inline unsigned toASCIIUpper(unsigned c) { return static_cast<unsigned>(c & ~((c >= 'a' && c <= 'z') << 5)); }
-
-    inline int toASCIIHexValue(char c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
-    inline int toASCIIHexValue(char upperValue, char lowerValue) { ASSERT(isASCIIHexDigit(upperValue) && isASCIIHexDigit(lowerValue)); return ((toASCIIHexValue(upperValue) << 4) & 0xF0) | toASCIIHexValue(lowerValue); }
-    inline int toASCIIHexValue(unsigned short c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    inline int toASCIIHexValue(wchar_t c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
-#endif
-    inline int toASCIIHexValue(int c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
-    inline int toASCIIHexValue(unsigned c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
-
-    inline char lowerNibbleToASCIIHexDigit(char c) { char nibble = c & 0xF; return nibble < 10 ? '0' + nibble : 'A' + nibble - 10; }
-    inline char upperNibbleToASCIIHexDigit(char c) { char nibble = (c >> 4) & 0xF; return nibble < 10 ? '0' + nibble : 'A' + nibble - 10; }
-
-    inline bool isASCIIPrintable(char c) { return c >= ' ' && c <= '~'; }
-    inline bool isASCIIPrintable(unsigned short c) { return c >= ' ' && c <= '~'; }
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    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::isASCIIAlpha;
-using WTF::isASCIIAlphanumeric;
-using WTF::isASCIIDigit;
-using WTF::isASCIIHexDigit;
-using WTF::isASCIILower;
-using WTF::isASCIIOctalDigit;
-using WTF::isASCIIPrintable;
-using WTF::isASCIISpace;
-using WTF::isASCIIUpper;
-using WTF::toASCIIHexValue;
-using WTF::toASCIILower;
-using WTF::toASCIIUpper;
-using WTF::lowerNibbleToASCIIHexDigit;
-using WTF::upperNibbleToASCIIHexDigit;
-
-#endif
diff --git a/wtf/AVLTree.h b/wtf/AVLTree.h
deleted file mode 100644 (file)
index ec8a639..0000000
+++ /dev/null
@@ -1,960 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Based on Abstract AVL Tree Template v1.5 by Walt Karas
- * <http://geocities.com/wkaras/gen_cpp/avl_tree.html>.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must 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 AVL_TREE_H_
-#define AVL_TREE_H_
-
-#include "Assertions.h"
-#include <wtf/FixedArray.h>
-
-namespace WTF {
-
-// Here is the reference class for BSet.
-//
-// class BSet
-//   {
-//   public:
-//
-//     class ANY_bitref
-//       {
-//       public:
-//         operator bool ();
-//         void operator = (bool b);
-//       };
-//
-//     // Does not have to initialize bits.
-//     BSet();
-//
-//     // Must return a valid value for index when 0 <= index < maxDepth
-//     ANY_bitref operator [] (unsigned index);
-//
-//     // Set all bits to 1.
-//     void set();
-//
-//     // Set all bits to 0.
-//     void reset();
-//   };
-
-template<unsigned maxDepth>
-class AVLTreeDefaultBSet {
-public:
-    bool& operator[](unsigned i) { ASSERT(i < maxDepth); return m_data[i]; }
-    void set() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = true; }
-    void reset() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = false; }
-
-private:
-    FixedArray<bool, maxDepth> m_data;
-};
-
-// How to determine maxDepth:
-// d  Minimum number of nodes
-// 2  2
-// 3  4
-// 4  7
-// 5  12
-// 6  20
-// 7  33
-// 8  54
-// 9  88
-// 10 143
-// 11 232
-// 12 376
-// 13 609
-// 14 986
-// 15 1,596
-// 16 2,583
-// 17 4,180
-// 18 6,764
-// 19 10,945
-// 20 17,710
-// 21 28,656
-// 22 46,367
-// 23 75,024
-// 24 121,392
-// 25 196,417
-// 26 317,810
-// 27 514,228
-// 28 832,039
-// 29 1,346,268
-// 30 2,178,308
-// 31 3,524,577
-// 32 5,702,886
-// 33 9,227,464
-// 34 14,930,351
-// 35 24,157,816
-// 36 39,088,168
-// 37 63,245,985
-// 38 102,334,154
-// 39 165,580,140
-// 40 267,914,295
-// 41 433,494,436
-// 42 701,408,732
-// 43 1,134,903,169
-// 44 1,836,311,902
-// 45 2,971,215,072
-//
-// E.g., if, in a particular instantiation, the maximum number of nodes in a tree instance is 1,000,000, the maximum depth should be 28.
-// You pick 28 because MN(28) is 832,039, which is less than or equal to 1,000,000, and MN(29) is 1,346,268, which is strictly greater than 1,000,000.
-
-template <class Abstractor, unsigned maxDepth = 32, class BSet = AVLTreeDefaultBSet<maxDepth> >
-class AVLTree {
-public:
-
-    typedef typename Abstractor::key key;
-    typedef typename Abstractor::handle handle;
-    typedef typename Abstractor::size size;
-
-    enum SearchType {
-        EQUAL = 1,
-        LESS = 2,
-        GREATER = 4,
-        LESS_EQUAL = EQUAL | LESS,
-        GREATER_EQUAL = EQUAL | GREATER
-    };
-
-
-    Abstractor& abstractor() { return abs; }
-
-    inline handle insert(handle h);
-
-    inline handle search(key k, SearchType st = EQUAL);
-    inline handle search_least();
-    inline handle search_greatest();
-
-    inline handle remove(key k);
-
-    inline handle subst(handle new_node);
-
-    void purge() { abs.root = null(); }
-
-    bool is_empty() { return abs.root == null(); }
-
-    AVLTree() { abs.root = null(); }
-
-    class Iterator {
-    public:
-
-        // Initialize depth to invalid value, to indicate iterator is
-        // invalid.   (Depth is zero-base.)
-        Iterator() { depth = ~0U; }
-
-        void start_iter(AVLTree &tree, key k, SearchType st = EQUAL)
-        {
-            // Mask of high bit in an int.
-            const int MASK_HIGH_BIT = (int) ~ ((~ (unsigned) 0) >> 1);
-
-            // Save the tree that we're going to iterate through in a
-            // member variable.
-            tree_ = &tree;
-
-            int cmp, target_cmp;
-            handle h = tree_->abs.root;
-            unsigned d = 0;
-
-            depth = ~0U;
-
-            if (h == null())
-              // Tree is empty.
-              return;
-
-            if (st & LESS)
-              // Key can be greater than key of starting node.
-              target_cmp = 1;
-            else if (st & GREATER)
-              // Key can be less than key of starting node.
-              target_cmp = -1;
-            else
-              // Key must be same as key of starting node.
-              target_cmp = 0;
-
-            for (;;) {
-                cmp = cmp_k_n(k, h);
-                if (cmp == 0) {
-                    if (st & EQUAL) {
-                        // Equal node was sought and found as starting node.
-                        depth = d;
-                        break;
-                    }
-                    cmp = -target_cmp;
-                } else if (target_cmp != 0) {
-                    if (!((cmp ^ target_cmp) & MASK_HIGH_BIT)) {
-                        // cmp and target_cmp are both negative or both positive.
-                        depth = d;
-                    }
-                }
-                h = cmp < 0 ? get_lt(h) : get_gt(h);
-                if (h == null())
-                    break;
-                branch[d] = cmp > 0;
-                path_h[d++] = h;
-            }
-        }
-
-        void start_iter_least(AVLTree &tree)
-        {
-            tree_ = &tree;
-
-            handle h = tree_->abs.root;
-
-            depth = ~0U;
-
-            branch.reset();
-
-            while (h != null()) {
-                if (depth != ~0U)
-                    path_h[depth] = h;
-                depth++;
-                h = get_lt(h);
-            }
-        }
-
-        void start_iter_greatest(AVLTree &tree)
-        {
-            tree_ = &tree;
-
-            handle h = tree_->abs.root;
-
-            depth = ~0U;
-
-            branch.set();
-
-            while (h != null()) {
-                if (depth != ~0U)
-                    path_h[depth] = h;
-                depth++;
-                h = get_gt(h);
-            }
-        }
-
-        handle operator*()
-        {
-            if (depth == ~0U)
-                return null();
-
-            return depth == 0 ? tree_->abs.root : path_h[depth - 1];
-        }
-
-        void operator++()
-        {
-            if (depth != ~0U) {
-                handle h = get_gt(**this);
-                if (h == null()) {
-                    do {
-                        if (depth == 0) {
-                            depth = ~0U;
-                            break;
-                        }
-                        depth--;
-                    } while (branch[depth]);
-                } else {
-                    branch[depth] = true;
-                    path_h[depth++] = h;
-                    for (;;) {
-                        h = get_lt(h);
-                        if (h == null())
-                            break;
-                        branch[depth] = false;
-                        path_h[depth++] = h;
-                    }
-                }
-            }
-        }
-
-        void operator--()
-        {
-            if (depth != ~0U) {
-                handle h = get_lt(**this);
-                if (h == null())
-                    do {
-                        if (depth == 0) {
-                            depth = ~0U;
-                            break;
-                        }
-                        depth--;
-                    } while (!branch[depth]);
-                else {
-                    branch[depth] = false;
-                    path_h[depth++] = h;
-                    for (;;) {
-                        h = get_gt(h);
-                        if (h == null())
-                            break;
-                        branch[depth] = true;
-                        path_h[depth++] = h;
-                    }
-                }
-            }
-        }
-
-        void operator++(int) { ++(*this); }
-        void operator--(int) { --(*this); }
-
-    protected:
-
-        // Tree being iterated over.
-        AVLTree *tree_;
-
-        // Records a path into the tree.  If branch[n] is true, indicates
-        // take greater branch from the nth node in the path, otherwise
-        // take the less branch.  branch[0] gives branch from root, and
-        // so on.
-        BSet branch;
-
-        // Zero-based depth of path into tree.
-        unsigned depth;
-
-        // Handles of nodes in path from root to current node (returned by *).
-        handle path_h[maxDepth - 1];
-
-        int cmp_k_n(key k, handle h) { return tree_->abs.compare_key_node(k, h); }
-        int cmp_n_n(handle h1, handle h2) { return tree_->abs.compare_node_node(h1, h2); }
-        handle get_lt(handle h) { return tree_->abs.get_less(h); }
-        handle get_gt(handle h) { return tree_->abs.get_greater(h); }
-        handle null() { return tree_->abs.null(); }
-    };
-
-    template<typename fwd_iter>
-    bool build(fwd_iter p, size num_nodes)
-    {
-        if (num_nodes == 0) {
-            abs.root = null();
-            return true;
-        }
-
-        // Gives path to subtree being built.  If branch[N] is false, branch
-        // less from the node at depth N, if true branch greater.
-        BSet branch;
-
-        // If rem[N] is true, then for the current subtree at depth N, it's
-        // greater subtree has one more node than it's less subtree.
-        BSet rem;
-
-            // Depth of root node of current subtree.
-        unsigned depth = 0;
-
-            // Number of nodes in current subtree.
-        size num_sub = num_nodes;
-
-        // The algorithm relies on a stack of nodes whose less subtree has
-        // been built, but whose right subtree has not yet been built.  The
-        // stack is implemented as linked list.  The nodes are linked
-        // together by having the "greater" handle of a node set to the
-        // next node in the list.  "less_parent" is the handle of the first
-        // node in the list.
-        handle less_parent = null();
-
-        // h is root of current subtree, child is one of its children.
-        handle h, child;
-
-        for (;;) {
-            while (num_sub > 2) {
-                // Subtract one for root of subtree.
-                num_sub--;
-                rem[depth] = !!(num_sub & 1);
-                branch[depth++] = false;
-                num_sub >>= 1;
-            }
-
-            if (num_sub == 2) {
-                // Build a subtree with two nodes, slanting to greater.
-                // I arbitrarily chose to always have the extra node in the
-                // greater subtree when there is an odd number of nodes to
-                // split between the two subtrees.
-
-                h = *p;
-                p++;
-                child = *p;
-                p++;
-                set_lt(child, null());
-                set_gt(child, null());
-                set_bf(child, 0);
-                set_gt(h, child);
-                set_lt(h, null());
-                set_bf(h, 1);
-            } else { // num_sub == 1
-                // Build a subtree with one node.
-
-                h = *p;
-                p++;
-                set_lt(h, null());
-                set_gt(h, null());
-                set_bf(h, 0);
-            }
-
-            while (depth) {
-                depth--;
-                if (!branch[depth])
-                    // We've completed a less subtree.
-                    break;
-
-                // We've completed a greater subtree, so attach it to
-                // its parent (that is less than it).  We pop the parent
-                // off the stack of less parents.
-                child = h;
-                h = less_parent;
-                less_parent = get_gt(h);
-                set_gt(h, child);
-                // num_sub = 2 * (num_sub - rem[depth]) + rem[depth] + 1
-                num_sub <<= 1;
-                num_sub += 1 - rem[depth];
-                if (num_sub & (num_sub - 1))
-                    // num_sub is not a power of 2
-                    set_bf(h, 0);
-                else
-                    // num_sub is a power of 2
-                    set_bf(h, 1);
-            }
-
-            if (num_sub == num_nodes)
-                // We've completed the full tree.
-                break;
-
-            // The subtree we've completed is the less subtree of the
-            // next node in the sequence.
-
-            child = h;
-            h = *p;
-            p++;
-            set_lt(h, child);
-
-            // Put h into stack of less parents.
-            set_gt(h, less_parent);
-            less_parent = h;
-
-            // Proceed to creating greater than subtree of h.
-            branch[depth] = true;
-            num_sub += rem[depth++];
-
-        } // end for (;;)
-
-        abs.root = h;
-
-        return true;
-    }
-
-protected:
-
-    friend class Iterator;
-
-    // Create a class whose sole purpose is to take advantage of
-    // the "empty member" optimization.
-    struct abs_plus_root : public Abstractor {
-        // The handle of the root element in the AVL tree.
-        handle root;
-    };
-
-    abs_plus_root abs;
-
-
-    handle get_lt(handle h) { return abs.get_less(h); }
-    void set_lt(handle h, handle lh) { abs.set_less(h, lh); }
-
-    handle get_gt(handle h) { return abs.get_greater(h); }
-    void set_gt(handle h, handle gh) { abs.set_greater(h, gh); }
-
-    int get_bf(handle h) { return abs.get_balance_factor(h); }
-    void set_bf(handle h, int bf) { abs.set_balance_factor(h, bf); }
-
-    int cmp_k_n(key k, handle h) { return abs.compare_key_node(k, h); }
-    int cmp_n_n(handle h1, handle h2) { return abs.compare_node_node(h1, h2); }
-
-    handle null() { return abs.null(); }
-
-private:
-
-    // Balances subtree, returns handle of root node of subtree
-    // after balancing.
-    handle balance(handle bal_h)
-    {
-        handle deep_h;
-
-        // Either the "greater than" or the "less than" subtree of
-        // this node has to be 2 levels deeper (or else it wouldn't
-        // need balancing).
-
-        if (get_bf(bal_h) > 0) {
-            // "Greater than" subtree is deeper.
-
-            deep_h = get_gt(bal_h);
-
-            if (get_bf(deep_h) < 0) {
-                handle old_h = bal_h;
-                bal_h = get_lt(deep_h);
-
-                set_gt(old_h, get_lt(bal_h));
-                set_lt(deep_h, get_gt(bal_h));
-                set_lt(bal_h, old_h);
-                set_gt(bal_h, deep_h);
-
-                int bf = get_bf(bal_h);
-                if (bf != 0) {
-                    if (bf > 0) {
-                        set_bf(old_h, -1);
-                        set_bf(deep_h, 0);
-                    } else {
-                        set_bf(deep_h, 1);
-                        set_bf(old_h, 0);
-                    }
-                    set_bf(bal_h, 0);
-                } else {
-                    set_bf(old_h, 0);
-                    set_bf(deep_h, 0);
-                }
-            } else {
-                set_gt(bal_h, get_lt(deep_h));
-                set_lt(deep_h, bal_h);
-                if (get_bf(deep_h) == 0) {
-                    set_bf(deep_h, -1);
-                    set_bf(bal_h, 1);
-                } else {
-                    set_bf(deep_h, 0);
-                    set_bf(bal_h, 0);
-                }
-                bal_h = deep_h;
-            }
-        } else {
-            // "Less than" subtree is deeper.
-
-            deep_h = get_lt(bal_h);
-
-            if (get_bf(deep_h) > 0) {
-                handle old_h = bal_h;
-                bal_h = get_gt(deep_h);
-                set_lt(old_h, get_gt(bal_h));
-                set_gt(deep_h, get_lt(bal_h));
-                set_gt(bal_h, old_h);
-                set_lt(bal_h, deep_h);
-
-                int bf = get_bf(bal_h);
-                if (bf != 0) {
-                    if (bf < 0) {
-                        set_bf(old_h, 1);
-                        set_bf(deep_h, 0);
-                    } else {
-                        set_bf(deep_h, -1);
-                        set_bf(old_h, 0);
-                    }
-                    set_bf(bal_h, 0);
-                } else {
-                    set_bf(old_h, 0);
-                    set_bf(deep_h, 0);
-                }
-            } else {
-                set_lt(bal_h, get_gt(deep_h));
-                set_gt(deep_h, bal_h);
-                if (get_bf(deep_h) == 0) {
-                    set_bf(deep_h, 1);
-                    set_bf(bal_h, -1);
-                } else {
-                    set_bf(deep_h, 0);
-                    set_bf(bal_h, 0);
-                }
-                bal_h = deep_h;
-            }
-        }
-
-        return bal_h;
-    }
-
-};
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::insert(handle h)
-{
-    set_lt(h, null());
-    set_gt(h, null());
-    set_bf(h, 0);
-
-    if (abs.root == null())
-        abs.root = h;
-    else {
-        // Last unbalanced node encountered in search for insertion point.
-        handle unbal = null();
-        // Parent of last unbalanced node.
-        handle parent_unbal = null();
-        // Balance factor of last unbalanced node.
-        int unbal_bf;
-
-        // Zero-based depth in tree.
-        unsigned depth = 0, unbal_depth = 0;
-
-        // Records a path into the tree.  If branch[n] is true, indicates
-        // take greater branch from the nth node in the path, otherwise
-        // take the less branch.  branch[0] gives branch from root, and
-        // so on.
-        BSet branch;
-
-        handle hh = abs.root;
-        handle parent = null();
-        int cmp;
-
-        do {
-            if (get_bf(hh) != 0) {
-                unbal = hh;
-                parent_unbal = parent;
-                unbal_depth = depth;
-            }
-            cmp = cmp_n_n(h, hh);
-            if (cmp == 0)
-                // Duplicate key.
-                return hh;
-            parent = hh;
-            hh = cmp < 0 ? get_lt(hh) : get_gt(hh);
-            branch[depth++] = cmp > 0;
-        } while (hh != null());
-
-        //  Add node to insert as leaf of tree.
-        if (cmp < 0)
-            set_lt(parent, h);
-        else
-            set_gt(parent, h);
-
-        depth = unbal_depth;
-
-        if (unbal == null())
-            hh = abs.root;
-        else {
-            cmp = branch[depth++] ? 1 : -1;
-            unbal_bf = get_bf(unbal);
-            if (cmp < 0)
-                unbal_bf--;
-            else  // cmp > 0
-                unbal_bf++;
-            hh = cmp < 0 ? get_lt(unbal) : get_gt(unbal);
-            if ((unbal_bf != -2) && (unbal_bf != 2)) {
-                // No rebalancing of tree is necessary.
-                set_bf(unbal, unbal_bf);
-                unbal = null();
-            }
-        }
-
-        if (hh != null())
-            while (h != hh) {
-                cmp = branch[depth++] ? 1 : -1;
-                if (cmp < 0) {
-                    set_bf(hh, -1);
-                    hh = get_lt(hh);
-                } else { // cmp > 0
-                    set_bf(hh, 1);
-                    hh = get_gt(hh);
-                }
-            }
-
-        if (unbal != null()) {
-            unbal = balance(unbal);
-            if (parent_unbal == null())
-                abs.root = unbal;
-            else {
-                depth = unbal_depth - 1;
-                cmp = branch[depth] ? 1 : -1;
-                if (cmp < 0)
-                    set_lt(parent_unbal, unbal);
-                else  // cmp > 0
-                    set_gt(parent_unbal, unbal);
-            }
-        }
-    }
-
-    return h;
-}
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::search(key k, typename AVLTree<Abstractor, maxDepth, BSet>::SearchType st)
-{
-    const int MASK_HIGH_BIT = (int) ~ ((~ (unsigned) 0) >> 1);
-
-    int cmp, target_cmp;
-    handle match_h = null();
-    handle h = abs.root;
-
-    if (st & LESS)
-        target_cmp = 1;
-    else if (st & GREATER)
-        target_cmp = -1;
-    else
-        target_cmp = 0;
-
-    while (h != null()) {
-        cmp = cmp_k_n(k, h);
-        if (cmp == 0) {
-            if (st & EQUAL) {
-                match_h = h;
-                break;
-            }
-            cmp = -target_cmp;
-        } else if (target_cmp != 0)
-            if (!((cmp ^ target_cmp) & MASK_HIGH_BIT))
-                // cmp and target_cmp are both positive or both negative.
-                match_h = h;
-        h = cmp < 0 ? get_lt(h) : get_gt(h);
-    }
-
-    return match_h;
-}
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::search_least()
-{
-    handle h = abs.root, parent = null();
-
-    while (h != null()) {
-        parent = h;
-        h = get_lt(h);
-    }
-
-    return parent;
-}
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::search_greatest()
-{
-    handle h = abs.root, parent = null();
-
-    while (h != null()) {
-        parent = h;
-        h = get_gt(h);
-    }
-
-    return parent;
-}
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::remove(key k)
-{
-    // Zero-based depth in tree.
-    unsigned depth = 0, rm_depth;
-
-    // Records a path into the tree.  If branch[n] is true, indicates
-    // take greater branch from the nth node in the path, otherwise
-    // take the less branch.  branch[0] gives branch from root, and
-    // so on.
-    BSet branch;
-
-    handle h = abs.root;
-    handle parent = null(), child;
-    int cmp, cmp_shortened_sub_with_path = 0;
-
-    for (;;) {
-        if (h == null())
-            // No node in tree with given key.
-            return null();
-        cmp = cmp_k_n(k, h);
-        if (cmp == 0)
-            // Found node to remove.
-            break;
-        parent = h;
-        h = cmp < 0 ? get_lt(h) : get_gt(h);
-        branch[depth++] = cmp > 0;
-        cmp_shortened_sub_with_path = cmp;
-    }
-    handle rm = h;
-    handle parent_rm = parent;
-    rm_depth = depth;
-
-    // If the node to remove is not a leaf node, we need to get a
-    // leaf node, or a node with a single leaf as its child, to put
-    // in the place of the node to remove.  We will get the greatest
-    // node in the less subtree (of the node to remove), or the least
-    // node in the greater subtree.  We take the leaf node from the
-    // deeper subtree, if there is one.
-
-    if (get_bf(h) < 0) {
-        child = get_lt(h);
-        branch[depth] = false;
-        cmp = -1;
-    } else {
-        child = get_gt(h);
-        branch[depth] = true;
-        cmp = 1;
-    }
-    depth++;
-
-    if (child != null()) {
-        cmp = -cmp;
-        do {
-            parent = h;
-            h = child;
-            if (cmp < 0) {
-                child = get_lt(h);
-                branch[depth] = false;
-            } else {
-                child = get_gt(h);
-                branch[depth] = true;
-            }
-            depth++;
-        } while (child != null());
-
-        if (parent == rm)
-            // Only went through do loop once.  Deleted node will be replaced
-            // in the tree structure by one of its immediate children.
-            cmp_shortened_sub_with_path = -cmp;
-        else
-            cmp_shortened_sub_with_path = cmp;
-
-        // Get the handle of the opposite child, which may not be null.
-        child = cmp > 0 ? get_lt(h) : get_gt(h);
-    }
-
-    if (parent == null())
-        // There were only 1 or 2 nodes in this tree.
-        abs.root = child;
-    else if (cmp_shortened_sub_with_path < 0)
-        set_lt(parent, child);
-    else
-        set_gt(parent, child);
-
-    // "path" is the parent of the subtree being eliminated or reduced
-    // from a depth of 2 to 1.  If "path" is the node to be removed, we
-    // set path to the node we're about to poke into the position of the
-    // node to be removed.
-    handle path = parent == rm ? h : parent;
-
-    if (h != rm) {
-        // Poke in the replacement for the node to be removed.
-        set_lt(h, get_lt(rm));
-        set_gt(h, get_gt(rm));
-        set_bf(h, get_bf(rm));
-        if (parent_rm == null())
-            abs.root = h;
-        else {
-            depth = rm_depth - 1;
-            if (branch[depth])
-                set_gt(parent_rm, h);
-            else
-                set_lt(parent_rm, h);
-        }
-    }
-
-    if (path != null()) {
-        // Create a temporary linked list from the parent of the path node
-        // to the root node.
-        h = abs.root;
-        parent = null();
-        depth = 0;
-        while (h != path) {
-            if (branch[depth++]) {
-                child = get_gt(h);
-                set_gt(h, parent);
-            } else {
-                child = get_lt(h);
-                set_lt(h, parent);
-            }
-            parent = h;
-            h = child;
-        }
-
-        // Climb from the path node to the root node using the linked
-        // list, restoring the tree structure and rebalancing as necessary.
-        bool reduced_depth = true;
-        int bf;
-        cmp = cmp_shortened_sub_with_path;
-        for (;;) {
-            if (reduced_depth) {
-                bf = get_bf(h);
-                if (cmp < 0)
-                    bf++;
-                else  // cmp > 0
-                    bf--;
-                if ((bf == -2) || (bf == 2)) {
-                    h = balance(h);
-                    bf = get_bf(h);
-                } else
-                    set_bf(h, bf);
-                reduced_depth = (bf == 0);
-            }
-            if (parent == null())
-                break;
-            child = h;
-            h = parent;
-            cmp = branch[--depth] ? 1 : -1;
-            if (cmp < 0)    {
-                parent = get_lt(h);
-                set_lt(h, child);
-            } else {
-                parent = get_gt(h);
-                set_gt(h, child);
-            }
-        }
-        abs.root = h;
-    }
-
-    return rm;
-}
-
-template <class Abstractor, unsigned maxDepth, class BSet>
-inline typename AVLTree<Abstractor, maxDepth, BSet>::handle
-AVLTree<Abstractor, maxDepth, BSet>::subst(handle new_node)
-{
-    handle h = abs.root;
-    handle parent = null();
-    int cmp, last_cmp;
-
-    /* Search for node already in tree with same key. */
-    for (;;) {
-        if (h == null())
-            /* No node in tree with same key as new node. */
-            return null();
-        cmp = cmp_n_n(new_node, h);
-        if (cmp == 0)
-            /* Found the node to substitute new one for. */
-            break;
-        last_cmp = cmp;
-        parent = h;
-        h = cmp < 0 ? get_lt(h) : get_gt(h);
-    }
-
-    /* Copy tree housekeeping fields from node in tree to new node. */
-    set_lt(new_node, get_lt(h));
-    set_gt(new_node, get_gt(h));
-    set_bf(new_node, get_bf(h));
-
-    if (parent == null())
-        /* New node is also new root. */
-        abs.root = new_node;
-    else {
-        /* Make parent point to new node. */
-        if (last_cmp < 0)
-            set_lt(parent, new_node);
-        else
-            set_gt(parent, new_node);
-    }
-
-    return h;
-}
-
-}
-
-#endif
diff --git a/wtf/Alignment.h b/wtf/Alignment.h
deleted file mode 100644 (file)
index 1903aad..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  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
diff --git a/wtf/AlwaysInline.h b/wtf/AlwaysInline.h
deleted file mode 100644 (file)
index bacbdd0..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *  Copyright (C) 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.
- *
- */
-
-#include "Platform.h"
-
-#ifndef ALWAYS_INLINE
-#if COMPILER(GCC) && defined(NDEBUG) && !COMPILER(MINGW)
-#define ALWAYS_INLINE inline __attribute__((__always_inline__))
-#elif (COMPILER(MSVC) || COMPILER(RVCT)) && defined(NDEBUG)
-#define ALWAYS_INLINE __forceinline
-#else
-#define ALWAYS_INLINE inline
-#endif
-#endif
-
-#ifndef NEVER_INLINE
-#if COMPILER(GCC)
-#define NEVER_INLINE __attribute__((__noinline__))
-#elif COMPILER(RVCT)
-#define NEVER_INLINE __declspec(noinline)
-#else
-#define NEVER_INLINE
-#endif
-#endif
-
-#ifndef UNLIKELY
-#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)
-#endif
-#endif
-
-#ifndef LIKELY
-#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)
-#endif
-#endif
-
-#ifndef NO_RETURN
-#if COMPILER(GCC)
-#define NO_RETURN __attribute((__noreturn__))
-#elif COMPILER(MSVC) || COMPILER(RVCT)
-#define NO_RETURN __declspec(noreturn)
-#else
-#define NO_RETURN
-#endif
-#endif
-
-#ifndef NO_RETURN_WITH_VALUE
-#if !COMPILER(MSVC)
-#define NO_RETURN_WITH_VALUE NO_RETURN
-#else
-#define NO_RETURN_WITH_VALUE
-#endif
-#endif
diff --git a/wtf/Assertions.cpp b/wtf/Assertions.cpp
deleted file mode 100644 (file)
index 7027143..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2003, 2006, 2007 Apple Inc.  All rights reserved.
- * Copyright (C) 2007-2009 Torch Mobile, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this 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.
- */
-
-// 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 <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include <CoreFoundation/CFString.h>
-
-#if COMPILER(MSVC) && !OS(WINCE) && !PLATFORM(BREWMP)
-#ifndef WINVER
-#define WINVER 0x0500
-#endif
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0500
-#endif
-#include <crtdbg.h>
-#endif
-
-#if OS(WINDOWS)
-#include <windows.h>
-#endif
-
-#if PLATFORM(BREWMP)
-#include <AEEdbg.h>
-#include <wtf/Vector.h>
-#endif
-
-#if PLATFORM(MAC)
-#include <cxxabi.h>
-#include <dlfcn.h>
-#include <execinfo.h>
-#endif
-
-extern "C" {
-
-#if PLATFORM(BREWMP)
-
-static void printLog(const Vector<char>& buffer)
-{
-    // Each call to DBGPRINTF generates at most 128 bytes of output on the Windows SDK.
-    // On Qualcomm chipset targets, DBGPRINTF() comes out the diag port (though this may change).
-    // The length of each output string is constrained even more than on the Windows SDK.
-#if COMPILER(MSVC)
-    const int printBufferSize = 128;
-#else
-    const int printBufferSize = 32;
-#endif
-
-    char printBuffer[printBufferSize + 1];
-    printBuffer[printBufferSize] = 0; // to guarantee null termination
-
-    const char* p = buffer.data();
-    const char* end = buffer.data() + buffer.size();
-    while (p < end) {
-        strncpy(printBuffer, p, printBufferSize);
-        dbg_Message(printBuffer, DBG_MSG_LEVEL_HIGH, __FILE__, __LINE__);
-        p += printBufferSize;
-    }
-}
-
-#endif
-
-WTF_ATTRIBUTE_PRINTF(1, 0)
-static void vprintf_stderr_common(const char* format, va_list args)
-{
-    if (strstr(format, "%@")) {
-        CFStringRef cfFormat = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8);
-        CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, cfFormat, args);
-
-        int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8);
-        char* buffer = (char*)malloc(length + 1);
-
-        CFStringGetCString(str, buffer, length, kCFStringEncodingUTF8);
-
-        fputs(buffer, stderr);
-
-        free(buffer);
-        CFRelease(str);
-        CFRelease(cfFormat);
-        return;
-    }
-#if OS(SYMBIAN)
-    vfprintf(stdout, format, args);
-#else
-    vfprintf(stderr, format, args);
-#endif
-}
-
-WTF_ATTRIBUTE_PRINTF(1, 2)
-static void printf_stderr_common(const char* format, ...)
-{
-    va_list args;
-    va_start(args, format);
-    vprintf_stderr_common(format, args);
-    va_end(args);
-}
-
-static void printCallSite(const char* file, int line, const char* function)
-{
-#if OS(WINDOWS) && !OS(WINCE) && defined(_DEBUG)
-    _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function);
-#else
-    // 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
-}
-
-void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion)
-{
-    if (assertion)
-        printf_stderr_common("ASSERTION FAILED: %s\n", assertion);
-    else
-        printf_stderr_common("SHOULD NEVER BE REACHED\n");
-    printCallSite(file, line, function);
-}
-
-void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...)
-{
-    printf_stderr_common("ASSERTION FAILED: ");
-    va_list args;
-    va_start(args, format);
-    vprintf_stderr_common(format, args);
-    va_end(args);
-    printf_stderr_common("\n%s\n", assertion);
-    printCallSite(file, line, function);
-}
-
-void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion)
-{
-    printf_stderr_common("ARGUMENT BAD: %s, %s\n", argName, assertion);
-    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: ");
-    va_list args;
-    va_start(args, format);
-    vprintf_stderr_common(format, args);
-    va_end(args);
-    printf_stderr_common("\n");
-    printCallSite(file, line, function);
-}
-
-void WTFReportError(const char* file, int line, const char* function, const char* format, ...)
-{
-    printf_stderr_common("ERROR: ");
-    va_list args;
-    va_start(args, format);
-    vprintf_stderr_common(format, args);
-    va_end(args);
-    printf_stderr_common("\n");
-    printCallSite(file, line, function);
-}
-
-void WTFLog(WTFLogChannel* channel, const char* format, ...)
-{
-    if (channel->state != WTFLogChannelOn)
-        return;
-
-    va_list args;
-    va_start(args, format);
-    vprintf_stderr_common(format, args);
-    va_end(args);
-    
-    size_t formatLength = strlen(format);
-    if (formatLength && format[formatLength - 1] != '\n')
-        printf_stderr_common("\n");
-}
-
-void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...)
-{
-    if (channel->state != WTFLogChannelOn)
-        return;
-
-    va_list args;
-    va_start(args, format);
-    vprintf_stderr_common(format, args);
-    va_end(args);
-
-    size_t formatLength = strlen(format);
-    if (formatLength && format[formatLength - 1] != '\n')
-        printf_stderr_common("\n");
-
-    printCallSite(file, line, function);
-}
-
-} // extern "C"
diff --git a/wtf/Assertions.h b/wtf/Assertions.h
deleted file mode 100644 (file)
index f6187bb..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright (C) 2003, 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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this 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_Assertions_h
-#define WTF_Assertions_h
-
-/*
-   no namespaces because this file has to be includable from C and Objective-C
-
-   Note, this file uses many GCC extensions, but it should be compatible with
-   C, Objective C, C++, and Objective C++.
-
-   For non-debug builds, everything is disabled by default.
-   Defining any of the symbols explicitly prevents this from having any effect.
-   
-   MSVC7 note: variadic macro support was added in MSVC8, so for now we disable
-   those macros in MSVC7. For more info, see the MSDN document on variadic 
-   macros here:
-   
-   http://msdn2.microsoft.com/en-us/library/ms177415(VS.80).aspx
-*/
-
-#include "Platform.h"
-
-#include <stdbool.h>
-
-#include <stddef.h>
-
-#if !COMPILER(MSVC)
-#include <inttypes.h>
-#endif
-
-#if OS(SYMBIAN)
-#include <e32def.h>
-#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
-#else
-#define ASSERTIONS_DISABLED_DEFAULT 0
-#endif
-
-#if COMPILER(MSVC7_OR_LOWER) || COMPILER(WINSCW)
-#define HAVE_VARIADIC_MACRO 0
-#else
-#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_MSG_DISABLED
-#if HAVE(VARIADIC_MACRO)
-#define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT
-#else
-#define ASSERT_MSG_DISABLED 1
-#endif
-#endif
-
-#ifndef ASSERT_ARG_DISABLED
-#define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT
-#endif
-
-#ifndef FATAL_DISABLED
-#if HAVE(VARIADIC_MACRO)
-#define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT
-#else
-#define FATAL_DISABLED 1
-#endif
-#endif
-
-#ifndef ERROR_DISABLED
-#if HAVE(VARIADIC_MACRO)
-#define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT
-#else
-#define ERROR_DISABLED 1
-#endif
-#endif
-
-#ifndef LOG_DISABLED
-#if HAVE(VARIADIC_MACRO)
-#define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT
-#else
-#define LOG_DISABLED 1
-#endif
-#endif
-
-#if COMPILER(GCC)
-#define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__
-#else
-#define WTF_PRETTY_FUNCTION __FUNCTION__
-#endif
-
-/* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute
-   emits a warning when %@ is used in the format string.  Until <rdar://problem/5195437> is resolved we can't include
-   the attribute when being used from Objective-C code in case it decides to use %@. */
-#if COMPILER(GCC) && !defined(__OBJC__)
-#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments)))
-#else
-#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) 
-#endif
-
-/* This macro is needed to prevent the clang static analyzer from generating false-positive reports in ASSERT() macros. */
-#ifdef __clang__
-#define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
-#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. */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum { WTFLogChannelOff, WTFLogChannelOn } WTFLogChannelState;
-
-typedef struct {
-    unsigned mask;
-    const char *defaultName;
-    WTFLogChannelState state;
-} WTFLogChannel;
-
-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
-}
-#endif
-
-/* CRASH() - Raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter.
-
-   Use CRASH() in response to known, unrecoverable errors like out-of-memory.
-   Macro is enabled in both debug and release mode.
-   To test for unknown errors and verify assumptions, use ASSERT instead, to avoid impacting performance in release builds.
-
-   Signals are ignored by the crash reporter on OS X so we must do better.
-*/
-#ifndef CRASH
-#if OS(SYMBIAN)
-#define CRASH() do { \
-    __DEBUGGER(); \
-    User::Panic(_L("Webkit CRASH"),0); \
-    } while(false)
-#elif PLATFORM(BREWMP)
-#define CRASH() do { \
-    dbg_Message("WebKit CRASH", DBG_MSG_LEVEL_FATAL, __FILE__, __LINE__); \
-    *(int *)(uintptr_t)0xbbadbeef = 0; \
-    ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
-} while(false)
-#else
-#define CRASH() do { \
-    WTFReportBacktrace(); \
-    *(int *)(uintptr_t)0xbbadbeef = 0; \
-    ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
-} while(false)
-#endif
-#endif
-
-/* BACKTRACE
-
-  Print a backtrace to the same location as ASSERT messages.
-*/
-
-#if BACKTRACE_DISABLED
-
-#define BACKTRACE() ((void)0)
-
-#else
-
-#define BACKTRACE() do { \
-    WTFReportBacktrace(); \
-} while(false)
-
-#endif
-
-/* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED
-
-  These macros are compiled out of release builds.
-  Expressions inside them are evaluated in debug builds only.
-*/
-
-#if OS(WINCE) && !PLATFORM(TORCHMOBILE)
-/* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */
-#include <windows.h>
-#undef min
-#undef max
-#undef ERROR
-#endif
-
-#if OS(WINDOWS) || OS(SYMBIAN)
-/* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */
-#undef ASSERT
-#endif
-
-#if PLATFORM(BREWMP)
-/* FIXME: We include this here only to avoid a conflict with the COMPILE_ASSERT macro. */
-#include <AEEClassIDs.h>
-
-/* FIXME: Change to use something other than COMPILE_ASSERT to avoid this conflict with the underlying platform */
-#undef COMPILE_ASSERT
-#endif
-
-#if ASSERT_DISABLED
-
-#define ASSERT(assertion) ((void)0)
-#define ASSERT_NOT_REACHED() ((void)0)
-
-#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT)
-template<typename T>
-inline void assertUnused(T& x) { (void)x; }
-#define ASSERT_UNUSED(variable, assertion) (assertUnused(variable))
-#else
-#define ASSERT_UNUSED(variable, assertion) ((void)variable)
-#endif
-
-#else
-
-#define ASSERT(assertion) do \
-    if (!(assertion)) { \
-        WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
-        CRASH(); \
-    } \
-while (0)
-
-#define ASSERT_NOT_REACHED() do { \
-    WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \
-    CRASH(); \
-} while (0)
-
-#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion)
-
-#endif
-
-/* ASSERT_WITH_MESSAGE */
-
-#if COMPILER(MSVC7_OR_LOWER)
-#define ASSERT_WITH_MESSAGE(assertion) ((void)0)
-#elif COMPILER(WINSCW)
-#define ASSERT_WITH_MESSAGE(assertion, arg...) ((void)0)
-#elif ASSERT_MSG_DISABLED
-#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0)
-#else
-#define ASSERT_WITH_MESSAGE(assertion, ...) do \
-    if (!(assertion)) { \
-        WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
-        CRASH(); \
-    } \
-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 */
-
-#if ASSERT_ARG_DISABLED
-
-#define ASSERT_ARG(argName, assertion) ((void)0)
-
-#else
-
-#define ASSERT_ARG(argName, assertion) do \
-    if (!(assertion)) { \
-        WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \
-        CRASH(); \
-    } \
-while (0)
-
-#endif
-
-/* COMPILE_ASSERT */
-#ifndef COMPILE_ASSERT
-#define COMPILE_ASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1]
-#endif
-
-/* FATAL */
-
-#if COMPILER(MSVC7_OR_LOWER)
-#define FATAL() ((void)0)
-#elif COMPILER(WINSCW)
-#define FATAL(arg...) ((void)0)
-#elif FATAL_DISABLED
-#define FATAL(...) ((void)0)
-#else
-#define FATAL(...) do { \
-    WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \
-    CRASH(); \
-} while (0)
-#endif
-
-/* LOG_ERROR */
-
-#if COMPILER(MSVC7_OR_LOWER)
-#define LOG_ERROR() ((void)0)
-#elif COMPILER(WINSCW)
-#define LOG_ERROR(arg...)  ((void)0)
-#elif ERROR_DISABLED
-#define LOG_ERROR(...) ((void)0)
-#else
-#define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__)
-#endif
-
-/* LOG */
-
-#if COMPILER(MSVC7_OR_LOWER)
-#define LOG() ((void)0)
-#elif COMPILER(WINSCW)
-#define LOG(arg...) ((void)0)
-#elif LOG_DISABLED
-#define LOG(channel, ...) ((void)0)
-#else
-#define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
-#define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel)
-#define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel
-#endif
-
-/* LOG_VERBOSE */
-
-#if COMPILER(MSVC7_OR_LOWER)
-#define LOG_VERBOSE(channel) ((void)0)
-#elif COMPILER(WINSCW)
-#define LOG_VERBOSE(channel, arg...) ((void)0)
-#elif LOG_DISABLED
-#define LOG_VERBOSE(channel, ...) ((void)0)
-#else
-#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 */
diff --git a/wtf/Atomics.h b/wtf/Atomics.h
deleted file mode 100644 (file)
index 1ebd487..0000000
+++ /dev/null
@@ -1,117 +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 Atomics_h
-#define Atomics_h
-
-#include "Platform.h"
-
-#if OS(WINDOWS)
-#include <windows.h>
-#elif OS(DARWIN)
-#include <libkern/OSAtomic.h>
-#elif OS(ANDROID)
-#include <cutils/atomic.h>
-#elif COMPILER(GCC) && !OS(SYMBIAN)
-#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))
-#include <ext/atomicity.h>
-#else
-#include <bits/atomicity.h>
-#endif
-#endif
-
-namespace WTF {
-
-#if OS(WINDOWS)
-#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)); }
-inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); }
-#else
-inline int atomicIncrement(int volatile* addend) { return InterlockedIncrement(reinterpret_cast<long volatile*>(addend)); }
-inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend)); }
-#endif
-
-#elif OS(DARWIN)
-#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)); }
-
-#elif OS(ANDROID)
-
-inline int atomicIncrement(int volatile* addend) { return android_atomic_inc(addend); }
-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_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; }
-
-#endif
-
-} // namespace WTF
-
-#if USE(LOCKFREE_THREADSAFEREFCOUNTED)
-using WTF::atomicDecrement;
-using WTF::atomicIncrement;
-#endif
-
-#endif // Atomics_h
diff --git a/wtf/Bitmap.h b/wtf/Bitmap.h
deleted file mode 100644 (file)
index 9ee7f4a..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- *  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
deleted file mode 100644 (file)
index a4d7425..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index f81d83e..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 682283c..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * 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
diff --git a/wtf/ByteArray.cpp b/wtf/ByteArray.cpp
deleted file mode 100644 (file)
index 910af59..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.
- */
-
-#include "config.h"
-#include "ByteArray.h"
-#include "StdLibExtras.h"
-
-namespace WTF {
-
-PassRefPtr<ByteArray> ByteArray::create(size_t size)
-{
-    unsigned char* buffer = new unsigned char[size + OBJECT_OFFSETOF(ByteArray, m_data)];
-    ASSERT((reinterpret_cast<size_t>(buffer) & 3) == 0);
-    return adoptRef(new (buffer) ByteArray(size));
-}
-
-}
diff --git a/wtf/ByteArray.h b/wtf/ByteArray.h
deleted file mode 100644 (file)
index bdec630..0000000
+++ /dev/null
@@ -1,104 +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 ByteArray_h
-#define ByteArray_h
-
-#include <limits.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/Platform.h>
-#include <wtf/RefCounted.h>
-
-namespace WTF {
-    class ByteArray : public RefCountedBase {
-    public:
-        unsigned length() const { return m_size; }
-
-        void set(unsigned index, double value)
-        {
-            if (index >= m_size)
-                return;
-            if (!(value > 0)) // Clamp NaN to 0
-                value = 0;
-            else if (value > 255)
-                value = 255;
-            m_data[index] = static_cast<unsigned char>(value + 0.5);
-        }
-
-        void set(unsigned index, unsigned char value)
-        {
-            if (index >= m_size)
-                return;
-            m_data[index] = value;
-        }
-
-        bool get(unsigned index, unsigned char& result) const
-        {
-            if (index >= m_size)
-                return false;
-            result = m_data[index];
-            return true;
-        }
-
-        unsigned char get(unsigned index) const
-        {
-            ASSERT(index < m_size);
-            return m_data[index];
-        }
-
-        unsigned char* data() { return m_data; }
-
-        void deref()
-        {
-            if (derefBase()) {
-                // We allocated with new unsigned char[] in create(),
-                // and then used placement new to construct the object.
-                this->~ByteArray();
-                delete[] reinterpret_cast<unsigned char*>(this);
-            }
-        }
-
-        static PassRefPtr<ByteArray> create(size_t size);
-
-    private:
-        ByteArray(size_t size)
-            : m_size(size)
-        {
-        }
-        size_t m_size;
-// MSVC can't handle correctly unsized array.
-// warning C4200: nonstandard extension used : zero-sized array in struct/union
-// Cannot generate copy-ctor or copy-assignment operator when UDT contains a zero-sized array
-#if COMPILER(MSVC)
-        unsigned char m_data[INT_MAX];
-#else
-        unsigned char m_data[];
-#endif
-    };
-} // namespace WTF
-
-using WTF::ByteArray;
-
-#endif
diff --git a/wtf/CMakeLists.txt b/wtf/CMakeLists.txt
deleted file mode 100644 (file)
index 87674b1..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-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
deleted file mode 100644 (file)
index e5d8bd7..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-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
deleted file mode 100644 (file)
index 9c558eb..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-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
-)
diff --git a/wtf/CONTRIBUTORS.pthreads-win32 b/wtf/CONTRIBUTORS.pthreads-win32
deleted file mode 100644 (file)
index 7de0f26..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-This is a copy of CONTRIBUTORS file for the Pthreads-win32 library, downloaded
-from http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/pthreads/CONTRIBUTORS?rev=1.32&cvsroot=pthreads-win32
-
-Included here to compliment the Pthreads-win32 license header in wtf/ThreadingWin.cpp file.
-WebKit is using derived sources of ThreadCondition code from Pthreads-win32.
-
--------------------------------------------------------------------------------
-
-Contributors (in approximate order of appearance)
-
-[See also the ChangeLog file where individuals are
-attributed in log entries. Likewise in the FAQ file.]
-
-Ben Elliston           bje at cygnus dot com
-                                       Initiated the project;
-                                       setup the project infrastructure (CVS, web page, etc.);
-                                       early prototype routines.
-Ross Johnson           rpj at callisto dot canberra dot edu dot au
-                                       early prototype routines;
-                                       ongoing project coordination/maintenance;
-                                       implementation of spin locks and barriers;
-                                       various enhancements;
-                                       bug fixes;
-                                       documentation;
-                                       testsuite.
-Robert Colquhoun       rjc at trump dot net dot au
-                                       Early bug fixes.
-John E. Bossom         John dot Bossom at cognos dot com
-                                       Contributed substantial original working implementation;
-                                       bug fixes;
-                                       ongoing guidance and standards interpretation.
-Anders Norlander       anorland at hem2 dot passagen dot se
-                                       Early enhancements and runtime checking for supported
-                                       Win32 routines.
-Tor Lillqvist          tml at iki dot fi
-                                       General enhancements;
-                                       early bug fixes to condition variables.
-Scott Lightner         scott at curriculum dot com
-                                       Bug fix.
-Kevin Ruland           Kevin dot Ruland at anheuser-busch dot com
-                                       Various bug fixes.
-Mike Russo             miker at eai dot com
-                                       Bug fix.
-Mark E. Armstrong      avail at pacbell dot net
-                                       Bug fixes.
-Lorin Hochstein        lmh at xiphos dot ca
-                                       general bug fixes; bug fixes to condition variables.
-Peter Slacik           Peter dot Slacik at tatramed dot sk
-                                       Bug fixes.
-Mumit Khan             khan at xraylith dot wisc dot edu
-                                       Fixes to work with Mingw32.
-Milan Gardian          mg at tatramed dot sk
-                                       Bug fixes and reports/analyses of obscure problems.
-Aurelio Medina         aureliom at crt dot com
-                                       First implementation of read-write locks.
-Graham Dumpleton       Graham dot Dumpleton at ra dot pad dot otc dot telstra dot com dot au
-                                       Bug fix in condition variables.
-Tristan Savatier       tristan at mpegtv dot com
-                                       WinCE port.
-Erik Hensema           erik at hensema dot xs4all dot nl
-                                       Bug fixes.
-Rich Peters            rpeters at micro-magic dot com
-Todd Owen              towen at lucidcalm dot dropbear dot id dot au
-                                       Bug fixes to dll loading.
-Jason Nye              jnye at nbnet dot nb dot ca
-                                       Implementation of async cancelation.
-Fred Forester          fforest at eticomm dot net
-Kevin D. Clark         kclark at cabletron dot com
-David Baggett          dmb at itasoftware dot com
-                                       Bug fixes.
-Paul Redondo           paul at matchvision dot com
-Scott McCaskill        scott at 3dfx dot com
-                                       Bug fixes.
-Jef Gearhart           jgearhart at tpssys dot com
-                                       Bug fix.
-Arthur Kantor          akantor at bexusa dot com
-                                       Mutex enhancements.
-Steven Reddie          smr at essemer dot com dot au
-                                       Bug fix.
-Alexander Terekhov     TEREKHOV at de dot ibm dot com
-                                       Re-implemented and improved read-write locks;
-                                       (with Louis Thomas) re-implemented and improved
-                                       condition variables;
-                                       enhancements to semaphores;
-                                       enhancements to mutexes;
-                                       new mutex implementation in 'futex' style;
-                                       suggested a robust implementation of pthread_once
-                                       similar to that implemented by V.Kliathcko;
-                                       system clock change handling re CV timeouts;
-                                       bug fixes.
-Thomas Pfaff           tpfaff at gmx dot net
-                                       Changes to make C version usable with C++ applications;
-                                       re-implemented mutex routines to avoid Win32 mutexes
-                                       and TryEnterCriticalSection;
-                                       procedure to fix Mingw32 thread-safety issues.
-Franco Bez             franco dot bez at gmx dot de
-                                       procedure to fix Mingw32 thread-safety issues.
-Louis Thomas           lthomas at arbitrade dot com
-                                       (with Alexander Terekhov) re-implemented and improved
-                                       condition variables.
-David Korn             dgk at research dot att dot com
-                                       Ported to UWIN.
-Phil Frisbie, Jr.      phil at hawksoft dot com
-                                       Bug fix.
-Ralf Brese             Ralf dot Brese at pdb4 dot siemens dot de
-                                       Bug fix.
-prionx at juno dot com         prionx at juno dot com
-                                       Bug fixes.
-Max Woodbury           mtew at cds dot duke dot edu
-                                       POSIX versioning conditionals;
-                                       reduced namespace pollution;
-                                       idea to separate routines to reduce statically
-                                       linked image sizes.
-Rob Fanner             rfanner at stonethree dot com
-                                       Bug fix.
-Michael Johnson        michaelj at maine dot rr dot com
-                                       Bug fix.
-Nicolas Barry          boozai at yahoo dot com
-                                       Bug fixes.
-Piet van Bruggen       pietvb at newbridges dot nl
-                                       Bug fix.
-Makoto Kato            raven at oldskool dot jp
-                                       AMD64 port.
-Panagiotis E. Hadjidoukas      peh at hpclab dot ceid dot upatras dot gr
-                                       Contributed the QueueUserAPCEx package which
-                                       makes preemptive async cancelation possible.
-Will Bryant            will dot bryant at ecosm dot com
-                                       Borland compiler patch and makefile.
-Anuj Goyal             anuj dot goyal at gmail dot com
-                                       Port to Digital Mars compiler.
-Gottlob Frege          gottlobfrege at  gmail dot com
-                                       re-implemented pthread_once (version 2)
-                                       (pthread_once cancellation added by rpj).
-Vladimir Kliatchko     vladimir at kliatchko dot com
-                                       reimplemented pthread_once with the same form
-                                       as described by A.Terekhov (later version 2);
-                                       implementation of MCS (Mellor-Crummey/Scott) locks.
\ No newline at end of file
diff --git a/wtf/CheckedArithmetic.h b/wtf/CheckedArithmetic.h
deleted file mode 100644 (file)
index 3de506d..0000000
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
- * 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 CheckedArithmetic_h
-#define CheckedArithmetic_h
-
-#include "Assertions.h"
-#include "TypeTraits.h"
-
-#include <limits>
-#include <stdint.h>
-
-/* Checked<T>
- *
- * This class provides a mechanism to perform overflow-safe integer arithmetic
- * without having to manually ensure that you have all the required bounds checks
- * directly in your code.
- *
- * There are two modes of operation:
- *  - The default is Checked<T, CrashOnOverflow>, and crashes at the point
- *    and overflow has occurred.
- *  - The alternative is Checked<T, RecordOverflow>, which uses an additional
- *    byte of storage to track whether an overflow has occurred, subsequent
- *    unchecked operations will crash if an overflow has occured
- *
- * It is possible to provide a custom overflow handler, in which case you need
- * to support these functions:
- *  - void overflowed();
- *    This function is called when an operation has produced an overflow.
- *  - bool hasOverflowed();
- *    This function must return true if overflowed() has been called on an
- *    instance and false if it has not.
- *  - void clearOverflow();
- *    Used to reset overflow tracking when a value is being overwritten with
- *    a new value.
- *
- * Checked<T> works for all integer types, with the following caveats:
- *  - Mixing signedness of operands is only supported for types narrower than
- *    64bits.
- *  - It does have a performance impact, so tight loops may want to be careful
- *    when using it.
- *
- */
-
-namespace WTF {
-
-class CrashOnOverflow {
-protected:
-    void overflowed()
-    {
-        CRASH();
-    }
-
-    void clearOverflow() { }
-
-public:
-    bool hasOverflowed() const { return false; }
-};
-
-class RecordOverflow {
-protected:
-    RecordOverflow()
-        : m_overflowed(false)
-    {
-    }
-
-    void overflowed()
-    {
-        m_overflowed = true;
-    }
-
-    void clearOverflow()
-    {
-        m_overflowed = false;
-    }
-
-public:
-    bool hasOverflowed() const { return m_overflowed; }
-
-private:
-    unsigned char m_overflowed;
-};
-
-template <typename T, class OverflowHandler = CrashOnOverflow> class Checked;
-template <typename T> struct RemoveChecked;
-template <typename T> struct RemoveChecked<Checked<T> >;
-
-template <typename Target, typename Source, bool targetSigned = std::numeric_limits<Target>::is_signed, bool sourceSigned = std::numeric_limits<Source>::is_signed> struct BoundsChecker;
-template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false> {
-    static bool inBounds(Source value)
-    {
-        // Same signedness so implicit type conversion will always increase precision
-        // to widest type
-        return value <= std::numeric_limits<Target>::max();
-    }
-};
-
-template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true> {
-    static bool inBounds(Source value)
-    {
-        // Same signedness so implicit type conversion will always increase precision
-        // to widest type
-        return std::numeric_limits<Target>::min() <= value && value <= std::numeric_limits<Target>::max();
-    }
-};
-
-template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true> {
-    static bool inBounds(Source value)
-    {
-        // Target is unsigned so any value less than zero is clearly unsafe
-        if (value < 0)
-            return false;
-        // If our (unsigned) Target is the same or greater width we can
-        // convert value to type Target without losing precision
-        if (sizeof(Target) >= sizeof(Source)) 
-            return static_cast<Target>(value) <= std::numeric_limits<Target>::max();
-        // The signed Source type has greater precision than the target so
-        // max(Target) -> Source will widen.
-        return value <= static_cast<Source>(std::numeric_limits<Target>::max());
-    }
-};
-
-template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false> {
-    static bool inBounds(Source value)
-    {
-        // Signed target with an unsigned source
-        if (sizeof(Target) <= sizeof(Source)) 
-            return value <= static_cast<Source>(std::numeric_limits<Target>::max());
-        // Target is Wider than Source so we're guaranteed to fit any value in
-        // unsigned Source
-        return true;
-    }
-};
-
-template <typename Target, typename Source, bool SameType = IsSameType<Target, Source>::value> struct BoundsCheckElider;
-template <typename Target, typename Source> struct BoundsCheckElider<Target, Source, true> {
-    static bool inBounds(Source) { return true; }
-};
-template <typename Target, typename Source> struct BoundsCheckElider<Target, Source, false> : public BoundsChecker<Target, Source> {
-};
-
-template <typename Target, typename Source> static inline bool isInBounds(Source value)
-{
-    return BoundsCheckElider<Target, Source>::inBounds(value);
-}
-
-template <typename T> struct RemoveChecked {
-    typedef T CleanType;
-    static const CleanType DefaultValue = 0;    
-};
-
-template <typename T> struct RemoveChecked<Checked<T, CrashOnOverflow> > {
-    typedef typename RemoveChecked<T>::CleanType CleanType;
-    static const CleanType DefaultValue = 0;
-};
-
-template <typename T> struct RemoveChecked<Checked<T, RecordOverflow> > {
-    typedef typename RemoveChecked<T>::CleanType CleanType;
-    static const CleanType DefaultValue = 0;
-};
-
-// The ResultBase and SignednessSelector are used to workaround typeof not being
-// available in MSVC
-template <typename U, typename V, bool uIsBigger = (sizeof(U) > sizeof(V)), bool sameSize = (sizeof(U) == sizeof(V))> struct ResultBase;
-template <typename U, typename V> struct ResultBase<U, V, true, false> {
-    typedef U ResultType;
-};
-
-template <typename U, typename V> struct ResultBase<U, V, false, false> {
-    typedef V ResultType;
-};
-
-template <typename U> struct ResultBase<U, U, false, true> {
-    typedef U ResultType;
-};
-
-template <typename U, typename V, bool uIsSigned = std::numeric_limits<U>::is_signed, bool vIsSigned = std::numeric_limits<V>::is_signed> struct SignednessSelector;
-template <typename U, typename V> struct SignednessSelector<U, V, true, true> {
-    typedef U ResultType;
-};
-
-template <typename U, typename V> struct SignednessSelector<U, V, false, false> {
-    typedef U ResultType;
-};
-
-template <typename U, typename V> struct SignednessSelector<U, V, true, false> {
-    typedef V ResultType;
-};
-
-template <typename U, typename V> struct SignednessSelector<U, V, false, true> {
-    typedef U ResultType;
-};
-
-template <typename U, typename V> struct ResultBase<U, V, false, true> {
-    typedef typename SignednessSelector<U, V>::ResultType ResultType;
-};
-
-template <typename U, typename V> struct Result : ResultBase<typename RemoveChecked<U>::CleanType, typename RemoveChecked<V>::CleanType> {
-};
-
-template <typename LHS, typename RHS, typename ResultType = typename Result<LHS, RHS>::ResultType, 
-    bool lhsSigned = std::numeric_limits<LHS>::is_signed, bool rhsSigned = std::numeric_limits<RHS>::is_signed> struct ArithmeticOperations;
-
-template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, true, true> {
-    // LHS and RHS are signed types
-
-    // Helper function
-    static inline bool signsMatch(LHS lhs, RHS rhs)
-    {
-        return (lhs ^ rhs) >= 0;
-    }
-
-    static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
-    {
-        if (signsMatch(lhs, rhs)) {
-            if (lhs >= 0) {
-                if ((std::numeric_limits<ResultType>::max() - rhs) < lhs)
-                    return false;
-            } else {
-                ResultType temp = lhs - std::numeric_limits<ResultType>::min();
-                if (rhs < -temp)
-                    return false;
-            }
-        } // if the signs do not match this operation can't overflow
-        result = lhs + rhs;
-        return true;
-    }
-
-    static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
-    {
-        if (!signsMatch(lhs, rhs)) {
-            if (lhs >= 0) {
-                if (lhs > std::numeric_limits<ResultType>::max() + rhs)
-                    return false;
-            } else {
-                if (rhs > std::numeric_limits<ResultType>::max() + lhs)
-                    return false;
-            }
-        } // if the signs match this operation can't overflow
-        result = lhs - rhs;
-        return true;
-    }
-
-    static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
-    {
-        if (signsMatch(lhs, rhs)) {
-            if (lhs >= 0) {
-                if (lhs && (std::numeric_limits<ResultType>::max() / lhs) < rhs)
-                    return false;
-            } else {
-                if (lhs == std::numeric_limits<ResultType>::min() || rhs == std::numeric_limits<ResultType>::min())
-                    return false;
-                if ((std::numeric_limits<ResultType>::max() / -lhs) < -rhs)
-                    return false;
-            }
-        } else {
-            if (lhs < 0) {
-                if (rhs && lhs < (std::numeric_limits<ResultType>::min() / rhs))
-                    return false;
-            } else {
-                if (lhs && rhs < (std::numeric_limits<ResultType>::min() / lhs))
-                    return false;
-            }
-        }
-        result = lhs * rhs;
-        return true;
-    }
-
-    static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
-
-};
-
-template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, false, false> {
-    // LHS and RHS are unsigned types so bounds checks are nice and easy
-    static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
-    {
-        ResultType temp = lhs + rhs;
-        if (temp < lhs)
-            return false;
-        result = temp;
-        return true;
-    }
-
-    static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
-    {
-        ResultType temp = lhs - rhs;
-        if (temp > lhs)
-            return false;
-        result = temp;
-        return true;
-    }
-
-    static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN
-    {
-        ResultType temp = lhs * rhs;
-        if (temp < lhs)
-            return false;
-        result = temp;
-        return true;
-    }
-
-    static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; }
-
-};
-
-template <typename ResultType> struct ArithmeticOperations<int, unsigned, ResultType, true, false> {
-    static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
-    {
-        int64_t temp = lhs + rhs;
-        if (temp < std::numeric_limits<ResultType>::min())
-            return false;
-        if (temp > std::numeric_limits<ResultType>::max())
-            return false;
-        result = static_cast<ResultType>(temp);
-        return true;
-    }
-    
-    static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result)
-    {
-        int64_t temp = lhs - rhs;
-        if (temp < std::numeric_limits<ResultType>::min())
-            return false;
-        if (temp > std::numeric_limits<ResultType>::max())
-            return false;
-        result = static_cast<ResultType>(temp);
-        return true;
-    }
-
-    static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result)
-    {
-        int64_t temp = lhs * rhs;
-        if (temp < std::numeric_limits<ResultType>::min())
-            return false;
-        if (temp > std::numeric_limits<ResultType>::max())
-            return false;
-        result = static_cast<ResultType>(temp);
-        return true;
-    }
-
-    static inline bool equals(int lhs, unsigned rhs)
-    {
-        return static_cast<int64_t>(lhs) == static_cast<int64_t>(rhs);
-    }
-};
-
-template <typename ResultType> struct ArithmeticOperations<unsigned, int, ResultType, false, true> {
-    static inline bool add(int64_t lhs, int64_t rhs, ResultType& result)
-    {
-        return ArithmeticOperations<int, unsigned, ResultType>::add(rhs, lhs, result);
-    }
-    
-    static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result)
-    {
-        return ArithmeticOperations<int, unsigned, ResultType>::sub(lhs, rhs, result);
-    }
-
-    static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result)
-    {
-        return ArithmeticOperations<int, unsigned, ResultType>::multiply(rhs, lhs, result);
-    }
-
-    static inline bool equals(unsigned lhs, int rhs)
-    {
-        return ArithmeticOperations<int, unsigned, ResultType>::equals(rhs, lhs);
-    }
-};
-
-template <typename U, typename V, typename R> static inline bool safeAdd(U lhs, V rhs, R& result)
-{
-    return ArithmeticOperations<U, V, R>::add(lhs, rhs, result);
-}
-
-template <typename U, typename V, typename R> static inline bool safeSub(U lhs, V rhs, R& result)
-{
-    return ArithmeticOperations<U, V, R>::sub(lhs, rhs, result);
-}
-
-template <typename U, typename V, typename R> static inline bool safeMultiply(U lhs, V rhs, R& result)
-{
-    return ArithmeticOperations<U, V, R>::multiply(lhs, rhs, result);
-}
-
-template <typename U, typename V> static inline bool safeEquals(U lhs, V rhs)
-{
-    return ArithmeticOperations<U, V>::equals(lhs, rhs);
-}
-
-enum ResultOverflowedTag { ResultOverflowed };
-    
-// FIXME: Needed to workaround http://llvm.org/bugs/show_bug.cgi?id=10801
-static inline bool workAroundClangBug() { return true; }
-
-template <typename T, class OverflowHandler> class Checked : public OverflowHandler {
-public:
-    template <typename _T, class _OverflowHandler> friend class Checked;
-    Checked()
-        : m_value(0)
-    {
-    }
-
-    Checked(ResultOverflowedTag)
-        : m_value(0)
-    {
-        // FIXME: Remove this when clang fixes http://llvm.org/bugs/show_bug.cgi?id=10801
-        if (workAroundClangBug())
-            this->overflowed();
-    }
-
-    template <typename U> Checked(U value)
-    {
-        if (!isInBounds<T>(value))
-            this->overflowed();
-        m_value = static_cast<T>(value);
-    }
-    
-    template <typename V> Checked(const Checked<T, V>& rhs)
-        : m_value(rhs.m_value)
-    {
-        if (rhs.hasOverflowed())
-            this->overflowed();
-    }
-    
-    template <typename U> Checked(const Checked<U, OverflowHandler>& rhs)
-        : OverflowHandler(rhs)
-    {
-        if (!isInBounds<T>(rhs.m_value))
-            this->overflowed();
-        m_value = static_cast<T>(rhs.m_value);
-    }
-    
-    template <typename U, typename V> Checked(const Checked<U, V>& rhs)
-    {
-        if (rhs.hasOverflowed())
-            this->overflowed();
-        if (!isInBounds<T>(rhs.m_value))
-            this->overflowed();
-        m_value = static_cast<T>(rhs.m_value);
-    }
-    
-    const Checked& operator=(Checked rhs)
-    {
-        this->clearOverflow();
-        if (rhs.hasOverflowed())
-            this->overflowed();
-        m_value = static_cast<T>(rhs.m_value);
-        return *this;
-    }
-    
-    template <typename U> const Checked& operator=(U value)
-    {
-        return *this = Checked(value);
-    }
-    
-    template <typename U, typename V> const Checked& operator=(const Checked<U, V>& rhs)
-    {
-        return *this = Checked(rhs);
-    }
-    
-    // prefix
-    const Checked& operator++()
-    {
-        if (m_value == std::numeric_limits<T>::max())
-            this->overflowed();
-        m_value++;
-        return *this;
-    }
-    
-    const Checked& operator--()
-    {
-        if (m_value == std::numeric_limits<T>::min())
-            this->overflowed();
-        m_value--;
-        return *this;
-    }
-    
-    // postfix operators
-    const Checked operator++(int)
-    {
-        if (m_value == std::numeric_limits<T>::max())
-            this->overflowed();
-        return Checked(m_value++);
-    }
-    
-    const Checked operator--(int)
-    {
-        if (m_value == std::numeric_limits<T>::min())
-            this->overflowed();
-        return Checked(m_value--);
-    }
-    
-    // Boolean operators
-    bool operator!() const
-    {
-        if (this->hasOverflowed())
-            CRASH();
-        return !m_value;
-    }
-
-    typedef void* (Checked::*UnspecifiedBoolType);
-    operator UnspecifiedBoolType*() const
-    {
-        if (this->hasOverflowed())
-            CRASH();
-        return (m_value) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0;
-    }
-
-    // Value accessors. unsafeGet() will crash if there's been an overflow.
-    T unsafeGet() const
-    {
-        if (this->hasOverflowed())
-            CRASH();
-        return m_value;
-    }
-    
-    bool safeGet(T& value) const WARN_UNUSED_RETURN
-    {
-        value = m_value;
-        return this->hasOverflowed();
-    }
-
-    // Mutating assignment
-    template <typename U> const Checked operator+=(U rhs)
-    {
-        if (!safeAdd(m_value, rhs, m_value))
-            this->overflowed();
-        return *this;
-    }
-
-    template <typename U> const Checked operator-=(U rhs)
-    {
-        if (!safeSub(m_value, rhs, m_value))
-            this->overflowed();
-        return *this;
-    }
-
-    template <typename U> const Checked operator*=(U rhs)
-    {
-        if (!safeMultiply(m_value, rhs, m_value))
-            this->overflowed();
-        return *this;
-    }
-    
-    template <typename U, typename V> const Checked operator+=(Checked<U, V> rhs)
-    {
-        if (rhs.hasOverflowed())
-            this->overflowed();
-        return *this += rhs.m_value;
-    }
-
-    template <typename U, typename V> const Checked operator-=(Checked<U, V> rhs)
-    {
-        if (rhs.hasOverflowed())
-            this->overflowed();
-        return *this -= rhs.m_value;
-    }
-
-    template <typename U, typename V> const Checked operator*=(Checked<U, V> rhs)
-    {
-        if (rhs.hasOverflowed())
-            this->overflowed();
-        return *this *= rhs.m_value;
-    }
-
-    // Equality comparisons
-    template <typename V> bool operator==(Checked<T, V> rhs)
-    {
-        return unsafeGet() == rhs.unsafeGet();
-    }
-
-    template <typename U> bool operator==(U rhs)
-    {
-        if (this->hasOverflowed())
-            this->overflowed();
-        return safeEquals(m_value, rhs);
-    }
-    
-    template <typename U, typename V> const Checked operator==(Checked<U, V> rhs)
-    {
-        return unsafeGet() == Checked(rhs.unsafeGet());
-    }
-
-    template <typename U> bool operator!=(U rhs)
-    {
-        return !(*this == rhs);
-    }
-
-private:
-    // Disallow implicit conversion of floating point to integer types
-    Checked(float);
-    Checked(double);
-    void operator=(float);
-    void operator=(double);
-    void operator+=(float);
-    void operator+=(double);
-    void operator-=(float);
-    void operator-=(double);
-    T m_value;
-};
-
-template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
-{
-    U x = 0;
-    V y = 0;
-    bool overflowed = lhs.safeGet(x) || rhs.safeGet(y);
-    typename Result<U, V>::ResultType result = 0;
-    overflowed |= !safeAdd(x, y, result);
-    if (overflowed)
-        return ResultOverflowed;
-    return result;
-}
-
-template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
-{
-    U x = 0;
-    V y = 0;
-    bool overflowed = lhs.safeGet(x) || rhs.safeGet(y);
-    typename Result<U, V>::ResultType result = 0;
-    overflowed |= !safeSub(x, y, result);
-    if (overflowed)
-        return ResultOverflowed;
-    return result;
-}
-
-template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs)
-{
-    U x = 0;
-    V y = 0;
-    bool overflowed = lhs.safeGet(x) || rhs.safeGet(y);
-    typename Result<U, V>::ResultType result = 0;
-    overflowed |= !safeMultiply(x, y, result);
-    if (overflowed)
-        return ResultOverflowed;
-    return result;
-}
-
-template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, V rhs)
-{
-    return lhs + Checked<V, OverflowHandler>(rhs);
-}
-
-template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, V rhs)
-{
-    return lhs - Checked<V, OverflowHandler>(rhs);
-}
-
-template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, V rhs)
-{
-    return lhs * Checked<V, OverflowHandler>(rhs);
-}
-
-template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(U lhs, Checked<V, OverflowHandler> rhs)
-{
-    return Checked<U, OverflowHandler>(lhs) + rhs;
-}
-
-template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(U lhs, Checked<V, OverflowHandler> rhs)
-{
-    return Checked<U, OverflowHandler>(lhs) - rhs;
-}
-
-template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(U lhs, Checked<V, OverflowHandler> rhs)
-{
-    return Checked<U, OverflowHandler>(lhs) * rhs;
-}
-
-}
-
-using WTF::Checked;
-using WTF::RecordOverflow;
-
-#endif
diff --git a/wtf/Complex.h b/wtf/Complex.h
deleted file mode 100644 (file)
index 40fe56a..0000000
+++ /dev/null
@@ -1,49 +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 WTF_Complex_h
-#define WTF_Complex_h
-
-#include <complex>
-#include <wtf/MathExtras.h>
-
-namespace WTF {
-
-typedef std::complex<double> Complex;
-
-inline Complex complexFromMagnitudePhase(double magnitude, double phase)
-{
-    return Complex(magnitude * cos(phase), magnitude * sin(phase));
-}
-
-} // namespace WTF
-
-using WTF::Complex;
-using WTF::complexFromMagnitudePhase;
-
-#endif // WTF_Complex_h
diff --git a/wtf/CrossThreadRefCounted.h b/wtf/CrossThreadRefCounted.h
deleted file mode 100644 (file)
index 3931755..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 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
- * 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 CrossThreadRefCounted_h
-#define CrossThreadRefCounted_h
-
-#include "PassRefPtr.h"
-#include "RefCounted.h"
-#include "Threading.h"
-
-#include <wtf/iphone/WebCoreThread.h>
-
-namespace WTF {
-
-    // Used to allowing sharing data across classes and threads (like ThreadSafeRefCounted).
-    //
-    // 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.
-    //
-    // Is this class threadsafe?
-    // While each instance of the class is not threadsafe, the copied instance is threadsafe
-    // 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 {
-        WTF_MAKE_NONCOPYABLE(CrossThreadRefCounted);
-    public:
-        static PassRefPtr<CrossThreadRefCounted<T> > create(T* data)
-        {
-            return adoptRef(new CrossThreadRefCounted<T>(data, 0));
-        }
-
-        // Used to make an instance that can be used on another thread.
-        PassRefPtr<CrossThreadRefCounted<T> > crossThreadCopy();
-
-        void ref();
-        void deref();
-        T* release();
-
-        bool isShared() const
-        {
-            return !m_refCounter.hasOneRef() || (m_threadSafeRefCounter && !m_threadSafeRefCounter->hasOneRef());
-        }
-
-    private:
-        CrossThreadRefCounted(T* data, ThreadSafeRefCountedBase* threadedCounter)
-            : m_threadSafeRefCounter(threadedCounter)
-            , m_data(data)
-#ifndef NDEBUG
-            , m_threadId(0)
-#endif
-        {
-            // We use RefCountedBase in an unusual way here, so get rid of the requirement
-            // that adoptRef be called on it.
-            m_refCounter.relaxAdoptionRequirement();
-        }
-
-        ~CrossThreadRefCounted()
-        {
-            if (!m_threadSafeRefCounter)
-                delete m_data;
-        }
-
-        void threadSafeDeref();
-
-#ifndef NDEBUG
-        bool isOwnedByCurrentThread() const {
-            return !m_threadId || m_threadId == currentThread() || ((isMainThread() || pthread_main_np()) && WebCoreWebThreadIsLockedOrDisabled());
-        }
-#endif
-
-        RefCountedBase m_refCounter;
-        ThreadSafeRefCountedBase* m_threadSafeRefCounter;
-        T* m_data;
-#ifndef NDEBUG
-        ThreadIdentifier m_threadId;
-#endif
-    };
-
-    template<class T>
-    void CrossThreadRefCounted<T>::ref()
-    {
-        ASSERT(isOwnedByCurrentThread());
-
-        m_refCounter.ref();
-#ifndef NDEBUG
-        // Store the threadId as soon as the ref count gets to 2.
-        // The class gets created with a ref count of 1 and then passed
-        // to another thread where to ref count get increased.  This
-        // is a heuristic but it seems to always work and has helped
-        // find some bugs.
-        if (!m_threadId && m_refCounter.refCount() == 2)
-            m_threadId = currentThread();
-#endif
-    }
-
-    template<class T>
-    void CrossThreadRefCounted<T>::deref()
-    {
-        ASSERT(isOwnedByCurrentThread());
-
-        if (m_refCounter.derefBase()) {
-            threadSafeDeref();
-            delete this;
-        } else {
-#ifndef NDEBUG
-            // Clear the threadId when the ref goes to 1 because it
-            // is safe to be passed to another thread at this point.
-            if (m_threadId && m_refCounter.refCount() == 1)
-                m_threadId = 0;
-#endif
-        }
-    }
-
-    template<class T>
-    T* CrossThreadRefCounted<T>::release()
-    {
-        ASSERT(!isShared());
-
-        T* data = m_data;
-        m_data = 0;
-        return data;
-    }
-
-    template<class T>
-    PassRefPtr<CrossThreadRefCounted<T> > CrossThreadRefCounted<T>::crossThreadCopy()
-    {
-        ASSERT(isOwnedByCurrentThread());
-
-        if (m_threadSafeRefCounter)
-            m_threadSafeRefCounter->ref();
-        else
-            m_threadSafeRefCounter = new ThreadSafeRefCountedBase(2);
-
-        return adoptRef(new CrossThreadRefCounted<T>(m_data, m_threadSafeRefCounter));
-    }
-
-
-    template<class T>
-    void CrossThreadRefCounted<T>::threadSafeDeref()
-    {
-        if (m_threadSafeRefCounter && m_threadSafeRefCounter->derefBase()) {
-            delete m_threadSafeRefCounter;
-            m_threadSafeRefCounter = 0;
-        }
-    }
-} // namespace WTF
-
-using WTF::CrossThreadRefCounted;
-
-#endif // CrossThreadRefCounted_h
diff --git a/wtf/CryptographicallyRandomNumber.cpp b/wtf/CryptographicallyRandomNumber.cpp
deleted file mode 100644 (file)
index ef097ab..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 348242e..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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
diff --git a/wtf/CurrentTime.cpp b/wtf/CurrentTime.cpp
deleted file mode 100644 (file)
index 4205227..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright (C) 2006, 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Google Inc. All rights reserved.
- * Copyright (C) 2007-2009 Torch Mobile, Inc.
- *
- * 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 "CurrentTime.h"
-
-#if OS(WINDOWS)
-
-// 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
-#include <windows.h>
-#include <math.h>
-#include <stdint.h>
-#include <time.h>
-
-#if USE(QUERY_PERFORMANCE_COUNTER)
-#if OS(WINCE)
-extern "C" time_t mktime(struct tm *t);
-#else
-#include <sys/timeb.h>
-#include <sys/types.h>
-#endif
-#endif
-
-#elif PLATFORM(GTK)
-#include <glib.h>
-#elif PLATFORM(WX)
-#include <wx/datetime.h>
-#elif PLATFORM(BREWMP)
-#include <AEEStdLib.h>
-#else
-#include <sys/time.h>
-#endif
-
-#if PLATFORM(CHROMIUM)
-#error Chromium uses a different timer implementation
-#endif
-
-namespace WTF {
-
-const double msPerSecond = 1000.0;
-
-#if OS(WINDOWS)
-
-#if USE(QUERY_PERFORMANCE_COUNTER)
-
-static LARGE_INTEGER qpcFrequency;
-static bool syncedTime;
-
-static double highResUpTime()
-{
-    // We use QPC, but only after sanity checking its result, due to bugs:
-    // http://support.microsoft.com/kb/274323
-    // http://support.microsoft.com/kb/895980
-    // http://msdn.microsoft.com/en-us/library/ms644904.aspx ("...you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL)."
-
-    static LARGE_INTEGER qpcLast;
-    static DWORD tickCountLast;
-    static bool inited;
-
-    LARGE_INTEGER qpc;
-    QueryPerformanceCounter(&qpc);
-    DWORD tickCount = GetTickCount();
-
-    if (inited) {
-        __int64 qpcElapsed = ((qpc.QuadPart - qpcLast.QuadPart) * 1000) / qpcFrequency.QuadPart;
-        __int64 tickCountElapsed;
-        if (tickCount >= tickCountLast)
-            tickCountElapsed = (tickCount - tickCountLast);
-        else {
-#if COMPILER(MINGW)
-            __int64 tickCountLarge = tickCount + 0x100000000ULL;
-#else
-            __int64 tickCountLarge = tickCount + 0x100000000I64;
-#endif
-            tickCountElapsed = tickCountLarge - tickCountLast;
-        }
-
-        // force a re-sync if QueryPerformanceCounter differs from GetTickCount by more than 500ms.
-        // (500ms value is from http://support.microsoft.com/kb/274323)
-        __int64 diff = tickCountElapsed - qpcElapsed;
-        if (diff > 500 || diff < -500)
-            syncedTime = false;
-    } else
-        inited = true;
-
-    qpcLast = qpc;
-    tickCountLast = tickCount;
-
-    return (1000.0 * qpc.QuadPart) / static_cast<double>(qpcFrequency.QuadPart);
-}
-
-static double lowResUTCTime()
-{
-#if OS(WINCE)
-    SYSTEMTIME systemTime;
-    GetSystemTime(&systemTime);
-    struct tm tmtime;
-    tmtime.tm_year = systemTime.wYear - 1900;
-    tmtime.tm_mon = systemTime.wMonth - 1;
-    tmtime.tm_mday = systemTime.wDay;
-    tmtime.tm_wday = systemTime.wDayOfWeek;
-    tmtime.tm_hour = systemTime.wHour;
-    tmtime.tm_min = systemTime.wMinute;
-    tmtime.tm_sec = systemTime.wSecond;
-    time_t timet = mktime(&tmtime);
-    return timet * msPerSecond + systemTime.wMilliseconds;
-#else
-    struct _timeb timebuffer;
-    _ftime(&timebuffer);
-    return timebuffer.time * msPerSecond + timebuffer.millitm;
-#endif
-}
-
-static bool qpcAvailable()
-{
-    static bool available;
-    static bool checked;
-
-    if (checked)
-        return available;
-
-    available = QueryPerformanceFrequency(&qpcFrequency);
-    checked = true;
-    return available;
-}
-
-double currentTime()
-{
-    // Use a combination of ftime and QueryPerformanceCounter.
-    // ftime returns the information we want, but doesn't have sufficient resolution.
-    // 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 double syncLowResUTCTime;
-    static double syncHighResUpTime;
-    static double lastUTCTime;
-
-    double lowResTime = lowResUTCTime();
-
-    if (!qpcAvailable())
-        return lowResTime / 1000.0;
-
-    double highResTime = highResUpTime();
-
-    if (!syncedTime) {
-        timeBeginPeriod(1); // increase time resolution around low-res time getter
-        syncLowResUTCTime = lowResTime = lowResUTCTime();
-        timeEndPeriod(1); // restore time resolution
-        syncHighResUpTime = highResTime;
-        syncedTime = true;
-    }
-
-    double highResElapsed = highResTime - syncHighResUpTime;
-    double utc = syncLowResUTCTime + highResElapsed;
-
-    // force a clock re-sync if we've drifted
-    double lowResElapsed = lowResTime - syncLowResUTCTime;
-    const double maximumAllowedDriftMsec = 15.625 * 2.0; // 2x the typical low-res accuracy
-    if (fabs(highResElapsed - lowResElapsed) > maximumAllowedDriftMsec)
-        syncedTime = false;
-
-    // make sure time doesn't run backwards (only correct if difference is < 2 seconds, since DST or clock changes could occur)
-    const double backwardTimeLimit = 2000.0;
-    if (utc < lastUTCTime && (lastUTCTime - utc) < backwardTimeLimit)
-        return lastUTCTime / 1000.0;
-    lastUTCTime = utc;
-    return utc / 1000.0;
-}
-
-#else
-
-static double currentSystemTime()
-{
-    FILETIME ft;
-    GetCurrentFT(&ft);
-
-    // As per Windows documentation for FILETIME, copy the resulting FILETIME structure to a
-    // ULARGE_INTEGER structure using memcpy (using memcpy instead of direct assignment can
-    // prevent alignment faults on 64-bit Windows).
-
-    ULARGE_INTEGER t;
-    memcpy(&t, &ft, sizeof(t));
-
-    // Windows file times are in 100s of nanoseconds.
-    // To convert to seconds, we have to divide by 10,000,000, which is more quickly
-    // done by multiplying by 0.0000001.
-
-    // Between January 1, 1601 and January 1, 1970, there were 369 complete years,
-    // of which 89 were leap years (1700, 1800, and 1900 were not leap years).
-    // That is a total of 134774 days, which is 11644473600 seconds.
-
-    return t.QuadPart * 0.0000001 - 11644473600.0;
-}
-
-double currentTime()
-{
-    static bool init = false;
-    static double lastTime;
-    static DWORD lastTickCount;
-    if (!init) {
-        lastTime = currentSystemTime();
-        lastTickCount = GetTickCount();
-        init = true;
-        return lastTime;
-    }
-
-    DWORD tickCountNow = GetTickCount();
-    DWORD elapsed = tickCountNow - lastTickCount;
-    double timeNow = lastTime + (double)elapsed / 1000.;
-    if (elapsed >= 0x7FFFFFFF) {
-        lastTime = timeNow;
-        lastTickCount = tickCountNow;
-    }
-    return timeNow;
-}
-
-#endif // USE(QUERY_PERFORMANCE_COUNTER)
-
-#elif PLATFORM(GTK)
-
-// Note: GTK on Windows will pick up the PLATFORM(WIN) implementation above which provides
-// better accuracy compared with Windows implementation of g_get_current_time:
-// (http://www.google.com/codesearch/p?hl=en#HHnNRjks1t0/glib-2.5.2/glib/gmain.c&q=g_get_current_time).
-// Non-Windows GTK builds could use gettimeofday() directly but for the sake of consistency lets use GTK function.
-double currentTime()
-{
-    GTimeVal now;
-    g_get_current_time(&now);
-    return static_cast<double>(now.tv_sec) + static_cast<double>(now.tv_usec / 1000000.0);
-}
-
-#elif PLATFORM(WX)
-
-double currentTime()
-{
-    wxDateTime now = wxDateTime::UNow();
-    return (double)now.GetTicks() + (double)(now.GetMillisecond() / 1000.0);
-}
-
-#elif PLATFORM(BREWMP)
-
-// GETUTCSECONDS returns the number of seconds since 1980/01/06 00:00:00 UTC,
-// and GETTIMEMS returns the number of milliseconds that have elapsed since the last
-// occurrence of 00:00:00 local time.
-// We can combine GETUTCSECONDS and GETTIMEMS to calculate the number of milliseconds
-// since 1970/01/01 00:00:00 UTC.
-double currentTime()
-{
-    // diffSeconds is the number of seconds from 1970/01/01 to 1980/01/06
-    const unsigned diffSeconds = 315964800;
-    return static_cast<double>(diffSeconds + GETUTCSECONDS() + ((GETTIMEMS() % 1000) / msPerSecond));
-}
-
-#else
-
-double currentTime()
-{
-    struct timeval now;
-    gettimeofday(&now, 0);
-    return now.tv_sec + now.tv_usec / 1000000.0;
-}
-
-#endif
-
-} // namespace WTF
diff --git a/wtf/CurrentTime.h b/wtf/CurrentTime.h
deleted file mode 100644 (file)
index 5fcb63a..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
- * Copyright (C) 2008 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 CurrentTime_h
-#define CurrentTime_h
-
-#include <time.h>
-
-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();
-
-// 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
-}
-
-} // namespace WTF
-
-using WTF::currentTime;
-using WTF::currentTimeMS;
-using WTF::getLocalTime;
-
-#endif // CurrentTime_h
-
diff --git a/wtf/DateMath.cpp b/wtf/DateMath.cpp
deleted file mode 100644 (file)
index 70c0cf4..0000000
+++ /dev/null
@@ -1,1170 +0,0 @@
-/*
- * 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) 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 Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. 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.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.
-
- * Copyright 2006-2008 the V8 project authors. 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 "DateMath.h"
-
-#include "Assertions.h"
-#include "ASCIICType.h"
-#include "CurrentTime.h"
-#if USE(JSC)
-#include "JSObject.h"
-#endif
-#include "MathExtras.h"
-#if USE(JSC)
-#include "ScopeChain.h"
-#endif
-#include "StdLibExtras.h"
-#include "StringExtras.h"
-
-#include <algorithm>
-#include <limits.h>
-#include <limits>
-#include <stdint.h>
-#include <time.h>
-
-
-#if HAVE(ERRNO_H)
-#include <errno.h>
-#endif
-
-#if OS(WINCE)
-extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t);
-extern "C" struct tm * localtime(const time_t *timer);
-#endif
-
-#if HAVE(SYS_TIME_H)
-#include <sys/time.h>
-#endif
-
-#if HAVE(SYS_TIMEB_H)
-#include <sys/timeb.h>
-#endif
-
-#if USE(JSC)
-#include "CallFrame.h"
-#endif
-
-#define NaN std::numeric_limits<double>::quiet_NaN()
-
-using namespace WTF;
-
-namespace WTF {
-
-/* Constants */
-
-static const double minutesPerDay = 24.0 * 60.0;
-static const double secondsPerDay = 24.0 * 60.0 * 60.0;
-static const double secondsPerYear = 24.0 * 60.0 * 60.0 * 365.0;
-
-static const double usecPerSec = 1000000.0;
-
-static const double maxUnixTime = 2145859200.0; // 12/31/2037
-// ECMAScript asks not to support for a date of which total
-// millisecond value is larger than the following value.
-// See 15.9.1.14 of ECMA-262 5th edition.
-static const double maxECMAScriptTime = 8.64E15;
-
-// Day of year for the first day of each month, where index 0 is January, and day 0 is January 1.
-// First for non-leap years, then for leap years.
-static const int firstDayOfMonth[2][12] = {
-    {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
-    {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
-};
-
-static inline bool isLeapYear(int year)
-{
-    if (year % 4 != 0)
-        return false;
-    if (year % 400 == 0)
-        return true;
-    if (year % 100 == 0)
-        return false;
-    return true;
-}
-
-static inline int daysInYear(int year)
-{
-    return 365 + isLeapYear(year);
-}
-
-static inline double daysFrom1970ToYear(int year)
-{
-    // The Gregorian Calendar rules for leap years:
-    // Every fourth year is a leap year.  2004, 2008, and 2012 are leap years.
-    // However, every hundredth year is not a leap year.  1900 and 2100 are not leap years.
-    // Every four hundred years, there's a leap year after all.  2000 and 2400 are leap years.
-
-    static const int leapDaysBefore1971By4Rule = 1970 / 4;
-    static const int excludedLeapDaysBefore1971By100Rule = 1970 / 100;
-    static const int leapDaysBefore1971By400Rule = 1970 / 400;
-
-    const double yearMinusOne = year - 1;
-    const double yearsToAddBy4Rule = floor(yearMinusOne / 4.0) - leapDaysBefore1971By4Rule;
-    const double yearsToExcludeBy100Rule = floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule;
-    const double yearsToAddBy400Rule = floor(yearMinusOne / 400.0) - leapDaysBefore1971By400Rule;
-
-    return 365.0 * (year - 1970) + yearsToAddBy4Rule - yearsToExcludeBy100Rule + yearsToAddBy400Rule;
-}
-
-static inline double msToDays(double ms)
-{
-    return floor(ms / msPerDay);
-}
-
-int msToYear(double ms)
-{
-    int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970);
-    double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear);
-    if (msFromApproxYearTo1970 > ms)
-        return approxYear - 1;
-    if (msFromApproxYearTo1970 + msPerDay * daysInYear(approxYear) <= ms)
-        return approxYear + 1;
-    return approxYear;
-}
-
-int dayInYear(double ms, int year)
-{
-    return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year));
-}
-
-static inline double msToMilliseconds(double ms)
-{
-    double result = fmod(ms, msPerDay);
-    if (result < 0)
-        result += msPerDay;
-    return result;
-}
-
-// 0: Sunday, 1: Monday, etc.
-static inline int msToWeekDay(double ms)
-{
-    int wd = (static_cast<int>(msToDays(ms)) + 4) % 7;
-    if (wd < 0)
-        wd += 7;
-    return wd;
-}
-
-static inline int msToSeconds(double ms)
-{
-    double result = fmod(floor(ms / msPerSecond), secondsPerMinute);
-    if (result < 0)
-        result += secondsPerMinute;
-    return static_cast<int>(result);
-}
-
-static inline int msToMinutes(double ms)
-{
-    double result = fmod(floor(ms / msPerMinute), minutesPerHour);
-    if (result < 0)
-        result += minutesPerHour;
-    return static_cast<int>(result);
-}
-
-static inline int msToHours(double ms)
-{
-    double result = fmod(floor(ms/msPerHour), hoursPerDay);
-    if (result < 0)
-        result += hoursPerDay;
-    return static_cast<int>(result);
-}
-
-int monthFromDayInYear(int dayInYear, bool leapYear)
-{
-    const int d = dayInYear;
-    int step;
-
-    if (d < (step = 31))
-        return 0;
-    step += (leapYear ? 29 : 28);
-    if (d < step)
-        return 1;
-    if (d < (step += 31))
-        return 2;
-    if (d < (step += 30))
-        return 3;
-    if (d < (step += 31))
-        return 4;
-    if (d < (step += 30))
-        return 5;
-    if (d < (step += 31))
-        return 6;
-    if (d < (step += 31))
-        return 7;
-    if (d < (step += 30))
-        return 8;
-    if (d < (step += 31))
-        return 9;
-    if (d < (step += 30))
-        return 10;
-    return 11;
-}
-
-static inline bool checkMonth(int dayInYear, int& startDayOfThisMonth, int& startDayOfNextMonth, int daysInThisMonth)
-{
-    startDayOfThisMonth = startDayOfNextMonth;
-    startDayOfNextMonth += daysInThisMonth;
-    return (dayInYear <= startDayOfNextMonth);
-}
-
-int dayInMonthFromDayInYear(int dayInYear, bool leapYear)
-{
-    const int d = dayInYear;
-    int step;
-    int next = 30;
-
-    if (d <= next)
-        return d + 1;
-    const int daysInFeb = (leapYear ? 29 : 28);
-    if (checkMonth(d, step, next, daysInFeb))
-        return d - step;
-    if (checkMonth(d, step, next, 31))
-        return d - step;
-    if (checkMonth(d, step, next, 30))
-        return d - step;
-    if (checkMonth(d, step, next, 31))
-        return d - step;
-    if (checkMonth(d, step, next, 30))
-        return d - step;
-    if (checkMonth(d, step, next, 31))
-        return d - step;
-    if (checkMonth(d, step, next, 31))
-        return d - step;
-    if (checkMonth(d, step, next, 30))
-        return d - step;
-    if (checkMonth(d, step, next, 31))
-        return d - step;
-    if (checkMonth(d, step, next, 30))
-        return d - step;
-    step = next;
-    return d - step;
-}
-
-static inline int monthToDayInYear(int month, bool isLeapYear)
-{
-    return firstDayOfMonth[isLeapYear][month];
-}
-
-static inline double timeToMS(double hour, double min, double sec, double ms)
-{
-    return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms);
-}
-
-double dateToDaysFrom1970(int year, int month, int day)
-{
-    year += month / 12;
-
-    month %= 12;
-    if (month < 0) {
-        month += 12;
-        --year;
-    }
-
-    double yearday = floor(daysFrom1970ToYear(year));
-    ASSERT((year >= 1970 && yearday >= 0) || (year < 1970 && yearday < 0));
-    int monthday = monthToDayInYear(month, isLeapYear(year));
-
-    return yearday + monthday + day - 1;
-}
-
-// There is a hard limit at 2038 that we currently do not have a workaround
-// for (rdar://problem/5052975).
-static inline int maximumYearForDST()
-{
-    return 2037;
-}
-
-static inline int minimumYearForDST()
-{
-    // Because of the 2038 issue (see maximumYearForDST) if the current year is
-    // greater than the max year minus 27 (2010), we want to use the max year
-    // minus 27 instead, to ensure there is a range of 28 years that all years
-    // can map to.
-    return std::min(msToYear(jsCurrentTime()), maximumYearForDST() - 27) ;
-}
-
-/*
- * Find an equivalent year for the one given, where equivalence is deterined by
- * the two years having the same leapness and the first day of the year, falling
- * on the same day of the week.
- *
- * This function returns a year between this current year and 2037, however this
- * function will potentially return incorrect results if the current year is after
- * 2010, (rdar://problem/5052975), if the year passed in is before 1900 or after
- * 2100, (rdar://problem/5055038).
- */
-int equivalentYearForDST(int year)
-{
-    // It is ok if the cached year is not the current year as long as the rules
-    // for DST did not change between the two years; if they did the app would need
-    // to be restarted.
-    static int minYear = minimumYearForDST();
-    int maxYear = maximumYearForDST();
-
-    int difference;
-    if (year > maxYear)
-        difference = minYear - year;
-    else if (year < minYear)
-        difference = maxYear - year;
-    else
-        return year;
-
-    int quotient = difference / 28;
-    int product = (quotient) * 28;
-
-    year += product;
-    ASSERT((year >= minYear && year <= maxYear) || (product - year == static_cast<int>(NaN)));
-    return year;
-}
-
-int32_t calculateUTCOffset()
-{
-#if PLATFORM(BREWMP)
-    time_t localTime = static_cast<time_t>(currentTime());
-#else
-    time_t localTime = time(0);
-#endif
-    tm localt;
-    getLocalTime(&localTime, &localt);
-
-    // Get the difference between this time zone and UTC on the 1st of January of this year.
-    localt.tm_sec = 0;
-    localt.tm_min = 0;
-    localt.tm_hour = 0;
-    localt.tm_mday = 1;
-    localt.tm_mon = 0;
-    // Not setting localt.tm_year!
-    localt.tm_wday = 0;
-    localt.tm_yday = 0;
-    localt.tm_isdst = 0;
-#if HAVE(TM_GMTOFF)
-    localt.tm_gmtoff = 0;
-#endif
-#if HAVE(TM_ZONE)
-    localt.tm_zone = 0;
-#endif
-    
-#if HAVE(TIMEGM)
-    time_t utcOffset = timegm(&localt) - mktime(&localt);
-#else
-    // Using a canned date of 01/01/2009 on platforms with weaker date-handling foo.
-    localt.tm_year = 109;
-    time_t utcOffset = 1230768000 - mktime(&localt);
-#endif
-
-    return static_cast<int32_t>(utcOffset * 1000);
-}
-
-/*
- * Get the DST offset for the time passed in.
- */
-static double calculateDSTOffsetSimple(double localTimeSeconds, double utcOffset)
-{
-    if (localTimeSeconds > maxUnixTime)
-        localTimeSeconds = maxUnixTime;
-    else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0)
-        localTimeSeconds += secondsPerDay;
-
-    //input is UTC so we have to shift back to local time to determine DST thus the + getUTCOffset()
-    double offsetTime = (localTimeSeconds * msPerSecond) + utcOffset;
-
-    // Offset from UTC but doesn't include DST obviously
-    int offsetHour =  msToHours(offsetTime);
-    int offsetMinute =  msToMinutes(offsetTime);
-
-    // FIXME: time_t has a potential problem in 2038
-    time_t localTime = static_cast<time_t>(localTimeSeconds);
-
-    tm localTM;
-    getLocalTime(&localTime, &localTM);
-
-    double diff = ((localTM.tm_hour - offsetHour) * secondsPerHour) + ((localTM.tm_min - offsetMinute) * 60);
-
-    if (diff < 0)
-        diff += secondsPerDay;
-
-    return (diff * msPerSecond);
-}
-
-// Get the DST offset, given a time in UTC
-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
-    // standard explicitly dictates that historical information should not be considered when
-    // determining DST. For this reason we shift away from years that localtime can handle but would
-    // return historically accurate information.
-    int year = msToYear(ms);
-    int equivalentYear = equivalentYearForDST(year);
-    if (year != equivalentYear) {
-        bool leapYear = isLeapYear(year);
-        int dayInYearLocal = dayInYear(ms, year);
-        int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear);
-        int month = monthFromDayInYear(dayInYearLocal, leapYear);
-        double day = dateToDaysFrom1970(equivalentYear, month, dayInMonth);
-        ms = (day * msPerDay) + msToMilliseconds(ms);
-    }
-
-    return calculateDSTOffsetSimple(ms / msPerSecond, utcOffset);
-}
-
-void initializeDates()
-{
-#ifndef NDEBUG
-    static bool alreadyInitialized;
-    ASSERT(!alreadyInitialized);
-    alreadyInitialized = true;
-#endif
-
-    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, double second)
-{
-    double days = (day - 32075)
-        + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4)
-        + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
-        - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4)
-        - 2440588;
-    return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second;
-}
-
-// We follow the recommendation of RFC 2822 to consider all
-// obsolete time zones not listed here equivalent to "-0000".
-static const struct KnownZone {
-#if !OS(WINDOWS)
-    const
-#endif
-        char tzName[4];
-    int tzOffset;
-} known_zones[] = {
-    { "UT", 0 },
-    { "GMT", 0 },
-    { "EST", -300 },
-    { "EDT", -240 },
-    { "CST", -360 },
-    { "CDT", -300 },
-    { "MST", -420 },
-    { "MDT", -360 },
-    { "PST", -480 },
-    { "PDT", -420 }
-};
-
-inline static void skipSpacesAndComments(const char*& s)
-{
-    int nesting = 0;
-    char ch;
-    while ((ch = *s)) {
-        if (!isASCIISpace(ch)) {
-            if (ch == '(')
-                nesting++;
-            else if (ch == ')' && nesting > 0)
-                nesting--;
-            else if (nesting == 0)
-                break;
-        }
-        s++;
-    }
-}
-
-// returns 0-11 (Jan-Dec); -1 on failure
-static int findMonth(const char* monthStr)
-{
-    ASSERT(monthStr);
-    char needle[4];
-    for (int i = 0; i < 3; ++i) {
-        if (!*monthStr)
-            return -1;
-        needle[i] = static_cast<char>(toASCIILower(*monthStr++));
-    }
-    needle[3] = '\0';
-    const char *haystack = "janfebmaraprmayjunjulaugsepoctnovdec";
-    const char *str = strstr(haystack, needle);
-    if (str) {
-        int position = static_cast<int>(str - haystack);
-        if (position % 3 == 0)
-            return position / 3;
-    }
-    return -1;
-}
-
-static bool parseLong(const char* string, char** stopPosition, int base, long* result)
-{
-    *result = strtol(string, stopPosition, base);
-    // Avoid the use of errno as it is not available on Windows CE
-    if (string == *stopPosition || *result == LONG_MIN || *result == LONG_MAX)
-        return false;
-    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)
-{
-    haveTZ = false;
-    offset = 0;
-
-    // This parses a date in the form:
-    //     Tuesday, 09-Nov-99 23:12:40 GMT
-    // or
-    //     Sat, 01-Jan-2000 08:00:00 GMT
-    // or
-    //     Sat, 01 Jan 2000 08:00:00 GMT
-    // or
-    //     01 Jan 99 22:00 +0100    (exceptions in rfc822/rfc2822)
-    // ### non RFC formats, added for Javascript:
-    //     [Wednesday] January 09 1999 23:12:40 GMT
-    //     [Wednesday] January 09 23:12:40 GMT 1999
-    //
-    // We ignore the weekday.
-     
-    // Skip leading space
-    skipSpacesAndComments(dateString);
-
-    long month = -1;
-    const char *wordStart = dateString;
-    // Check contents of first words if not number
-    while (*dateString && !isASCIIDigit(*dateString)) {
-        if (isASCIISpace(*dateString) || *dateString == '(') {
-            if (dateString - wordStart >= 3)
-                month = findMonth(wordStart);
-            skipSpacesAndComments(dateString);
-            wordStart = dateString;
-        } else
-           dateString++;
-    }
-
-    // Missing delimiter between month and day (like "January29")?
-    if (month == -1 && wordStart != dateString)
-        month = findMonth(wordStart);
-
-    skipSpacesAndComments(dateString);
-
-    if (!*dateString)
-        return NaN;
-
-    // ' 09-Nov-99 23:12:40 GMT'
-    char* newPosStr;
-    long day;
-    if (!parseLong(dateString, &newPosStr, 10, &day))
-        return NaN;
-    dateString = newPosStr;
-
-    if (!*dateString)
-        return NaN;
-
-    if (day < 0)
-        return NaN;
-
-    long year = 0;
-    if (day > 31) {
-        // ### where is the boundary and what happens below?
-        if (*dateString != '/')
-            return NaN;
-        // looks like a YYYY/MM/DD date
-        if (!*++dateString)
-            return NaN;
-        year = day;
-        if (!parseLong(dateString, &newPosStr, 10, &month))
-            return NaN;
-        month -= 1;
-        dateString = newPosStr;
-        if (*dateString++ != '/' || !*dateString)
-            return NaN;
-        if (!parseLong(dateString, &newPosStr, 10, &day))
-            return NaN;
-        dateString = newPosStr;
-    } else if (*dateString == '/' && month == -1) {
-        dateString++;
-        // This looks like a MM/DD/YYYY date, not an RFC date.
-        month = day - 1; // 0-based
-        if (!parseLong(dateString, &newPosStr, 10, &day))
-            return NaN;
-        if (day < 1 || day > 31)
-            return NaN;
-        dateString = newPosStr;
-        if (*dateString == '/')
-            dateString++;
-        if (!*dateString)
-            return NaN;
-     } else {
-        if (*dateString == '-')
-            dateString++;
-
-        skipSpacesAndComments(dateString);
-
-        if (*dateString == ',')
-            dateString++;
-
-        if (month == -1) { // not found yet
-            month = findMonth(dateString);
-            if (month == -1)
-                return NaN;
-
-            while (*dateString && *dateString != '-' && *dateString != ',' && !isASCIISpace(*dateString))
-                dateString++;
-
-            if (!*dateString)
-                return NaN;
-
-            // '-99 23:12:40 GMT'
-            if (*dateString != '-' && *dateString != '/' && *dateString != ',' && !isASCIISpace(*dateString))
-                return NaN;
-            dateString++;
-        }
-    }
-
-    if (month < 0 || month > 11)
-        return NaN;
-
-    // '99 23:12:40 GMT'
-    if (year <= 0 && *dateString) {
-        if (!parseLong(dateString, &newPosStr, 10, &year))
-            return NaN;
-    }
-
-    // Don't fail if the time is missing.
-    long hour = 0;
-    long minute = 0;
-    long second = 0;
-    if (!*newPosStr)
-        dateString = newPosStr;
-    else {
-        // ' 23:12:40 GMT'
-        if (!(isASCIISpace(*newPosStr) || *newPosStr == ',')) {
-            if (*newPosStr != ':')
-                return NaN;
-            // There was no year; the number was the hour.
-            year = -1;
-        } else {
-            // in the normal case (we parsed the year), advance to the next number
-            dateString = ++newPosStr;
-            skipSpacesAndComments(dateString);
-        }
-
-        parseLong(dateString, &newPosStr, 10, &hour);
-        // Do not check for errno here since we want to continue
-        // even if errno was set becasue we are still looking
-        // for the timezone!
-
-        // Read a number? If not, this might be a timezone name.
-        if (newPosStr != dateString) {
-            dateString = newPosStr;
-
-            if (hour < 0 || hour > 23)
-                return NaN;
-
-            if (!*dateString)
-                return NaN;
-
-            // ':12:40 GMT'
-            if (*dateString++ != ':')
-                return NaN;
-
-            if (!parseLong(dateString, &newPosStr, 10, &minute))
-                return NaN;
-            dateString = newPosStr;
-
-            if (minute < 0 || minute > 59)
-                return NaN;
-
-            // ':40 GMT'
-            if (*dateString && *dateString != ':' && !isASCIISpace(*dateString))
-                return NaN;
-
-            // seconds are optional in rfc822 + rfc2822
-            if (*dateString ==':') {
-                dateString++;
-
-                if (!parseLong(dateString, &newPosStr, 10, &second))
-                    return NaN;
-                dateString = newPosStr;
-
-                if (second < 0 || second > 59)
-                    return NaN;
-            }
-
-            skipSpacesAndComments(dateString);
-
-            if (strncasecmp(dateString, "AM", 2) == 0) {
-                if (hour > 12)
-                    return NaN;
-                if (hour == 12)
-                    hour = 0;
-                dateString += 2;
-                skipSpacesAndComments(dateString);
-            } else if (strncasecmp(dateString, "PM", 2) == 0) {
-                if (hour > 12)
-                    return NaN;
-                if (hour != 12)
-                    hour += 12;
-                dateString += 2;
-                skipSpacesAndComments(dateString);
-            }
-        }
-    }
-    
-    // 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).
-    if (*dateString) {
-        if (strncasecmp(dateString, "GMT", 3) == 0 || strncasecmp(dateString, "UTC", 3) == 0) {
-            dateString += 3;
-            haveTZ = true;
-        }
-
-        if (*dateString == '+' || *dateString == '-') {
-            long o;
-            if (!parseLong(dateString, &newPosStr, 10, &o))
-                return NaN;
-            dateString = newPosStr;
-
-            if (o < -9959 || o > 9959)
-                return NaN;
-
-            int sgn = (o < 0) ? -1 : 1;
-            o = labs(o);
-            if (*dateString != ':') {
-                offset = ((o / 100) * 60 + (o % 100)) * sgn;
-            } else { // GMT+05:00
-                long o2;
-                if (!parseLong(dateString, &newPosStr, 10, &o2))
-                    return NaN;
-                dateString = newPosStr;
-                offset = (o * 60 + o2) * sgn;
-            }
-            haveTZ = true;
-        } else {
-            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);
-                    haveTZ = true;
-                    break;
-                }
-            }
-        }
-    }
-
-    skipSpacesAndComments(dateString);
-
-    if (*dateString && year == -1) {
-        if (!parseLong(dateString, &newPosStr, 10, &year))
-            return NaN;
-        dateString = newPosStr;
-    }
-
-    skipSpacesAndComments(dateString);
-
-    // Trailing garbage
-    if (*dateString)
-        return NaN;
-
-    // Y2K: Handle 2 digit years.
-    if (year >= 0 && year < 100) {
-        if (year < 50)
-            year += 2000;
-        else
-            year += 1900;
-    }
-    
-    return ymdhmsToSeconds(year, month + 1, day, hour, minute, second) * msPerSecond;
-}
-
-double parseDateFromNullTerminatedCharacters(const char* dateString)
-{
-    bool haveTZ;
-    int offset;
-    double ms = parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset);
-    if (isnan(ms))
-        return NaN;
-
-    // fall back to local timezone
-    if (!haveTZ) {
-        double utcOffset = calculateUTCOffset();
-        double dstOffset = calculateDSTOffset(ms, utcOffset);
-        offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute);
-    }
-    return ms - (offset * msPerMinute);
-}
-
-double timeClip(double t)
-{
-    if (!isfinite(t))
-        return NaN;
-    if (fabs(t) > maxECMAScriptTime)
-        return NaN;
-    return trunc(t);
-}
-} // namespace WTF
-
-#if USE(JSC)
-namespace JSC {
-
-// Get the DST offset for the time passed in.
-//
-// NOTE: The implementation relies on the fact that no time zones have
-// more than one daylight savings offset change per month.
-// If this function is called with NaN it returns NaN.
-static double getDSTOffset(ExecState* exec, double ms, double utcOffset)
-{
-    DSTOffsetCache& cache = exec->globalData().dstOffsetCache;
-    double start = cache.start;
-    double end = cache.end;
-
-    if (start <= ms) {
-        // If the time fits in the cached interval, return the cached offset.
-        if (ms <= end) return cache.offset;
-
-        // Compute a possible new interval end.
-        double newEnd = end + cache.increment;
-
-        if (ms <= newEnd) {
-            double endOffset = calculateDSTOffset(newEnd, utcOffset);
-            if (cache.offset == endOffset) {
-                // If the offset at the end of the new interval still matches
-                // the offset in the cache, we grow the cached time interval
-                // and return the offset.
-                cache.end = newEnd;
-                cache.increment = msPerMonth;
-                return endOffset;
-            } else {
-                double offset = calculateDSTOffset(ms, utcOffset);
-                if (offset == endOffset) {
-                    // The offset at the given time is equal to the offset at the
-                    // new end of the interval, so that means that we've just skipped
-                    // the point in time where the DST offset change occurred. Updated
-                    // the interval to reflect this and reset the increment.
-                    cache.start = ms;
-                    cache.end = newEnd;
-                    cache.increment = msPerMonth;
-                } else {
-                    // The interval contains a DST offset change and the given time is
-                    // before it. Adjust the increment to avoid a linear search for
-                    // the offset change point and change the end of the interval.
-                    cache.increment /= 3;
-                    cache.end = ms;
-                }
-                // Update the offset in the cache and return it.
-                cache.offset = offset;
-                return offset;
-            }
-        }
-    }
-
-    // Compute the DST offset for the time and shrink the cache interval
-    // to only contain the time. This allows fast repeated DST offset
-    // computations for the same time.
-    double offset = calculateDSTOffset(ms, utcOffset);
-    cache.offset = offset;
-    cache.start = ms;
-    cache.end = ms;
-    cache.increment = msPerMonth;
-    return offset;
-}
-
-/*
- * Get the difference in milliseconds between this time zone and UTC (GMT)
- * NOT including DST.
- */
-double getUTCOffset(ExecState* exec)
-{
-    double utcOffset = exec->globalData().cachedUTCOffset;
-    if (!isnan(utcOffset))
-        return utcOffset;
-    exec->globalData().cachedUTCOffset = calculateUTCOffset();
-    return exec->globalData().cachedUTCOffset;
-}
-
-double gregorianDateTimeToMS(ExecState* exec, const GregorianDateTime& t, double milliSeconds, bool inputIsUTC)
-{
-    double day = dateToDaysFrom1970(t.year + 1900, t.month, t.monthDay);
-    double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds);
-    double result = (day * WTF::msPerDay) + ms;
-
-    if (!inputIsUTC) { // convert to UTC
-        double utcOffset = getUTCOffset(exec);
-        result -= utcOffset;
-        result -= getDSTOffset(exec, result, utcOffset);
-    }
-
-    return result;
-}
-
-// input is UTC
-void msToGregorianDateTime(ExecState* exec, double ms, bool outputIsUTC, GregorianDateTime& tm)
-{
-    double dstOff = 0.0;
-    double utcOff = 0.0;
-    if (!outputIsUTC) {
-        utcOff = getUTCOffset(exec);
-        dstOff = getDSTOffset(exec, ms, utcOff);
-        ms += dstOff + utcOff;
-    }
-
-    const int year = msToYear(ms);
-    tm.second   =  msToSeconds(ms);
-    tm.minute   =  msToMinutes(ms);
-    tm.hour     =  msToHours(ms);
-    tm.weekDay  =  msToWeekDay(ms);
-    tm.yearDay  =  dayInYear(ms, year);
-    tm.monthDay =  dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year));
-    tm.month    =  monthFromDayInYear(tm.yearDay, isLeapYear(year));
-    tm.year     =  year - 1900;
-    tm.isDST    =  dstOff != 0.0;
-    tm.utcOffset = static_cast<long>((dstOff + utcOff) / WTF::msPerSecond);
-    tm.timeZone = nullptr;
-}
-
-double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateString)
-{
-    ASSERT(exec);
-    bool haveTZ;
-    int offset;
-    double ms = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset);
-    if (isnan(ms))
-        return NaN;
-
-    // fall back to local timezone
-    if (!haveTZ) {
-        double utcOffset = getUTCOffset(exec);
-        double dstOffset = getDSTOffset(exec, ms, utcOffset);
-        offset = static_cast<int>((utcOffset + dstOffset) / WTF::msPerMinute);
-    }
-    return ms - (offset * WTF::msPerMinute);
-}
-
-} // namespace JSC
-#endif // USE(JSC)
diff --git a/wtf/DateMath.h b/wtf/DateMath.h
deleted file mode 100644 (file)
index 2ac284e..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * 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
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- */
-
-#ifndef DateMath_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 <wtf/OwnArrayPtr.h>
-#include <wtf/PassOwnArrayPtr.h>
-#include <wtf/UnusedParam.h>
-
-namespace WTF {
-void initializeDates();
-int equivalentYearForDST(int year);
-
-// Not really math related, but this is currently the only shared place to put these.
-double parseES5DateFromNullTerminatedCharacters(const char* dateString);
-double parseDateFromNullTerminatedCharacters(const char* dateString);
-double timeClip(double);
-
-inline double jsCurrentTime()
-{
-    // JavaScript doesn't recognize fractions of a millisecond.
-    return floor(WTF::currentTimeMS());
-}
-
-const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
-const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-const double hoursPerDay = 24.0;
-const double minutesPerHour = 60.0;
-const double secondsPerHour = 60.0 * 60.0;
-const double secondsPerMinute = 60.0;
-const double msPerSecond = 1000.0;
-const double msPerMinute = 60.0 * 1000.0;
-const double msPerHour = 60.0 * 60.0 * 1000.0;
-const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0;
-const double msPerMonth = 2592000000.0;
-
-// Returns the number of days from 1970-01-01 to the specified date.
-double dateToDaysFrom1970(int year, int month, int day);
-int msToYear(double ms);
-int dayInYear(double ms, int year);
-int monthFromDayInYear(int dayInYear, bool leapYear);
-int dayInMonthFromDayInYear(int dayInYear, bool leapYear);
-
-// Returns offset milliseconds for UTC and DST.
-int32_t calculateUTCOffset();
-double calculateDSTOffset(double ms, double utcOffset);
-
-} // namespace WTF
-
-using WTF::adoptArrayPtr;
-using WTF::dateToDaysFrom1970;
-using WTF::dayInMonthFromDayInYear;
-using WTF::dayInYear;
-using WTF::minutesPerHour;
-using WTF::monthFromDayInYear;
-using WTF::msPerDay;
-using WTF::msPerMinute;
-using WTF::msPerSecond;
-using WTF::msToYear;
-using WTF::secondsPerMinute;
-using WTF::parseDateFromNullTerminatedCharacters;
-using WTF::calculateUTCOffset;
-using WTF::calculateDSTOffset;
-
-#if USE(JSC)
-namespace JSC {
-class ExecState;
-struct GregorianDateTime;
-
-void msToGregorianDateTime(ExecState*, double, bool outputIsUTC, GregorianDateTime&);
-double gregorianDateTimeToMS(ExecState*, const GregorianDateTime&, double, bool inputIsUTC);
-double getUTCOffset(ExecState*);
-double parseDateFromNullTerminatedCharacters(ExecState*, const char* dateString);
-
-// Intentionally overridding the default tm of the system.
-// The members of tm differ on various operating systems.
-struct GregorianDateTime {
-    WTF_MAKE_NONCOPYABLE(GregorianDateTime);
-public:
-    GregorianDateTime()
-        : second(0)
-        , minute(0)
-        , hour(0)
-        , weekDay(0)
-        , monthDay(0)
-        , yearDay(0)
-        , month(0)
-        , year(0)
-        , isDST(0)
-        , utcOffset(0)
-    {
-    }
-
-    GregorianDateTime(ExecState* exec, const tm& inTm)
-        : second(inTm.tm_sec)
-        , minute(inTm.tm_min)
-        , hour(inTm.tm_hour)
-        , weekDay(inTm.tm_wday)
-        , monthDay(inTm.tm_mday)
-        , yearDay(inTm.tm_yday)
-        , month(inTm.tm_mon)
-        , year(inTm.tm_year)
-        , isDST(inTm.tm_isdst)
-    {
-        UNUSED_PARAM(exec);
-#if HAVE(TM_GMTOFF)
-        utcOffset = static_cast<int>(inTm.tm_gmtoff);
-#else
-        utcOffset = static_cast<int>(getUTCOffset(exec) / WTF::msPerSecond + (isDST ? WTF::secondsPerHour : 0));
-#endif
-
-#if HAVE(TM_ZONE)
-        int inZoneSize = strlen(inTm.tm_zone) + 1;
-        timeZone = adoptArrayPtr(new char[inZoneSize]);
-        strncpy(timeZone.get(), inTm.tm_zone, inZoneSize);
-#else
-        timeZone = nullptr;
-#endif
-    }
-
-    operator tm() const
-    {
-        tm ret;
-        memset(&ret, 0, sizeof(ret));
-
-        ret.tm_sec   =  second;
-        ret.tm_min   =  minute;
-        ret.tm_hour  =  hour;
-        ret.tm_wday  =  weekDay;
-        ret.tm_mday  =  monthDay;
-        ret.tm_yday  =  yearDay;
-        ret.tm_mon   =  month;
-        ret.tm_year  =  year;
-        ret.tm_isdst =  isDST;
-
-#if HAVE(TM_GMTOFF)
-        ret.tm_gmtoff = static_cast<long>(utcOffset);
-#endif
-#if HAVE(TM_ZONE)
-        ret.tm_zone = timeZone.get();
-#endif
-
-        return ret;
-    }
-
-    void copyFrom(const GregorianDateTime& rhs)
-    {
-        second = rhs.second;
-        minute = rhs.minute;
-        hour = rhs.hour;
-        weekDay = rhs.weekDay;
-        monthDay = rhs.monthDay;
-        yearDay = rhs.yearDay;
-        month = rhs.month;
-        year = rhs.year;
-        isDST = rhs.isDST;
-        utcOffset = rhs.utcOffset;
-        if (rhs.timeZone) {
-            int inZoneSize = strlen(rhs.timeZone.get()) + 1;
-            timeZone = adoptArrayPtr(new char[inZoneSize]);
-            strncpy(timeZone.get(), rhs.timeZone.get(), inZoneSize);
-        } else
-            timeZone = nullptr;
-    }
-
-    int second;
-    int minute;
-    int hour;
-    int weekDay;
-    int monthDay;
-    int yearDay;
-    int month;
-    int year;
-    int isDST;
-    int utcOffset;
-    OwnArrayPtr<char> timeZone;
-};
-
-static inline int gmtoffset(const GregorianDateTime& t)
-{
-    return t.utcOffset;
-}
-} // namespace JSC
-#endif // USE(JSC)
-
-#endif // DateMath_h
diff --git a/wtf/DecimalNumber.cpp b/wtf/DecimalNumber.cpp
deleted file mode 100644 (file)
index 70304e2..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index c42f00b..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 341d58d..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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
diff --git a/wtf/Deque.h b/wtf/Deque.h
deleted file mode 100644 (file)
index 8e42335..0000000
+++ /dev/null
@@ -1,688 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009 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 WTF_Deque_h
-#define WTF_Deque_h
-
-// FIXME: Could move what Vector and Deque share into a separate file.
-// Deque doesn't actually use Vector.
-
-#include "PassTraits.h"
-#include "Vector.h"
-
-namespace WTF {
-
-    template<typename T, 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, size_t inlineCapacity = 0>
-    class Deque {
-        WTF_MAKE_FAST_ALLOCATED;
-    public:
-        typedef DequeIterator<T, inlineCapacity> iterator;
-        typedef DequeConstIterator<T, inlineCapacity> const_iterator;
-        typedef DequeReverseIterator<T, inlineCapacity> reverse_iterator;
-        typedef DequeConstReverseIterator<T, inlineCapacity> const_reverse_iterator;
-        typedef PassTraits<T> Pass;
-        typedef typename PassTraits<T>::PassType PassType;
-
-        Deque();
-        Deque(const Deque<T, inlineCapacity>&);
-        Deque& operator=(const Deque<T, inlineCapacity>&);
-        ~Deque();
-
-        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; }
-
-        iterator begin() { return iterator(this, m_start); }
-        iterator end() { return iterator(this, m_end); }
-        const_iterator begin() const { return const_iterator(this, m_start); }
-        const_iterator end() const { return const_iterator(this, m_end); }
-        reverse_iterator rbegin() { return reverse_iterator(this, m_end); }
-        reverse_iterator rend() { return reverse_iterator(this, m_start); }
-        const_reverse_iterator rbegin() const { return const_reverse_iterator(this, m_end); }
-        const_reverse_iterator rend() const { return const_reverse_iterator(this, 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&);
-        void removeFirst();
-        void remove(iterator&);
-        void remove(const_iterator&);
-
-        void clear();
-
-        template<typename Predicate>
-        iterator findIf(Predicate&);
-
-    private:
-        friend class DequeIteratorBase<T, inlineCapacity>;
-
-        typedef VectorBuffer<T, inlineCapacity> Buffer;
-        typedef VectorTypeOperations<T> TypeOperations;
-        typedef DequeIteratorBase<T, inlineCapacity> IteratorBase;
-
-        void remove(size_t position);
-        void invalidateIterators();
-        void destroyAll();
-        void checkValidity() const;
-        void checkIndexValidity(size_t) const;
-        void expandCapacityIfNeeded();
-        void expandCapacity();
-
-        size_t m_start;
-        size_t m_end;
-        Buffer m_buffer;
-#ifndef NDEBUG
-        mutable IteratorBase* m_iterators;
-#endif
-    };
-
-    template<typename T, size_t inlineCapacity = 0>
-    class DequeIteratorBase {
-    private:
-        typedef DequeIteratorBase<T, inlineCapacity> Base;
-
-    protected:
-        DequeIteratorBase();
-        DequeIteratorBase(const Deque<T, inlineCapacity>*, size_t);
-        DequeIteratorBase(const Base&);
-        Base& operator=(const Base&);
-        ~DequeIteratorBase();
-
-        void assign(const Base& other) { *this = other; }
-
-        void increment();
-        void decrement();
-
-        T* before() const;
-        T* after() const;
-
-        bool isEqual(const Base&) const;
-
-    private:
-        void addToIteratorsList();
-        void removeFromIteratorsList();
-        void checkValidity() const;
-        void checkValidity(const Base&) const;
-
-        Deque<T, inlineCapacity>* m_deque;
-        size_t m_index;
-
-        friend class Deque<T, inlineCapacity>;
-
-#ifndef NDEBUG
-        mutable DequeIteratorBase* m_next;
-        mutable DequeIteratorBase* m_previous;
-#endif
-    };
-
-    template<typename T, size_t inlineCapacity = 0>
-    class DequeIterator : public DequeIteratorBase<T, inlineCapacity> {
-    private:
-        typedef DequeIteratorBase<T, inlineCapacity> Base;
-        typedef DequeIterator<T, inlineCapacity> Iterator;
-
-    public:
-        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; }
-
-        T& operator*() const { return *Base::after(); }
-        T* operator->() const { return Base::after(); }
-
-        bool operator==(const Iterator& other) const { return Base::isEqual(other); }
-        bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
-
-        Iterator& operator++() { Base::increment(); return *this; }
-        // postfix ++ intentionally omitted
-        Iterator& operator--() { Base::decrement(); return *this; }
-        // postfix -- intentionally omitted
-    };
-
-    template<typename T, size_t inlineCapacity = 0>
-    class DequeConstIterator : public DequeIteratorBase<T, inlineCapacity> {
-    private:
-        typedef DequeIteratorBase<T, inlineCapacity> Base;
-        typedef DequeConstIterator<T, inlineCapacity> Iterator;
-        typedef DequeIterator<T, inlineCapacity> NonConstIterator;
-
-    public:
-        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& operator=(const Iterator& other) { Base::assign(other); return *this; }
-        DequeConstIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; }
-
-        const T& operator*() const { return *Base::after(); }
-        const T* operator->() const { return Base::after(); }
-
-        bool operator==(const Iterator& other) const { return Base::isEqual(other); }
-        bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
-
-        Iterator& operator++() { Base::increment(); return *this; }
-        // postfix ++ intentionally omitted
-        Iterator& operator--() { Base::decrement(); return *this; }
-        // postfix -- intentionally omitted
-    };
-
-    template<typename T, size_t inlineCapacity = 0>
-    class DequeReverseIterator : public DequeIteratorBase<T, inlineCapacity> {
-    private:
-        typedef DequeIteratorBase<T, inlineCapacity> Base;
-        typedef DequeReverseIterator<T, inlineCapacity> Iterator;
-
-    public:
-        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; }
-
-        T& operator*() const { return *Base::before(); }
-        T* operator->() const { return Base::before(); }
-
-        bool operator==(const Iterator& other) const { return Base::isEqual(other); }
-        bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
-
-        Iterator& operator++() { Base::decrement(); return *this; }
-        // postfix ++ intentionally omitted
-        Iterator& operator--() { Base::increment(); return *this; }
-        // postfix -- intentionally omitted
-    };
-
-    template<typename T, size_t inlineCapacity = 0>
-    class DequeConstReverseIterator : public DequeIteratorBase<T, inlineCapacity> {
-    private:
-        typedef DequeIteratorBase<T, inlineCapacity> Base;
-        typedef DequeConstReverseIterator<T, inlineCapacity> Iterator;
-        typedef DequeReverseIterator<T, inlineCapacity> NonConstIterator;
-
-    public:
-        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& operator=(const Iterator& other) { Base::assign(other); return *this; }
-        DequeConstReverseIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; }
-
-        const T& operator*() const { return *Base::before(); }
-        const T* operator->() const { return Base::before(); }
-
-        bool operator==(const Iterator& other) const { return Base::isEqual(other); }
-        bool operator!=(const Iterator& other) const { return !Base::isEqual(other); }
-
-        Iterator& operator++() { Base::decrement(); return *this; }
-        // postfix ++ intentionally omitted
-        Iterator& operator--() { Base::increment(); return *this; }
-        // postfix -- intentionally omitted
-    };
-
-#ifdef NDEBUG
-    template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::checkValidity() const { }
-    template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::checkIndexValidity(size_t) const { }
-    template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::invalidateIterators() { }
-#else
-    template<typename T, 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);
-        } else {
-            ASSERT(m_start < m_buffer.capacity());
-            ASSERT(m_end < m_buffer.capacity());
-        }
-    }
-
-    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_start);
-            ASSERT(index <= m_end);
-        } else {
-            ASSERT(index >= m_start || index <= m_end);
-        }
-    }
-
-    template<typename T, size_t inlineCapacity>
-    void Deque<T, inlineCapacity>::invalidateIterators()
-    {
-        IteratorBase* next;
-        for (IteratorBase* p = m_iterators; p; p = next) {
-            next = p->m_next;
-            p->m_deque = 0;
-            p->m_next = 0;
-            p->m_previous = 0;
-        }
-        m_iterators = 0;
-    }
-#endif
-
-    template<typename T, size_t inlineCapacity>
-    inline Deque<T, inlineCapacity>::Deque()
-        : m_start(0)
-        , m_end(0)
-#ifndef NDEBUG
-        , m_iterators(0)
-#endif
-    {
-        checkValidity();
-    }
-
-    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())
-#ifndef NDEBUG
-        , m_iterators(0)
-#endif
-    {
-        const T* otherBuffer = other.m_buffer.buffer();
-        if (m_start <= m_end)
-            TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_end, m_buffer.buffer() + m_start);
-        else {
-            TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, m_buffer.buffer());
-            TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_buffer.capacity(), m_buffer.buffer() + m_start);
-        }
-    }
-
-    template<typename T, size_t inlineCapacity>
-    void deleteAllValues(const Deque<T, inlineCapacity>& collection)
-    {
-        typedef typename Deque<T, inlineCapacity>::const_iterator iterator;
-        iterator end = collection.end();
-        for (iterator it = collection.begin(); it != end; ++it)
-            delete *it;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline Deque<T, inlineCapacity>& Deque<T, inlineCapacity>::operator=(const Deque<T, inlineCapacity>& other)
-    {
-        // FIXME: This is inefficient if we're using an inline buffer and T is
-        // expensive to copy since it will copy the buffer twice instead of once.
-        Deque<T> copy(other);
-        swap(copy);
-        return *this;
-    }
-
-    template<typename T, 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);
-        else {
-            TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_end);
-            TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_buffer.capacity());
-        }
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline Deque<T, inlineCapacity>::~Deque()
-    {
-        checkValidity();
-        invalidateIterators();
-        destroyAll();
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void Deque<T, inlineCapacity>::swap(Deque<T, inlineCapacity>& other)
-    {
-        checkValidity();
-        other.checkValidity();
-        invalidateIterators();
-        std::swap(m_start, other.m_start);
-        std::swap(m_end, other.m_end);
-        m_buffer.swap(other.m_buffer);
-        checkValidity();
-        other.checkValidity();
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void Deque<T, inlineCapacity>::clear()
-    {
-        checkValidity();
-        invalidateIterators();
-        destroyAll();
-        m_start = 0;
-        m_end = 0;
-        checkValidity();
-    }
-
-    template<typename T, size_t inlineCapacity>
-    template<typename Predicate>
-    inline DequeIterator<T, inlineCapacity> Deque<T, inlineCapacity>::findIf(Predicate& predicate)
-    {
-        iterator end_iterator = end();
-        for (iterator it = begin(); it != end_iterator; ++it) {
-            if (predicate(*it))
-                return it;
-        }
-        return end_iterator;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void Deque<T, inlineCapacity>::expandCapacityIfNeeded()
-    {
-        if (m_start) {
-            if (m_end + 1 != m_start)
-                return;
-        } else if (m_end) {
-            if (m_end != m_buffer.capacity() - 1)
-                return;
-        } else if (m_buffer.capacity())
-            return;
-
-        expandCapacity();
-    }
-
-    template<typename T, size_t inlineCapacity>
-    void Deque<T, inlineCapacity>::expandCapacity()
-    {
-        checkValidity();
-        size_t oldCapacity = m_buffer.capacity();
-        size_t newCapacity = max(static_cast<size_t>(16), oldCapacity + oldCapacity / 4 + 1);
-        T* oldBuffer = m_buffer.buffer();
-        m_buffer.allocateBuffer(newCapacity);
-        if (m_start <= m_end)
-            TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffer.buffer() + m_start);
-        else {
-            TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer());
-            size_t newStart = newCapacity - (oldCapacity - m_start);
-            TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.buffer() + newStart);
-            m_start = newStart;
-        }
-        m_buffer.deallocateBuffer(oldBuffer);
-        checkValidity();
-    }
-
-    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();
-        new (&m_buffer.buffer()[m_end]) T(value);
-        if (m_end == m_buffer.capacity() - 1)
-            m_end = 0;
-        else
-            ++m_end;
-        checkValidity();
-    }
-
-    template<typename T, size_t inlineCapacity> template<typename U>
-    inline void Deque<T, inlineCapacity>::prepend(const U& value)
-    {
-        checkValidity();
-        expandCapacityIfNeeded();
-        if (!m_start)
-            m_start = m_buffer.capacity() - 1;
-        else
-            --m_start;
-        new (&m_buffer.buffer()[m_start]) T(value);
-        checkValidity();
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void Deque<T, inlineCapacity>::removeFirst()
-    {
-        checkValidity();
-        invalidateIterators();
-        ASSERT(!isEmpty());
-        TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_start + 1]);
-        if (m_start == m_buffer.capacity() - 1)
-            m_start = 0;
-        else
-            ++m_start;
-        checkValidity();
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void Deque<T, inlineCapacity>::remove(iterator& it)
-    {
-        it.checkValidity();
-        remove(it.m_index);
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void Deque<T, inlineCapacity>::remove(const_iterator& it)
-    {
-        it.checkValidity();
-        remove(it.m_index);
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void Deque<T, inlineCapacity>::remove(size_t position)
-    {
-        if (position == m_end)
-            return;
-
-        checkValidity();
-        invalidateIterators();
-
-        T* buffer = m_buffer.buffer();
-        TypeOperations::destruct(&buffer[position], &buffer[position + 1]);
-
-        // Find which segment of the circular buffer contained the remove element, and only move elements in that part.
-        if (position >= m_start) {
-            TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buffer + m_start + 1);
-            m_start = (m_start + 1) % m_buffer.capacity();
-        } else {
-            TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end, buffer + position);
-            m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity();
-        }
-        checkValidity();
-    }
-
-#ifdef NDEBUG
-    template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::checkValidity() const { }
-    template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::checkValidity(const DequeIteratorBase<T, inlineCapacity>&) const { }
-    template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::addToIteratorsList() { }
-    template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::removeFromIteratorsList() { }
-#else
-    template<typename T, size_t inlineCapacity>
-    void DequeIteratorBase<T, inlineCapacity>::checkValidity() const
-    {
-        ASSERT(m_deque);
-        m_deque->checkIndexValidity(m_index);
-    }
-
-    template<typename T, size_t inlineCapacity>
-    void DequeIteratorBase<T, inlineCapacity>::checkValidity(const Base& other) const
-    {
-        checkValidity();
-        other.checkValidity();
-        ASSERT(m_deque == other.m_deque);
-    }
-
-    template<typename T, size_t inlineCapacity>
-    void DequeIteratorBase<T, inlineCapacity>::addToIteratorsList()
-    {
-        if (!m_deque)
-            m_next = 0;
-        else {
-            m_next = m_deque->m_iterators;
-            m_deque->m_iterators = this;
-            if (m_next)
-                m_next->m_previous = this;
-        }
-        m_previous = 0;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    void DequeIteratorBase<T, inlineCapacity>::removeFromIteratorsList()
-    {
-        if (!m_deque) {
-            ASSERT(!m_next);
-            ASSERT(!m_previous);
-        } else {
-            if (m_next) {
-                ASSERT(m_next->m_previous == this);
-                m_next->m_previous = m_previous;
-            }
-            if (m_previous) {
-                ASSERT(m_deque->m_iterators != this);
-                ASSERT(m_previous->m_next == this);
-                m_previous->m_next = m_next;
-            } else {
-                ASSERT(m_deque->m_iterators == this);
-                m_deque->m_iterators = m_next;
-            }
-        }
-        m_next = 0;
-        m_previous = 0;
-    }
-#endif
-
-    template<typename T, size_t inlineCapacity>
-    inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase()
-        : m_deque(0)
-    {
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const Deque<T, inlineCapacity>* deque, size_t index)
-        : m_deque(const_cast<Deque<T, inlineCapacity>*>(deque))
-        , m_index(index)
-    {
-        addToIteratorsList();
-        checkValidity();
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const Base& other)
-        : m_deque(other.m_deque)
-        , m_index(other.m_index)
-    {
-        addToIteratorsList();
-        checkValidity();
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline DequeIteratorBase<T, inlineCapacity>& DequeIteratorBase<T, inlineCapacity>::operator=(const Base& other)
-    {
-        checkValidity();
-        other.checkValidity();
-        removeFromIteratorsList();
-
-        m_deque = other.m_deque;
-        m_index = other.m_index;
-        addToIteratorsList();
-        checkValidity();
-        return *this;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline DequeIteratorBase<T, inlineCapacity>::~DequeIteratorBase()
-    {
-#ifndef NDEBUG
-        removeFromIteratorsList();
-        m_deque = 0;
-#endif
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline bool DequeIteratorBase<T, inlineCapacity>::isEqual(const Base& other) const
-    {
-        checkValidity(other);
-        return m_index == other.m_index;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void DequeIteratorBase<T, inlineCapacity>::increment()
-    {
-        checkValidity();
-        ASSERT(m_index != m_deque->m_end);
-        ASSERT(m_deque->m_buffer.capacity());
-        if (m_index == m_deque->m_buffer.capacity() - 1)
-            m_index = 0;
-        else
-            ++m_index;
-        checkValidity();
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void DequeIteratorBase<T, inlineCapacity>::decrement()
-    {
-        checkValidity();
-        ASSERT(m_index != m_deque->m_start);
-        ASSERT(m_deque->m_buffer.capacity());
-        if (!m_index)
-            m_index = m_deque->m_buffer.capacity() - 1;
-        else
-            --m_index;
-        checkValidity();
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline T* DequeIteratorBase<T, inlineCapacity>::after() const
-    {
-        checkValidity();
-        ASSERT(m_index != m_deque->m_end);
-        return &m_deque->m_buffer.buffer()[m_index];
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline T* DequeIteratorBase<T, inlineCapacity>::before() const
-    {
-        checkValidity();
-        ASSERT(m_index != m_deque->m_start);
-        if (!m_index)
-            return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1];
-        return &m_deque->m_buffer.buffer()[m_index - 1];
-    }
-
-} // namespace WTF
-
-using WTF::Deque;
-
-#endif // WTF_Deque_h
diff --git a/wtf/DisallowCType.h b/wtf/DisallowCType.h
deleted file mode 100644 (file)
index 541f3a8..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 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:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must 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_DisallowCType_h
-#define WTF_DisallowCType_h
-
-#include "Platform.h"
-
-#define _DONT_USE_CTYPE_INLINE_
-
-// The behavior of many of the functions in the <ctype.h> header is dependent
-// on the current locale. But almost all uses of these functions are for
-// locale-independent, ASCII-specific purposes. In WebKit code we use our own
-// ASCII-specific functions instead. This header makes sure we get a compile-time
-// error if we use one of the <ctype.h> functions by accident.
-
-#include <ctype.h>
-
-#undef isalnum
-#undef isalpha
-#undef isascii
-#undef isblank
-#undef iscntrl
-#undef isdigit
-#undef isgraph
-#undef islower
-#undef isprint
-#undef ispunct
-#undef isspace
-#undef isupper
-#undef isxdigit
-#undef toascii
-#undef tolower
-#undef toupper
-
-#define isalnum isalnum_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isalpha isalpha_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isascii isascii_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isblank isblank_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define iscntrl iscntrl_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isdigit isdigit_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isgraph isgraph_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define islower islower_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isprint isprint_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define ispunct ispunct_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isspace isspace_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isupper isupper_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define isxdigit isxdigit_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define toascii toascii_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define tolower tolower_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-#define toupper toupper_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h
-
-#endif
diff --git a/wtf/DoublyLinkedList.h b/wtf/DoublyLinkedList.h
deleted file mode 100644 (file)
index 9351263..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index b7d4b41..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 38acce3..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 109b0db..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 3fadd37..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 */
diff --git a/wtf/FastAllocBase.h b/wtf/FastAllocBase.h
deleted file mode 100644 (file)
index e4899ab..0000000
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright (C) 2008, 2009 Paul Pedriana <ppedriana@ea.com>. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must 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 FastAllocBase_h
-#define FastAllocBase_h
-
-// Provides customizable overrides of fastMalloc/fastFree and operator new/delete
-//
-// Provided functionality:
-//    Macro: WTF_MAKE_FAST_ALLOCATED
-//    namespace WTF {
-//
-//        T*    fastNew<T>();
-//        T*    fastNew<T>(arg);
-//        T*    fastNew<T>(arg, arg);
-//        T*    fastNewArray<T>(count);
-//        void  fastDelete(T* p);
-//        void  fastDeleteArray(T* p);
-//        void  fastNonNullDelete(T* p);
-//        void  fastNonNullDeleteArray(T* p);
-//    }
-//
-// FastDelete assumes that the underlying
-//
-// Example usage:
-//    class Widget {
-//        WTF_MAKE_FAST_ALLOCATED
-//    ...
-//    };
-//
-//    struct Data {
-//        WTF_MAKE_FAST_ALLOCATED
-//    public:
-//    ...
-//    };
-//
-//    char* charPtr = fastNew<char>();
-//    fastDelete(charPtr);
-//
-//    char* charArrayPtr = fastNewArray<char>(37);
-//    fastDeleteArray(charArrayPtr);
-//
-//    void** voidPtrPtr = fastNew<void*>();
-//    fastDelete(voidPtrPtr);
-//
-//    void** voidPtrArrayPtr = fastNewArray<void*>(37);
-//    fastDeleteArray(voidPtrArrayPtr);
-//
-//    POD* podPtr = fastNew<POD>();
-//    fastDelete(podPtr);
-//
-//    POD* podArrayPtr = fastNewArray<POD>(37);
-//    fastDeleteArray(podArrayPtr);
-//
-//    Object* objectPtr = fastNew<Object>();
-//    fastDelete(objectPtr);
-//
-//    Object* objectArrayPtr = fastNewArray<Object>(37);
-//    fastDeleteArray(objectArrayPtr);
-//
-
-#include <new>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include "Assertions.h"
-#include "FastMalloc.h"
-#include "TypeTraits.h"
-
-#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
-
-namespace WTF {
-
-    // fastNew / fastDelete
-
-    template <typename T>
-    inline T* fastNew()
-    {
-        void* p = fastMalloc(sizeof(T));
-
-        if (!p)
-            return 0;
-
-        fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
-        return ::new(p) T;
-    }
-
-    template <typename T, typename Arg1>
-    inline T* fastNew(Arg1 arg1)
-    {
-        void* p = fastMalloc(sizeof(T));
-
-        if (!p)
-            return 0;
-
-        fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
-        return ::new(p) T(arg1);
-    }
-
-    template <typename T, typename Arg1, typename Arg2>
-    inline T* fastNew(Arg1 arg1, Arg2 arg2)
-    {
-        void* p = fastMalloc(sizeof(T));
-
-        if (!p)
-            return 0;
-
-        fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
-        return ::new(p) T(arg1, arg2);
-    }
-
-    template <typename T, typename Arg1, typename Arg2, typename Arg3>
-    inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3)
-    {
-        void* p = fastMalloc(sizeof(T));
-
-        if (!p)
-            return 0;
-
-        fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
-        return ::new(p) T(arg1, arg2, arg3);
-    }
-
-    template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-    inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
-    {
-        void* p = fastMalloc(sizeof(T));
-
-        if (!p)
-            return 0;
-
-        fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
-        return ::new(p) T(arg1, arg2, arg3, arg4);
-    }
-
-    template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
-    inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
-    {
-        void* p = fastMalloc(sizeof(T));
-
-        if (!p)
-            return 0;
-
-        fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew);
-        return ::new(p) T(arg1, arg2, arg3, arg4, arg5);
-    }
-
-    namespace Internal {
-
-        // We define a union of pointer to an integer and pointer to T.
-        // When non-POD arrays are allocated we add a few leading bytes to tell what
-        // the size of the array is. We return to the user the pointer to T.
-        // The way to think of it is as if we allocate a struct like so:
-        //    struct Array {
-        //        AllocAlignmentInteger m_size;
-        //        T m_T[array count];
-        //    };
-
-        template <typename T>
-        union ArraySize {
-            AllocAlignmentInteger* size;
-            T* t;
-        };
-
-        // This is a support template for fastNewArray.
-        // This handles the case wherein T has a trivial ctor and a trivial dtor.
-        template <typename T, bool trivialCtor, bool trivialDtor>
-        struct NewArrayImpl {
-            static T* fastNewArray(size_t count)
-            {
-                T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
-                fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
-                return p;
-            }
-        };
-
-        // This is a support template for fastNewArray.
-        // This handles the case wherein T has a non-trivial ctor and a trivial dtor.
-        template <typename T>
-        struct NewArrayImpl<T, false, true> {
-            static T* fastNewArray(size_t count)
-            {
-                T* p = static_cast<T*>(fastMalloc(sizeof(T) * count));
-
-                if (!p)
-                    return 0;
-
-                fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
-
-                for (T* pObject = p, *pObjectEnd = pObject + count; pObject != pObjectEnd; ++pObject)
-                    ::new(pObject) T;
-
-                return p;
-            }
-        };
-
-        // This is a support template for fastNewArray.
-        // This handles the case wherein T has a trivial ctor and a non-trivial dtor.
-        template <typename T>
-        struct NewArrayImpl<T, true, false> {
-            static T* fastNewArray(size_t count)
-            {
-                void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
-                ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
-
-                if (!p)
-                    return 0;
-
-                fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
-                *a.size++ = count;
-                // No need to construct the objects in this case.
-
-                return a.t;
-            }
-        };
-
-        // This is a support template for fastNewArray.
-        // This handles the case wherein T has a non-trivial ctor and a non-trivial dtor.
-        template <typename T>
-        struct NewArrayImpl<T, false, false> {
-            static T* fastNewArray(size_t count)
-            {
-                void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count));
-                ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) };
-
-                if (!p)
-                    return 0;
-
-                fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray);
-                *a.size++ = count;
-
-                for (T* pT = a.t, *pTEnd = pT + count; pT != pTEnd; ++pT)
-                    ::new(pT) T;
-
-                return a.t;
-            }
-        };
-    } // namespace Internal
-
-    template <typename T>
-    inline T* fastNewArray(size_t count)
-    {
-        return Internal::NewArrayImpl<T, WTF::HasTrivialConstructor<T>::value, WTF::HasTrivialDestructor<T>::value>::fastNewArray(count);
-    }
-
-    template <typename T>
-    inline void fastDelete(T* p)
-    {
-        if (!p)
-            return;
-
-        fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
-        p->~T();
-        fastFree(p);
-    }
-
-    template <typename T>
-    inline void fastDeleteSkippingDestructor(T* p)
-    {
-        if (!p)
-            return;
-
-        fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
-        fastFree(p);
-    }
-
-    namespace Internal {
-        // This is a support template for fastDeleteArray.
-        // This handles the case wherein T has a trivial dtor.
-        template <typename T, bool trivialDtor>
-        struct DeleteArrayImpl {
-            static void fastDeleteArray(void* p)
-            {
-                // No need to destruct the objects in this case.
-                // We expect that fastFree checks for null.
-                fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
-                fastFree(p);
-            }
-        };
-
-        // This is a support template for fastDeleteArray.
-        // This handles the case wherein T has a non-trivial dtor.
-        template <typename T>
-        struct DeleteArrayImpl<T, false> {
-            static void fastDeleteArray(T* p)
-            {
-                if (!p)
-                    return;
-
-                ArraySize<T> a;
-                a.t = p;
-                a.size--; // Decrement size pointer
-
-                T* pEnd = p + *a.size;
-                while (pEnd-- != p)
-                    pEnd->~T();
-
-                fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
-                fastFree(a.size);
-            }
-        };
-
-    } // namespace Internal
-
-    template <typename T>
-    void fastDeleteArray(T* p)
-    {
-        Internal::DeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastDeleteArray(p);
-    }
-
-
-    template <typename T>
-    inline void fastNonNullDelete(T* p)
-    {
-        fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew);
-        p->~T();
-        fastFree(p);
-    }
-
-    namespace Internal {
-        // This is a support template for fastDeleteArray.
-        // This handles the case wherein T has a trivial dtor.
-        template <typename T, bool trivialDtor>
-        struct NonNullDeleteArrayImpl {
-            static void fastNonNullDeleteArray(void* p)
-            {
-                fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray);
-                // No need to destruct the objects in this case.
-                fastFree(p);
-            }
-        };
-
-        // This is a support template for fastDeleteArray.
-        // This handles the case wherein T has a non-trivial dtor.
-        template <typename T>
-        struct NonNullDeleteArrayImpl<T, false> {
-            static void fastNonNullDeleteArray(T* p)
-            {
-                ArraySize<T> a;
-                a.t = p;
-                a.size--;
-
-                T* pEnd = p + *a.size;
-                while (pEnd-- != p)
-                    pEnd->~T();
-
-                fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray);
-                fastFree(a.size);
-            }
-        };
-
-    } // namespace Internal
-
-    template <typename T>
-    void fastNonNullDeleteArray(T* p)
-    {
-        Internal::NonNullDeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastNonNullDeleteArray(p);
-    }
-
-
-} // namespace WTF
-
-using WTF::fastDeleteSkippingDestructor;
-
-#endif // FastAllocBase_h
diff --git a/wtf/FastMalloc.cpp b/wtf/FastMalloc.cpp
deleted file mode 100644 (file)
index c42c3c4..0000000
+++ /dev/null
@@ -1,4654 +0,0 @@
-// Copyright (c) 2005, 2007, Google 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
-// 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.
-
-// ---
-// Author: Sanjay Ghemawat <opensource@google.com>
-//
-// A malloc that uses a per-thread cache to satisfy small malloc requests.
-// (The time for malloc/free of a small object drops from 300 ns to 50 ns.)
-//
-// See doc/tcmalloc.html for a high-level
-// description of how this malloc works.
-//
-// SYNCHRONIZATION
-//  1. The thread-specific lists are accessed without acquiring any locks.
-//     This is safe because each such list is only accessed by one thread.
-//  2. We have a lock per central free-list, and hold it while manipulating
-//     the central free list for a particular size.
-//  3. The central page allocator is protected by "pageheap_lock".
-//  4. The pagemap (which maps from page-number to descriptor),
-//     can be read without holding any locks, and written while holding
-//     the "pageheap_lock".
-//  5. To improve performance, a subset of the information one can get
-//     from the pagemap is cached in a data structure, pagemap_cache_,
-//     that atomically reads and writes its entries.  This cache can be
-//     read and written without locking.
-//
-//     This multi-threaded access to the pagemap is safe for fairly
-//     subtle reasons.  We basically assume that when an object X is
-//     allocated by thread A and deallocated by thread B, there must
-//     have been appropriate synchronization in the handoff of object
-//     X from thread A to thread B.  The same logic applies to pagemap_cache_.
-//
-// THE PAGEID-TO-SIZECLASS CACHE
-// Hot PageID-to-sizeclass mappings are held by pagemap_cache_.  If this cache
-// returns 0 for a particular PageID then that means "no information," not that
-// the sizeclass is 0.  The cache may have stale information for pages that do
-// not hold the beginning of any free()'able object.  Staleness is eliminated
-// in Populate() for pages with sizeclass > 0 objects, and in do_malloc() and
-// do_memalign() for all other relevant pages.
-//
-// TODO: Bias reclamation to larger addresses
-// TODO: implement mallinfo/mallopt
-// TODO: Better testing
-//
-// 9/28/2003 (new page-level allocator replaces ptmalloc2):
-// * malloc/free of small objects goes from ~300 ns to ~50 ns.
-// * allocation of a reasonably complicated struct
-//   goes from about 1100 ns to about 300 ns.
-
-#include "config.h"
-#include "FastMalloc.h"
-
-#include "Assertions.h"
-#include <limits>
-#if ENABLE(WTF_MULTIPLE_THREADS)
-#include <pthread.h>
-#endif
-#include <wtf/StdLibExtras.h>
-
-#ifndef NO_TCMALLOC_SAMPLES
-#ifdef WTF_CHANGES
-#define NO_TCMALLOC_SAMPLES
-#endif
-#endif
-
-#if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) && defined(NDEBUG)
-#define FORCE_SYSTEM_MALLOC 0
-#else
-#define FORCE_SYSTEM_MALLOC 1
-#endif
-
-// Use a background thread to periodically scavenge memory to release back to the system
-#define USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY 0
-
-#ifndef NDEBUG
-namespace WTF {
-
-#if ENABLE(WTF_MULTIPLE_THREADS)
-static pthread_key_t isForbiddenKey;
-static pthread_once_t isForbiddenKeyOnce = PTHREAD_ONCE_INIT;
-static void initializeIsForbiddenKey()
-{
-  pthread_key_create(&isForbiddenKey, 0);
-}
-
-#if !ASSERT_DISABLED
-static bool isForbidden()
-{
-    pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey);
-    return !!pthread_getspecific(isForbiddenKey);
-}
-#endif
-
-void fastMallocForbid()
-{
-    pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey);
-    pthread_setspecific(isForbiddenKey, &isForbiddenKey);
-}
-
-void fastMallocAllow()
-{
-    pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey);
-    pthread_setspecific(isForbiddenKey, 0);
-}
-
-#else
-
-static bool staticIsForbidden;
-static bool isForbidden()
-{
-    return staticIsForbidden;
-}
-
-void fastMallocForbid()
-{
-    staticIsForbidden = true;
-}
-
-void fastMallocAllow()
-{
-    staticIsForbidden = false;
-}
-#endif // ENABLE(WTF_MULTIPLE_THREADS)
-
-} // namespace WTF
-#endif // NDEBUG
-
-#include <string.h>
-
-namespace WTF {
-
-
-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();
-}
-
-} // namespace Internal
-
-
-void* fastZeroedMalloc(size_t n) 
-{
-    void* result = fastMalloc(n);
-    memset(result, 0, n);
-    return result;
-}
-
-char* fastStrDup(const char* src)
-{
-    size_t len = strlen(src) + 1;
-    char* dup = static_cast<char*>(fastMalloc(len));
-    memcpy(dup, src, len);
-    return dup;
-}
-
-TryMallocReturnValue tryFastZeroedMalloc(size_t n) 
-{
-    void* result;
-    if (!tryFastMalloc(n).getValue(result))
-        return 0;
-    memset(result, 0, n);
-    return result;
-}
-
-} // namespace WTF
-
-#if FORCE_SYSTEM_MALLOC
-
-#if PLATFORM(BREWMP)
-#include "brew/SystemMallocBrew.h"
-#endif
-
-#if OS(DARWIN)
-#include <malloc/malloc.h>
-#elif OS(WINDOWS)
-#include <malloc.h>
-#endif
-
-namespace WTF {
-
-TryMallocReturnValue tryFastMalloc(size_t n) 
-{
-    ASSERT(!isForbidden());
-
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= n)  // If overflow would occur...
-        return 0;
-
-    void* result = malloc(n + Internal::ValidationBufferSize);
-    if (!result)
-        return 0;
-    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);
-#endif
-}
-
-void* fastMalloc(size_t n) 
-{
-    ASSERT(!isForbidden());
-
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    TryMallocReturnValue returnValue = tryFastMalloc(n);
-    void* result;
-    if (!returnValue.getValue(result))
-        CRASH();
-#else
-    void* result = malloc(n);
-#endif
-
-    if (!result) {
-#if PLATFORM(BREWMP)
-        // The behavior of malloc(0) is implementation defined.
-        // To make sure that fastMalloc never returns 0, retry with fastMalloc(1).
-        if (!n)
-            return fastMalloc(1);
-#endif
-        CRASH();
-    }
-
-    return result;
-}
-
-TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size)
-{
-    ASSERT(!isForbidden());
-
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    size_t totalBytes = n_elements * element_size;
-    if (n_elements > 1 && element_size && (totalBytes / element_size) != n_elements)
-        return 0;
-
-    TryMallocReturnValue returnValue = tryFastMalloc(totalBytes);
-    void* result;
-    if (!returnValue.getValue(result))
-        return 0;
-    memset(result, 0, totalBytes);
-    fastMallocValidate(result);
-    return result;
-#else
-    return calloc(n_elements, element_size);
-#endif
-}
-
-void* fastCalloc(size_t n_elements, size_t element_size)
-{
-    ASSERT(!isForbidden());
-
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    TryMallocReturnValue returnValue = tryFastCalloc(n_elements, element_size);
-    void* result;
-    if (!returnValue.getValue(result))
-        CRASH();
-#else
-    void* result = calloc(n_elements, element_size);
-#endif
-
-    if (!result) {
-#if PLATFORM(BREWMP)
-        // If either n_elements or element_size is 0, the behavior of calloc is implementation defined.
-        // To make sure that fastCalloc never returns 0, retry with fastCalloc(1, 1).
-        if (!n_elements || !element_size)
-            return fastCalloc(1, 1);
-#endif
-        CRASH();
-    }
-
-    return result;
-}
-
-void fastFree(void* p)
-{
-    ASSERT(!isForbidden());
-
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    if (!p)
-        return;
-    
-    fastMallocMatchValidateFree(p, Internal::AllocTypeMalloc);
-    Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p);
-    memset(p, 0xCC, header->m_size);
-    free(header);
-#else
-    free(p);
-#endif
-}
-
-TryMallocReturnValue tryFastRealloc(void* p, size_t n)
-{
-    ASSERT(!isForbidden());
-
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    if (p) {
-        if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= n)  // If overflow would occur...
-            return 0;
-        fastMallocValidate(p);
-        Internal::ValidationHeader* result = static_cast<Internal::ValidationHeader*>(realloc(Internal::fastMallocValidationHeader(p), n + Internal::ValidationBufferSize));
-        if (!result)
-            return 0;
-        result->m_size = n;
-        result = result + 1;
-        *fastMallocValidationSuffix(result) = Internal::ValidationSuffix;
-        fastMallocValidate(result);
-        return result;
-    } else {
-        return fastMalloc(n);
-    }
-#else
-    return realloc(p, n);
-#endif
-}
-
-void* fastRealloc(void* p, size_t n)
-{
-    ASSERT(!isForbidden());
-
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    TryMallocReturnValue returnValue = tryFastRealloc(p, n);
-    void* result;
-    if (!returnValue.getValue(result))
-        CRASH();
-#else
-    void* result = realloc(p, n);
-#endif
-
-    if (!result)
-        CRASH();
-    return result;
-}
-
-void releaseFastMallocFreeMemory() { }
-    
-FastMallocStatistics fastMallocStatistics()
-{
-    FastMallocStatistics statistics = { 0, 0, 0 };
-    return statistics;
-}
-
-size_t fastMallocSize(const void* p)
-{
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    return Internal::fastMallocValidationHeader(const_cast<void*>(p))->m_size;
-#elif OS(DARWIN)
-    return malloc_size(p);
-#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;
-#endif
-}
-
-} // namespace WTF
-
-#if OS(DARWIN)
-// This symbol is present in the JavaScriptCore exports file even when FastMalloc is disabled.
-// It will never be used in this case, so it's type and value are less interesting than its presence.
-extern "C" const int jscore_fastmalloc_introspection = 0;
-#endif
-
-#else // FORCE_SYSTEM_MALLOC
-
-#if HAVE(STDINT_H)
-#include <stdint.h>
-#elif HAVE(INTTYPES_H)
-#include <inttypes.h>
-#else
-#include <sys/types.h>
-#endif
-
-#include "AlwaysInline.h"
-#include "Assertions.h"
-#include "TCPackedCache.h"
-#include "TCPageMap.h"
-#include "TCSpinLock.h"
-#include "TCSystemAlloc.h"
-#include <algorithm>
-#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(WINDOWS)
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#endif
-
-#ifdef WTF_CHANGES
-
-#if OS(DARWIN)
-#include "MallocZoneSupport.h"
-#include <wtf/HashSet.h>
-#include <wtf/Vector.h>
-#endif
-
-#if HAVE(HEADER_DETECTION_H)
-#include "HeaderDetection.h"
-#endif
-
-#if HAVE(DISPATCH_H)
-#include <dispatch/dispatch.h>
-#endif
-
-#if HAVE(PTHREAD_MACHDEP_H)
-#include <System/pthread_machdep.h>
-
-#if defined(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0)
-#define WTF_USE_PTHREAD_GETSPECIFIC_DIRECT 1
-#endif
-#endif
-
-#ifndef PRIuS
-#define PRIuS "zu"
-#endif
-
-// Calling pthread_getspecific through a global function pointer is faster than a normal
-// 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 OS(DARWIN)
-#if !USE(PTHREAD_GETSPECIFIC_DIRECT)
-static void* (*pthread_getspecific_function_pointer)(pthread_key_t) = pthread_getspecific;
-#define pthread_getspecific(key) pthread_getspecific_function_pointer(key)
-#else
-#define pthread_getspecific(key) _pthread_getspecific_direct(key)
-#define pthread_setspecific(key, val) _pthread_setspecific_direct(key, (val))
-#endif
-#endif
-
-#define DEFINE_VARIABLE(type, name, value, meaning) \
-  namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead {  \
-  type FLAGS_##name(value);                                \
-  char FLAGS_no##name;                                                        \
-  }                                                                           \
-  using FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead::FLAGS_##name
-  
-#define DEFINE_int64(name, value, meaning) \
-  DEFINE_VARIABLE(int64_t, name, value, meaning)
-  
-#define DEFINE_double(name, value, meaning) \
-  DEFINE_VARIABLE(double, name, value, meaning)
-
-namespace WTF {
-
-#define malloc fastMalloc
-#define calloc fastCalloc
-#define free fastFree
-#define realloc fastRealloc
-
-#define MESSAGE LOG_ERROR
-#define CHECK_CONDITION ASSERT
-
-#if OS(DARWIN)
-struct Span;
-class TCMalloc_Central_FreeListPadded;
-class TCMalloc_PageHeap;
-class TCMalloc_ThreadCache;
-template <typename T> class PageHeapAllocator;
-
-class FastMallocZone {
-public:
-    static void init();
-
-    static kern_return_t enumerate(task_t, void*, unsigned typeMmask, vm_address_t zoneAddress, memory_reader_t, vm_range_recorder_t);
-    static size_t goodSize(malloc_zone_t*, size_t size) { return size; }
-    static boolean_t check(malloc_zone_t*) { return true; }
-    static void  print(malloc_zone_t*, boolean_t) { }
-    static void log(malloc_zone_t*, void*) { }
-    static void forceLock(malloc_zone_t*) { }
-    static void forceUnlock(malloc_zone_t*) { }
-    static void statistics(malloc_zone_t*, malloc_statistics_t* stats) { memset(stats, 0, sizeof(malloc_statistics_t)); }
-
-private:
-    FastMallocZone(TCMalloc_PageHeap*, TCMalloc_ThreadCache**, TCMalloc_Central_FreeListPadded*, PageHeapAllocator<Span>*, PageHeapAllocator<TCMalloc_ThreadCache>*);
-    static size_t size(malloc_zone_t*, const void*);
-    static void* zoneMalloc(malloc_zone_t*, size_t);
-    static void* zoneCalloc(malloc_zone_t*, size_t numItems, size_t size);
-    static void zoneFree(malloc_zone_t*, void*);
-    static void* zoneRealloc(malloc_zone_t*, void*, size_t);
-    static void* zoneValloc(malloc_zone_t*, size_t) { LOG_ERROR("valloc is not supported"); return 0; }
-    static void zoneDestroy(malloc_zone_t*) { }
-
-    malloc_zone_t m_zone;
-    TCMalloc_PageHeap* m_pageHeap;
-    TCMalloc_ThreadCache** m_threadHeaps;
-    TCMalloc_Central_FreeListPadded* m_centralCaches;
-    PageHeapAllocator<Span>* m_spanAllocator;
-    PageHeapAllocator<TCMalloc_ThreadCache>* m_pageHeapAllocator;
-};
-
-#endif
-
-#endif
-
-#ifndef WTF_CHANGES
-// This #ifdef should almost never be set.  Set NO_TCMALLOC_SAMPLES if
-// you're porting to a system where you really can't get a stacktrace.
-#ifdef NO_TCMALLOC_SAMPLES
-// We use #define so code compiles even if you #include stacktrace.h somehow.
-# define GetStackTrace(stack, depth, skip)  (0)
-#else
-# include <google/stacktrace.h>
-#endif
-#endif
-
-// Even if we have support for thread-local storage in the compiler
-// and linker, the OS may not support it.  We need to check that at
-// runtime.  Right now, we have to keep a manual set of "bad" OSes.
-#if defined(HAVE_TLS)
-  static bool kernel_supports_tls = false;      // be conservative
-  static inline bool KernelSupportsTLS() {
-    return kernel_supports_tls;
-  }
-# if !HAVE_DECL_UNAME   // if too old for uname, probably too old for TLS
-    static void CheckIfKernelSupportsTLS() {
-      kernel_supports_tls = false;
-    }
-# else
-#   include <sys/utsname.h>    // DECL_UNAME checked for <sys/utsname.h> too
-    static void CheckIfKernelSupportsTLS() {
-      struct utsname buf;
-      if (uname(&buf) != 0) {   // should be impossible
-        MESSAGE("uname failed assuming no TLS support (errno=%d)\n", errno);
-        kernel_supports_tls = false;
-      } else if (strcasecmp(buf.sysname, "linux") == 0) {
-        // The linux case: the first kernel to support TLS was 2.6.0
-        if (buf.release[0] < '2' && buf.release[1] == '.')    // 0.x or 1.x
-          kernel_supports_tls = false;
-        else if (buf.release[0] == '2' && buf.release[1] == '.' &&
-                 buf.release[2] >= '0' && buf.release[2] < '6' &&
-                 buf.release[3] == '.')                       // 2.0 - 2.5
-          kernel_supports_tls = false;
-        else
-          kernel_supports_tls = true;
-      } else {        // some other kernel, we'll be optimisitic
-        kernel_supports_tls = true;
-      }
-      // TODO(csilvers): VLOG(1) the tls status once we support RAW_VLOG
-    }
-#  endif  // HAVE_DECL_UNAME
-#endif    // HAVE_TLS
-
-// __THROW is defined in glibc systems.  It means, counter-intuitively,
-// "This function will never throw an exception."  It's an optional
-// optimization tool, but we may need to use it to match glibc prototypes.
-#ifndef __THROW    // I guess we're not on a glibc system
-# define __THROW   // __THROW is just an optimization, so ok to make it ""
-#endif
-
-//-------------------------------------------------------------------
-// Configuration
-//-------------------------------------------------------------------
-
-// Not all possible combinations of the following parameters make
-// sense.  In particular, if kMaxSize increases, you may have to
-// increase kNumClasses as well.
-static const size_t kPageShift  = 12;
-static const size_t kPageSize   = 1 << kPageShift;
-static const size_t kMaxSize    = 8u * kPageSize;
-static const size_t kAlignShift = 3;
-static const size_t kAlignment  = 1 << kAlignShift;
-static const size_t kNumClasses = 68;
-
-// Allocates a big block of memory for the pagemap once we reach more than
-// 128MB
-static const size_t kPageMapBigAllocationThreshold = 128 << 20;
-
-// Minimum number of pages to fetch from system at a time.  Must be
-// significantly bigger than kPageSize to amortize system-call
-// overhead, and also to reduce external fragementation.  Also, we
-// should keep this value big because various incarnations of Linux
-// have small limits on the number of mmap() regions per
-// address-space.
-static const size_t kMinSystemAlloc = 1 << (20 - kPageShift);
-
-// Number of objects to move between a per-thread list and a central
-// list in one shot.  We want this to be not too small so we can
-// amortize the lock overhead for accessing the central list.  Making
-// it too big may temporarily cause unnecessary memory wastage in the
-// per-thread free list until the scavenger cleans up the list.
-static int num_objects_to_move[kNumClasses];
-
-// Maximum length we allow a per-thread free-list to have before we
-// move objects from it into the corresponding central free-list.  We
-// want this big to avoid locking the central free-list too often.  It
-// should not hurt to make this list somewhat big because the
-// scavenging code will shrink it down when its contents are not in use.
-static const int kMaxFreeListLength = 256;
-
-// Lower and upper bounds on the per-thread cache sizes
-static const size_t kMinThreadCacheSize = kMaxSize * 2;
-static const size_t kMaxThreadCacheSize = 512 * 1024;
-
-// Default bound on the total amount of thread caches
-static const size_t kDefaultOverallThreadCacheSize = 16 << 20;
-
-// For all span-lengths < kMaxPages we keep an exact-size list.
-// REQUIRED: kMaxPages >= kMinSystemAlloc;
-static const size_t kMaxPages = kMinSystemAlloc;
-
-/* The smallest prime > 2^n */
-static int primes_list[] = {
-    // Small values might cause high rates of sampling
-    // and hence commented out.
-    // 2, 5, 11, 17, 37, 67, 131, 257,
-    // 521, 1031, 2053, 4099, 8209, 16411,
-    32771, 65537, 131101, 262147, 524309, 1048583,
-    2097169, 4194319, 8388617, 16777259, 33554467 };
-
-// Twice the approximate gap between sampling actions.
-// I.e., we take one sample approximately once every
-//      tcmalloc_sample_parameter/2
-// bytes of allocation, i.e., ~ once every 128KB.
-// Must be a prime number.
-#ifdef NO_TCMALLOC_SAMPLES
-DEFINE_int64(tcmalloc_sample_parameter, 0,
-             "Unused: code is compiled with NO_TCMALLOC_SAMPLES");
-static size_t sample_period = 0;
-#else
-DEFINE_int64(tcmalloc_sample_parameter, 262147,
-         "Twice the approximate gap between sampling actions."
-         " Must be a prime number. Otherwise will be rounded up to a "
-         " larger prime number");
-static size_t sample_period = 262147;
-#endif
-
-// Protects sample_period above
-static SpinLock sample_period_lock = SPINLOCK_INITIALIZER;
-
-// Parameters for controlling how fast memory is returned to the OS.
-
-DEFINE_double(tcmalloc_release_rate, 1,
-              "Rate at which we release unused memory to the system.  "
-              "Zero means we never release memory back to the system.  "
-              "Increase this flag to return memory faster; decrease it "
-              "to return memory slower.  Reasonable rates are in the "
-              "range [0,10]");
-
-//-------------------------------------------------------------------
-// Mapping from size to size_class and vice versa
-//-------------------------------------------------------------------
-
-// Sizes <= 1024 have an alignment >= 8.  So for such sizes we have an
-// array indexed by ceil(size/8).  Sizes > 1024 have an alignment >= 128.
-// So for these larger sizes we have an array indexed by ceil(size/128).
-//
-// We flatten both logical arrays into one physical array and use
-// arithmetic to compute an appropriate index.  The constants used by
-// ClassIndex() were selected to make the flattening work.
-//
-// Examples:
-//   Size       Expression                      Index
-//   -------------------------------------------------------
-//   0          (0 + 7) / 8                     0
-//   1          (1 + 7) / 8                     1
-//   ...
-//   1024       (1024 + 7) / 8                  128
-//   1025       (1025 + 127 + (120<<7)) / 128   129
-//   ...
-//   32768      (32768 + 127 + (120<<7)) / 128  376
-static const size_t kMaxSmallSize = 1024;
-static const int shift_amount[2] = { 3, 7 };  // For divides by 8 or 128
-static const int add_amount[2] = { 7, 127 + (120 << 7) };
-static unsigned char class_array[377];
-
-// Compute index of the class_array[] entry for a given size
-static inline int ClassIndex(size_t s) {
-  const int i = (s > kMaxSmallSize);
-  return static_cast<int>((s + add_amount[i]) >> shift_amount[i]);
-}
-
-// Mapping from size class to max size storable in that class
-static size_t class_to_size[kNumClasses];
-
-// Mapping from size class to number of pages to allocate at a time
-static size_t class_to_pages[kNumClasses];
-
-// TransferCache is used to cache transfers of num_objects_to_move[size_class]
-// back and forth between thread caches and the central cache for a given size
-// class.
-struct TCEntry {
-  void *head;  // Head of chain of objects.
-  void *tail;  // Tail of chain of objects.
-};
-// A central cache freelist can have anywhere from 0 to kNumTransferEntries
-// slots to put link list chains into.  To keep memory usage bounded the total
-// number of TCEntries across size classes is fixed.  Currently each size
-// class is initially given one TCEntry which also means that the maximum any
-// one class can have is kNumClasses.
-static const int kNumTransferEntries = kNumClasses;
-
-// Note: the following only works for "n"s that fit in 32-bits, but
-// that is fine since we only use it for small sizes.
-static inline int LgFloor(size_t n) {
-  int log = 0;
-  for (int i = 4; i >= 0; --i) {
-    int shift = (1 << i);
-    size_t x = n >> shift;
-    if (x != 0) {
-      n = x;
-      log += shift;
-    }
-  }
-  ASSERT(n == 1);
-  return log;
-}
-
-// Some very basic linked list functions for dealing with using void * as
-// storage.
-
-static inline void *SLL_Next(void *t) {
-  return *(reinterpret_cast<void**>(t));
-}
-
-static inline void SLL_SetNext(void *t, void *n) {
-  *(reinterpret_cast<void**>(t)) = n;
-}
-
-static inline void SLL_Push(void **list, void *element) {
-  SLL_SetNext(element, *list);
-  *list = element;
-}
-
-static inline void *SLL_Pop(void **list) {
-  void *result = *list;
-  *list = SLL_Next(*list);
-  return result;
-}
-
-
-// Remove N elements from a linked list to which head points.  head will be
-// modified to point to the new head.  start and end will point to the first
-// and last nodes of the range.  Note that end will point to NULL after this
-// function is called.
-static inline void SLL_PopRange(void **head, int N, void **start, void **end) {
-  if (N == 0) {
-    *start = NULL;
-    *end = NULL;
-    return;
-  }
-
-  void *tmp = *head;
-  for (int i = 1; i < N; ++i) {
-    tmp = SLL_Next(tmp);
-  }
-
-  *start = *head;
-  *end = tmp;
-  *head = SLL_Next(tmp);
-  // Unlink range from list.
-  SLL_SetNext(tmp, NULL);
-}
-
-static inline void SLL_PushRange(void **head, void *start, void *end) {
-  if (!start) return;
-  SLL_SetNext(end, *head);
-  *head = start;
-}
-
-static inline size_t SLL_Size(void *head) {
-  int count = 0;
-  while (head) {
-    count++;
-    head = SLL_Next(head);
-  }
-  return count;
-}
-
-// Setup helper functions.
-
-static ALWAYS_INLINE size_t SizeClass(size_t size) {
-  return class_array[ClassIndex(size)];
-}
-
-// Get the byte-size for a specified class
-static ALWAYS_INLINE size_t ByteSizeForClass(size_t cl) {
-  return class_to_size[cl];
-}
-static int NumMoveSize(size_t size) {
-  if (size == 0) return 0;
-  // Use approx 64k transfers between thread and central caches.
-  int num = static_cast<int>(64.0 * 1024.0 / size);
-  if (num < 2) num = 2;
-  // Clamp well below kMaxFreeListLength to avoid ping pong between central
-  // and thread caches.
-  if (num > static_cast<int>(0.8 * kMaxFreeListLength))
-    num = static_cast<int>(0.8 * kMaxFreeListLength);
-
-  // Also, avoid bringing in too many objects into small object free
-  // lists.  There are lots of such lists, and if we allow each one to
-  // fetch too many at a time, we end up having to scavenge too often
-  // (especially when there are lots of threads and each thread gets a
-  // small allowance for its thread cache).
-  //
-  // TODO: Make thread cache free list sizes dynamic so that we do not
-  // have to equally divide a fixed resource amongst lots of threads.
-  if (num > 32) num = 32;
-
-  return num;
-}
-
-// Initialize the mapping arrays
-static void InitSizeClasses() {
-  // Do some sanity checking on add_amount[]/shift_amount[]/class_array[]
-  if (ClassIndex(0) < 0) {
-    MESSAGE("Invalid class index %d for size 0\n", ClassIndex(0));
-    CRASH();
-  }
-  if (static_cast<size_t>(ClassIndex(kMaxSize)) >= sizeof(class_array)) {
-    MESSAGE("Invalid class index %d for kMaxSize\n", ClassIndex(kMaxSize));
-    CRASH();
-  }
-
-  // Compute the size classes we want to use
-  size_t sc = 1;   // Next size class to assign
-  unsigned char alignshift = kAlignShift;
-  int last_lg = -1;
-  for (size_t size = kAlignment; size <= kMaxSize; size += (1 << alignshift)) {
-    int lg = LgFloor(size);
-    if (lg > last_lg) {
-      // Increase alignment every so often.
-      //
-      // Since we double the alignment every time size doubles and
-      // size >= 128, this means that space wasted due to alignment is
-      // at most 16/128 i.e., 12.5%.  Plus we cap the alignment at 256
-      // bytes, so the space wasted as a percentage starts falling for
-      // sizes > 2K.
-      if ((lg >= 7) && (alignshift < 8)) {
-        alignshift++;
-      }
-      last_lg = lg;
-    }
-
-    // Allocate enough pages so leftover is less than 1/8 of total.
-    // This bounds wasted space to at most 12.5%.
-    size_t psize = kPageSize;
-    while ((psize % size) > (psize >> 3)) {
-      psize += kPageSize;
-    }
-    const size_t my_pages = psize >> kPageShift;
-
-    if (sc > 1 && my_pages == class_to_pages[sc-1]) {
-      // See if we can merge this into the previous class without
-      // increasing the fragmentation of the previous class.
-      const size_t my_objects = (my_pages << kPageShift) / size;
-      const size_t prev_objects = (class_to_pages[sc-1] << kPageShift)
-                                  / class_to_size[sc-1];
-      if (my_objects == prev_objects) {
-        // Adjust last class to include this size
-        class_to_size[sc-1] = size;
-        continue;
-      }
-    }
-
-    // Add new class
-    class_to_pages[sc] = my_pages;
-    class_to_size[sc] = size;
-    sc++;
-  }
-  if (sc != kNumClasses) {
-    MESSAGE("wrong number of size classes: found %" PRIuS " instead of %d\n",
-            sc, int(kNumClasses));
-    CRASH();
-  }
-
-  // Initialize the mapping arrays
-  int next_size = 0;
-  for (unsigned char c = 1; c < kNumClasses; c++) {
-    const size_t max_size_in_class = class_to_size[c];
-    for (size_t s = next_size; s <= max_size_in_class; s += kAlignment) {
-      class_array[ClassIndex(s)] = c;
-    }
-    next_size = static_cast<int>(max_size_in_class + kAlignment);
-  }
-
-  // Double-check sizes just to be safe
-  for (size_t size = 0; size <= kMaxSize; size++) {
-    const size_t sc = SizeClass(size);
-    if (sc == 0) {
-      MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size);
-      CRASH();
-    }
-    if (sc > 1 && size <= class_to_size[sc-1]) {
-      MESSAGE("Allocating unnecessarily large class %" PRIuS " for %" PRIuS
-              "\n", sc, size);
-      CRASH();
-    }
-    if (sc >= kNumClasses) {
-      MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size);
-      CRASH();
-    }
-    const size_t s = class_to_size[sc];
-    if (size > s) {
-     MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc);
-      CRASH();
-    }
-    if (s == 0) {
-      MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc);
-      CRASH();
-    }
-  }
-
-  // Initialize the num_objects_to_move array.
-  for (size_t cl = 1; cl  < kNumClasses; ++cl) {
-    num_objects_to_move[cl] = NumMoveSize(ByteSizeForClass(cl));
-  }
-
-#ifndef WTF_CHANGES
-  if (false) {
-    // Dump class sizes and maximum external wastage per size class
-    for (size_t cl = 1; cl  < kNumClasses; ++cl) {
-      const int alloc_size = class_to_pages[cl] << kPageShift;
-      const int alloc_objs = alloc_size / class_to_size[cl];
-      const int min_used = (class_to_size[cl-1] + 1) * alloc_objs;
-      const int max_waste = alloc_size - min_used;
-      MESSAGE("SC %3d [ %8d .. %8d ] from %8d ; %2.0f%% maxwaste\n",
-              int(cl),
-              int(class_to_size[cl-1] + 1),
-              int(class_to_size[cl]),
-              int(class_to_pages[cl] << kPageShift),
-              max_waste * 100.0 / alloc_size
-              );
-    }
-  }
-#endif
-}
-
-// -------------------------------------------------------------------------
-// Simple allocator for objects of a specified type.  External locking
-// is required before accessing one of these objects.
-// -------------------------------------------------------------------------
-
-// Metadata allocator -- keeps stats about how many bytes allocated
-static uint64_t metadata_system_bytes = 0;
-static void* MetaDataAlloc(size_t bytes) {
-  void* result = TCMalloc_SystemAlloc(bytes, 0);
-  if (result != NULL) {
-    metadata_system_bytes += bytes;
-  }
-  return result;
-}
-
-template <class T>
-class PageHeapAllocator {
- private:
-  // How much to allocate from system at a time
-  static const size_t kAllocIncrement = 32 << 10;
-
-  // Aligned size of T
-  static const size_t kAlignedSize
-  = (((sizeof(T) + kAlignment - 1) / kAlignment) * kAlignment);
-
-  // Free area from which to carve new objects
-  char* free_area_;
-  size_t free_avail_;
-
-  // Linked list of all regions allocated by this allocator
-  void* allocated_regions_;
-
-  // Free list of already carved objects
-  void* free_list_;
-
-  // Number of allocated but unfreed objects
-  int inuse_;
-
- public:
-  void Init() {
-    ASSERT(kAlignedSize <= kAllocIncrement);
-    inuse_ = 0;
-    allocated_regions_ = 0;
-    free_area_ = NULL;
-    free_avail_ = 0;
-    free_list_ = NULL;
-  }
-
-  T* New() {
-    // Consult free list
-    void* result;
-    if (free_list_ != NULL) {
-      result = free_list_;
-      free_list_ = *(reinterpret_cast<void**>(result));
-    } else {
-      if (free_avail_ < kAlignedSize) {
-        // Need more room
-        char* new_allocation = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement));
-        if (!new_allocation)
-          CRASH();
-
-        *reinterpret_cast_ptr<void**>(new_allocation) = allocated_regions_;
-        allocated_regions_ = new_allocation;
-        free_area_ = new_allocation + kAlignedSize;
-        free_avail_ = kAllocIncrement - kAlignedSize;
-      }
-      result = free_area_;
-      free_area_ += kAlignedSize;
-      free_avail_ -= kAlignedSize;
-    }
-    inuse_++;
-    return reinterpret_cast<T*>(result);
-  }
-
-  void Delete(T* p) {
-    *(reinterpret_cast<void**>(p)) = free_list_;
-    free_list_ = p;
-    inuse_--;
-  }
-
-  int inuse() const { return inuse_; }
-
-#if defined(WTF_CHANGES) && OS(DARWIN)
-  template <class Recorder>
-  void recordAdministrativeRegions(Recorder& recorder, const RemoteMemoryReader& reader)
-  {
-      for (void* adminAllocation = allocated_regions_; adminAllocation; adminAllocation = reader.nextEntryInLinkedList(reinterpret_cast<void**>(adminAllocation)))
-          recorder.recordRegion(reinterpret_cast<vm_address_t>(adminAllocation), kAllocIncrement);
-  }
-#endif
-};
-
-// -------------------------------------------------------------------------
-// Span - a contiguous run of pages
-// -------------------------------------------------------------------------
-
-// Type that can hold a page number
-typedef uintptr_t PageID;
-
-// Type that can hold the length of a run of pages
-typedef uintptr_t Length;
-
-static const Length kMaxValidPages = (~static_cast<Length>(0)) >> kPageShift;
-
-// Convert byte size into pages.  This won't overflow, but may return
-// an unreasonably large value if bytes is huge enough.
-static inline Length pages(size_t bytes) {
-  return (bytes >> kPageShift) +
-      ((bytes & (kPageSize - 1)) > 0 ? 1 : 0);
-}
-
-// Convert a user size into the number of bytes that will actually be
-// allocated
-static size_t AllocationSize(size_t bytes) {
-  if (bytes > kMaxSize) {
-    // Large object: we allocate an integral number of pages
-    ASSERT(bytes <= (kMaxValidPages << kPageShift));
-    return pages(bytes) << kPageShift;
-  } else {
-    // Small object: find the size class to which it belongs
-    return ByteSizeForClass(SizeClass(bytes));
-  }
-}
-
-// Information kept for a span (a contiguous run of pages).
-struct Span {
-  PageID        start;          // Starting page number
-  Length        length;         // Number of pages in span
-  Span*         next;           // Used when in link list
-  Span*         prev;           // Used when in link list
-  void*         objects;        // Linked list of free objects
-  unsigned int  free : 1;       // Is the span free
-#ifndef NO_TCMALLOC_SAMPLES
-  unsigned int  sample : 1;     // Sampled object?
-#endif
-  unsigned int  sizeclass : 8;  // Size-class for small objects (or 0)
-  unsigned int  refcount : 11;  // Number of non-free objects
-  bool decommitted : 1;
-
-#undef SPAN_HISTORY
-#ifdef SPAN_HISTORY
-  // For debugging, we can keep a log events per span
-  int nexthistory;
-  char history[64];
-  int value[64];
-#endif
-};
-
-#define ASSERT_SPAN_COMMITTED(span) ASSERT(!span->decommitted)
-
-#ifdef SPAN_HISTORY
-void Event(Span* span, char op, int v = 0) {
-  span->history[span->nexthistory] = op;
-  span->value[span->nexthistory] = v;
-  span->nexthistory++;
-  if (span->nexthistory == sizeof(span->history)) span->nexthistory = 0;
-}
-#else
-#define Event(s,o,v) ((void) 0)
-#endif
-
-// Allocator/deallocator for spans
-static PageHeapAllocator<Span> span_allocator;
-static Span* NewSpan(PageID p, Length len) {
-  Span* result = span_allocator.New();
-  memset(result, 0, sizeof(*result));
-  result->start = p;
-  result->length = len;
-#ifdef SPAN_HISTORY
-  result->nexthistory = 0;
-#endif
-  return result;
-}
-
-static inline void DeleteSpan(Span* span) {
-#ifndef NDEBUG
-  // In debug mode, trash the contents of deleted Spans
-  memset(span, 0x3f, sizeof(*span));
-#endif
-  span_allocator.Delete(span);
-}
-
-// -------------------------------------------------------------------------
-// Doubly linked list of spans.
-// -------------------------------------------------------------------------
-
-static inline void DLL_Init(Span* list) {
-  list->next = list;
-  list->prev = list;
-}
-
-static inline void DLL_Remove(Span* span) {
-  span->prev->next = span->next;
-  span->next->prev = span->prev;
-  span->prev = NULL;
-  span->next = NULL;
-}
-
-static ALWAYS_INLINE bool DLL_IsEmpty(const Span* list) {
-  return list->next == list;
-}
-
-static int DLL_Length(const Span* list) {
-  int result = 0;
-  for (Span* s = list->next; s != list; s = s->next) {
-    result++;
-  }
-  return result;
-}
-
-#if 0 /* Not needed at the moment -- causes compiler warnings if not used */
-static void DLL_Print(const char* label, const Span* list) {
-  MESSAGE("%-10s %p:", label, list);
-  for (const Span* s = list->next; s != list; s = s->next) {
-    MESSAGE(" <%p,%u,%u>", s, s->start, s->length);
-  }
-  MESSAGE("\n");
-}
-#endif
-
-static inline void DLL_Prepend(Span* list, Span* span) {
-  ASSERT(span->next == NULL);
-  ASSERT(span->prev == NULL);
-  span->next = list->next;
-  span->prev = list;
-  list->next->prev = span;
-  list->next = span;
-}
-
-// -------------------------------------------------------------------------
-// Stack traces kept for sampled allocations
-//   The following state is protected by pageheap_lock_.
-// -------------------------------------------------------------------------
-
-// size/depth are made the same size as a pointer so that some generic
-// code below can conveniently cast them back and forth to void*.
-static const int kMaxStackDepth = 31;
-struct StackTrace {
-  uintptr_t size;          // Size of object
-  uintptr_t depth;         // Number of PC values stored in array below
-  void*     stack[kMaxStackDepth];
-};
-static PageHeapAllocator<StackTrace> stacktrace_allocator;
-static Span sampled_objects;
-
-// -------------------------------------------------------------------------
-// Map from page-id to per-page data
-// -------------------------------------------------------------------------
-
-// We use PageMap2<> for 32-bit and PageMap3<> for 64-bit machines.
-// We also use a simple one-level cache for hot PageID-to-sizeclass mappings,
-// because sometimes the sizeclass is all the information we need.
-
-// Selector class -- general selector uses 3-level map
-template <int BITS> class MapSelector {
- public:
-  typedef TCMalloc_PageMap3<BITS-kPageShift> Type;
-  typedef PackedCache<BITS, uint64_t> CacheType;
-};
-
-#if defined(WTF_CHANGES)
-#if CPU(X86_64)
-// On all known X86-64 platforms, the upper 16 bits are always unused and therefore 
-// can be excluded from the PageMap key.
-// See http://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
-
-static const size_t kBitsUnusedOn64Bit = 16;
-#else
-static const size_t kBitsUnusedOn64Bit = 0;
-#endif
-
-// A three-level map for 64-bit machines
-template <> class MapSelector<64> {
- public:
-  typedef TCMalloc_PageMap3<64 - kPageShift - kBitsUnusedOn64Bit> Type;
-  typedef PackedCache<64, uint64_t> CacheType;
-};
-#endif
-
-// A two-level map for 32-bit machines
-template <> class MapSelector<32> {
- public:
-  typedef TCMalloc_PageMap2<32 - kPageShift> Type;
-  typedef PackedCache<32 - kPageShift, uint16_t> CacheType;
-};
-
-// -------------------------------------------------------------------------
-// Page-level allocator
-//  * Eager coalescing
-//
-// Heap for page-level allocation.  We allow allocating and freeing a
-// contiguous runs of pages (called a "span").
-// -------------------------------------------------------------------------
-
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-// The page heap maintains a free list for spans that are no longer in use by
-// the central cache or any thread caches. We use a background thread to
-// periodically scan the free list and release a percentage of it back to the OS.
-
-// If free_committed_pages_ exceeds kMinimumFreeCommittedPageCount, the
-// background thread:
-//     - wakes up
-//     - pauses for kScavengeDelayInSeconds
-//     - returns to the OS a percentage of the memory that remained unused during
-//       that pause (kScavengePercentage * min_free_committed_pages_since_last_scavenge_)
-// The goal of this strategy is to reduce memory pressure in a timely fashion
-// while avoiding thrashing the OS allocator.
-
-// Time delay before the page heap scavenger will consider returning pages to
-// the OS.
-static const int kScavengeDelayInSeconds = 2;
-
-// Approximate percentage of free committed pages to return to the OS in one
-// scavenge.
-static const float kScavengePercentage = .5f;
-
-// number of span lists to keep spans in when memory is returned.
-static const int kMinSpanListsWithSpans = 32;
-
-// Number of free committed pages that we want to keep around.  The minimum number of pages used when there
-// is 1 span in each of the first kMinSpanListsWithSpans spanlists.  Currently 528 pages.
-static const size_t kMinimumFreeCommittedPageCount = kMinSpanListsWithSpans * ((1.0f+kMinSpanListsWithSpans) / 2.0f);
-
-#endif
-
-static SpinLock pageheap_lock = SPINLOCK_INITIALIZER;
-
-class TCMalloc_PageHeap {
- public:
-  void init();
-
-  // Allocate a run of "n" pages.  Returns zero if out of memory.
-  Span* New(Length n);
-
-  // Delete the span "[p, p+n-1]".
-  // REQUIRES: span was returned by earlier call to New() and
-  //           has not yet been deleted.
-  void Delete(Span* span);
-
-  // Mark an allocated span as being used for small objects of the
-  // specified size-class.
-  // REQUIRES: span was returned by an earlier call to New()
-  //           and has not yet been deleted.
-  void RegisterSizeClass(Span* span, size_t sc);
-
-  // Split an allocated span into two spans: one of length "n" pages
-  // followed by another span of length "span->length - n" pages.
-  // Modifies "*span" to point to the first span of length "n" pages.
-  // Returns a pointer to the second span.
-  //
-  // REQUIRES: "0 < n < span->length"
-  // REQUIRES: !span->free
-  // REQUIRES: span->sizeclass == 0
-  Span* Split(Span* span, Length n);
-
-  // Return the descriptor for the specified page.
-  inline Span* GetDescriptor(PageID p) const {
-    return reinterpret_cast<Span*>(pagemap_.get(p));
-  }
-
-#ifdef WTF_CHANGES
-  inline Span* GetDescriptorEnsureSafe(PageID p)
-  {
-      pagemap_.Ensure(p, 1);
-      return GetDescriptor(p);
-  }
-    
-  size_t ReturnedBytes() const;
-#endif
-
-  // Dump state to stderr
-#ifndef WTF_CHANGES
-  void Dump(TCMalloc_Printer* out);
-#endif
-
-  // Return number of bytes allocated from system
-  inline uint64_t SystemBytes() const { return system_bytes_; }
-
-  // Return number of free bytes in heap
-  uint64_t FreeBytes() const {
-    return (static_cast<uint64_t>(free_pages_) << kPageShift);
-  }
-
-  bool Check();
-  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();
-
-  // Return 0 if we have no information, or else the correct sizeclass for p.
-  // Reads and writes to pagemap_cache_ do not require locking.
-  // The entries are 64 bits on 64-bit hardware and 16 bits on
-  // 32-bit hardware, and we don't mind raciness as long as each read of
-  // an entry yields a valid entry, not a partially updated entry.
-  size_t GetSizeClassIfCached(PageID p) const {
-    return pagemap_cache_.GetOrDefault(p, 0);
-  }
-  void CacheSizeClass(PageID p, size_t cl) const { pagemap_cache_.Put(p, cl); }
-
- private:
-  // Pick the appropriate map and cache types based on pointer size
-  typedef MapSelector<8*sizeof(uintptr_t)>::Type PageMap;
-  typedef MapSelector<8*sizeof(uintptr_t)>::CacheType PageMapCache;
-  PageMap pagemap_;
-  mutable PageMapCache pagemap_cache_;
-
-  // We segregate spans of a given size into two circular linked
-  // lists: one for normal spans, and one for spans whose memory
-  // has been returned to the system.
-  struct SpanList {
-    Span        normal;
-    Span        returned;
-  };
-
-  // List of free spans of length >= kMaxPages
-  SpanList large_;
-
-  // Array mapping from span length to a doubly linked list of free spans
-  SpanList free_[kMaxPages];
-
-  // Number of pages kept in free lists
-  uintptr_t free_pages_;
-
-  // Bytes allocated from system
-  uint64_t system_bytes_;
-
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-  // Number of pages kept in free lists that are still committed.
-  Length free_committed_pages_;
-
-  // Minimum number of free committed pages since last scavenge. (Can be 0 if
-  // we've committed new pages since the last scavenge.)
-  Length min_free_committed_pages_since_last_scavenge_;
-#endif
-
-  bool GrowHeap(Length n);
-
-  // REQUIRES   span->length >= n
-  // Remove span from its free list, and move any leftover part of
-  // span into appropriate free lists.  Also update "span" to have
-  // length exactly "n" and mark it as non-free so it can be returned
-  // to the client.
-  //
-  // "released" is true iff "span" was found on a "returned" list.
-  void Carve(Span* span, Length n, bool released);
-
-  void RecordSpan(Span* span) {
-    pagemap_.set(span->start, span);
-    if (span->length > 1) {
-      pagemap_.set(span->start + span->length - 1, span);
-    }
-  }
-  
-    // Allocate a large span of length == n.  If successful, returns a
-  // span of exactly the specified length.  Else, returns NULL.
-  Span* AllocLarge(Length n);
-
-#if !USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-  // Incrementally release some memory to the system.
-  // IncrementalScavenge(n) is called whenever n pages are freed.
-  void IncrementalScavenge(Length n);
-#endif
-
-  // Number of pages to deallocate before doing more scavenging
-  int64_t scavenge_counter_;
-
-  // Index of last free list we scavenged
-  size_t scavenge_index_;
-  
-#if defined(WTF_CHANGES) && OS(DARWIN)
-  friend class FastMallocZone;
-#endif
-
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-  void initializeScavenger();
-  ALWAYS_INLINE void signalScavenger();
-  void scavenge();
-  ALWAYS_INLINE bool shouldScavenge() const;
-
-#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();
-
-  // Keeps track of whether the background thread is actively scavenging memory every kScavengeDelayInSeconds, or
-  // it's blocked waiting for more pages to be deleted.
-  bool m_scavengeThreadActive;
-
-  pthread_mutex_t m_scavengeMutex;
-  pthread_cond_t m_scavengeCondition;
-#endif
-
-#endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-};
-
-void TCMalloc_PageHeap::init()
-{
-  pagemap_.init(MetaDataAlloc);
-  pagemap_cache_ = PageMapCache(0);
-  free_pages_ = 0;
-  system_bytes_ = 0;
-
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-  free_committed_pages_ = 0;
-  min_free_committed_pages_since_last_scavenge_ = 0;
-#endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-
-  scavenge_counter_ = 0;
-  // Start scavenging at kMaxPages list
-  scavenge_index_ = kMaxPages-1;
-  COMPILE_ASSERT(kNumClasses <= (1 << PageMapCache::kValuebits), valuebits);
-  DLL_Init(&large_.normal);
-  DLL_Init(&large_.returned);
-  for (size_t i = 0; i < kMaxPages; i++) {
-    DLL_Init(&free_[i].normal);
-    DLL_Init(&free_[i].returned);
-  }
-
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-  initializeScavenger();
-#endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-}
-
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-
-#if HAVE(DISPATCH_H)
-
-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_scavengingSuspended = true;
-}
-
-ALWAYS_INLINE bool TCMalloc_PageHeap::isScavengerSuspended()
-{
-    ASSERT(pageheap_lock.IsHeld());
-    return m_scavengingSuspended;
-}
-
-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()
-{
-    ASSERT(IsHeld(pageheap_lock));
-    HANDLE scavengeQueueTimer = m_scavengeQueueTimer;
-    m_scavengeQueueTimer = 0;
-    DeleteTimerQueueTimer(0, scavengeQueueTimer, 0);
-}
-
-#else
-
-void TCMalloc_PageHeap::initializeScavenger()
-{
-    // 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()
-{
-    // 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
-
-void TCMalloc_PageHeap::scavenge()
-{
-    size_t pagesToRelease = min_free_committed_pages_since_last_scavenge_ * kScavengePercentage;
-    size_t targetPageCount = std::max<size_t>(kMinimumFreeCommittedPageCount, free_committed_pages_ - pagesToRelease);
-
-    Length lastFreeCommittedPages = free_committed_pages_;
-    while (free_committed_pages_ > targetPageCount) {
-        ASSERT(Check());
-        for (int i = kMaxPages; i > 0 && free_committed_pages_ >= targetPageCount; i--) {
-            SpanList* slist = (static_cast<size_t>(i) == kMaxPages) ? &large_ : &free_[i];
-            // If the span size is bigger than kMinSpanListsWithSpans pages return all the spans in the list, else return all but 1 span.  
-            // Return only 50% of a spanlist at a time so spans of size 1 are not the only ones left.
-            size_t 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);
-                ASSERT(!s->decommitted);
-                if (!s->decommitted) {
-                    TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
-                                           static_cast<size_t>(s->length << kPageShift));
-                    ASSERT(free_committed_pages_ >= s->length);
-                    free_committed_pages_ -= s->length;
-                    s->decommitted = true;
-                }
-                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_;
-}
-
-ALWAYS_INLINE bool TCMalloc_PageHeap::shouldScavenge() const 
-{
-    return free_committed_pages_ > kMinimumFreeCommittedPageCount; 
-}
-
-#endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-
-inline Span* TCMalloc_PageHeap::New(Length n) {
-  ASSERT(Check());
-  ASSERT(n > 0);
-
-  // Find first size >= n that has a non-empty list
-  for (Length s = n; s < kMaxPages; s++) {
-    Span* ll = NULL;
-    bool released = false;
-    if (!DLL_IsEmpty(&free_[s].normal)) {
-      // Found normal span
-      ll = &free_[s].normal;
-    } else if (!DLL_IsEmpty(&free_[s].returned)) {
-      // Found returned span; reallocate it
-      ll = &free_[s].returned;
-      released = true;
-    } else {
-      // Keep looking in larger classes
-      continue;
-    }
-
-    Span* result = ll->next;
-    Carve(result, n, released);
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-    // The newly allocated memory is from a span that's in the normal span list (already committed).  Update the
-    // free committed pages count.
-    ASSERT(free_committed_pages_ >= n);
-    free_committed_pages_ -= n;
-    if (free_committed_pages_ < min_free_committed_pages_since_last_scavenge_) 
-      min_free_committed_pages_since_last_scavenge_ = free_committed_pages_;
-#endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-    ASSERT(Check());
-    free_pages_ -= n;
-    return result;
-  }
-
-  Span* result = AllocLarge(n);
-  if (result != NULL) {
-      ASSERT_SPAN_COMMITTED(result);
-      return result;
-  }
-
-  // Grow the heap and try again
-  if (!GrowHeap(n)) {
-    ASSERT(Check());
-    return NULL;
-  }
-
-  return AllocLarge(n);
-}
-
-Span* TCMalloc_PageHeap::AllocLarge(Length n) {
-  // find the best span (closest to n in size).
-  // The following loops implements address-ordered best-fit.
-  bool from_released = false;
-  Span *best = NULL;
-
-  // Search through normal list
-  for (Span* span = large_.normal.next;
-       span != &large_.normal;
-       span = span->next) {
-    if (span->length >= n) {
-      if ((best == NULL)
-          || (span->length < best->length)
-          || ((span->length == best->length) && (span->start < best->start))) {
-        best = span;
-        from_released = false;
-      }
-    }
-  }
-
-  // Search through released list in case it has a better fit
-  for (Span* span = large_.returned.next;
-       span != &large_.returned;
-       span = span->next) {
-    if (span->length >= n) {
-      if ((best == NULL)
-          || (span->length < best->length)
-          || ((span->length == best->length) && (span->start < best->start))) {
-        best = span;
-        from_released = true;
-      }
-    }
-  }
-
-  if (best != NULL) {
-    Carve(best, n, from_released);
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-    // The newly allocated memory is from a span that's in the normal span list (already committed).  Update the
-    // free committed pages count.
-    ASSERT(free_committed_pages_ >= n);
-    free_committed_pages_ -= n;
-    if (free_committed_pages_ < min_free_committed_pages_since_last_scavenge_)
-      min_free_committed_pages_since_last_scavenge_ = free_committed_pages_;
-#endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-    ASSERT(Check());
-    free_pages_ -= n;
-    return best;
-  }
-  return NULL;
-}
-
-Span* TCMalloc_PageHeap::Split(Span* span, Length n) {
-  ASSERT(0 < n);
-  ASSERT(n < span->length);
-  ASSERT(!span->free);
-  ASSERT(span->sizeclass == 0);
-  Event(span, 'T', n);
-
-  const Length extra = span->length - n;
-  Span* leftover = NewSpan(span->start + n, extra);
-  Event(leftover, 'U', extra);
-  RecordSpan(leftover);
-  pagemap_.set(span->start + n - 1, span); // Update map from pageid to span
-  span->length = n;
-
-  return leftover;
-}
-
-inline void TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) {
-  ASSERT(n > 0);
-  DLL_Remove(span);
-  span->free = 0;
-  Event(span, 'A', n);
-
-  if (released) {
-    // If the span chosen to carve from is decommited, commit the entire span at once to avoid committing spans 1 page at a time.
-    ASSERT(span->decommitted);
-    TCMalloc_SystemCommit(reinterpret_cast<void*>(span->start << kPageShift), static_cast<size_t>(span->length << kPageShift));
-    span->decommitted = false;
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-    free_committed_pages_ += span->length;
-#endif
-  }
-  
-  const int extra = static_cast<int>(span->length - n);
-  ASSERT(extra >= 0);
-  if (extra > 0) {
-    Span* leftover = NewSpan(span->start + n, extra);
-    leftover->free = 1;
-    leftover->decommitted = false;
-    Event(leftover, 'S', extra);
-    RecordSpan(leftover);
-
-    // Place leftover span on appropriate free list
-    SpanList* listpair = (static_cast<size_t>(extra) < kMaxPages) ? &free_[extra] : &large_;
-    Span* dst = &listpair->normal;
-    DLL_Prepend(dst, leftover);
-
-    span->length = n;
-    pagemap_.set(span->start + n - 1, span);
-  }
-}
-
-static ALWAYS_INLINE void mergeDecommittedStates(Span* destination, Span* other)
-{
-    if (destination->decommitted && !other->decommitted) {
-        TCMalloc_SystemRelease(reinterpret_cast<void*>(other->start << kPageShift),
-                               static_cast<size_t>(other->length << kPageShift));
-    } else if (other->decommitted && !destination->decommitted) {
-        TCMalloc_SystemRelease(reinterpret_cast<void*>(destination->start << kPageShift),
-                               static_cast<size_t>(destination->length << kPageShift));
-        destination->decommitted = true;
-    }
-}
-
-inline void TCMalloc_PageHeap::Delete(Span* span) {
-  ASSERT(Check());
-  ASSERT(!span->free);
-  ASSERT(span->length > 0);
-  ASSERT(GetDescriptor(span->start) == span);
-  ASSERT(GetDescriptor(span->start + span->length - 1) == span);
-  span->sizeclass = 0;
-#ifndef NO_TCMALLOC_SAMPLES
-  span->sample = 0;
-#endif
-
-  // Coalesce -- we guarantee that "p" != 0, so no bounds checking
-  // necessary.  We do not bother resetting the stale pagemap
-  // entries for the pieces we are merging together because we only
-  // care about the pagemap entries for the boundaries.
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-  // Track the total size of the neighboring free spans that are committed.
-  Length neighboringCommittedSpansLength = 0;
-#endif
-  const PageID p = span->start;
-  const Length n = span->length;
-  Span* prev = GetDescriptor(p-1);
-  if (prev != NULL && prev->free) {
-    // Merge preceding span into this span
-    ASSERT(prev->start + prev->length == p);
-    const Length len = prev->length;
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-    if (!prev->decommitted)
-        neighboringCommittedSpansLength += len;
-#endif
-    mergeDecommittedStates(span, prev);
-    DLL_Remove(prev);
-    DeleteSpan(prev);
-    span->start -= len;
-    span->length += len;
-    pagemap_.set(span->start, span);
-    Event(span, 'L', len);
-  }
-  Span* next = GetDescriptor(p+n);
-  if (next != NULL && next->free) {
-    // Merge next span into this span
-    ASSERT(next->start == p+n);
-    const Length len = next->length;
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-    if (!next->decommitted)
-        neighboringCommittedSpansLength += len;
-#endif
-    mergeDecommittedStates(span, next);
-    DLL_Remove(next);
-    DeleteSpan(next);
-    span->length += len;
-    pagemap_.set(span->start + span->length - 1, span);
-    Event(span, 'R', len);
-  }
-
-  Event(span, 'D', span->length);
-  span->free = 1;
-  if (span->decommitted) {
-    if (span->length < kMaxPages)
-      DLL_Prepend(&free_[span->length].returned, span);
-    else
-      DLL_Prepend(&large_.returned, span);
-  } else {
-    if (span->length < kMaxPages)
-      DLL_Prepend(&free_[span->length].normal, span);
-    else
-      DLL_Prepend(&large_.normal, span);
-  }
-  free_pages_ += n;
-
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-  if (span->decommitted) {
-      // If the merged span is decommitted, that means we decommitted any neighboring spans that were
-      // committed.  Update the free committed pages count.
-      free_committed_pages_ -= neighboringCommittedSpansLength;
-      if (free_committed_pages_ < min_free_committed_pages_since_last_scavenge_)
-            min_free_committed_pages_since_last_scavenge_ = free_committed_pages_;
-  } else {
-      // If the merged span remains committed, add the deleted span's size to the free committed pages count.
-      free_committed_pages_ += n;
-  }
-
-  // Make sure the scavenge thread becomes active if we have enough freed pages to release some back to the system.
-  signalScavenger();
-#else
-  IncrementalScavenge(n);
-#endif
-
-  ASSERT(Check());
-}
-
-#if !USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-void TCMalloc_PageHeap::IncrementalScavenge(Length n) {
-  // Fast path; not yet time to release memory
-  scavenge_counter_ -= n;
-  if (scavenge_counter_ >= 0) return;  // Not yet time to scavenge
-
-  static const size_t kDefaultReleaseDelay = 64;
-
-  // Find index of free list to scavenge
-  size_t index = scavenge_index_ + 1;
-  for (size_t i = 0; i < kMaxPages+1; i++) {
-    if (index > kMaxPages) index = 0;
-    SpanList* slist = (index == kMaxPages) ? &large_ : &free_[index];
-    if (!DLL_IsEmpty(&slist->normal)) {
-      // Release the last span on the normal portion of this list
-      Span* s = slist->normal.prev;
-      DLL_Remove(s);
-      TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
-                             static_cast<size_t>(s->length << kPageShift));
-      s->decommitted = true;
-      DLL_Prepend(&slist->returned, s);
-
-      scavenge_counter_ = std::max<size_t>(16UL, std::min<size_t>(kDefaultReleaseDelay, kDefaultReleaseDelay - (free_pages_ / kDefaultReleaseDelay)));
-
-      if (index == kMaxPages && !DLL_IsEmpty(&slist->normal))
-        scavenge_index_ = index - 1;
-      else
-        scavenge_index_ = index;
-      return;
-    }
-    index++;
-  }
-
-  // Nothing to scavenge, delay for a while
-  scavenge_counter_ = kDefaultReleaseDelay;
-}
-#endif
-
-void TCMalloc_PageHeap::RegisterSizeClass(Span* span, size_t sc) {
-  // Associate span object with all interior pages as well
-  ASSERT(!span->free);
-  ASSERT(GetDescriptor(span->start) == span);
-  ASSERT(GetDescriptor(span->start+span->length-1) == span);
-  Event(span, 'C', sc);
-  span->sizeclass = static_cast<unsigned int>(sc);
-  for (Length i = 1; i < span->length-1; i++) {
-    pagemap_.set(span->start+i, span);
-  }
-}
-    
-#ifdef WTF_CHANGES
-size_t TCMalloc_PageHeap::ReturnedBytes() const {
-    size_t result = 0;
-    for (unsigned s = 0; s < kMaxPages; s++) {
-        const int r_length = DLL_Length(&free_[s].returned);
-        unsigned r_pages = s * r_length;
-        result += r_pages << kPageShift;
-    }
-    
-    for (Span* s = large_.returned.next; s != &large_.returned; s = s->next)
-        result += s->length << kPageShift;
-    return result;
-}
-#endif
-
-#ifndef WTF_CHANGES
-static double PagesToMB(uint64_t pages) {
-  return (pages << kPageShift) / 1048576.0;
-}
-
-void TCMalloc_PageHeap::Dump(TCMalloc_Printer* out) {
-  int nonempty_sizes = 0;
-  for (int s = 0; s < kMaxPages; s++) {
-    if (!DLL_IsEmpty(&free_[s].normal) || !DLL_IsEmpty(&free_[s].returned)) {
-      nonempty_sizes++;
-    }
-  }
-  out->printf("------------------------------------------------\n");
-  out->printf("PageHeap: %d sizes; %6.1f MB free\n",
-              nonempty_sizes, PagesToMB(free_pages_));
-  out->printf("------------------------------------------------\n");
-  uint64_t total_normal = 0;
-  uint64_t total_returned = 0;
-  for (int s = 0; s < kMaxPages; s++) {
-    const int n_length = DLL_Length(&free_[s].normal);
-    const int r_length = DLL_Length(&free_[s].returned);
-    if (n_length + r_length > 0) {
-      uint64_t n_pages = s * n_length;
-      uint64_t r_pages = s * r_length;
-      total_normal += n_pages;
-      total_returned += r_pages;
-      out->printf("%6u pages * %6u spans ~ %6.1f MB; %6.1f MB cum"
-                  "; unmapped: %6.1f MB; %6.1f MB cum\n",
-                  s,
-                  (n_length + r_length),
-                  PagesToMB(n_pages + r_pages),
-                  PagesToMB(total_normal + total_returned),
-                  PagesToMB(r_pages),
-                  PagesToMB(total_returned));
-    }
-  }
-
-  uint64_t n_pages = 0;
-  uint64_t r_pages = 0;
-  int n_spans = 0;
-  int r_spans = 0;
-  out->printf("Normal large spans:\n");
-  for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) {
-    out->printf("   [ %6" PRIuS " pages ] %6.1f MB\n",
-                s->length, PagesToMB(s->length));
-    n_pages += s->length;
-    n_spans++;
-  }
-  out->printf("Unmapped large spans:\n");
-  for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) {
-    out->printf("   [ %6" PRIuS " pages ] %6.1f MB\n",
-                s->length, PagesToMB(s->length));
-    r_pages += s->length;
-    r_spans++;
-  }
-  total_normal += n_pages;
-  total_returned += r_pages;
-  out->printf(">255   large * %6u spans ~ %6.1f MB; %6.1f MB cum"
-              "; unmapped: %6.1f MB; %6.1f MB cum\n",
-              (n_spans + r_spans),
-              PagesToMB(n_pages + r_pages),
-              PagesToMB(total_normal + total_returned),
-              PagesToMB(r_pages),
-              PagesToMB(total_returned));
-}
-#endif
-
-bool TCMalloc_PageHeap::GrowHeap(Length n) {
-  ASSERT(kMaxPages >= kMinSystemAlloc);
-  if (n > kMaxValidPages) return false;
-  Length ask = (n>kMinSystemAlloc) ? n : static_cast<Length>(kMinSystemAlloc);
-  size_t actual_size;
-  void* ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
-  if (ptr == NULL) {
-    if (n < ask) {
-      // Try growing just "n" pages
-      ask = n;
-      ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
-    }
-    if (ptr == NULL) return false;
-  }
-  ask = actual_size >> kPageShift;
-
-  uint64_t old_system_bytes = system_bytes_;
-  system_bytes_ += (ask << kPageShift);
-  const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
-  ASSERT(p > 0);
-
-  // If we have already a lot of pages allocated, just pre allocate a bunch of
-  // memory for the page map. This prevents fragmentation by pagemap metadata
-  // when a program keeps allocating and freeing large blocks.
-
-  if (old_system_bytes < kPageMapBigAllocationThreshold
-      && system_bytes_ >= kPageMapBigAllocationThreshold) {
-    pagemap_.PreallocateMoreMemory();
-  }
-
-  // Make sure pagemap_ has entries for all of the new pages.
-  // Plus ensure one before and one after so coalescing code
-  // does not need bounds-checking.
-  if (pagemap_.Ensure(p-1, ask+2)) {
-    // Pretend the new area is allocated and then Delete() it to
-    // cause any necessary coalescing to occur.
-    //
-    // We do not adjust free_pages_ here since Delete() will do it for us.
-    Span* span = NewSpan(p, ask);
-    RecordSpan(span);
-    Delete(span);
-    ASSERT(Check());
-    return true;
-  } else {
-    // We could not allocate memory within "pagemap_"
-    // TODO: Once we can return memory to the system, return the new span
-    return false;
-  }
-}
-
-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, false);
-  CheckList(&large_.returned, kMaxPages, 1000000000, true);
-  for (Length s = 1; s < kMaxPages; s++) {
-    CheckList(&free_[s].normal, s, s, false);
-    CheckList(&free_[s].returned, s, s, true);
-  }
-  return true;
-}
-
-#if ASSERT_DISABLED
-bool TCMalloc_PageHeap::CheckList(Span*, Length, Length, bool) {
-  return true;
-}
-#else
-bool TCMalloc_PageHeap::CheckList(Span* list, Length min_pages, Length max_pages, bool decommitted) {
-  for (Span* s = list->next; s != list; s = s->next) {
-    CHECK_CONDITION(s->free);
-    CHECK_CONDITION(s->length >= min_pages);
-    CHECK_CONDITION(s->length <= max_pages);
-    CHECK_CONDITION(GetDescriptor(s->start) == s);
-    CHECK_CONDITION(GetDescriptor(s->start+s->length-1) == s);
-    CHECK_CONDITION(s->decommitted == decommitted);
-  }
-  return true;
-}
-#endif
-
-static void ReleaseFreeList(Span* list, Span* returned) {
-  // Walk backwards through list so that when we push these
-  // spans on the "returned" list, we preserve the order.
-  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));
-  }
-}
-
-void TCMalloc_PageHeap::ReleaseFreePages() {
-  for (Length s = 0; s < kMaxPages; s++) {
-    ReleaseFreeList(&free_[s].normal, &free_[s].returned);
-  }
-  ReleaseFreeList(&large_.normal, &large_.returned);
-  ASSERT(Check());
-}
-
-//-------------------------------------------------------------------
-// Free list
-//-------------------------------------------------------------------
-
-class TCMalloc_ThreadCache_FreeList {
- private:
-  void*    list_;       // Linked list of nodes
-  uint16_t length_;     // Current length
-  uint16_t lowater_;    // Low water mark for list length
-
- public:
-  void Init() {
-    list_ = NULL;
-    length_ = 0;
-    lowater_ = 0;
-  }
-
-  // Return current length of list
-  int length() const {
-    return length_;
-  }
-
-  // Is list empty?
-  bool empty() const {
-    return list_ == NULL;
-  }
-
-  // Low-water mark management
-  int lowwatermark() const { return lowater_; }
-  void clear_lowwatermark() { lowater_ = length_; }
-
-  ALWAYS_INLINE void Push(void* ptr) {
-    SLL_Push(&list_, ptr);
-    length_++;
-  }
-
-  void PushRange(int N, void *start, void *end) {
-    SLL_PushRange(&list_, start, end);
-    length_ = length_ + static_cast<uint16_t>(N);
-  }
-
-  void PopRange(int N, void **start, void **end) {
-    SLL_PopRange(&list_, N, start, end);
-    ASSERT(length_ >= N);
-    length_ = length_ - static_cast<uint16_t>(N);
-    if (length_ < lowater_) lowater_ = length_;
-  }
-
-  ALWAYS_INLINE void* Pop() {
-    ASSERT(list_ != NULL);
-    length_--;
-    if (length_ < lowater_) lowater_ = length_;
-    return SLL_Pop(&list_);
-  }
-
-#ifdef WTF_CHANGES
-  template <class Finder, class Reader>
-  void enumerateFreeObjects(Finder& finder, const Reader& reader)
-  {
-      for (void* nextObject = list_; nextObject; nextObject = reader.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject)))
-          finder.visit(nextObject);
-  }
-#endif
-};
-
-//-------------------------------------------------------------------
-// Data kept per thread
-//-------------------------------------------------------------------
-
-class TCMalloc_ThreadCache {
- private:
-  typedef TCMalloc_ThreadCache_FreeList FreeList;
-#if OS(WINDOWS)
-  typedef DWORD ThreadIdentifier;
-#else
-  typedef pthread_t ThreadIdentifier;
-#endif
-
-  size_t        size_;                  // Combined size of data
-  ThreadIdentifier tid_;                // Which thread owns it
-  bool          in_setspecific_;           // Called pthread_setspecific?
-  FreeList      list_[kNumClasses];     // Array indexed by size-class
-
-  // We sample allocations, biased by the size of the allocation
-  uint32_t      rnd_;                   // Cheap random number generator
-  size_t        bytes_until_sample_;    // Bytes until we sample next
-
-  // Allocate a new heap. REQUIRES: pageheap_lock is held.
-  static inline TCMalloc_ThreadCache* NewHeap(ThreadIdentifier tid);
-
-  // Use only as pthread thread-specific destructor function.
-  static void DestroyThreadCache(void* ptr);
- public:
-  // All ThreadCache objects are kept in a linked list (for stats collection)
-  TCMalloc_ThreadCache* next_;
-  TCMalloc_ThreadCache* prev_;
-
-  void Init(ThreadIdentifier tid);
-  void Cleanup();
-
-  // Accessors (mostly just for printing stats)
-  int freelist_length(size_t cl) const { return list_[cl].length(); }
-
-  // Total byte size in cache
-  size_t Size() const { return size_; }
-
-  ALWAYS_INLINE void* Allocate(size_t size);
-  void Deallocate(void* ptr, size_t size_class);
-
-  ALWAYS_INLINE void FetchFromCentralCache(size_t cl, size_t allocationSize);
-  void ReleaseToCentralCache(size_t cl, int N);
-  void Scavenge();
-  void Print() const;
-
-  // Record allocation of "k" bytes.  Return true iff allocation
-  // should be sampled
-  bool SampleAllocation(size_t k);
-
-  // Pick next sampling point
-  void PickNextSample(size_t k);
-
-  static void                  InitModule();
-  static void                  InitTSD();
-  static TCMalloc_ThreadCache* GetThreadHeap();
-  static TCMalloc_ThreadCache* GetCache();
-  static TCMalloc_ThreadCache* GetCacheIfPresent();
-  static TCMalloc_ThreadCache* CreateCacheIfNecessary();
-  static void                  DeleteCache(TCMalloc_ThreadCache* heap);
-  static void                  BecomeIdle();
-  static void                  RecomputeThreadCacheSize();
-
-#ifdef WTF_CHANGES
-  template <class Finder, class Reader>
-  void enumerateFreeObjects(Finder& finder, const Reader& reader)
-  {
-      for (unsigned sizeClass = 0; sizeClass < kNumClasses; sizeClass++)
-          list_[sizeClass].enumerateFreeObjects(finder, reader);
-  }
-#endif
-};
-
-//-------------------------------------------------------------------
-// Data kept per size-class in central cache
-//-------------------------------------------------------------------
-
-class TCMalloc_Central_FreeList {
- public:
-  void Init(size_t cl);
-
-  // These methods all do internal locking.
-
-  // Insert the specified range into the central freelist.  N is the number of
-  // elements in the range.
-  void InsertRange(void *start, void *end, int N);
-
-  // Returns the actual number of fetched elements into N.
-  void RemoveRange(void **start, void **end, int *N);
-
-  // Returns the number of free objects in cache.
-  size_t length() {
-    SpinLockHolder h(&lock_);
-    return counter_;
-  }
-
-  // Returns the number of free objects in the transfer cache.
-  int tc_length() {
-    SpinLockHolder h(&lock_);
-    return used_slots_ * num_objects_to_move[size_class_];
-  }
-
-#ifdef WTF_CHANGES
-  template <class Finder, class Reader>
-  void enumerateFreeObjects(Finder& finder, const Reader& reader, TCMalloc_Central_FreeList* remoteCentralFreeList)
-  {
-    for (Span* span = &empty_; span && span != &empty_; span = (span->next ? reader(span->next) : 0))
-      ASSERT(!span->objects);
-
-    ASSERT(!nonempty_.objects);
-    static const ptrdiff_t nonemptyOffset = reinterpret_cast<const char*>(&nonempty_) - reinterpret_cast<const char*>(this);
-
-    Span* remoteNonempty = reinterpret_cast<Span*>(reinterpret_cast<char*>(remoteCentralFreeList) + nonemptyOffset);
-    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.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject)))
-        finder.visit(nextObject);
-    }
-  }
-#endif
-
- private:
-  // REQUIRES: lock_ is held
-  // Remove object from cache and return.
-  // Return NULL if no free entries in cache.
-  void* FetchFromSpans();
-
-  // REQUIRES: lock_ is held
-  // Remove object from cache and return.  Fetches
-  // from pageheap if cache is empty.  Only returns
-  // NULL on allocation failure.
-  void* FetchFromSpansSafe();
-
-  // REQUIRES: lock_ is held
-  // Release a linked list of objects to spans.
-  // May temporarily release lock_.
-  void ReleaseListToSpans(void *start);
-
-  // REQUIRES: lock_ is held
-  // Release an object to spans.
-  // May temporarily release lock_.
-  ALWAYS_INLINE void ReleaseToSpans(void* object);
-
-  // REQUIRES: lock_ is held
-  // Populate cache by fetching from the page heap.
-  // May temporarily release lock_.
-  ALWAYS_INLINE void Populate();
-
-  // REQUIRES: lock is held.
-  // Tries to make room for a TCEntry.  If the cache is full it will try to
-  // expand it at the cost of some other cache size.  Return false if there is
-  // no space.
-  bool MakeCacheSpace();
-
-  // REQUIRES: lock_ for locked_size_class is held.
-  // Picks a "random" size class to steal TCEntry slot from.  In reality it
-  // just iterates over the sizeclasses but does so without taking a lock.
-  // Returns true on success.
-  // May temporarily lock a "random" size class.
-  static ALWAYS_INLINE bool EvictRandomSizeClass(size_t locked_size_class, bool force);
-
-  // REQUIRES: lock_ is *not* held.
-  // Tries to shrink the Cache.  If force is true it will relase objects to
-  // spans if it allows it to shrink the cache.  Return false if it failed to
-  // shrink the cache.  Decrements cache_size_ on succeess.
-  // May temporarily take lock_.  If it takes lock_, the locked_size_class
-  // lock is released to the thread from holding two size class locks
-  // concurrently which could lead to a deadlock.
-  bool ShrinkCache(int locked_size_class, bool force);
-
-  // This lock protects all the data members.  cached_entries and cache_size_
-  // may be looked at without holding the lock.
-  SpinLock lock_;
-
-  // We keep linked lists of empty and non-empty spans.
-  size_t   size_class_;     // My size class
-  Span     empty_;          // Dummy header for list of empty spans
-  Span     nonempty_;       // Dummy header for list of non-empty spans
-  size_t   counter_;        // Number of free objects in cache entry
-
-  // Here we reserve space for TCEntry cache slots.  Since one size class can
-  // end up getting all the TCEntries quota in the system we just preallocate
-  // sufficient number of entries here.
-  TCEntry tc_slots_[kNumTransferEntries];
-
-  // Number of currently used cached entries in tc_slots_.  This variable is
-  // updated under a lock but can be read without one.
-  int32_t used_slots_;
-  // The current number of slots for this size class.  This is an
-  // adaptive value that is increased if there is lots of traffic
-  // on a given size class.
-  int32_t cache_size_;
-};
-
-// Pad each CentralCache object to multiple of 64 bytes
-class TCMalloc_Central_FreeListPadded : public TCMalloc_Central_FreeList {
- private:
-  char pad_[(64 - (sizeof(TCMalloc_Central_FreeList) % 64)) % 64];
-};
-
-//-------------------------------------------------------------------
-// Global variables
-//-------------------------------------------------------------------
-
-// Central cache -- a collection of free-lists, one per size-class.
-// We have a separate lock per free-list to reduce contention.
-static TCMalloc_Central_FreeListPadded central_cache[kNumClasses];
-
-// Page-level allocator
-static AllocAlignmentInteger pageheap_memory[(sizeof(TCMalloc_PageHeap) + sizeof(AllocAlignmentInteger) - 1) / sizeof(AllocAlignmentInteger)];
-static bool phinited = false;
-
-// Avoid extra level of indirection by making "pageheap" be just an alias
-// of pageheap_memory.
-typedef union {
-    void* m_memory;
-    TCMalloc_PageHeap* m_pageHeap;
-} PageHeapUnion;
-
-static inline TCMalloc_PageHeap* getPageHeap()
-{
-    PageHeapUnion u = { &pageheap_memory[0] };
-    return u.m_pageHeap;
-}
-
-#define pageheap getPageHeap()
-
-#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
-
-#if HAVE(DISPATCH_H) || OS(WINDOWS)
-
-void TCMalloc_PageHeap::periodicScavenge()
-{
-    SpinLockHolder h(&pageheap_lock);
-    pageheap->scavenge();
-
-    if (shouldScavenge()) {
-        rescheduleScavenger();
-        return;
-    }
-
-    suspendScavenger();
-}
-
-ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger()
-{
-    ASSERT(pageheap_lock.IsHeld());
-    if (isScavengerSuspended() && shouldScavenge())
-        scheduleScavenger();
-}
-
-#else
-
-void TCMalloc_PageHeap::scavengerThread()
-{
-#if HAVE(PTHREAD_SETNAME_NP)
-  pthread_setname_np("JavaScriptCore: FastMalloc scavenger");
-#endif
-
-  while (1) {
-      if (!shouldScavenge()) {
-          pthread_mutex_lock(&m_scavengeMutex);
-          m_scavengeThreadActive = false;
-          // Block until there are enough free committed pages to release back to the system.
-          pthread_cond_wait(&m_scavengeCondition, &m_scavengeMutex);
-          m_scavengeThreadActive = true;
-          pthread_mutex_unlock(&m_scavengeMutex);
-      }
-      sleep(kScavengeDelayInSeconds);
-      {
-          SpinLockHolder h(&pageheap_lock);
-          pageheap->scavenge();
-      }
-  }
-}
-
-#endif
-
-#endif
-
-// If TLS is available, we also store a copy
-// of the per-thread object in a __thread variable
-// since __thread variables are faster to read
-// than pthread_getspecific().  We still need
-// pthread_setspecific() because __thread
-// variables provide no way to run cleanup
-// code when a thread is destroyed.
-#ifdef HAVE_TLS
-static __thread TCMalloc_ThreadCache *threadlocal_heap;
-#endif
-// Thread-specific key.  Initialization here is somewhat tricky
-// because some Linux startup code invokes malloc() before it
-// is in a good enough state to handle pthread_keycreate().
-// Therefore, we use TSD keys only after tsd_inited is set to true.
-// Until then, we use a slow path to get the heap object.
-static bool tsd_inited = false;
-#if USE(PTHREAD_GETSPECIFIC_DIRECT)
-static const pthread_key_t heap_key = __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0;
-#else
-static pthread_key_t heap_key;
-#endif
-#if OS(WINDOWS)
-DWORD tlsIndex = TLS_OUT_OF_INDEXES;
-#endif
-
-static ALWAYS_INLINE void setThreadHeap(TCMalloc_ThreadCache* heap)
-{
-#if USE(PTHREAD_GETSPECIFIC_DIRECT)
-    // Can't have two libraries both doing this in the same process,
-    // so check and make this crash right away.
-    if (pthread_getspecific(heap_key))
-        CRASH();
-#endif
-
-    // Still do pthread_setspecific even if there's an alternate form
-    // of thread-local storage in use, to benefit from the delete callback.
-    pthread_setspecific(heap_key, heap);
-
-#if OS(WINDOWS)
-    TlsSetValue(tlsIndex, heap);
-#endif
-}
-
-// Allocator for thread heaps
-static PageHeapAllocator<TCMalloc_ThreadCache> threadheap_allocator;
-
-// Linked list of heap objects.  Protected by pageheap_lock.
-static TCMalloc_ThreadCache* thread_heaps = NULL;
-static int thread_heap_count = 0;
-
-// Overall thread cache size.  Protected by pageheap_lock.
-static size_t overall_thread_cache_size = kDefaultOverallThreadCacheSize;
-
-// Global per-thread cache size.  Writes are protected by
-// pageheap_lock.  Reads are done without any locking, which should be
-// fine as long as size_t can be written atomically and we don't place
-// invariants between this variable and other pieces of state.
-static volatile size_t per_thread_cache_size = kMaxThreadCacheSize;
-
-//-------------------------------------------------------------------
-// Central cache implementation
-//-------------------------------------------------------------------
-
-void TCMalloc_Central_FreeList::Init(size_t cl) {
-  lock_.Init();
-  size_class_ = cl;
-  DLL_Init(&empty_);
-  DLL_Init(&nonempty_);
-  counter_ = 0;
-
-  cache_size_ = 1;
-  used_slots_ = 0;
-  ASSERT(cache_size_ <= kNumTransferEntries);
-}
-
-void TCMalloc_Central_FreeList::ReleaseListToSpans(void* start) {
-  while (start) {
-    void *next = SLL_Next(start);
-    ReleaseToSpans(start);
-    start = next;
-  }
-}
-
-ALWAYS_INLINE void TCMalloc_Central_FreeList::ReleaseToSpans(void* object) {
-  const PageID p = reinterpret_cast<uintptr_t>(object) >> kPageShift;
-  Span* span = pageheap->GetDescriptor(p);
-  ASSERT(span != NULL);
-  ASSERT(span->refcount > 0);
-
-  // If span is empty, move it to non-empty list
-  if (span->objects == NULL) {
-    DLL_Remove(span);
-    DLL_Prepend(&nonempty_, span);
-    Event(span, 'N', 0);
-  }
-
-  // The following check is expensive, so it is disabled by default
-  if (false) {
-    // Check that object does not occur in list
-    unsigned got = 0;
-    for (void* p = span->objects; p != NULL; p = *((void**) p)) {
-      ASSERT(p != object);
-      got++;
-    }
-    ASSERT(got + span->refcount ==
-           (span->length<<kPageShift)/ByteSizeForClass(span->sizeclass));
-  }
-
-  counter_++;
-  span->refcount--;
-  if (span->refcount == 0) {
-    Event(span, '#', 0);
-    counter_ -= (span->length<<kPageShift) / ByteSizeForClass(span->sizeclass);
-    DLL_Remove(span);
-
-    // Release central list lock while operating on pageheap
-    lock_.Unlock();
-    {
-      SpinLockHolder h(&pageheap_lock);
-      pageheap->Delete(span);
-    }
-    lock_.Lock();
-  } else {
-    *(reinterpret_cast<void**>(object)) = span->objects;
-    span->objects = object;
-  }
-}
-
-ALWAYS_INLINE bool TCMalloc_Central_FreeList::EvictRandomSizeClass(
-    size_t locked_size_class, bool force) {
-  static int race_counter = 0;
-  int t = race_counter++;  // Updated without a lock, but who cares.
-  if (t >= static_cast<int>(kNumClasses)) {
-    while (t >= static_cast<int>(kNumClasses)) {
-      t -= kNumClasses;
-    }
-    race_counter = t;
-  }
-  ASSERT(t >= 0);
-  ASSERT(t < static_cast<int>(kNumClasses));
-  if (t == static_cast<int>(locked_size_class)) return false;
-  return central_cache[t].ShrinkCache(static_cast<int>(locked_size_class), force);
-}
-
-bool TCMalloc_Central_FreeList::MakeCacheSpace() {
-  // Is there room in the cache?
-  if (used_slots_ < cache_size_) return true;
-  // Check if we can expand this cache?
-  if (cache_size_ == kNumTransferEntries) return false;
-  // Ok, we'll try to grab an entry from some other size class.
-  if (EvictRandomSizeClass(size_class_, false) ||
-      EvictRandomSizeClass(size_class_, true)) {
-    // Succeeded in evicting, we're going to make our cache larger.
-    cache_size_++;
-    return true;
-  }
-  return false;
-}
-
-
-namespace {
-class LockInverter {
- private:
-  SpinLock *held_, *temp_;
- public:
-  inline explicit LockInverter(SpinLock* held, SpinLock *temp)
-    : held_(held), temp_(temp) { held_->Unlock(); temp_->Lock(); }
-  inline ~LockInverter() { temp_->Unlock(); held_->Lock();  }
-};
-}
-
-bool TCMalloc_Central_FreeList::ShrinkCache(int locked_size_class, bool force) {
-  // Start with a quick check without taking a lock.
-  if (cache_size_ == 0) return false;
-  // We don't evict from a full cache unless we are 'forcing'.
-  if (force == false && used_slots_ == cache_size_) return false;
-
-  // Grab lock, but first release the other lock held by this thread.  We use
-  // the lock inverter to ensure that we never hold two size class locks
-  // concurrently.  That can create a deadlock because there is no well
-  // defined nesting order.
-  LockInverter li(&central_cache[locked_size_class].lock_, &lock_);
-  ASSERT(used_slots_ <= cache_size_);
-  ASSERT(0 <= cache_size_);
-  if (cache_size_ == 0) return false;
-  if (used_slots_ == cache_size_) {
-    if (force == false) return false;
-    // ReleaseListToSpans releases the lock, so we have to make all the
-    // updates to the central list before calling it.
-    cache_size_--;
-    used_slots_--;
-    ReleaseListToSpans(tc_slots_[used_slots_].head);
-    return true;
-  }
-  cache_size_--;
-  return true;
-}
-
-void TCMalloc_Central_FreeList::InsertRange(void *start, void *end, int N) {
-  SpinLockHolder h(&lock_);
-  if (N == num_objects_to_move[size_class_] &&
-    MakeCacheSpace()) {
-    int slot = used_slots_++;
-    ASSERT(slot >=0);
-    ASSERT(slot < kNumTransferEntries);
-    TCEntry *entry = &tc_slots_[slot];
-    entry->head = start;
-    entry->tail = end;
-    return;
-  }
-  ReleaseListToSpans(start);
-}
-
-void TCMalloc_Central_FreeList::RemoveRange(void **start, void **end, int *N) {
-  int num = *N;
-  ASSERT(num > 0);
-
-  SpinLockHolder h(&lock_);
-  if (num == num_objects_to_move[size_class_] && used_slots_ > 0) {
-    int slot = --used_slots_;
-    ASSERT(slot >= 0);
-    TCEntry *entry = &tc_slots_[slot];
-    *start = entry->head;
-    *end = entry->tail;
-    return;
-  }
-
-  // TODO: Prefetch multiple TCEntries?
-  void *tail = FetchFromSpansSafe();
-  if (!tail) {
-    // We are completely out of memory.
-    *start = *end = NULL;
-    *N = 0;
-    return;
-  }
-
-  SLL_SetNext(tail, NULL);
-  void *head = tail;
-  int count = 1;
-  while (count < num) {
-    void *t = FetchFromSpans();
-    if (!t) break;
-    SLL_Push(&head, t);
-    count++;
-  }
-  *start = head;
-  *end = tail;
-  *N = count;
-}
-
-
-void* TCMalloc_Central_FreeList::FetchFromSpansSafe() {
-  void *t = FetchFromSpans();
-  if (!t) {
-    Populate();
-    t = FetchFromSpans();
-  }
-  return t;
-}
-
-void* TCMalloc_Central_FreeList::FetchFromSpans() {
-  if (DLL_IsEmpty(&nonempty_)) return NULL;
-  Span* span = nonempty_.next;
-
-  ASSERT(span->objects != NULL);
-  ASSERT_SPAN_COMMITTED(span);
-  span->refcount++;
-  void* result = span->objects;
-  span->objects = *(reinterpret_cast<void**>(result));
-  if (span->objects == NULL) {
-    // Move to empty list
-    DLL_Remove(span);
-    DLL_Prepend(&empty_, span);
-    Event(span, 'E', 0);
-  }
-  counter_--;
-  return result;
-}
-
-// Fetch memory from the system and add to the central cache freelist.
-ALWAYS_INLINE void TCMalloc_Central_FreeList::Populate() {
-  // Release central list lock while operating on pageheap
-  lock_.Unlock();
-  const size_t npages = class_to_pages[size_class_];
-
-  Span* span;
-  {
-    SpinLockHolder h(&pageheap_lock);
-    span = pageheap->New(npages);
-    if (span) pageheap->RegisterSizeClass(span, size_class_);
-  }
-  if (span == NULL) {
-#if HAVE(ERRNO_H)
-    MESSAGE("allocation failed: %d\n", errno);
-#elif OS(WINDOWS)
-    MESSAGE("allocation failed: %d\n", ::GetLastError());
-#else
-    MESSAGE("allocation failed\n");
-#endif
-    lock_.Lock();
-    return;
-  }
-  ASSERT_SPAN_COMMITTED(span);
-  ASSERT(span->length == npages);
-  // Cache sizeclass info eagerly.  Locking is not necessary.
-  // (Instead of being eager, we could just replace any stale info
-  // about this span, but that seems to be no better in practice.)
-  for (size_t i = 0; i < npages; i++) {
-    pageheap->CacheSizeClass(span->start + i, size_class_);
-  }
-
-  // Split the block into pieces and add to the free-list
-  // TODO: coloring of objects to avoid cache conflicts?
-  void** tail = &span->objects;
-  char* ptr = reinterpret_cast<char*>(span->start << kPageShift);
-  char* limit = ptr + (npages << kPageShift);
-  const size_t size = ByteSizeForClass(size_class_);
-  int num = 0;
-  char* nptr;
-  while ((nptr = ptr + size) <= limit) {
-    *tail = ptr;
-    tail = reinterpret_cast_ptr<void**>(ptr);
-    ptr = nptr;
-    num++;
-  }
-  ASSERT(ptr <= limit);
-  *tail = NULL;
-  span->refcount = 0; // No sub-object in use yet
-
-  // Add span to list of non-empty spans
-  lock_.Lock();
-  DLL_Prepend(&nonempty_, span);
-  counter_ += num;
-}
-
-//-------------------------------------------------------------------
-// TCMalloc_ThreadCache implementation
-//-------------------------------------------------------------------
-
-inline bool TCMalloc_ThreadCache::SampleAllocation(size_t k) {
-  if (bytes_until_sample_ < k) {
-    PickNextSample(k);
-    return true;
-  } else {
-    bytes_until_sample_ -= k;
-    return false;
-  }
-}
-
-void TCMalloc_ThreadCache::Init(ThreadIdentifier tid) {
-  size_ = 0;
-  next_ = NULL;
-  prev_ = NULL;
-  tid_  = tid;
-  in_setspecific_ = false;
-  for (size_t cl = 0; cl < kNumClasses; ++cl) {
-    list_[cl].Init();
-  }
-
-  // Initialize RNG -- run it for a bit to get to good values
-  bytes_until_sample_ = 0;
-  rnd_ = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(this));
-  for (int i = 0; i < 100; i++) {
-    PickNextSample(static_cast<size_t>(FLAGS_tcmalloc_sample_parameter * 2));
-  }
-}
-
-void TCMalloc_ThreadCache::Cleanup() {
-  // Put unused memory back into central cache
-  for (size_t cl = 0; cl < kNumClasses; ++cl) {
-    if (list_[cl].length() > 0) {
-      ReleaseToCentralCache(cl, list_[cl].length());
-    }
-  }
-}
-
-ALWAYS_INLINE void* TCMalloc_ThreadCache::Allocate(size_t size) {
-  ASSERT(size <= kMaxSize);
-  const size_t cl = SizeClass(size);
-  FreeList* list = &list_[cl];
-  size_t allocationSize = ByteSizeForClass(cl);
-  if (list->empty()) {
-    FetchFromCentralCache(cl, allocationSize);
-    if (list->empty()) return NULL;
-  }
-  size_ -= allocationSize;
-  return list->Pop();
-}
-
-inline void TCMalloc_ThreadCache::Deallocate(void* ptr, size_t cl) {
-  size_ += ByteSizeForClass(cl);
-  FreeList* list = &list_[cl];
-  list->Push(ptr);
-  // If enough data is free, put back into central cache
-  if (list->length() > kMaxFreeListLength) {
-    ReleaseToCentralCache(cl, num_objects_to_move[cl]);
-  }
-  if (size_ >= per_thread_cache_size) Scavenge();
-}
-
-// Remove some objects of class "cl" from central cache and add to thread heap
-ALWAYS_INLINE void TCMalloc_ThreadCache::FetchFromCentralCache(size_t cl, size_t allocationSize) {
-  int fetch_count = num_objects_to_move[cl];
-  void *start, *end;
-  central_cache[cl].RemoveRange(&start, &end, &fetch_count);
-  list_[cl].PushRange(fetch_count, start, end);
-  size_ += allocationSize * fetch_count;
-}
-
-// Remove some objects of class "cl" from thread heap and add to central cache
-inline void TCMalloc_ThreadCache::ReleaseToCentralCache(size_t cl, int N) {
-  ASSERT(N > 0);
-  FreeList* src = &list_[cl];
-  if (N > src->length()) N = src->length();
-  size_ -= N*ByteSizeForClass(cl);
-
-  // We return prepackaged chains of the correct size to the central cache.
-  // TODO: Use the same format internally in the thread caches?
-  int batch_size = num_objects_to_move[cl];
-  while (N > batch_size) {
-    void *tail, *head;
-    src->PopRange(batch_size, &head, &tail);
-    central_cache[cl].InsertRange(head, tail, batch_size);
-    N -= batch_size;
-  }
-  void *tail, *head;
-  src->PopRange(N, &head, &tail);
-  central_cache[cl].InsertRange(head, tail, N);
-}
-
-// Release idle memory to the central cache
-inline void TCMalloc_ThreadCache::Scavenge() {
-  // If the low-water mark for the free list is L, it means we would
-  // not have had to allocate anything from the central cache even if
-  // we had reduced the free list size by L.  We aim to get closer to
-  // that situation by dropping L/2 nodes from the free list.  This
-  // may not release much memory, but if so we will call scavenge again
-  // pretty soon and the low-water marks will be high on that call.
-  //int64 start = CycleClock::Now();
-
-  for (size_t cl = 0; cl < kNumClasses; cl++) {
-    FreeList* list = &list_[cl];
-    const int lowmark = list->lowwatermark();
-    if (lowmark > 0) {
-      const int drop = (lowmark > 1) ? lowmark/2 : 1;
-      ReleaseToCentralCache(cl, drop);
-    }
-    list->clear_lowwatermark();
-  }
-
-  //int64 finish = CycleClock::Now();
-  //CycleTimer ct;
-  //MESSAGE("GC: %.0f ns\n", ct.CyclesToUsec(finish-start)*1000.0);
-}
-
-void TCMalloc_ThreadCache::PickNextSample(size_t k) {
-  // Make next "random" number
-  // x^32+x^22+x^2+x^1+1 is a primitive polynomial for random numbers
-  static const uint32_t kPoly = (1 << 22) | (1 << 2) | (1 << 1) | (1 << 0);
-  uint32_t r = rnd_;
-  rnd_ = (r << 1) ^ ((static_cast<int32_t>(r) >> 31) & kPoly);
-
-  // Next point is "rnd_ % (sample_period)".  I.e., average
-  // increment is "sample_period/2".
-  const int flag_value = static_cast<int>(FLAGS_tcmalloc_sample_parameter);
-  static int last_flag_value = -1;
-
-  if (flag_value != last_flag_value) {
-    SpinLockHolder h(&sample_period_lock);
-    int i;
-    for (i = 0; i < (static_cast<int>(sizeof(primes_list)/sizeof(primes_list[0])) - 1); i++) {
-      if (primes_list[i] >= flag_value) {
-        break;
-      }
-    }
-    sample_period = primes_list[i];
-    last_flag_value = flag_value;
-  }
-
-  bytes_until_sample_ += rnd_ % sample_period;
-
-  if (k > (static_cast<size_t>(-1) >> 2)) {
-    // If the user has asked for a huge allocation then it is possible
-    // for the code below to loop infinitely.  Just return (note that
-    // this throws off the sampling accuracy somewhat, but a user who
-    // is allocating more than 1G of memory at a time can live with a
-    // minor inaccuracy in profiling of small allocations, and also
-    // would rather not wait for the loop below to terminate).
-    return;
-  }
-
-  while (bytes_until_sample_ < k) {
-    // Increase bytes_until_sample_ by enough average sampling periods
-    // (sample_period >> 1) to allow us to sample past the current
-    // allocation.
-    bytes_until_sample_ += (sample_period >> 1);
-  }
-
-  bytes_until_sample_ -= k;
-}
-
-void TCMalloc_ThreadCache::InitModule() {
-  // There is a slight potential race here because of double-checked
-  // locking idiom.  However, as long as the program does a small
-  // allocation before switching to multi-threaded mode, we will be
-  // fine.  We increase the chances of doing such a small allocation
-  // by doing one in the constructor of the module_enter_exit_hook
-  // object declared below.
-  SpinLockHolder h(&pageheap_lock);
-  if (!phinited) {
-#ifdef WTF_CHANGES
-    InitTSD();
-#endif
-    InitSizeClasses();
-    threadheap_allocator.Init();
-    span_allocator.Init();
-    span_allocator.New(); // Reduce cache conflicts
-    span_allocator.New(); // Reduce cache conflicts
-    stacktrace_allocator.Init();
-    DLL_Init(&sampled_objects);
-    for (size_t i = 0; i < kNumClasses; ++i) {
-      central_cache[i].Init(i);
-    }
-    pageheap->init();
-    phinited = 1;
-#if defined(WTF_CHANGES) && OS(DARWIN)
-    FastMallocZone::init();
-#endif
-  }
-}
-
-inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::NewHeap(ThreadIdentifier tid) {
-  // Create the heap and add it to the linked list
-  TCMalloc_ThreadCache *heap = threadheap_allocator.New();
-  heap->Init(tid);
-  heap->next_ = thread_heaps;
-  heap->prev_ = NULL;
-  if (thread_heaps != NULL) thread_heaps->prev_ = heap;
-  thread_heaps = heap;
-  thread_heap_count++;
-  RecomputeThreadCacheSize();
-  return heap;
-}
-
-inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetThreadHeap() {
-#ifdef HAVE_TLS
-    // __thread is faster, but only when the kernel supports it
-  if (KernelSupportsTLS())
-    return threadlocal_heap;
-#elif OS(WINDOWS)
-    return static_cast<TCMalloc_ThreadCache*>(TlsGetValue(tlsIndex));
-#else
-    return static_cast<TCMalloc_ThreadCache*>(pthread_getspecific(heap_key));
-#endif
-}
-
-inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetCache() {
-  TCMalloc_ThreadCache* ptr = NULL;
-  if (!tsd_inited) {
-    InitModule();
-  } else {
-    ptr = GetThreadHeap();
-  }
-  if (ptr == NULL) ptr = CreateCacheIfNecessary();
-  return ptr;
-}
-
-// In deletion paths, we do not try to create a thread-cache.  This is
-// because we may be in the thread destruction code and may have
-// already cleaned up the cache for this thread.
-inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetCacheIfPresent() {
-  if (!tsd_inited) return NULL;
-  void* const p = GetThreadHeap();
-  return reinterpret_cast<TCMalloc_ThreadCache*>(p);
-}
-
-void TCMalloc_ThreadCache::InitTSD() {
-  ASSERT(!tsd_inited);
-#if USE(PTHREAD_GETSPECIFIC_DIRECT)
-  pthread_key_init_np(heap_key, DestroyThreadCache);
-#else
-  pthread_key_create(&heap_key, DestroyThreadCache);
-#endif
-#if OS(WINDOWS)
-  tlsIndex = TlsAlloc();
-#endif
-  tsd_inited = true;
-    
-#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));
-#endif
-#ifndef WTF_CHANGES
-  SpinLockHolder h(&pageheap_lock);
-#else
-  ASSERT(pageheap_lock.IsHeld());
-#endif
-  for (TCMalloc_ThreadCache* h = thread_heaps; h != NULL; h = h->next_) {
-#if OS(WINDOWS)
-    if (h->tid_ == 0) {
-      h->tid_ = GetCurrentThreadId();
-    }
-#else
-    if (pthread_equal(h->tid_, zero)) {
-      h->tid_ = pthread_self();
-    }
-#endif
-  }
-}
-
-TCMalloc_ThreadCache* TCMalloc_ThreadCache::CreateCacheIfNecessary() {
-  // Initialize per-thread data if necessary
-  TCMalloc_ThreadCache* heap = NULL;
-  {
-    SpinLockHolder h(&pageheap_lock);
-
-#if OS(WINDOWS)
-    DWORD me;
-    if (!tsd_inited) {
-      me = 0;
-    } else {
-      me = GetCurrentThreadId();
-    }
-#else
-    // Early on in glibc's life, we cannot even call pthread_self()
-    pthread_t me;
-    if (!tsd_inited) {
-      memset(&me, 0, sizeof(me));
-    } else {
-      me = pthread_self();
-    }
-#endif
-
-    // This may be a recursive malloc call from pthread_setspecific()
-    // 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 OS(WINDOWS)
-      if (h->tid_ == me) {
-#else
-      if (pthread_equal(h->tid_, me)) {
-#endif
-        heap = h;
-        break;
-      }
-    }
-
-    if (heap == NULL) heap = NewHeap(me);
-  }
-
-  // We call pthread_setspecific() outside the lock because it may
-  // call malloc() recursively.  The recursive call will never get
-  // here again because it will find the already allocated heap in the
-  // linked list of heaps.
-  if (!heap->in_setspecific_ && tsd_inited) {
-    heap->in_setspecific_ = true;
-    setThreadHeap(heap);
-  }
-  return heap;
-}
-
-void TCMalloc_ThreadCache::BecomeIdle() {
-  if (!tsd_inited) return;              // No caches yet
-  TCMalloc_ThreadCache* heap = GetThreadHeap();
-  if (heap == NULL) return;             // No thread cache to remove
-  if (heap->in_setspecific_) return;    // Do not disturb the active caller
-
-  heap->in_setspecific_ = true;
-  setThreadHeap(NULL);
-#ifdef HAVE_TLS
-  // Also update the copy in __thread
-  threadlocal_heap = NULL;
-#endif
-  heap->in_setspecific_ = false;
-  if (GetThreadHeap() == heap) {
-    // Somehow heap got reinstated by a recursive call to malloc
-    // from pthread_setspecific.  We give up in this case.
-    return;
-  }
-
-  // We can now get rid of the heap
-  DeleteCache(heap);
-}
-
-void TCMalloc_ThreadCache::DestroyThreadCache(void* ptr) {
-  // Note that "ptr" cannot be NULL since pthread promises not
-  // to invoke the destructor on NULL values, but for safety,
-  // we check anyway.
-  if (ptr == NULL) return;
-#ifdef HAVE_TLS
-  // Prevent fast path of GetThreadHeap() from returning heap.
-  threadlocal_heap = NULL;
-#endif
-  DeleteCache(reinterpret_cast<TCMalloc_ThreadCache*>(ptr));
-}
-
-void TCMalloc_ThreadCache::DeleteCache(TCMalloc_ThreadCache* heap) {
-  // Remove all memory from heap
-  heap->Cleanup();
-
-  // Remove from linked list
-  SpinLockHolder h(&pageheap_lock);
-  if (heap->next_ != NULL) heap->next_->prev_ = heap->prev_;
-  if (heap->prev_ != NULL) heap->prev_->next_ = heap->next_;
-  if (thread_heaps == heap) thread_heaps = heap->next_;
-  thread_heap_count--;
-  RecomputeThreadCacheSize();
-
-  threadheap_allocator.Delete(heap);
-}
-
-void TCMalloc_ThreadCache::RecomputeThreadCacheSize() {
-  // Divide available space across threads
-  int n = thread_heap_count > 0 ? thread_heap_count : 1;
-  size_t space = overall_thread_cache_size / n;
-
-  // Limit to allowed range
-  if (space < kMinThreadCacheSize) space = kMinThreadCacheSize;
-  if (space > kMaxThreadCacheSize) space = kMaxThreadCacheSize;
-
-  per_thread_cache_size = space;
-}
-
-void TCMalloc_ThreadCache::Print() const {
-  for (size_t cl = 0; cl < kNumClasses; ++cl) {
-    MESSAGE("      %5" PRIuS " : %4d len; %4d lo\n",
-            ByteSizeForClass(cl),
-            list_[cl].length(),
-            list_[cl].lowwatermark());
-  }
-}
-
-// Extract interesting stats
-struct TCMallocStats {
-  uint64_t system_bytes;        // Bytes alloced from system
-  uint64_t thread_bytes;        // Bytes in thread caches
-  uint64_t central_bytes;       // Bytes in central cache
-  uint64_t transfer_bytes;      // Bytes in central transfer cache
-  uint64_t pageheap_bytes;      // Bytes in page heap
-  uint64_t metadata_bytes;      // Bytes alloced for metadata
-};
-
-#ifndef WTF_CHANGES
-// Get stats into "r".  Also get per-size-class counts if class_count != NULL
-static void ExtractStats(TCMallocStats* r, uint64_t* class_count) {
-  r->central_bytes = 0;
-  r->transfer_bytes = 0;
-  for (int cl = 0; cl < kNumClasses; ++cl) {
-    const int length = central_cache[cl].length();
-    const int tc_length = central_cache[cl].tc_length();
-    r->central_bytes += static_cast<uint64_t>(ByteSizeForClass(cl)) * length;
-    r->transfer_bytes +=
-      static_cast<uint64_t>(ByteSizeForClass(cl)) * tc_length;
-    if (class_count) class_count[cl] = length + tc_length;
-  }
-
-  // Add stats from per-thread heaps
-  r->thread_bytes = 0;
-  { // scope
-    SpinLockHolder h(&pageheap_lock);
-    for (TCMalloc_ThreadCache* h = thread_heaps; h != NULL; h = h->next_) {
-      r->thread_bytes += h->Size();
-      if (class_count) {
-        for (size_t cl = 0; cl < kNumClasses; ++cl) {
-          class_count[cl] += h->freelist_length(cl);
-        }
-      }
-    }
-  }
-
-  { //scope
-    SpinLockHolder h(&pageheap_lock);
-    r->system_bytes = pageheap->SystemBytes();
-    r->metadata_bytes = metadata_system_bytes;
-    r->pageheap_bytes = pageheap->FreeBytes();
-  }
-}
-#endif
-
-#ifndef WTF_CHANGES
-// WRITE stats to "out"
-static void DumpStats(TCMalloc_Printer* out, int level) {
-  TCMallocStats stats;
-  uint64_t class_count[kNumClasses];
-  ExtractStats(&stats, (level >= 2 ? class_count : NULL));
-
-  if (level >= 2) {
-    out->printf("------------------------------------------------\n");
-    uint64_t cumulative = 0;
-    for (int cl = 0; cl < kNumClasses; ++cl) {
-      if (class_count[cl] > 0) {
-        uint64_t class_bytes = class_count[cl] * ByteSizeForClass(cl);
-        cumulative += class_bytes;
-        out->printf("class %3d [ %8" PRIuS " bytes ] : "
-                "%8" PRIu64 " objs; %5.1f MB; %5.1f cum MB\n",
-                cl, ByteSizeForClass(cl),
-                class_count[cl],
-                class_bytes / 1048576.0,
-                cumulative / 1048576.0);
-      }
-    }
-
-    SpinLockHolder h(&pageheap_lock);
-    pageheap->Dump(out);
-  }
-
-  const uint64_t bytes_in_use = stats.system_bytes
-                                - stats.pageheap_bytes
-                                - stats.central_bytes
-                                - stats.transfer_bytes
-                                - stats.thread_bytes;
-
-  out->printf("------------------------------------------------\n"
-              "MALLOC: %12" PRIu64 " Heap size\n"
-              "MALLOC: %12" PRIu64 " Bytes in use by application\n"
-              "MALLOC: %12" PRIu64 " Bytes free in page heap\n"
-              "MALLOC: %12" PRIu64 " Bytes free in central cache\n"
-              "MALLOC: %12" PRIu64 " Bytes free in transfer cache\n"
-              "MALLOC: %12" PRIu64 " Bytes free in thread caches\n"
-              "MALLOC: %12" PRIu64 " Spans in use\n"
-              "MALLOC: %12" PRIu64 " Thread heaps in use\n"
-              "MALLOC: %12" PRIu64 " Metadata allocated\n"
-              "------------------------------------------------\n",
-              stats.system_bytes,
-              bytes_in_use,
-              stats.pageheap_bytes,
-              stats.central_bytes,
-              stats.transfer_bytes,
-              stats.thread_bytes,
-              uint64_t(span_allocator.inuse()),
-              uint64_t(threadheap_allocator.inuse()),
-              stats.metadata_bytes);
-}
-
-static void PrintStats(int level) {
-  const int kBufferSize = 16 << 10;
-  char* buffer = new char[kBufferSize];
-  TCMalloc_Printer printer(buffer, kBufferSize);
-  DumpStats(&printer, level);
-  write(STDERR_FILENO, buffer, strlen(buffer));
-  delete[] buffer;
-}
-
-static void** DumpStackTraces() {
-  // Count how much space we need
-  int needed_slots = 0;
-  {
-    SpinLockHolder h(&pageheap_lock);
-    for (Span* s = sampled_objects.next; s != &sampled_objects; s = s->next) {
-      StackTrace* stack = reinterpret_cast<StackTrace*>(s->objects);
-      needed_slots += 3 + stack->depth;
-    }
-    needed_slots += 100;            // Slop in case sample grows
-    needed_slots += needed_slots/8; // An extra 12.5% slop
-  }
-
-  void** result = new void*[needed_slots];
-  if (result == NULL) {
-    MESSAGE("tcmalloc: could not allocate %d slots for stack traces\n",
-            needed_slots);
-    return NULL;
-  }
-
-  SpinLockHolder h(&pageheap_lock);
-  int used_slots = 0;
-  for (Span* s = sampled_objects.next; s != &sampled_objects; s = s->next) {
-    ASSERT(used_slots < needed_slots);  // Need to leave room for terminator
-    StackTrace* stack = reinterpret_cast<StackTrace*>(s->objects);
-    if (used_slots + 3 + stack->depth >= needed_slots) {
-      // No more room
-      break;
-    }
-
-    result[used_slots+0] = reinterpret_cast<void*>(static_cast<uintptr_t>(1));
-    result[used_slots+1] = reinterpret_cast<void*>(stack->size);
-    result[used_slots+2] = reinterpret_cast<void*>(stack->depth);
-    for (int d = 0; d < stack->depth; d++) {
-      result[used_slots+3+d] = stack->stack[d];
-    }
-    used_slots += 3 + stack->depth;
-  }
-  result[used_slots] = reinterpret_cast<void*>(static_cast<uintptr_t>(0));
-  return result;
-}
-#endif
-
-#ifndef WTF_CHANGES
-
-// TCMalloc's support for extra malloc interfaces
-class TCMallocImplementation : public MallocExtension {
- public:
-  virtual void GetStats(char* buffer, int buffer_length) {
-    ASSERT(buffer_length > 0);
-    TCMalloc_Printer printer(buffer, buffer_length);
-
-    // Print level one stats unless lots of space is available
-    if (buffer_length < 10000) {
-      DumpStats(&printer, 1);
-    } else {
-      DumpStats(&printer, 2);
-    }
-  }
-
-  virtual void** ReadStackTraces() {
-    return DumpStackTraces();
-  }
-
-  virtual bool GetNumericProperty(const char* name, size_t* value) {
-    ASSERT(name != NULL);
-
-    if (strcmp(name, "generic.current_allocated_bytes") == 0) {
-      TCMallocStats stats;
-      ExtractStats(&stats, NULL);
-      *value = stats.system_bytes
-               - stats.thread_bytes
-               - stats.central_bytes
-               - stats.pageheap_bytes;
-      return true;
-    }
-
-    if (strcmp(name, "generic.heap_size") == 0) {
-      TCMallocStats stats;
-      ExtractStats(&stats, NULL);
-      *value = stats.system_bytes;
-      return true;
-    }
-
-    if (strcmp(name, "tcmalloc.slack_bytes") == 0) {
-      // We assume that bytes in the page heap are not fragmented too
-      // badly, and are therefore available for allocation.
-      SpinLockHolder l(&pageheap_lock);
-      *value = pageheap->FreeBytes();
-      return true;
-    }
-
-    if (strcmp(name, "tcmalloc.max_total_thread_cache_bytes") == 0) {
-      SpinLockHolder l(&pageheap_lock);
-      *value = overall_thread_cache_size;
-      return true;
-    }
-
-    if (strcmp(name, "tcmalloc.current_total_thread_cache_bytes") == 0) {
-      TCMallocStats stats;
-      ExtractStats(&stats, NULL);
-      *value = stats.thread_bytes;
-      return true;
-    }
-
-    return false;
-  }
-
-  virtual bool SetNumericProperty(const char* name, size_t value) {
-    ASSERT(name != NULL);
-
-    if (strcmp(name, "tcmalloc.max_total_thread_cache_bytes") == 0) {
-      // Clip the value to a reasonable range
-      if (value < kMinThreadCacheSize) value = kMinThreadCacheSize;
-      if (value > (1<<30)) value = (1<<30);     // Limit to 1GB
-
-      SpinLockHolder l(&pageheap_lock);
-      overall_thread_cache_size = static_cast<size_t>(value);
-      TCMalloc_ThreadCache::RecomputeThreadCacheSize();
-      return true;
-    }
-
-    return false;
-  }
-
-  virtual void MarkThreadIdle() {
-    TCMalloc_ThreadCache::BecomeIdle();
-  }
-
-  virtual void ReleaseFreeMemory() {
-    SpinLockHolder h(&pageheap_lock);
-    pageheap->ReleaseFreePages();
-  }
-};
-#endif
-
-// The constructor allocates an object to ensure that initialization
-// runs before main(), and therefore we do not have a chance to become
-// multi-threaded before initialization.  We also create the TSD key
-// here.  Presumably by the time this constructor runs, glibc is in
-// good enough shape to handle pthread_key_create().
-//
-// The constructor also takes the opportunity to tell STL to use
-// tcmalloc.  We want to do this early, before construct time, so
-// all user STL allocations go through tcmalloc (which works really
-// well for STL).
-//
-// The destructor prints stats when the program exits.
-class TCMallocGuard {
- public:
-
-  TCMallocGuard() {
-#ifdef HAVE_TLS    // this is true if the cc/ld/libc combo support TLS
-    // Check whether the kernel also supports TLS (needs to happen at runtime)
-    CheckIfKernelSupportsTLS();
-#endif
-#ifndef WTF_CHANGES
-#ifdef WIN32                    // patch the windows VirtualAlloc, etc.
-    PatchWindowsFunctions();    // defined in windows/patch_functions.cc
-#endif
-#endif
-    free(malloc(1));
-    TCMalloc_ThreadCache::InitTSD();
-    free(malloc(1));
-#ifndef WTF_CHANGES
-    MallocExtension::Register(new TCMallocImplementation);
-#endif
-  }
-
-#ifndef WTF_CHANGES
-  ~TCMallocGuard() {
-    const char* env = getenv("MALLOCSTATS");
-    if (env != NULL) {
-      int level = atoi(env);
-      if (level < 1) level = 1;
-      PrintStats(level);
-    }
-#ifdef WIN32
-    UnpatchWindowsFunctions();
-#endif
-  }
-#endif
-};
-
-#ifndef WTF_CHANGES
-static TCMallocGuard module_enter_exit_hook;
-#endif
-
-
-//-------------------------------------------------------------------
-// Helpers for the exported routines below
-//-------------------------------------------------------------------
-
-#ifndef WTF_CHANGES
-
-static Span* DoSampledAllocation(size_t size) {
-
-  // Grab the stack trace outside the heap lock
-  StackTrace tmp;
-  tmp.depth = GetStackTrace(tmp.stack, kMaxStackDepth, 1);
-  tmp.size = size;
-
-  SpinLockHolder h(&pageheap_lock);
-  // Allocate span
-  Span *span = pageheap->New(pages(size == 0 ? 1 : size));
-  if (span == NULL) {
-    return NULL;
-  }
-
-  // Allocate stack trace
-  StackTrace *stack = stacktrace_allocator.New();
-  if (stack == NULL) {
-    // Sampling failed because of lack of memory
-    return span;
-  }
-
-  *stack = tmp;
-  span->sample = 1;
-  span->objects = stack;
-  DLL_Prepend(&sampled_objects, span);
-
-  return span;
-}
-#endif
-
-static inline bool CheckCachedSizeClass(void *ptr) {
-  PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
-  size_t cached_value = pageheap->GetSizeClassIfCached(p);
-  return cached_value == 0 ||
-      cached_value == pageheap->GetDescriptor(p)->sizeclass;
-}
-
-static inline void* CheckedMallocResult(void *result)
-{
-  ASSERT(result == 0 || CheckCachedSizeClass(result));
-  return result;
-}
-
-static inline void* SpanToMallocResult(Span *span) {
-  ASSERT_SPAN_COMMITTED(span);
-  pageheap->CacheSizeClass(span->start, 0);
-  return
-      CheckedMallocResult(reinterpret_cast<void*>(span->start << kPageShift));
-}
-
-#ifdef WTF_CHANGES
-template <bool crashOnFailure>
-#endif
-static ALWAYS_INLINE void* do_malloc(size_t size) {
-  void* ret = NULL;
-
-#ifdef WTF_CHANGES
-    ASSERT(!isForbidden());
-#endif
-
-  // The following call forces module initialization
-  TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCache();
-#ifndef WTF_CHANGES
-  if ((FLAGS_tcmalloc_sample_parameter > 0) && heap->SampleAllocation(size)) {
-    Span* span = DoSampledAllocation(size);
-    if (span != NULL) {
-      ret = SpanToMallocResult(span);
-    }
-  } else
-#endif
-  if (size > kMaxSize) {
-    // Use page-level allocator
-    SpinLockHolder h(&pageheap_lock);
-    Span* span = pageheap->New(pages(size));
-    if (span != NULL) {
-      ret = SpanToMallocResult(span);
-    }
-  } else {
-    // The common case, and also the simplest.  This just pops the
-    // size-appropriate freelist, afer replenishing it if it's empty.
-    ret = CheckedMallocResult(heap->Allocate(size));
-  }
-  if (!ret) {
-#ifdef WTF_CHANGES
-    if (crashOnFailure) // This branch should be optimized out by the compiler.
-        CRASH();
-#else
-    errno = ENOMEM;
-#endif
-  }
-  return ret;
-}
-
-static ALWAYS_INLINE void do_free(void* ptr) {
-  if (ptr == NULL) return;
-  ASSERT(pageheap != NULL);  // Should not call free() before malloc()
-  const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
-  Span* span = NULL;
-  size_t cl = pageheap->GetSizeClassIfCached(p);
-
-  if (cl == 0) {
-    span = pageheap->GetDescriptor(p);
-    cl = span->sizeclass;
-    pageheap->CacheSizeClass(p, cl);
-  }
-  if (cl != 0) {
-#ifndef NO_TCMALLOC_SAMPLES
-    ASSERT(!pageheap->GetDescriptor(p)->sample);
-#endif
-    TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCacheIfPresent();
-    if (heap != NULL) {
-      heap->Deallocate(ptr, cl);
-    } else {
-      // Delete directly into central cache
-      SLL_SetNext(ptr, NULL);
-      central_cache[cl].InsertRange(ptr, ptr, 1);
-    }
-  } else {
-    SpinLockHolder h(&pageheap_lock);
-    ASSERT(reinterpret_cast<uintptr_t>(ptr) % kPageSize == 0);
-    ASSERT(span != NULL && span->start == p);
-#ifndef NO_TCMALLOC_SAMPLES
-    if (span->sample) {
-      DLL_Remove(span);
-      stacktrace_allocator.Delete(reinterpret_cast<StackTrace*>(span->objects));
-      span->objects = NULL;
-    }
-#endif
-    pageheap->Delete(span);
-  }
-}
-
-#ifndef WTF_CHANGES
-// For use by exported routines below that want specific alignments
-//
-// Note: this code can be slow, and can significantly fragment memory.
-// The expectation is that memalign/posix_memalign/valloc/pvalloc will
-// not be invoked very often.  This requirement simplifies our
-// implementation and allows us to tune for expected allocation
-// patterns.
-static void* do_memalign(size_t align, size_t size) {
-  ASSERT((align & (align - 1)) == 0);
-  ASSERT(align > 0);
-  if (pageheap == NULL) TCMalloc_ThreadCache::InitModule();
-
-  // Allocate at least one byte to avoid boundary conditions below
-  if (size == 0) size = 1;
-
-  if (size <= kMaxSize && align < kPageSize) {
-    // Search through acceptable size classes looking for one with
-    // enough alignment.  This depends on the fact that
-    // InitSizeClasses() currently produces several size classes that
-    // are aligned at powers of two.  We will waste time and space if
-    // we miss in the size class array, but that is deemed acceptable
-    // since memalign() should be used rarely.
-    size_t cl = SizeClass(size);
-    while (cl < kNumClasses && ((class_to_size[cl] & (align - 1)) != 0)) {
-      cl++;
-    }
-    if (cl < kNumClasses) {
-      TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCache();
-      return CheckedMallocResult(heap->Allocate(class_to_size[cl]));
-    }
-  }
-
-  // We will allocate directly from the page heap
-  SpinLockHolder h(&pageheap_lock);
-
-  if (align <= kPageSize) {
-    // Any page-level allocation will be fine
-    // TODO: We could put the rest of this page in the appropriate
-    // TODO: cache but it does not seem worth it.
-    Span* span = pageheap->New(pages(size));
-    return span == NULL ? NULL : SpanToMallocResult(span);
-  }
-
-  // Allocate extra pages and carve off an aligned portion
-  const Length alloc = pages(size + align);
-  Span* span = pageheap->New(alloc);
-  if (span == NULL) return NULL;
-
-  // Skip starting portion so that we end up aligned
-  Length skip = 0;
-  while ((((span->start+skip) << kPageShift) & (align - 1)) != 0) {
-    skip++;
-  }
-  ASSERT(skip < alloc);
-  if (skip > 0) {
-    Span* rest = pageheap->Split(span, skip);
-    pageheap->Delete(span);
-    span = rest;
-  }
-
-  // Skip trailing portion that we do not need to return
-  const Length needed = pages(size);
-  ASSERT(span->length >= needed);
-  if (span->length > needed) {
-    Span* trailer = pageheap->Split(span, needed);
-    pageheap->Delete(trailer);
-  }
-  return SpanToMallocResult(span);
-}
-#endif
-
-// Helpers for use by exported routines below:
-
-#ifndef WTF_CHANGES
-static inline void do_malloc_stats() {
-  PrintStats(1);
-}
-#endif
-
-static inline int do_mallopt(int, int) {
-  return 1;     // Indicates error
-}
-
-#ifdef HAVE_STRUCT_MALLINFO  // mallinfo isn't defined on freebsd, for instance
-static inline struct mallinfo do_mallinfo() {
-  TCMallocStats stats;
-  ExtractStats(&stats, NULL);
-
-  // Just some of the fields are filled in.
-  struct mallinfo info;
-  memset(&info, 0, sizeof(info));
-
-  // Unfortunately, the struct contains "int" field, so some of the
-  // size values will be truncated.
-  info.arena     = static_cast<int>(stats.system_bytes);
-  info.fsmblks   = static_cast<int>(stats.thread_bytes
-                                    + stats.central_bytes
-                                    + stats.transfer_bytes);
-  info.fordblks  = static_cast<int>(stats.pageheap_bytes);
-  info.uordblks  = static_cast<int>(stats.system_bytes
-                                    - stats.thread_bytes
-                                    - stats.central_bytes
-                                    - stats.transfer_bytes
-                                    - stats.pageheap_bytes);
-
-  return info;
-}
-#endif
-
-//-------------------------------------------------------------------
-// Exported routines
-//-------------------------------------------------------------------
-
-// CAVEAT: The code structure below ensures that MallocHook methods are always
-//         called from the stack frame of the invoked allocation function.
-//         heap-checker.cc depends on this to start a stack trace from
-//         the call to the (de)allocation function.
-
-#ifndef WTF_CHANGES
-extern "C" 
-#else
-#define do_malloc do_malloc<crashOnFailure>
-
-template <bool crashOnFailure>
-ALWAYS_INLINE void* malloc(size_t);
-
-void* fastMalloc(size_t size)
-{
-    return malloc<true>(size);
-}
-
-TryMallocReturnValue tryFastMalloc(size_t size)
-{
-    return malloc<false>(size);
-}
-
-template <bool crashOnFailure>
-ALWAYS_INLINE
-#endif
-void* malloc(size_t size) {
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= size)  // If overflow would occur...
-        return 0;
-    void* result = do_malloc(size + Internal::ValidationBufferSize);
-    if (!result)
-        return 0;
-
-    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
-
-#ifndef WTF_CHANGES
-  MallocHook::InvokeNewHook(result, size);
-#endif
-  return result;
-}
-
-#ifndef WTF_CHANGES
-extern "C" 
-#endif
-void free(void* ptr) {
-#ifndef WTF_CHANGES
-  MallocHook::InvokeDeleteHook(ptr);
-#endif
-
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    if (!ptr)
-        return;
-
-    fastMallocValidate(ptr);
-    Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(ptr);
-    memset(ptr, 0xCC, header->m_size);
-    do_free(header);
-#else
-    do_free(ptr);
-#endif
-}
-
-#ifndef WTF_CHANGES
-extern "C" 
-#else
-template <bool crashOnFailure>
-ALWAYS_INLINE void* calloc(size_t, size_t);
-
-void* fastCalloc(size_t n, size_t 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)
-{
-    void* result = calloc<false>(n, elem_size);
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    fastMallocValidate(result);
-#endif
-    return result;
-}
-
-template <bool crashOnFailure>
-ALWAYS_INLINE
-#endif
-void* calloc(size_t n, size_t elem_size) {
-  size_t totalBytes = n * elem_size;
-    
-  // Protect against overflow
-  if (n > 1 && elem_size && (totalBytes / elem_size) != n)
-    return 0;
-
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    void* result = malloc<crashOnFailure>(totalBytes);
-    if (!result)
-        return 0;
-
-    memset(result, 0, totalBytes);
-    fastMallocValidate(result);
-#else
-    void* result = do_malloc(totalBytes);
-    if (result != NULL) {
-        memset(result, 0, totalBytes);
-    }
-#endif
-
-#ifndef WTF_CHANGES
-  MallocHook::InvokeNewHook(result, totalBytes);
-#endif
-  return result;
-}
-
-// Since cfree isn't used anywhere, we don't compile it in.
-#ifndef WTF_CHANGES
-#ifndef WTF_CHANGES
-extern "C" 
-#endif
-void cfree(void* ptr) {
-#ifndef WTF_CHANGES
-    MallocHook::InvokeDeleteHook(ptr);
-#endif
-  do_free(ptr);
-}
-#endif
-
-#ifndef WTF_CHANGES
-extern "C" 
-#else
-template <bool crashOnFailure>
-ALWAYS_INLINE void* realloc(void*, size_t);
-
-void* fastRealloc(void* old_ptr, size_t 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)
-{
-#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>
-ALWAYS_INLINE
-#endif
-void* realloc(void* old_ptr, size_t new_size) {
-  if (old_ptr == NULL) {
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    void* result = malloc<crashOnFailure>(new_size);
-#else
-    void* result = do_malloc(new_size);
-#ifndef WTF_CHANGES
-    MallocHook::InvokeNewHook(result, new_size);
-#endif
-#endif
-    return result;
-  }
-  if (new_size == 0) {
-#ifndef WTF_CHANGES
-    MallocHook::InvokeDeleteHook(old_ptr);
-#endif
-    free(old_ptr);
-    return NULL;
-  }
-
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= new_size)  // If overflow would occur...
-        return 0;
-    Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(old_ptr);
-    fastMallocValidate(old_ptr);
-    old_ptr = header;
-    header->m_size = new_size;
-    new_size += Internal::ValidationBufferSize;
-#endif
-
-  // Get the size of the old entry
-  const PageID p = reinterpret_cast<uintptr_t>(old_ptr) >> kPageShift;
-  size_t cl = pageheap->GetSizeClassIfCached(p);
-  Span *span = NULL;
-  size_t old_size;
-  if (cl == 0) {
-    span = pageheap->GetDescriptor(p);
-    cl = span->sizeclass;
-    pageheap->CacheSizeClass(p, cl);
-  }
-  if (cl != 0) {
-    old_size = ByteSizeForClass(cl);
-  } else {
-    ASSERT(span != NULL);
-    old_size = span->length << kPageShift;
-  }
-
-  // Reallocate if the new size is larger than the old size,
-  // or if the new size is significantly smaller than the old size.
-  if ((new_size > old_size) || (AllocationSize(new_size) < old_size)) {
-    // Need to reallocate
-    void* new_ptr = do_malloc(new_size);
-    if (new_ptr == NULL) {
-      return NULL;
-    }
-#ifndef WTF_CHANGES
-    MallocHook::InvokeNewHook(new_ptr, new_size);
-#endif
-    memcpy(new_ptr, old_ptr, ((old_size < new_size) ? old_size : new_size));
-#ifndef WTF_CHANGES
-    MallocHook::InvokeDeleteHook(old_ptr);
-#endif
-    // We could use a variant of do_free() that leverages the fact
-    // that we already know the sizeclass of old_ptr.  The benefit
-    // would be small, so don't bother.
-    do_free(old_ptr);
-#if ENABLE(WTF_MALLOC_VALIDATION)
-    new_ptr = static_cast<Internal::ValidationHeader*>(new_ptr) + 1;
-    *Internal::fastMallocValidationSuffix(new_ptr) = Internal::ValidationSuffix;
-#endif
-    return new_ptr;
-  } else {
-#if ENABLE(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;
-  }
-}
-
-#ifdef WTF_CHANGES
-#undef do_malloc
-#else
-
-static SpinLock set_new_handler_lock = SPINLOCK_INITIALIZER;
-
-static inline void* cpp_alloc(size_t size, bool nothrow) {
-  for (;;) {
-    void* p = do_malloc(size);
-#ifdef PREANSINEW
-    return p;
-#else
-    if (p == NULL) {  // allocation failed
-      // Get the current new handler.  NB: this function is not
-      // thread-safe.  We make a feeble stab at making it so here, but
-      // this lock only protects against tcmalloc interfering with
-      // itself, not with other libraries calling set_new_handler.
-      std::new_handler nh;
-      {
-        SpinLockHolder h(&set_new_handler_lock);
-        nh = std::set_new_handler(0);
-        (void) std::set_new_handler(nh);
-      }
-      // If no new_handler is established, the allocation failed.
-      if (!nh) {
-        if (nothrow) return 0;
-        throw std::bad_alloc();
-      }
-      // Otherwise, try the new_handler.  If it returns, retry the
-      // allocation.  If it throws std::bad_alloc, fail the allocation.
-      // if it throws something else, don't interfere.
-      try {
-        (*nh)();
-      } catch (const std::bad_alloc&) {
-        if (!nothrow) throw;
-        return p;
-      }
-    } else {  // allocation success
-      return p;
-    }
-#endif
-  }
-}
-
-#if ENABLE(GLOBAL_FASTMALLOC_NEW)
-
-void* operator new(size_t size) {
-  void* p = cpp_alloc(size, false);
-  // We keep this next instruction out of cpp_alloc for a reason: when
-  // it's in, and new just calls cpp_alloc, the optimizer may fold the
-  // new call into cpp_alloc, which messes up our whole section-based
-  // stacktracing (see ATTRIBUTE_SECTION, above).  This ensures cpp_alloc
-  // isn't the last thing this fn calls, and prevents the folding.
-  MallocHook::InvokeNewHook(p, size);
-  return p;
-}
-
-void* operator new(size_t size, const std::nothrow_t&) __THROW {
-  void* p = cpp_alloc(size, true);
-  MallocHook::InvokeNewHook(p, size);
-  return p;
-}
-
-void operator delete(void* p) __THROW {
-  MallocHook::InvokeDeleteHook(p);
-  do_free(p);
-}
-
-void operator delete(void* p, const std::nothrow_t&) __THROW {
-  MallocHook::InvokeDeleteHook(p);
-  do_free(p);
-}
-
-void* operator new[](size_t size) {
-  void* p = cpp_alloc(size, false);
-  // We keep this next instruction out of cpp_alloc for a reason: when
-  // it's in, and new just calls cpp_alloc, the optimizer may fold the
-  // new call into cpp_alloc, which messes up our whole section-based
-  // stacktracing (see ATTRIBUTE_SECTION, above).  This ensures cpp_alloc
-  // isn't the last thing this fn calls, and prevents the folding.
-  MallocHook::InvokeNewHook(p, size);
-  return p;
-}
-
-void* operator new[](size_t size, const std::nothrow_t&) __THROW {
-  void* p = cpp_alloc(size, true);
-  MallocHook::InvokeNewHook(p, size);
-  return p;
-}
-
-void operator delete[](void* p) __THROW {
-  MallocHook::InvokeDeleteHook(p);
-  do_free(p);
-}
-
-void operator delete[](void* p, const std::nothrow_t&) __THROW {
-  MallocHook::InvokeDeleteHook(p);
-  do_free(p);
-}
-
-#endif
-
-extern "C" void* memalign(size_t align, size_t size) __THROW {
-  void* result = do_memalign(align, size);
-  MallocHook::InvokeNewHook(result, size);
-  return result;
-}
-
-extern "C" int posix_memalign(void** result_ptr, size_t align, size_t size)
-    __THROW {
-  if (((align % sizeof(void*)) != 0) ||
-      ((align & (align - 1)) != 0) ||
-      (align == 0)) {
-    return EINVAL;
-  }
-
-  void* result = do_memalign(align, size);
-  MallocHook::InvokeNewHook(result, size);
-  if (result == NULL) {
-    return ENOMEM;
-  } else {
-    *result_ptr = result;
-    return 0;
-  }
-}
-
-static size_t pagesize = 0;
-
-extern "C" void* valloc(size_t size) __THROW {
-  // Allocate page-aligned object of length >= size bytes
-  if (pagesize == 0) pagesize = getpagesize();
-  void* result = do_memalign(pagesize, size);
-  MallocHook::InvokeNewHook(result, size);
-  return result;
-}
-
-extern "C" void* pvalloc(size_t size) __THROW {
-  // Round up size to a multiple of pagesize
-  if (pagesize == 0) pagesize = getpagesize();
-  size = (size + pagesize - 1) & ~(pagesize - 1);
-  void* result = do_memalign(pagesize, size);
-  MallocHook::InvokeNewHook(result, size);
-  return result;
-}
-
-extern "C" void malloc_stats(void) {
-  do_malloc_stats();
-}
-
-extern "C" int mallopt(int cmd, int value) {
-  return do_mallopt(cmd, value);
-}
-
-#ifdef HAVE_STRUCT_MALLINFO
-extern "C" struct mallinfo mallinfo(void) {
-  return do_mallinfo();
-}
-#endif
-
-//-------------------------------------------------------------------
-// Some library routines on RedHat 9 allocate memory using malloc()
-// and free it using __libc_free() (or vice-versa).  Since we provide
-// our own implementations of malloc/free, we need to make sure that
-// the __libc_XXX variants (defined as part of glibc) also point to
-// the same implementations.
-//-------------------------------------------------------------------
-
-#if defined(__GLIBC__)
-extern "C" {
-#if COMPILER(GCC) && !defined(__MACH__) && defined(HAVE___ATTRIBUTE__)
-  // Potentially faster variants that use the gcc alias extension.
-  // Mach-O (Darwin) does not support weak aliases, hence the __MACH__ check.
-# define ALIAS(x) __attribute__ ((weak, alias (x)))
-  void* __libc_malloc(size_t size)              ALIAS("malloc");
-  void  __libc_free(void* ptr)                  ALIAS("free");
-  void* __libc_realloc(void* ptr, size_t size)  ALIAS("realloc");
-  void* __libc_calloc(size_t n, size_t size)    ALIAS("calloc");
-  void  __libc_cfree(void* ptr)                 ALIAS("cfree");
-  void* __libc_memalign(size_t align, size_t s) ALIAS("memalign");
-  void* __libc_valloc(size_t size)              ALIAS("valloc");
-  void* __libc_pvalloc(size_t size)             ALIAS("pvalloc");
-  int __posix_memalign(void** r, size_t a, size_t s) ALIAS("posix_memalign");
-# undef ALIAS
-# else   /* not __GNUC__ */
-  // Portable wrappers
-  void* __libc_malloc(size_t size)              { return malloc(size);       }
-  void  __libc_free(void* ptr)                  { free(ptr);                 }
-  void* __libc_realloc(void* ptr, size_t size)  { return realloc(ptr, size); }
-  void* __libc_calloc(size_t n, size_t size)    { return calloc(n, size);    }
-  void  __libc_cfree(void* ptr)                 { cfree(ptr);                }
-  void* __libc_memalign(size_t align, size_t s) { return memalign(align, s); }
-  void* __libc_valloc(size_t size)              { return valloc(size);       }
-  void* __libc_pvalloc(size_t size)             { return pvalloc(size);      }
-  int __posix_memalign(void** r, size_t a, size_t s) {
-    return posix_memalign(r, a, s);
-  }
-# endif  /* __GNUC__ */
-}
-#endif   /* __GLIBC__ */
-
-// Override __libc_memalign in libc on linux boxes specially.
-// They have a bug in libc that causes them to (very rarely) allocate
-// with __libc_memalign() yet deallocate with free() and the
-// definitions above don't catch it.
-// This function is an exception to the rule of calling MallocHook method
-// from the stack frame of the allocation function;
-// heap-checker handles this special case explicitly.
-static void *MemalignOverride(size_t align, size_t size, const void *caller)
-    __THROW {
-  void* result = do_memalign(align, size);
-  MallocHook::InvokeNewHook(result, size);
-  return result;
-}
-void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride;
-
-#endif
-
-#ifdef WTF_CHANGES
-void releaseFastMallocFreeMemory()
-{
-    // Flush free pages in the current thread cache back to the page heap.
-    // Low watermark mechanism in Scavenge() prevents full return on the first pass.
-    // The second pass flushes everything.
-    if (TCMalloc_ThreadCache* threadCache = TCMalloc_ThreadCache::GetCacheIfPresent()) {
-        threadCache->Scavenge();
-        threadCache->Scavenge();
-    }
-
-    SpinLockHolder h(&pageheap_lock);
-    pageheap->ReleaseFreePages();
-}
-    
-FastMallocStatistics fastMallocStatistics()
-{
-    FastMallocStatistics statistics;
-
-    SpinLockHolder lockHolder(&pageheap_lock);
-    statistics.reservedVMBytes = static_cast<size_t>(pageheap->SystemBytes());
-    statistics.committedVMBytes = statistics.reservedVMBytes - pageheap->ReturnedBytes();
-
-    statistics.freeListBytes = 0;
-    for (unsigned cl = 0; cl < kNumClasses; ++cl) {
-        const int length = central_cache[cl].length();
-        const int tc_length = central_cache[cl].tc_length();
-
-        statistics.freeListBytes += ByteSizeForClass(cl) * (length + tc_length);
-    }
-    for (TCMalloc_ThreadCache* threadCache = thread_heaps; threadCache ; threadCache = threadCache->next_)
-        statistics.freeListBytes += threadCache->Size();
-
-    return statistics;
-}
-
-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);
-
-    if (!span || span->free)
-        return 0;
-
-    for (void* free = span->objects; free != NULL; free = *((void**) free)) {
-        if (ptr == free)
-            return 0;
-    }
-
-    if (size_t cl = span->sizeclass)
-        return ByteSizeForClass(cl);
-
-    return span->length << kPageShift;
-#endif
-}
-
-#if OS(DARWIN)
-
-class FreeObjectFinder {
-    const RemoteMemoryReader& m_reader;
-    HashSet<void*> m_freeObjects;
-
-public:
-    FreeObjectFinder(const RemoteMemoryReader& reader) : m_reader(reader) { }
-
-    void visit(void* ptr) { m_freeObjects.add(ptr); }
-    bool isFreeObject(void* ptr) const { return m_freeObjects.contains(ptr); }
-    bool isFreeObject(vm_address_t ptr) const { return isFreeObject(reinterpret_cast<void*>(ptr)); }
-    size_t freeObjectCount() const { return m_freeObjects.size(); }
-
-    void findFreeObjects(TCMalloc_ThreadCache* threadCache)
-    {
-        for (; threadCache; threadCache = (threadCache->next_ ? m_reader(threadCache->next_) : 0))
-            threadCache->enumerateFreeObjects(*this, m_reader);
-    }
-
-    void findFreeObjects(TCMalloc_Central_FreeListPadded* centralFreeList, size_t numSizes, TCMalloc_Central_FreeListPadded* remoteCentralFreeList)
-    {
-        for (unsigned i = 0; i < numSizes; i++)
-            centralFreeList[i].enumerateFreeObjects(*this, m_reader, remoteCentralFreeList + i);
-    }
-};
-
-class PageMapFreeObjectFinder {
-    const RemoteMemoryReader& m_reader;
-    FreeObjectFinder& m_freeObjectFinder;
-
-public:
-    PageMapFreeObjectFinder(const RemoteMemoryReader& reader, FreeObjectFinder& freeObjectFinder)
-        : m_reader(reader)
-        , m_freeObjectFinder(freeObjectFinder)
-    { }
-
-    int visit(void* ptr) const
-    {
-        if (!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
-            for (void* nextObject = span->objects; nextObject; nextObject = m_reader.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject)))
-                m_freeObjectFinder.visit(nextObject);
-        }
-        return span->length;
-    }
-};
-
-class PageMapMemoryUsageRecorder {
-    task_t m_task;
-    void* m_context;
-    unsigned m_typeMask;
-    vm_range_recorder_t* m_recorder;
-    const RemoteMemoryReader& m_reader;
-    const FreeObjectFinder& m_freeObjectFinder;
-
-    HashSet<void*> m_seenPointers;
-    Vector<Span*> m_coalescedSpans;
-
-public:
-    PageMapMemoryUsageRecorder(task_t task, void* context, unsigned typeMask, vm_range_recorder_t* recorder, const RemoteMemoryReader& reader, const FreeObjectFinder& freeObjectFinder)
-        : m_task(task)
-        , m_context(context)
-        , m_typeMask(typeMask)
-        , m_recorder(recorder)
-        , m_reader(reader)
-        , m_freeObjectFinder(freeObjectFinder)
-    { }
-
-    ~PageMapMemoryUsageRecorder()
-    {
-        ASSERT(!m_coalescedSpans.size());
-    }
-
-    void recordPendingRegions()
-    {
-        Span* lastSpan = m_coalescedSpans[m_coalescedSpans.size() - 1];
-        vm_range_t ptrRange = { m_coalescedSpans[0]->start << kPageShift, 0 };
-        ptrRange.size = (lastSpan->start << kPageShift) - ptrRange.address + (lastSpan->length * kPageSize);
-
-        // Mark the memory region the spans represent as a candidate for containing pointers
-        if (m_typeMask & MALLOC_PTR_REGION_RANGE_TYPE)
-            (*m_recorder)(m_task, m_context, MALLOC_PTR_REGION_RANGE_TYPE, &ptrRange, 1);
-
-        if (!(m_typeMask & MALLOC_PTR_IN_USE_RANGE_TYPE)) {
-            m_coalescedSpans.clear();
-            return;
-        }
-
-        Vector<vm_range_t, 1024> allocatedPointers;
-        for (size_t i = 0; i < m_coalescedSpans.size(); ++i) {
-            Span *theSpan = m_coalescedSpans[i];
-            if (theSpan->free)
-                continue;
-
-            vm_address_t spanStartAddress = theSpan->start << kPageShift;
-            vm_size_t spanSizeInBytes = theSpan->length * kPageSize;
-
-            if (!theSpan->sizeclass) {
-                // If it's an allocated large object span, mark it as in use
-                if (!m_freeObjectFinder.isFreeObject(spanStartAddress))
-                    allocatedPointers.append((vm_range_t){spanStartAddress, spanSizeInBytes});
-            } else {
-                const size_t objectSize = ByteSizeForClass(theSpan->sizeclass);
-
-                // Mark each allocated small object within the span as in use
-                const vm_address_t endOfSpan = spanStartAddress + spanSizeInBytes;
-                for (vm_address_t object = spanStartAddress; object + objectSize <= endOfSpan; object += objectSize) {
-                    if (!m_freeObjectFinder.isFreeObject(object))
-                        allocatedPointers.append((vm_range_t){object, objectSize});
-                }
-            }
-        }
-
-        (*m_recorder)(m_task, m_context, MALLOC_PTR_IN_USE_RANGE_TYPE, allocatedPointers.data(), allocatedPointers.size());
-
-        m_coalescedSpans.clear();
-    }
-
-    int visit(void* ptr)
-    {
-        if (!ptr)
-            return 1;
-
-        Span* span = m_reader(reinterpret_cast<Span*>(ptr));
-        if (!span || !span->start)
-            return 1;
-
-        if (m_seenPointers.contains(ptr))
-            return span->length;
-        m_seenPointers.add(ptr);
-
-        if (!m_coalescedSpans.size()) {
-            m_coalescedSpans.append(span);
-            return span->length;
-        }
-
-        Span* previousSpan = m_coalescedSpans[m_coalescedSpans.size() - 1];
-        vm_address_t previousSpanStartAddress = previousSpan->start << kPageShift;
-        vm_size_t previousSpanSizeInBytes = previousSpan->length * kPageSize;
-
-        // If the new span is adjacent to the previous span, do nothing for now.
-        vm_address_t spanStartAddress = span->start << kPageShift;
-        if (spanStartAddress == previousSpanStartAddress + previousSpanSizeInBytes) {
-            m_coalescedSpans.append(span);
-            return span->length;
-        }
-
-        // New span is not adjacent to previous span, so record the spans coalesced so far.
-        recordPendingRegions();
-        m_coalescedSpans.append(span);
-
-        return span->length;
-    }
-};
-
-class AdminRegionRecorder {
-    task_t m_task;
-    void* m_context;
-    unsigned m_typeMask;
-    vm_range_recorder_t* m_recorder;
-    const RemoteMemoryReader& m_reader;
-
-    Vector<vm_range_t, 1024> m_pendingRegions;
-
-public:
-    AdminRegionRecorder(task_t task, void* context, unsigned typeMask, vm_range_recorder_t* recorder, const RemoteMemoryReader& reader)
-        : m_task(task)
-        , m_context(context)
-        , m_typeMask(typeMask)
-        , m_recorder(recorder)
-        , m_reader(reader)
-    { }
-
-    void recordRegion(vm_address_t ptr, size_t size)
-    {
-        if (m_typeMask & MALLOC_ADMIN_REGION_RANGE_TYPE)
-            m_pendingRegions.append((vm_range_t){ ptr, size });
-    }
-
-    void visit(void *ptr, size_t size)
-    {
-        recordRegion(reinterpret_cast<vm_address_t>(ptr), size);
-    }
-
-    void recordPendingRegions()
-    {
-        if (m_pendingRegions.size()) {
-            (*m_recorder)(m_task, m_context, MALLOC_ADMIN_REGION_RANGE_TYPE, m_pendingRegions.data(), m_pendingRegions.size());
-            m_pendingRegions.clear();
-        }
-    }
-
-    ~AdminRegionRecorder()
-    {
-        ASSERT(!m_pendingRegions.size());
-    }
-};
-
-kern_return_t FastMallocZone::enumerate(task_t task, void* context, unsigned typeMask, vm_address_t zoneAddress, memory_reader_t reader, vm_range_recorder_t recorder)
-{
-    RemoteMemoryReader memoryReader(task, reader);
-
-    InitSizeClasses();
-
-    FastMallocZone* mzone = memoryReader(reinterpret_cast<FastMallocZone*>(zoneAddress));
-    TCMalloc_PageHeap* pageHeap = memoryReader(mzone->m_pageHeap);
-    TCMalloc_ThreadCache** threadHeapsPointer = memoryReader(mzone->m_threadHeaps);
-    TCMalloc_ThreadCache* threadHeaps = memoryReader(*threadHeapsPointer);
-
-    TCMalloc_Central_FreeListPadded* centralCaches = memoryReader(mzone->m_centralCaches, sizeof(TCMalloc_Central_FreeListPadded) * kNumClasses);
-
-    FreeObjectFinder finder(memoryReader);
-    finder.findFreeObjects(threadHeaps);
-    finder.findFreeObjects(centralCaches, kNumClasses, mzone->m_centralCaches);
-
-    TCMalloc_PageHeap::PageMap* pageMap = &pageHeap->pagemap_;
-    PageMapFreeObjectFinder pageMapFinder(memoryReader, finder);
-    pageMap->visitValues(pageMapFinder, memoryReader);
-
-    PageMapMemoryUsageRecorder usageRecorder(task, context, typeMask, recorder, memoryReader, finder);
-    pageMap->visitValues(usageRecorder, memoryReader);
-    usageRecorder.recordPendingRegions();
-
-    AdminRegionRecorder adminRegionRecorder(task, context, typeMask, recorder, memoryReader);
-    pageMap->visitAllocations(adminRegionRecorder, memoryReader);
-
-    PageHeapAllocator<Span>* spanAllocator = memoryReader(mzone->m_spanAllocator);
-    PageHeapAllocator<TCMalloc_ThreadCache>* pageHeapAllocator = memoryReader(mzone->m_pageHeapAllocator);
-
-    spanAllocator->recordAdministrativeRegions(adminRegionRecorder, memoryReader);
-    pageHeapAllocator->recordAdministrativeRegions(adminRegionRecorder, memoryReader);
-
-    adminRegionRecorder.recordPendingRegions();
-
-    return 0;
-}
-
-size_t FastMallocZone::size(malloc_zone_t*, const void*)
-{
-    return 0;
-}
-
-void* FastMallocZone::zoneMalloc(malloc_zone_t*, size_t)
-{
-    return 0;
-}
-
-void* FastMallocZone::zoneCalloc(malloc_zone_t*, size_t, size_t)
-{
-    return 0;
-}
-
-void FastMallocZone::zoneFree(malloc_zone_t*, void* ptr)
-{
-    // Due to <rdar://problem/5671357> zoneFree may be called by the system free even if the pointer
-    // is not in this zone.  When this happens, the pointer being freed was not allocated by any
-    // zone so we need to print a useful error for the application developer.
-    malloc_printf("*** error for object %p: pointer being freed was not allocated\n", ptr);
-}
-
-void* FastMallocZone::zoneRealloc(malloc_zone_t*, void*, size_t)
-{
-    return 0;
-}
-
-
-#undef malloc
-#undef free
-#undef realloc
-#undef calloc
-
-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.
-
-    };
-}
-
-FastMallocZone::FastMallocZone(TCMalloc_PageHeap* pageHeap, TCMalloc_ThreadCache** threadHeaps, TCMalloc_Central_FreeListPadded* centralCaches, PageHeapAllocator<Span>* spanAllocator, PageHeapAllocator<TCMalloc_ThreadCache>* pageHeapAllocator)
-    : m_pageHeap(pageHeap)
-    , m_threadHeaps(threadHeaps)
-    , m_centralCaches(centralCaches)
-    , m_spanAllocator(spanAllocator)
-    , m_pageHeapAllocator(pageHeapAllocator)
-{
-    memset(&m_zone, 0, sizeof(m_zone));
-    m_zone.version = 4;
-    m_zone.zone_name = "JavaScriptCore FastMalloc";
-    m_zone.size = &FastMallocZone::size;
-    m_zone.malloc = &FastMallocZone::zoneMalloc;
-    m_zone.calloc = &FastMallocZone::zoneCalloc;
-    m_zone.realloc = &FastMallocZone::zoneRealloc;
-    m_zone.free = &FastMallocZone::zoneFree;
-    m_zone.valloc = &FastMallocZone::zoneValloc;
-    m_zone.destroy = &FastMallocZone::zoneDestroy;
-    m_zone.introspect = &jscore_fastmalloc_introspection;
-    malloc_zone_register(&m_zone);
-}
-
-
-void FastMallocZone::init()
-{
-    static FastMallocZone zone(pageheap, &thread_heaps, static_cast<TCMalloc_Central_FreeListPadded*>(central_cache), &span_allocator, &threadheap_allocator);
-}
-
-#endif // OS(DARWIN)
-
-} // namespace WTF
-#endif // WTF_CHANGES
-
-#endif // FORCE_SYSTEM_MALLOC
diff --git a/wtf/FastMalloc.h b/wtf/FastMalloc.h
deleted file mode 100644 (file)
index 37cf086..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- *  Copyright (C) 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 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_FastMalloc_h
-#define WTF_FastMalloc_h
-
-#include "Platform.h"
-#include "PossiblyNull.h"
-#include <stdlib.h>
-#include <new>
-
-namespace WTF {
-
-    // These functions call CRASH() if an allocation fails.
-    void* fastMalloc(size_t);
-    void* fastZeroedMalloc(size_t);
-    void* fastCalloc(size_t numElements, size_t elementSize);
-    void* fastRealloc(void*, size_t);
-    char* fastStrDup(const char*);
-    size_t fastMallocSize(const void*);
-
-    struct TryMallocReturnValue {
-        TryMallocReturnValue(void* data)
-            : m_data(data)
-        {
-        }
-        TryMallocReturnValue(const TryMallocReturnValue& source)
-            : m_data(source.m_data)
-        {
-            source.m_data = 0;
-        }
-        ~TryMallocReturnValue() { ASSERT(!m_data); }
-        template <typename T> bool getValue(T& data) WARN_UNUSED_RETURN;
-        template <typename T> operator PossiblyNull<T>()
-        { 
-            T value; 
-            getValue(value); 
-            return PossiblyNull<T>(value);
-        } 
-    private:
-        mutable void* m_data;
-    };
-    
-    template <typename T> bool TryMallocReturnValue::getValue(T& data)
-    {
-        union u { void* data; T target; } res;
-        res.data = m_data;
-        data = res.target;
-        bool returnValue = !!m_data;
-        m_data = 0;
-        return returnValue;
-    }
-
-    TryMallocReturnValue tryFastMalloc(size_t n);
-    TryMallocReturnValue tryFastZeroedMalloc(size_t n);
-    TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size);
-    TryMallocReturnValue tryFastRealloc(void* p, size_t n);
-
-    void fastFree(void*);
-
-#ifndef NDEBUG    
-    void fastMallocForbid();
-    void fastMallocAllow();
-#endif
-
-    void releaseFastMallocFreeMemory();
-    
-    struct FastMallocStatistics {
-        size_t reservedVMBytes;
-        size_t committedVMBytes;
-        size_t freeListBytes;
-    };
-    FastMallocStatistics fastMallocStatistics();
-
-    // 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[].
-        };
-
-        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(WTF_MALLOC_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 {
-    
-        // Handle a detected alloc/free mismatch. By default this calls CRASH().
-        void fastMallocMatchFailed(void* p);
-
-        inline ValidationHeader* fastMallocValidationHeader(void* p)
-        {
-            return reinterpret_cast<ValidationHeader*>(static_cast<char*>(p) - sizeof(ValidationHeader));
-        }
-
-        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 fastMallocValidationHeader(p)->m_type;
-        }
-
-        // Set the AllocType tag to be associaged with the allocated block p.
-        inline void setFastMallocMatchValidationType(void* p, AllocType allocType)
-        {
-            fastMallocValidationHeader(p)->m_type = allocType;
-        }
-
-    } // 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)
-    {
-        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);
-
-        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)
-    {
-    }
-
-    inline void fastMallocMatchValidateFree(void*, Internal::AllocType)
-    {
-    }
-
-#endif
-
-} // namespace WTF
-
-using WTF::fastCalloc;
-using WTF::fastFree;
-using WTF::fastMalloc;
-using WTF::fastMallocSize;
-using WTF::fastRealloc;
-using WTF::fastStrDup;
-using WTF::fastZeroedMalloc;
-using WTF::tryFastCalloc;
-using WTF::tryFastMalloc;
-using WTF::tryFastRealloc;
-using WTF::tryFastZeroedMalloc;
-
-#ifndef NDEBUG    
-using WTF::fastMallocForbid;
-using WTF::fastMallocAllow;
-#endif
-
-#if COMPILER(GCC) && OS(DARWIN)
-#define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline))
-#elif COMPILER(GCC)
-#define WTF_PRIVATE_INLINE inline __attribute__((always_inline))
-#elif COMPILER(MSVC) || COMPILER(RVCT)
-#define WTF_PRIVATE_INLINE __forceinline
-#else
-#define WTF_PRIVATE_INLINE inline
-#endif
-
-#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.
-// But since WebKit code never uses exceptions or nothrow at all, this is probably OK.
-// Long term we will adopt FastAllocBase.h everywhere, and and replace this with
-// debug-only code to make sure we don't use the system malloc via the default operator
-// new by accident.
-
-#if ENABLE(GLOBAL_FASTMALLOC_NEW)
-
-#if COMPILER(MSVC)
-#pragma warning(push)
-#pragma warning(disable: 4290) // Disable the C++ exception specification ignored warning.
-#endif
-WTF_PRIVATE_INLINE void* operator new(size_t size) throw (std::bad_alloc) { return fastMalloc(size); }
-WTF_PRIVATE_INLINE void* operator new(size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); }
-WTF_PRIVATE_INLINE void operator delete(void* p) throw() { fastFree(p); }
-WTF_PRIVATE_INLINE void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); }
-WTF_PRIVATE_INLINE void* operator new[](size_t size) throw (std::bad_alloc) { return fastMalloc(size); }
-WTF_PRIVATE_INLINE void* operator new[](size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); }
-WTF_PRIVATE_INLINE void operator delete[](void* p) throw() { fastFree(p); }
-WTF_PRIVATE_INLINE void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); }
-#if COMPILER(MSVC)
-#pragma warning(pop)
-#endif
-
-#endif
-
-#endif
-
-#endif /* WTF_FastMalloc_h */
diff --git a/wtf/FixedArray.h b/wtf/FixedArray.h
deleted file mode 100644 (file)
index c67d18c..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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
diff --git a/wtf/Forward.h b/wtf/Forward.h
deleted file mode 100644 (file)
index 28be168..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  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
- *  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_Forward_h
-#define WTF_Forward_h
-
-#include <stddef.h>
-
-namespace WTF {
-    template<typename T> class ListRefPtr;
-    template<typename T> class OwnArrayPtr;
-    template<typename T> class OwnPtr;
-    template<typename T> class PassOwnArrayPtr;
-    template<typename T> class PassOwnPtr;
-    template<typename T> class PassRefPtr;
-    template<typename T> class RefPtr;
-    template<typename T, size_t inlineCapacity> class Vector;
-
-    class AtomicString;
-    class AtomicStringImpl;
-    class CString;
-    class Decoder;
-    class Encoder;
-    class String;
-    class StringBuffer;
-    class StringImpl;
-}
-
-using WTF::ListRefPtr;
-using WTF::OwnArrayPtr;
-using WTF::OwnPtr;
-using WTF::PassOwnArrayPtr;
-using WTF::PassOwnPtr;
-using WTF::PassRefPtr;
-using WTF::RefPtr;
-using WTF::Vector;
-
-using WTF::AtomicString;
-using WTF::AtomicStringImpl;
-using WTF::CString;
-using WTF::Encoder;
-using WTF::Decoder;
-using WTF::String;
-using WTF::StringBuffer;
-using WTF::StringImpl;
-
-#endif // WTF_Forward_h
diff --git a/wtf/GetPtr.h b/wtf/GetPtr.h
deleted file mode 100644 (file)
index 25a0e6d..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  Copyright (C) 2006 Apple Computer, 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_GetPtr_h
-#define WTF_GetPtr_h
-
-namespace WTF {
-
-    template <typename T> inline T* getPtr(T* p)
-    {
-        return p;
-    }
-
-} // namespace WTF
-
-#endif // WTF_GetPtr_h
diff --git a/wtf/HashCountedSet.h b/wtf/HashCountedSet.h
deleted file mode 100644 (file)
index b97d8c8..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2005, 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.
- *
- */
-
-#ifndef WTF_HashCountedSet_h
-#define WTF_HashCountedSet_h
-
-#include "Assertions.h"
-#include "HashMap.h"
-#include "Vector.h"
-
-namespace WTF {
-
-    template<typename Value, typename HashFunctions = typename DefaultHash<Value>::Hash,
-        typename Traits = HashTraits<Value> > class HashCountedSet {
-        WTF_MAKE_FAST_ALLOCATED;
-    private:
-        typedef HashMap<Value, unsigned, HashFunctions, Traits> ImplType;
-    public:
-        typedef Value ValueType;
-        typedef typename ImplType::iterator iterator;
-        typedef typename ImplType::const_iterator const_iterator;
-        
-        HashCountedSet() {}
-        
-        int size() const;
-        int capacity() const;
-        bool isEmpty() const;
-        
-        // Iterators iterate over pairs of values and counts.
-        iterator begin();
-        iterator end();
-        const_iterator begin() const;
-        const_iterator end() const;
-        
-        iterator find(const ValueType&);
-        const_iterator find(const ValueType&) const;
-        bool contains(const ValueType&) const;
-        unsigned count(const ValueType&) const;
-
-        // Increases the count if an equal value is already present
-        // the return value is a pair of an interator to the new value's 
-        // location, and a bool that is true if an new entry was added.
-        std::pair<iterator, bool> add(const ValueType&);
-        
-        // Reduces the count of the value, and removes it if count
-        // goes down to zero, returns true if the value is removed.
-        bool remove(const ValueType&);
-        bool remove(iterator);
-        // Removes the value, regardless of its count.
-        void removeAll(iterator);
-        void removeAll(const ValueType&);
-
-        // Clears the whole set.
-        void clear();
-
-    private:
-        ImplType m_impl;
-    };
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline int HashCountedSet<Value, HashFunctions, Traits>::size() const
-    {
-        return m_impl.size(); 
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline int HashCountedSet<Value, HashFunctions, Traits>::capacity() const
-    {
-        return m_impl.capacity(); 
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline bool HashCountedSet<Value, HashFunctions, Traits>::isEmpty() const
-    {
-        return size() == 0; 
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline typename HashCountedSet<Value, HashFunctions, Traits>::iterator HashCountedSet<Value, HashFunctions, Traits>::begin()
-    {
-        return m_impl.begin(); 
-    }
-
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline typename HashCountedSet<Value, HashFunctions, Traits>::iterator HashCountedSet<Value, HashFunctions, Traits>::end()
-    {
-        return m_impl.end(); 
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator HashCountedSet<Value, HashFunctions, Traits>::begin() const
-    {
-        return m_impl.begin(); 
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator HashCountedSet<Value, HashFunctions, Traits>::end() const
-    {
-        return m_impl.end(); 
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline typename HashCountedSet<Value, HashFunctions, Traits>::iterator HashCountedSet<Value, HashFunctions, Traits>::find(const ValueType& value)
-    {
-        return m_impl.find(value); 
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator HashCountedSet<Value, HashFunctions, Traits>::find(const ValueType& value) const
-    {
-        return m_impl.find(value); 
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline bool HashCountedSet<Value, HashFunctions, Traits>::contains(const ValueType& value) const
-    {
-        return m_impl.contains(value); 
-    }
-
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline unsigned HashCountedSet<Value, HashFunctions, Traits>::count(const ValueType& value) const
-    {
-        return m_impl.get(value);
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline std::pair<typename HashCountedSet<Value, HashFunctions, Traits>::iterator, bool> HashCountedSet<Value, HashFunctions, Traits>::add(const ValueType &value)
-    {
-        pair<iterator, bool> result = m_impl.add(value, 0); 
-        ++result.first->second;
-        return result;
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline bool HashCountedSet<Value, HashFunctions, Traits>::remove(const ValueType& value)
-    {
-        return remove(find(value));
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline bool HashCountedSet<Value, HashFunctions, Traits>::remove(iterator it)
-    {
-        if (it == end())
-            return false;
-
-        unsigned oldVal = it->second;
-        ASSERT(oldVal);
-        unsigned newVal = oldVal - 1;
-        if (newVal) {
-            it->second = newVal;
-            return false;
-        }
-
-        m_impl.remove(it);
-        return true;
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline void HashCountedSet<Value, HashFunctions, Traits>::removeAll(const ValueType& value)
-    {
-        removeAll(find(value));
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline void HashCountedSet<Value, HashFunctions, Traits>::removeAll(iterator it)
-    {
-        if (it == end())
-            return;
-
-        m_impl.remove(it);
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline void HashCountedSet<Value, HashFunctions, Traits>::clear()
-    {
-        m_impl.clear(); 
-    }
-    
-    template<typename Value, typename HashFunctions, typename Traits, typename VectorType>
-    inline void copyToVector(const HashCountedSet<Value, HashFunctions, Traits>& collection, VectorType& vector)
-    {
-        typedef typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator iterator;
-        
-        vector.resize(collection.size());
-        
-        iterator it = collection.begin();
-        iterator end = collection.end();
-        for (unsigned i = 0; it != end; ++it, ++i)
-            vector[i] = *it;
-    }
-
-    template<typename Value, typename HashFunctions, typename Traits>
-    inline void copyToVector(const HashCountedSet<Value, HashFunctions, Traits>& collection, Vector<Value>& vector)
-    {
-        typedef typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator iterator;
-        
-        vector.resize(collection.size());
-        
-        iterator it = collection.begin();
-        iterator end = collection.end();
-        for (unsigned i = 0; it != end; ++it, ++i)
-            vector[i] = (*it).first;
-    }
-
-
-} // namespace khtml
-
-using WTF::HashCountedSet;
-
-#endif /* WTF_HashCountedSet_h */
diff --git a/wtf/HashFunctions.h b/wtf/HashFunctions.h
deleted file mode 100644 (file)
index 2c66a2d..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2005, 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.
- *
- */
-
-#ifndef WTF_HashFunctions_h
-#define WTF_HashFunctions_h
-
-#include "RefPtr.h"
-#include <stdint.h>
-
-namespace WTF {
-
-    template<size_t size> struct IntTypes;
-    template<> struct IntTypes<1> { typedef int8_t SignedType; typedef uint8_t UnsignedType; };
-    template<> struct IntTypes<2> { typedef int16_t SignedType; typedef uint16_t UnsignedType; };
-    template<> struct IntTypes<4> { typedef int32_t SignedType; typedef uint32_t UnsignedType; };
-    template<> struct IntTypes<8> { typedef int64_t SignedType; typedef uint64_t UnsignedType; };
-
-    // integer hash function
-
-    // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
-    inline unsigned intHash(uint8_t key8)
-    {
-        unsigned key = key8;
-        key += ~(key << 15);
-        key ^= (key >> 10);
-        key += (key << 3);
-        key ^= (key >> 6);
-        key += ~(key << 11);
-        key ^= (key >> 16);
-        return key;
-    }
-
-    // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
-    inline unsigned intHash(uint16_t key16)
-    {
-        unsigned key = key16;
-        key += ~(key << 15);
-        key ^= (key >> 10);
-        key += (key << 3);
-        key ^= (key >> 6);
-        key += ~(key << 11);
-        key ^= (key >> 16);
-        return key;
-    }
-
-    // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
-    inline unsigned intHash(uint32_t key) 
-    {
-        key += ~(key << 15);
-        key ^= (key >> 10);
-        key += (key << 3);
-        key ^= (key >> 6);
-        key += ~(key << 11);
-        key ^= (key >> 16);
-        return key;
-    }
-    
-    // Thomas Wang's 64 bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm
-    inline unsigned intHash(uint64_t key)
-    {
-        key += ~(key << 32);
-        key ^= (key >> 22);
-        key += ~(key << 13);
-        key ^= (key >> 8);
-        key += (key << 3);
-        key ^= (key >> 15);
-        key += ~(key << 27);
-        key ^= (key >> 31);
-        return static_cast<unsigned>(key);
-    }
-
-    template<typename T> struct IntHash {
-        static unsigned hash(T key) { return intHash(static_cast<typename IntTypes<sizeof(T)>::UnsignedType>(key)); }
-        static bool equal(T a, T b) { return a == b; }
-        static const bool safeToCompareToEmptyOrDeleted = true;
-    };
-
-    template<typename T> struct FloatHash {
-        static unsigned hash(T key)
-        {
-            union {
-                T key;
-                typename IntTypes<sizeof(T)>::UnsignedType bits;
-            } u;
-            u.key = key;
-            return intHash(u.bits);
-        }
-        static bool equal(T a, T b) { return a == b; }
-        static const bool safeToCompareToEmptyOrDeleted = true;
-    };
-
-    // pointer identity hash function
-
-    template<typename T> struct PtrHash {
-        static unsigned hash(T key)
-        {
-#if COMPILER(MSVC)
-#pragma warning(push)
-#pragma warning(disable: 4244) // work around what seems to be a bug in MSVC's conversion warnings
-#endif
-            return IntHash<uintptr_t>::hash(reinterpret_cast<uintptr_t>(key));
-#if COMPILER(MSVC)
-#pragma warning(pop)
-#endif
-        }
-        static bool equal(T a, T b) { return a == b; }
-        static const bool safeToCompareToEmptyOrDeleted = true;
-    };
-    template<typename P> struct PtrHash<RefPtr<P> > : PtrHash<P*> {
-        using PtrHash<P*>::hash;
-        static unsigned hash(const RefPtr<P>& key) { return hash(key.get()); }
-        using PtrHash<P*>::equal;
-        static bool equal(const RefPtr<P>& a, const RefPtr<P>& b) { return a == b; }
-        static bool equal(P* a, const RefPtr<P>& b) { return a == b; }
-        static bool equal(const RefPtr<P>& a, P* b) { return a == b; }
-    };
-
-    // default hash function for each type
-
-    template<typename T> struct DefaultHash;
-
-    template<typename T, typename U> struct PairHash {
-        static unsigned hash(const std::pair<T, U>& p)
-        {
-            return intHash((static_cast<uint64_t>(DefaultHash<T>::Hash::hash(p.first)) << 32 | DefaultHash<U>::Hash::hash(p.second)));
-        }
-        static bool equal(const std::pair<T, U>& a, const std::pair<T, U>& b)
-        {
-            return DefaultHash<T>::Hash::equal(a.first, b.first) && DefaultHash<U>::Hash::equal(a.second, b.second);
-        }
-        static const bool safeToCompareToEmptyOrDeleted = DefaultHash<T>::Hash::safeToCompareToEmptyOrDeleted 
-                                                            && DefaultHash<U>::Hash::safeToCompareToEmptyOrDeleted;
-    };
-
-    // make IntHash the default hash function for many integer types
-
-    template<> struct DefaultHash<short> { typedef IntHash<unsigned> Hash; };
-    template<> struct DefaultHash<unsigned short> { typedef IntHash<unsigned> Hash; };
-    template<> struct DefaultHash<int> { typedef IntHash<unsigned> Hash; };
-    template<> struct DefaultHash<unsigned> { typedef IntHash<unsigned> Hash; };
-    template<> struct DefaultHash<long> { typedef IntHash<unsigned long> Hash; };
-    template<> struct DefaultHash<unsigned long> { typedef IntHash<unsigned long> Hash; };
-    template<> struct DefaultHash<long long> { typedef IntHash<unsigned long long> Hash; };
-    template<> struct DefaultHash<unsigned long long> { typedef IntHash<unsigned long long> Hash; };
-
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    template<> struct DefaultHash<wchar_t> { typedef IntHash<wchar_t> Hash; };
-#endif
-
-    template<> struct DefaultHash<float> { typedef FloatHash<float> Hash; };
-    template<> struct DefaultHash<double> { typedef FloatHash<double> Hash; };
-
-    // make PtrHash the default hash function for pointer types that don't specialize
-
-    template<typename P> struct DefaultHash<P*> { typedef PtrHash<P*> Hash; };
-    template<typename P> struct DefaultHash<RefPtr<P> > { typedef PtrHash<RefPtr<P> > Hash; };
-
-    template<typename T, typename U> struct DefaultHash<std::pair<T, U> > { typedef PairHash<T, U> Hash; };
-
-} // namespace WTF
-
-using WTF::DefaultHash;
-using WTF::IntHash;
-using WTF::PtrHash;
-
-#endif // WTF_HashFunctions_h
diff --git a/wtf/HashIterators.h b/wtf/HashIterators.h
deleted file mode 100644 (file)
index 6afa2fa..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this 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_HashIterators_h
-#define WTF_HashIterators_h
-
-namespace WTF {
-
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstKeysIterator;
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstValuesIterator;
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableKeysIterator;
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableValuesIterator;
-
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > {
-    private:
-        typedef std::pair<KeyType, MappedType> ValueType;
-    public:
-        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(); }
-        const ValueType& operator*() const { return *get(); }
-        const ValueType* operator->() const { return get(); }
-
-        HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        Keys keys() { return Keys(*this); }
-        Values values() { return Values(*this); }
-
-        typename HashTableType::const_iterator m_impl;
-    };
-
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > {
-    private:
-        typedef std::pair<KeyType, MappedType> ValueType;
-    public:
-        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(); }
-        ValueType& operator*() const { return *get(); }
-        ValueType* operator->() const { return get(); }
-
-        HashTableIteratorAdapter& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        operator HashTableConstIteratorAdapter<HashTableType, ValueType>() {
-            typename HashTableType::const_iterator i = m_impl;
-            return i;
-        }
-
-        Keys keys() { return Keys(*this); }
-        Values values() { return Values(*this); }
-
-        typename HashTableType::iterator m_impl;
-    };
-
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstKeysIterator {
-    private:
-        typedef HashTableConstIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > ConstIterator;
-
-    public:
-        HashTableConstKeysIterator(const ConstIterator& impl) : m_impl(impl) {}
-        
-        const KeyType* get() const { return &(m_impl.get()->first); }
-        const KeyType& operator*() const { return *get(); }
-        const KeyType* operator->() const { return get(); }
-
-        HashTableConstKeysIterator& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        ConstIterator m_impl;
-    };
-
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstValuesIterator {
-    private:
-        typedef HashTableConstIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > ConstIterator;
-
-    public:
-        HashTableConstValuesIterator(const ConstIterator& impl) : m_impl(impl) {}
-        
-        const MappedType* get() const { return &(m_impl.get()->second); }
-        const MappedType& operator*() const { return *get(); }
-        const MappedType* operator->() const { return get(); }
-
-        HashTableConstValuesIterator& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        ConstIterator m_impl;
-    };
-
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableKeysIterator {
-    private:
-        typedef HashTableIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > Iterator;
-        typedef HashTableConstIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > ConstIterator;
-
-    public:
-        HashTableKeysIterator(const Iterator& impl) : m_impl(impl) {}
-        
-        KeyType* get() const { return &(m_impl.get()->first); }
-        KeyType& operator*() const { return *get(); }
-        KeyType* operator->() const { return get(); }
-
-        HashTableKeysIterator& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        operator HashTableConstKeysIterator<HashTableType, KeyType, MappedType>() {
-            ConstIterator i = m_impl;
-            return i;
-        }
-
-        Iterator m_impl;
-    };
-
-    template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableValuesIterator {
-    private:
-        typedef HashTableIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > Iterator;
-        typedef HashTableConstIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > ConstIterator;
-
-    public:
-        HashTableValuesIterator(const Iterator& impl) : m_impl(impl) {}
-        
-        MappedType* get() const { return &(m_impl.get()->second); }
-        MappedType& operator*() const { return *get(); }
-        MappedType* operator->() const { return get(); }
-
-        HashTableValuesIterator& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        operator HashTableConstValuesIterator<HashTableType, KeyType, MappedType>() {
-            ConstIterator i = m_impl;
-            return i;
-        }
-
-        Iterator m_impl;
-    };
-
-    template<typename T, typename U, typename V>
-        inline bool operator==(const HashTableConstKeysIterator<T, U, V>& a, const HashTableConstKeysIterator<T, U, V>& b)
-    {
-        return a.m_impl == b.m_impl;
-    }
-
-    template<typename T, typename U, typename V>
-        inline bool operator!=(const HashTableConstKeysIterator<T, U, V>& a, const HashTableConstKeysIterator<T, U, V>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
-
-    template<typename T, typename U, typename V>
-        inline bool operator==(const HashTableConstValuesIterator<T, U, V>& a, const HashTableConstValuesIterator<T, U, V>& b)
-    {
-        return a.m_impl == b.m_impl;
-    }
-
-    template<typename T, typename U, typename V>
-        inline bool operator!=(const HashTableConstValuesIterator<T, U, V>& a, const HashTableConstValuesIterator<T, U, V>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
-
-    template<typename T, typename U, typename V>
-        inline bool operator==(const HashTableKeysIterator<T, U, V>& a, const HashTableKeysIterator<T, U, V>& b)
-    {
-        return a.m_impl == b.m_impl;
-    }
-
-    template<typename T, typename U, typename V>
-        inline bool operator!=(const HashTableKeysIterator<T, U, V>& a, const HashTableKeysIterator<T, U, V>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
-
-    template<typename T, typename U, typename V>
-        inline bool operator==(const HashTableValuesIterator<T, U, V>& a, const HashTableValuesIterator<T, U, V>& b)
-    {
-        return a.m_impl == b.m_impl;
-    }
-
-    template<typename T, typename U, typename V>
-        inline bool operator!=(const HashTableValuesIterator<T, U, V>& a, const HashTableValuesIterator<T, U, V>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
-
-
-} // namespace WTF
-
-#endif // WTF_HashIterators_h
diff --git a/wtf/HashMap.h b/wtf/HashMap.h
deleted file mode 100644 (file)
index 7731546..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * 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_HashMap_h
-#define WTF_HashMap_h
-
-#include "HashTable.h"
-
-namespace WTF {
-
-    template<typename PairType> struct PairFirstExtractor;
-
-    template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
-        typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg> >
-    class HashMap {
-        WTF_MAKE_FAST_ALLOCATED;
-    private:
-        typedef KeyTraitsArg KeyTraits;
-        typedef MappedTraitsArg MappedTraits;
-        typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits;
-
-    public:
-        typedef typename KeyTraits::TraitType KeyType;
-        typedef typename MappedTraits::TraitType MappedType;
-        typedef typename ValueTraits::TraitType ValueType;
-
-    private:
-        typedef HashArg HashFunctions;
-
-        typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>,
-            HashFunctions, ValueTraits, KeyTraits> HashTableType;
-
-    public:
-        typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
-        typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
-
-        void swap(HashMap&);
-
-        int size() const;
-        int capacity() const;
-        bool isEmpty() const;
-
-        // iterators iterate over pairs of keys and values
-        iterator begin();
-        iterator end();
-        const_iterator begin() const;
-        const_iterator end() const;
-
-        iterator find(const KeyType&);
-        const_iterator find(const KeyType&) const;
-        bool contains(const KeyType&) const;
-        MappedType get(const KeyType&) const;
-
-        // replaces value but not key if key is already present
-        // return value is a pair of the iterator to the key location, 
-        // and a boolean that's true if a new value was actually added
-        pair<iterator, bool> set(const KeyType&, const MappedType&); 
-
-        // does nothing if key is already present
-        // return value is a pair of the iterator to the key location, 
-        // and a boolean that's true if a new value was actually added
-        pair<iterator, bool> add(const KeyType&, const MappedType&); 
-
-        void remove(const KeyType&);
-        void remove(iterator);
-        void clear();
-
-        MappedType take(const KeyType&); // efficient combination of get with remove
-
-        // An alternate version of find() that finds the object by hashing and comparing
-        // with some other type, to avoid the cost of type conversion. HashTranslator
-        // 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> bool contains(const T&) const;
-
-        // An alternate version of add() that finds the object by hashing and comparing
-        // with some other type, to avoid the cost of type conversion if the object is already
-        // in the table. HashTranslator must have the following function members:
-        //   static unsigned hash(const T&);
-        //   static bool equal(const ValueType&, const T&);
-        //   static translate(ValueType&, const T&, unsigned hashCode);
-        template<typename T, typename HashTranslator> pair<iterator, bool> add(const T&, const MappedType&);
-
-        void checkConsistency() const;
-
-    private:
-        pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&);
-
-        HashTableType m_impl;
-    };
-
-    template<typename PairType> struct PairFirstExtractor {
-        static const typename PairType::first_type& extract(const PairType& p) { return p.first; }
-    };
-
-    template<typename ValueType, typename ValueTraits, typename HashFunctions>
-    struct HashMapTranslator {
-        typedef typename ValueType::first_type KeyType;
-        typedef typename ValueType::second_type MappedType;
-
-        static unsigned hash(const KeyType& key) { return HashFunctions::hash(key); }
-        static bool equal(const KeyType& a, const KeyType& b) { return HashFunctions::equal(a, b); }
-        static void translate(ValueType& location, const KeyType& key, const MappedType& mapped)
-        {
-            location.first = key;
-            location.second = mapped;
-        }
-    };
-
-    template<typename ValueType, typename ValueTraits, typename T, typename Translator>
-    struct HashMapTranslatorAdapter {
-        typedef typename ValueType::first_type KeyType;
-        typedef typename ValueType::second_type MappedType;
-
-        static unsigned hash(const T& key) { return Translator::hash(key); }
-        static bool equal(const KeyType& a, const T& b) { return Translator::equal(a, b); }
-        static void translate(ValueType& location, const T& key, const MappedType& mapped, unsigned hashCode)
-        {
-            Translator::translate(location.first, key, hashCode);
-            location.second = mapped;
-        }
-    };
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void HashMap<T, U, V, W, X>::swap(HashMap& other)
-    {
-        m_impl.swap(other.m_impl); 
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline int HashMap<T, U, V, W, X>::size() const
-    {
-        return m_impl.size(); 
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline int HashMap<T, U, V, W, X>::capacity() const
-    { 
-        return m_impl.capacity(); 
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline bool HashMap<T, U, V, W, X>::isEmpty() const
-    {
-        return m_impl.isEmpty();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::begin()
-    {
-        return m_impl.begin();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::end()
-    {
-        return m_impl.end();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::begin() const
-    {
-        return m_impl.begin();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::end() const
-    {
-        return m_impl.end();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::find(const KeyType& key)
-    {
-        return m_impl.find(key);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::find(const KeyType& key) const
-    {
-        return m_impl.find(key);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline bool HashMap<T, U, V, W, X>::contains(const KeyType& key) const
-    {
-        return m_impl.contains(key);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    template<typename TYPE, typename HashTranslator>
-    inline typename HashMap<T, U, V, W, X>::iterator
-    HashMap<T, U, V, W, X>::find(const TYPE& value)
-    {
-        typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter;
-        return m_impl.template find<TYPE, Adapter>(value);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    template<typename TYPE, typename HashTranslator>
-    inline typename HashMap<T, U, V, W, X>::const_iterator 
-    HashMap<T, U, V, W, X>::find(const TYPE& value) const
-    {
-        typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter;
-        return m_impl.template find<TYPE, Adapter>(value);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    template<typename TYPE, typename HashTranslator>
-    inline bool
-    HashMap<T, U, V, W, X>::contains(const TYPE& value) const
-    {
-        typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter;
-        return m_impl.template contains<TYPE, Adapter>(value);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline pair<typename HashMap<T, U, V, W, X>::iterator, bool>
-    HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped) 
-    {
-        typedef HashMapTranslator<ValueType, ValueTraits, HashFunctions> TranslatorType;
-        return m_impl.template add<KeyType, MappedType, TranslatorType>(key, mapped);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    pair<typename HashMap<T, U, V, W, X>::iterator, bool>
-    HashMap<T, U, V, W, X>::set(const KeyType& key, const MappedType& mapped) 
-    {
-        pair<iterator, bool> result = inlineAdd(key, mapped);
-        if (!result.second) {
-            // add call above didn't change anything, so set the mapped value
-            result.first->second = mapped;
-        }
-        return result;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    template<typename TYPE, typename HashTranslator>
-    pair<typename HashMap<T, U, V, W, X>::iterator, bool>
-    HashMap<T, U, V, W, X>::add(const TYPE& key, const MappedType& value)
-    {
-        typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter;
-        return m_impl.template addPassingHashCode<TYPE, MappedType, Adapter>(key, value);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    pair<typename HashMap<T, U, V, W, X>::iterator, bool>
-    HashMap<T, U, V, W, X>::add(const KeyType& key, const MappedType& mapped)
-    {
-        return inlineAdd(key, mapped);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename MappedTraits>
-    typename HashMap<T, U, V, W, MappedTraits>::MappedType
-    HashMap<T, U, V, W, MappedTraits>::get(const KeyType& key) const
-    {
-        ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
-        if (!entry)
-            return MappedTraits::emptyValue();
-        return entry->second;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void HashMap<T, U, V, W, X>::remove(iterator it)
-    {
-        if (it.m_impl == m_impl.end())
-            return;
-        m_impl.internalCheckTableConsistency();
-        m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void HashMap<T, U, V, W, X>::remove(const KeyType& key)
-    {
-        remove(find(key));
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void HashMap<T, U, V, W, X>::clear()
-    {
-        m_impl.clear();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename MappedTraits>
-    typename HashMap<T, U, V, W, MappedTraits>::MappedType
-    HashMap<T, U, V, W, MappedTraits>::take(const KeyType& key)
-    {
-        // This can probably be made more efficient to avoid ref/deref churn.
-        iterator it = find(key);
-        if (it == end())
-            return MappedTraits::emptyValue();
-        typename HashMap<T, U, V, W, MappedTraits>::MappedType result = it->second;
-        remove(it);
-        return result;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void HashMap<T, U, V, W, X>::checkConsistency() const
-    {
-        m_impl.checkTableConsistency();
-    }
-
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    bool operator==(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
-    {
-        if (a.size() != b.size())
-            return false;
-
-        typedef typename HashMap<T, U, V, W, X>::const_iterator const_iterator;
-
-        const_iterator end = a.end();
-        const_iterator notFound = b.end();
-        for (const_iterator it = a.begin(); it != end; ++it) {
-            const_iterator bPos = b.find(it->first);
-            if (bPos == notFound || it->second != bPos->second)
-                return false;
-        }
-
-        return true;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline bool operator!=(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b)
-    {
-        return !(a == b);
-    }
-
-    template<typename MappedType, typename HashTableType>
-    void deleteAllPairSeconds(HashTableType& collection)
-    {
-        typedef typename HashTableType::const_iterator iterator;
-        iterator end = collection.end();
-        for (iterator it = collection.begin(); it != end; ++it)
-            delete it->second;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void deleteAllValues(const HashMap<T, U, V, W, X>& collection)
-    {
-        deleteAllPairSeconds<typename HashMap<T, U, V, W, X>::MappedType>(collection);
-    }
-
-    template<typename KeyType, typename HashTableType>
-    void deleteAllPairFirsts(HashTableType& collection)
-    {
-        typedef typename HashTableType::const_iterator iterator;
-        iterator end = collection.end();
-        for (iterator it = collection.begin(); it != end; ++it)
-            delete it->first;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void deleteAllKeys(const HashMap<T, U, V, W, X>& collection)
-    {
-        deleteAllPairFirsts<typename HashMap<T, U, V, W, X>::KeyType>(collection);
-    }
-    
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline void copyKeysToVector(const HashMap<T, U, V, W, X>& collection, Y& vector)
-    {
-        typedef typename HashMap<T, U, V, W, X>::const_iterator::Keys iterator;
-        
-        vector.resize(collection.size());
-        
-        iterator it = collection.begin().keys();
-        iterator end = collection.end().keys();
-        for (unsigned i = 0; it != end; ++it, ++i)
-            vector[i] = *it;
-    }  
-
-    template<typename T, typename U, typename V, typename W, typename X, typename Y>
-    inline void copyValuesToVector(const HashMap<T, U, V, W, X>& collection, Y& vector)
-    {
-        typedef typename HashMap<T, U, V, W, X>::const_iterator::Values iterator;
-        
-        vector.resize(collection.size());
-        
-        iterator it = collection.begin().values();
-        iterator end = collection.end().values();
-        for (unsigned i = 0; it != end; ++it, ++i)
-            vector[i] = *it;
-    }   
-
-} // namespace WTF
-
-using WTF::HashMap;
-
-#include "RefPtrHashMap.h"
-
-#endif /* WTF_HashMap_h */
diff --git a/wtf/HashSet.h b/wtf/HashSet.h
deleted file mode 100644 (file)
index 82245f3..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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_HashSet_h
-#define WTF_HashSet_h
-
-#include "FastAllocBase.h"
-#include "HashTable.h"
-
-namespace WTF {
-
-    template<typename Value, typename HashFunctions, typename Traits> class HashSet;
-    template<typename Value, typename HashFunctions, typename Traits>
-    void deleteAllValues(const HashSet<Value, HashFunctions, Traits>&);
-    template<typename Value, typename HashFunctions, typename Traits>
-    void fastDeleteAllValues(const HashSet<Value, HashFunctions, Traits>&);
-
-    template<typename T> struct IdentityExtractor;
-
-    template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash,
-        typename TraitsArg = HashTraits<ValueArg> > class HashSet {
-        WTF_MAKE_FAST_ALLOCATED;
-    private:
-        typedef HashArg HashFunctions;
-        typedef TraitsArg ValueTraits;
-
-    public:
-        typedef typename ValueTraits::TraitType ValueType;
-
-    private:
-        typedef HashTable<ValueType, ValueType, IdentityExtractor<ValueType>,
-            HashFunctions, ValueTraits, ValueTraits> HashTableType;
-
-    public:
-        typedef HashTableConstIteratorAdapter<HashTableType, ValueType> iterator;
-        typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
-
-        void swap(HashSet&);
-
-        int size() const;
-        int capacity() const;
-        bool isEmpty() const;
-
-        iterator begin() const;
-        iterator end() 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. HashTranslator
-        // 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&) 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, 
-        // and a bool that is true if an new entry was added.
-        pair<iterator, bool> add(const ValueType&);
-
-        // An alternate version of add() that finds the object by hashing and comparing
-        // with some other type, to avoid the cost of type conversion if the object is already
-        // in the table. HashTranslator must have the following function members:
-        //   static unsigned hash(const T&);
-        //   static bool equal(const ValueType&, const T&);
-        //   static translate(ValueType&, const T&, unsigned hashCode);
-        template<typename T, typename HashTranslator> pair<iterator, bool> add(const T&);
-
-        void remove(const ValueType&);
-        void remove(iterator);
-        void clear();
-
-    private:
-        friend void deleteAllValues<>(const HashSet&);
-        friend void fastDeleteAllValues<>(const HashSet&);
-
-        HashTableType m_impl;
-    };
-
-    template<typename T> struct IdentityExtractor {
-        static const T& extract(const T& t) { return t; }
-    };
-
-    template<typename ValueType, typename ValueTraits, typename T, typename Translator>
-    struct HashSetTranslatorAdapter {
-        static unsigned hash(const T& key) { return Translator::hash(key); }
-        static bool equal(const ValueType& a, const T& b) { return Translator::equal(a, b); }
-        static void translate(ValueType& location, const T& key, const T&, unsigned hashCode)
-        {
-            Translator::translate(location, key, hashCode);
-        }
-    };
-
-    template<typename T, typename U, typename V>
-    inline void HashSet<T, U, V>::swap(HashSet& other)
-    {
-        m_impl.swap(other.m_impl); 
-    }
-
-    template<typename T, typename U, typename V>
-    inline int HashSet<T, U, V>::size() const
-    {
-        return m_impl.size(); 
-    }
-
-    template<typename T, typename U, typename V>
-    inline int HashSet<T, U, V>::capacity() const
-    {
-        return m_impl.capacity(); 
-    }
-
-    template<typename T, typename U, typename V>
-    inline bool HashSet<T, U, V>::isEmpty() const
-    {
-        return m_impl.isEmpty(); 
-    }
-
-    template<typename T, typename U, typename V>
-    inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::begin() const
-    {
-        return m_impl.begin(); 
-    }
-
-    template<typename T, typename U, typename V>
-    inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::end() 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) const
-    {
-        return m_impl.find(value); 
-    }
-
-    template<typename T, typename U, typename V>
-    inline bool HashSet<T, U, V>::contains(const ValueType& value) const
-    {
-        return m_impl.contains(value); 
-    }
-
-    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) const
-    {
-        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>
-    inline bool HashSet<Value, HashFunctions, Traits>::contains(const T& value) const
-    {
-        typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, HashTranslator> Adapter;
-        return m_impl.template contains<T, Adapter>(value);
-    }
-
-    template<typename T, typename U, typename V>
-    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>
-    inline pair<typename HashSet<Value, HashFunctions, Traits>::iterator, bool>
-    HashSet<Value, HashFunctions, Traits>::add(const T& value)
-    {
-        typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, HashTranslator> Adapter;
-        return m_impl.template addPassingHashCode<T, T, Adapter>(value, value);
-    }
-
-    template<typename T, typename U, typename V>
-    inline void HashSet<T, U, V>::remove(iterator it)
-    {
-        if (it.m_impl == m_impl.end())
-            return;
-        m_impl.internalCheckTableConsistency();
-        m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
-    }
-
-    template<typename T, typename U, typename V>
-    inline void HashSet<T, U, V>::remove(const ValueType& value)
-    {
-        remove(find(value));
-    }
-
-    template<typename T, typename U, typename V>
-    inline void HashSet<T, U, V>::clear()
-    {
-        m_impl.clear(); 
-    }
-
-    template<typename ValueType, typename HashTableType>
-    void deleteAllValues(HashTableType& collection)
-    {
-        typedef typename HashTableType::const_iterator iterator;
-        iterator end = collection.end();
-        for (iterator it = collection.begin(); it != end; ++it)
-            delete *it;
-    }
-
-    template<typename T, typename U, typename V>
-    inline void deleteAllValues(const HashSet<T, U, V>& collection)
-    {
-        deleteAllValues<typename HashSet<T, U, V>::ValueType>(collection.m_impl);
-    }
-
-    template<typename ValueType, typename HashTableType>
-    void fastDeleteAllValues(HashTableType& collection)
-    {
-        typedef typename HashTableType::const_iterator iterator;
-        iterator end = collection.end();
-        for (iterator it = collection.begin(); it != end; ++it)
-            fastDelete(*it);
-    }
-
-    template<typename T, typename U, typename V>
-    inline void fastDeleteAllValues(const HashSet<T, U, V>& collection)
-    {
-        fastDeleteAllValues<typename HashSet<T, U, V>::ValueType>(collection.m_impl);
-    }
-    
-    template<typename T, typename U, typename V, typename W>
-    inline void copyToVector(const HashSet<T, U, V>& collection, W& vector)
-    {
-        typedef typename HashSet<T, U, V>::const_iterator iterator;
-        
-        vector.resize(collection.size());
-        
-        iterator it = collection.begin();
-        iterator end = collection.end();
-        for (unsigned i = 0; it != end; ++it, ++i)
-            vector[i] = *it;
-    }  
-
-} // namespace WTF
-
-using WTF::HashSet;
-
-#endif /* WTF_HashSet_h */
diff --git a/wtf/HashTable.cpp b/wtf/HashTable.cpp
deleted file mode 100644 (file)
index 71d3f86..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-    Copyright (C) 2005 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 "HashTable.h"
-
-namespace WTF {
-
-#if DUMP_HASHTABLE_STATS
-
-int HashTableStats::numAccesses;
-int HashTableStats::numCollisions;
-int HashTableStats::collisionGraph[4096];
-int HashTableStats::maxCollisions;
-int HashTableStats::numRehashes;
-int HashTableStats::numRemoves;
-int HashTableStats::numReinserts;
-
-static HashTableStats logger;
-
-static Mutex& hashTableStatsMutex()
-{
-    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
-    return mutex;
-}
-
-HashTableStats::~HashTableStats()
-{
-    // Don't lock hashTableStatsMutex here because it can cause deadlocks at shutdown 
-    // if any thread was killed while holding the mutex.
-    printf("\nWTF::HashTable statistics\n\n");
-    printf("%d accesses\n", numAccesses);
-    printf("%d total collisions, average %.2f probes per access\n", numCollisions, 1.0 * (numAccesses + numCollisions) / numAccesses);
-    printf("longest collision chain: %d\n", maxCollisions);
-    for (int i = 1; i <= maxCollisions; i++) {
-        printf("  %d lookups with exactly %d collisions (%.2f%% , %.2f%% with this many or more)\n", collisionGraph[i], i, 100.0 * (collisionGraph[i] - collisionGraph[i+1]) / numAccesses, 100.0 * collisionGraph[i] / numAccesses);
-    }
-    printf("%d rehashes\n", numRehashes);
-    printf("%d reinserts\n", numReinserts);
-}
-
-void HashTableStats::recordCollisionAtCount(int count)
-{
-    MutexLocker lock(hashTableStatsMutex());
-    if (count > maxCollisions)
-        maxCollisions = count;
-    numCollisions++;
-    collisionGraph[count]++;
-}
-
-#endif
-
-} // namespace WTF
diff --git a/wtf/HashTable.h b/wtf/HashTable.h
deleted file mode 100644 (file)
index 79e8b3f..0000000
+++ /dev/null
@@ -1,1183 +0,0 @@
-/*
- * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2008 David Levin <levin@chromium.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 WTF_HashTable_h
-#define WTF_HashTable_h
-
-#include "FastMalloc.h"
-#include "HashTraits.h"
-#include "ValueCheck.h"
-#include <wtf/Assertions.h>
-#include <wtf/Threading.h>
-
-namespace WTF {
-
-#define DUMP_HASHTABLE_STATS 0
-// Enables internal WTF consistency checks that are invoked automatically. Non-WTF callers can call checkTableConsistency() even if internal checks are disabled.
-#define CHECK_HASHTABLE_CONSISTENCY 0
-
-#ifdef NDEBUG
-#define CHECK_HASHTABLE_ITERATORS 0
-#define CHECK_HASHTABLE_USE_AFTER_DESTRUCTION 0
-#else
-#define CHECK_HASHTABLE_ITERATORS 1
-#define CHECK_HASHTABLE_USE_AFTER_DESTRUCTION 1
-#endif
-
-#if DUMP_HASHTABLE_STATS
-
-    struct HashTableStats {
-        ~HashTableStats();
-        // All of the variables are accessed in ~HashTableStats when the static struct is destroyed.
-
-        // The following variables are all atomically incremented when modified.
-        static int numAccesses;
-        static int numRehashes;
-        static int numRemoves;
-        static int numReinserts;
-
-        // The following variables are only modified in the recordCollisionAtCount method within a mutex.
-        static int maxCollisions;
-        static int numCollisions;
-        static int collisionGraph[4096];
-
-        static void recordCollisionAtCount(int count);
-    };
-
-#endif
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    class HashTable;
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    class HashTableIterator;
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    class HashTableConstIterator;
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*,
-        HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*);
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*);
-
-#if !CHECK_HASHTABLE_ITERATORS
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    inline void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*,
-        HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*) { }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    inline void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*) { }
-
-#endif
-
-    typedef enum { HashItemKnownGood } HashItemKnownGoodTag;
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    class HashTableConstIterator {
-    private:
-        typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> HashTableType;
-        typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> iterator;
-        typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator;
-        typedef Value ValueType;
-        typedef const ValueType& ReferenceType;
-        typedef const ValueType* PointerType;
-
-        friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>;
-        friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>;
-
-        void skipEmptyBuckets()
-        {
-            while (m_position != m_endPosition && HashTableType::isEmptyOrDeletedBucket(*m_position))
-                ++m_position;
-        }
-
-        HashTableConstIterator(const HashTableType* table, PointerType position, PointerType endPosition)
-            : m_position(position), m_endPosition(endPosition)
-        {
-            addIterator(table, this);
-            skipEmptyBuckets();
-        }
-
-        HashTableConstIterator(const HashTableType* table, PointerType position, PointerType endPosition, HashItemKnownGoodTag)
-            : m_position(position), m_endPosition(endPosition)
-        {
-            addIterator(table, this);
-        }
-
-    public:
-        HashTableConstIterator()
-        {
-            addIterator(static_cast<const HashTableType*>(0), this);
-        }
-
-        // default copy, assignment and destructor are OK if CHECK_HASHTABLE_ITERATORS is 0
-
-#if CHECK_HASHTABLE_ITERATORS
-        ~HashTableConstIterator()
-        {
-            removeIterator(this);
-        }
-
-        HashTableConstIterator(const const_iterator& other)
-            : m_position(other.m_position), m_endPosition(other.m_endPosition)
-        {
-            addIterator(other.m_table, this);
-        }
-
-        const_iterator& operator=(const const_iterator& other)
-        {
-            m_position = other.m_position;
-            m_endPosition = other.m_endPosition;
-
-            removeIterator(this);
-            addIterator(other.m_table, this);
-
-            return *this;
-        }
-#endif
-
-        PointerType get() const
-        {
-            checkValidity();
-            return m_position;
-        }
-        ReferenceType operator*() const { return *get(); }
-        PointerType operator->() const { return get(); }
-
-        const_iterator& operator++()
-        {
-            checkValidity();
-            ASSERT(m_position != m_endPosition);
-            ++m_position;
-            skipEmptyBuckets();
-            return *this;
-        }
-
-        // postfix ++ intentionally omitted
-
-        // Comparison.
-        bool operator==(const const_iterator& other) const
-        {
-            checkValidity(other);
-            return m_position == other.m_position;
-        }
-        bool operator!=(const const_iterator& other) const
-        {
-            checkValidity(other);
-            return m_position != other.m_position;
-        }
-
-    private:
-        void checkValidity() const
-        {
-#if CHECK_HASHTABLE_ITERATORS
-            ASSERT(m_table);
-#endif
-        }
-
-
-#if CHECK_HASHTABLE_ITERATORS
-        void checkValidity(const const_iterator& other) const
-        {
-            ASSERT(m_table);
-            ASSERT_UNUSED(other, other.m_table);
-            ASSERT(m_table == other.m_table);
-        }
-#else
-        void checkValidity(const const_iterator&) const { }
-#endif
-
-        PointerType m_position;
-        PointerType m_endPosition;
-
-#if CHECK_HASHTABLE_ITERATORS
-    public:
-        // Any modifications of the m_next or m_previous of an iterator that is in a linked list of a HashTable::m_iterator,
-        // should be guarded with m_table->m_mutex.
-        mutable const HashTableType* m_table;
-        mutable const_iterator* m_next;
-        mutable const_iterator* m_previous;
-#endif
-    };
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    class HashTableIterator {
-    private:
-        typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> HashTableType;
-        typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> iterator;
-        typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator;
-        typedef Value ValueType;
-        typedef ValueType& ReferenceType;
-        typedef ValueType* PointerType;
-
-        friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>;
-
-        HashTableIterator(HashTableType* table, PointerType pos, PointerType end) : m_iterator(table, pos, end) { }
-        HashTableIterator(HashTableType* table, PointerType pos, PointerType end, HashItemKnownGoodTag tag) : m_iterator(table, pos, end, tag) { }
-
-    public:
-        HashTableIterator() { }
-
-        // default copy, assignment and destructor are OK
-
-        PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
-        ReferenceType operator*() const { return *get(); }
-        PointerType operator->() const { return get(); }
-
-        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; }
-
-        operator const_iterator() const { return m_iterator; }
-
-    private:
-        const_iterator m_iterator;
-    };
-
-    using std::swap;
-
-    // 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 hashTableSwap(pair<T, U>& a, pair<T, U>& b)
-    {
-        swap(a.first, b.first);
-        swap(a.second, b.second);
-    }
-
-    template<typename T, bool useSwap> struct Mover;
-    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 {
-    public:
-        static unsigned hash(const Key& key) { return HashFunctions::hash(key); }
-        static bool equal(const Key& a, const Key& b) { return HashFunctions::equal(a, b); }
-        static void translate(Value& location, const Key&, const Value& value) { location = value; }
-    };
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    class HashTable {
-    public:
-        typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> iterator;
-        typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator;
-        typedef Traits ValueTraits;
-        typedef Key KeyType;
-        typedef Value ValueType;
-        typedef IdentityHashTranslator<Key, Value, HashFunctions> IdentityTranslatorType;
-
-        HashTable();
-        ~HashTable() 
-        {
-            invalidateIterators(); 
-            deallocateTable(m_table, m_tableSize); 
-#if CHECK_HASHTABLE_USE_AFTER_DESTRUCTION
-            m_table = (ValueType*)(uintptr_t)0xbbadbeef;
-#endif
-        }
-
-        HashTable(const HashTable&);
-        void swap(HashTable&);
-        HashTable& operator=(const HashTable&);
-
-        iterator begin() { return makeIterator(m_table); }
-        iterator end() { return makeKnownGoodIterator(m_table + m_tableSize); }
-        const_iterator begin() const { return makeConstIterator(m_table); }
-        const_iterator end() const { return makeKnownGoodConstIterator(m_table + m_tableSize); }
-
-        int size() const { return m_keyCount; }
-        int capacity() const { return m_tableSize; }
-        bool isEmpty() const { return !m_keyCount; }
-
-        pair<iterator, bool> add(const ValueType& value) { return add<KeyType, ValueType, IdentityTranslatorType>(Extractor::extract(value), value); }
-
-        // A special version of add() that finds the object by hashing and comparing
-        // with some other type, to avoid the cost of type conversion if the object is already
-        // in the table.
-        template<typename T, typename Extra, typename HashTranslator> pair<iterator, bool> add(const T& key, const Extra&);
-        template<typename T, typename Extra, typename HashTranslator> pair<iterator, bool> addPassingHashCode(const T& key, const Extra&);
-
-        iterator find(const KeyType& key) { return find<KeyType, IdentityTranslatorType>(key); }
-        const_iterator find(const KeyType& key) const { return find<KeyType, IdentityTranslatorType>(key); }
-        bool contains(const KeyType& key) const { return contains<KeyType, IdentityTranslatorType>(key); }
-
-        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;
-
-        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(); }
-        static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); }
-        static bool isEmptyOrDeletedBucket(const ValueType& value) { return isEmptyBucket(value) || isDeletedBucket(value); }
-
-        ValueType* lookup(const Key& key) { return lookup<Key, IdentityTranslatorType>(key); }
-        template<typename T, typename HashTranslator> ValueType* lookup(const T&);
-
-#if !ASSERT_DISABLED
-        void checkTableConsistency() const;
-#else
-        static void checkTableConsistency() { }
-#endif
-#if CHECK_HASHTABLE_CONSISTENCY
-        void internalCheckTableConsistency() const { checkTableConsistency(); }
-        void internalCheckTableConsistencyExceptSize() const { checkTableConsistencyExceptSize(); }
-#else
-        static void internalCheckTableConsistencyExceptSize() { }
-        static void internalCheckTableConsistency() { }
-#endif
-
-    private:
-        static ValueType* allocateTable(int size);
-        static void deallocateTable(ValueType* table, int size);
-
-        typedef pair<ValueType*, bool> LookupType;
-        typedef pair<LookupType, unsigned> FullLookupType;
-
-        LookupType lookupForWriting(const Key& key) { return lookupForWriting<Key, IdentityTranslatorType>(key); };
-        template<typename T, typename HashTranslator> FullLookupType fullLookupForWriting(const T&);
-        template<typename T, typename HashTranslator> LookupType lookupForWriting(const T&);
-
-        template<typename T, typename HashTranslator> void checkKey(const T&);
-
-        void removeAndInvalidateWithoutEntryConsistencyCheck(ValueType*);
-        void removeAndInvalidate(ValueType*);
-        void remove(ValueType*);
-
-        bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_maxLoad >= m_tableSize; }
-        bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_tableSize * 2; }
-        bool shouldShrink() const { return m_keyCount * m_minLoad < m_tableSize && m_tableSize > m_minTableSize; }
-        void expand();
-        void shrink() { rehash(m_tableSize / 2); }
-
-        void rehash(int newTableSize);
-        void reinsert(ValueType&);
-
-        static void initializeBucket(ValueType& bucket) { new (&bucket) ValueType(Traits::emptyValue()); }
-        static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Traits::constructDeletedValue(bucket); }
-
-        FullLookupType makeLookupResult(ValueType* position, bool found, unsigned hash)
-            { return FullLookupType(LookupType(position, found), hash); }
-
-        iterator makeIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize); }
-        const_iterator makeConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize); }
-        iterator makeKnownGoodIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); }
-        const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); }
-
-#if !ASSERT_DISABLED
-        void checkTableConsistencyExceptSize() const;
-#else
-        static void checkTableConsistencyExceptSize() { }
-#endif
-
-#if CHECK_HASHTABLE_ITERATORS
-        void invalidateIterators();
-#else
-        static void invalidateIterators() { }
-#endif
-
-        static const int m_minTableSize = 64;
-        static const int m_maxLoad = 2;
-        static const int m_minLoad = 6;
-
-        ValueType* m_table;
-        int m_tableSize;
-        int m_tableSizeMask;
-        int m_keyCount;
-        int m_deletedCount;
-
-#if CHECK_HASHTABLE_ITERATORS
-    public:
-        // All access to m_iterators should be guarded with m_mutex.
-        mutable const_iterator* m_iterators;
-        mutable Mutex m_mutex;
-#endif
-    };
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::HashTable()
-        : m_table(0)
-        , m_tableSize(0)
-        , m_tableSizeMask(0)
-        , m_keyCount(0)
-        , m_deletedCount(0)
-#if CHECK_HASHTABLE_ITERATORS
-        , m_iterators(0)
-#endif
-    {
-    }
-
-    static inline unsigned doubleHash(unsigned key)
-    {
-        key = ~key + (key >> 23);
-        key ^= (key << 12);
-        key ^= (key >> 7);
-        key ^= (key << 2);
-        key ^= (key >> 20);
-        return key;
-    }
-
-#if ASSERT_DISABLED
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    template<typename T, typename HashTranslator>
-    inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkKey(const T&)
-    {
-    }
-
-#else
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    template<typename T, typename HashTranslator>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkKey(const T& key)
-    {
-        if (!HashFunctions::safeToCompareToEmptyOrDeleted)
-            return;
-        ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key));
-        ValueType deletedValue = Traits::emptyValue();
-        deletedValue.~ValueType();
-        Traits::constructDeletedValue(deletedValue);
-        ASSERT(!HashTranslator::equal(Extractor::extract(deletedValue), key));
-        new (&deletedValue) ValueType(Traits::emptyValue());
-    }
-
-#endif
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    template<typename T, typename HashTranslator>
-    inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookup(const T& key)
-    {
-        checkKey<T, HashTranslator>(key);
-
-        int k = 0;
-        int sizeMask = m_tableSizeMask;
-        ValueType* table = m_table;
-        unsigned h = HashTranslator::hash(key);
-        int i = h & sizeMask;
-
-        if (!table)
-            return 0;
-
-#if DUMP_HASHTABLE_STATS
-        atomicIncrement(&HashTableStats::numAccesses);
-        int probeCount = 0;
-#endif
-
-        while (1) {
-            ValueType* entry = table + i;
-                
-            // we count on the compiler to optimize out this branch
-            if (HashFunctions::safeToCompareToEmptyOrDeleted) {
-                if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return entry;
-                
-                if (isEmptyBucket(*entry))
-                    return 0;
-            } else {
-                if (isEmptyBucket(*entry))
-                    return 0;
-                
-                if (!isDeletedBucket(*entry) && HashTranslator::equal(Extractor::extract(*entry), key))
-                    return entry;
-            }
-#if DUMP_HASHTABLE_STATS
-            ++probeCount;
-            HashTableStats::recordCollisionAtCount(probeCount);
-#endif
-            if (k == 0)
-                k = 1 | doubleHash(h);
-            i = (i + k) & sizeMask;
-        }
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    template<typename T, typename HashTranslator>
-    inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookupForWriting(const T& key)
-    {
-        ASSERT(m_table);
-        checkKey<T, HashTranslator>(key);
-
-        int k = 0;
-        ValueType* table = m_table;
-        int sizeMask = m_tableSizeMask;
-        unsigned h = HashTranslator::hash(key);
-        int i = h & sizeMask;
-
-#if DUMP_HASHTABLE_STATS
-        atomicIncrement(&HashTableStats::numAccesses);
-        int probeCount = 0;
-#endif
-
-        ValueType* deletedEntry = 0;
-
-        while (1) {
-            ValueType* entry = table + i;
-            
-            // we count on the compiler to optimize out this branch
-            if (HashFunctions::safeToCompareToEmptyOrDeleted) {
-                if (isEmptyBucket(*entry))
-                    return LookupType(deletedEntry ? deletedEntry : entry, false);
-                
-                if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return LookupType(entry, true);
-                
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-            } else {
-                if (isEmptyBucket(*entry))
-                    return LookupType(deletedEntry ? deletedEntry : entry, false);
-            
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-                else if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return LookupType(entry, true);
-            }
-#if DUMP_HASHTABLE_STATS
-            ++probeCount;
-            HashTableStats::recordCollisionAtCount(probeCount);
-#endif
-            if (k == 0)
-                k = 1 | doubleHash(h);
-            i = (i + k) & sizeMask;
-        }
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    template<typename T, typename HashTranslator>
-    inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::fullLookupForWriting(const T& key)
-    {
-        ASSERT(m_table);
-        checkKey<T, HashTranslator>(key);
-
-        int k = 0;
-        ValueType* table = m_table;
-        int sizeMask = m_tableSizeMask;
-        unsigned h = HashTranslator::hash(key);
-        int i = h & sizeMask;
-
-#if DUMP_HASHTABLE_STATS
-        atomicIncrement(&HashTableStats::numAccesses);
-        int probeCount = 0;
-#endif
-
-        ValueType* deletedEntry = 0;
-
-        while (1) {
-            ValueType* entry = table + i;
-            
-            // we count on the compiler to optimize out this branch
-            if (HashFunctions::safeToCompareToEmptyOrDeleted) {
-                if (isEmptyBucket(*entry))
-                    return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h);
-                
-                if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return makeLookupResult(entry, true, h);
-                
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-            } else {
-                if (isEmptyBucket(*entry))
-                    return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h);
-            
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-                else if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return makeLookupResult(entry, true, h);
-            }
-#if DUMP_HASHTABLE_STATS
-            ++probeCount;
-            HashTableStats::recordCollisionAtCount(probeCount);
-#endif
-            if (k == 0)
-                k = 1 | doubleHash(h);
-            i = (i + k) & sizeMask;
-        }
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    template<typename T, typename Extra, typename HashTranslator>
-    inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::add(const T& key, const Extra& extra)
-    {
-        checkKey<T, HashTranslator>(key);
-
-        invalidateIterators();
-
-        if (!m_table)
-            expand();
-
-        internalCheckTableConsistency();
-
-        ASSERT(m_table);
-
-        int k = 0;
-        ValueType* table = m_table;
-        int sizeMask = m_tableSizeMask;
-        unsigned h = HashTranslator::hash(key);
-        int i = h & sizeMask;
-
-#if DUMP_HASHTABLE_STATS
-        atomicIncrement(&HashTableStats::numAccesses);
-        int probeCount = 0;
-#endif
-
-        ValueType* deletedEntry = 0;
-        ValueType* entry;
-        while (1) {
-            entry = table + i;
-            
-            // we count on the compiler to optimize out this branch
-            if (HashFunctions::safeToCompareToEmptyOrDeleted) {
-                if (isEmptyBucket(*entry))
-                    break;
-                
-                if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return std::make_pair(makeKnownGoodIterator(entry), false);
-                
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-            } else {
-                if (isEmptyBucket(*entry))
-                    break;
-            
-                if (isDeletedBucket(*entry))
-                    deletedEntry = entry;
-                else if (HashTranslator::equal(Extractor::extract(*entry), key))
-                    return std::make_pair(makeKnownGoodIterator(entry), false);
-            }
-#if DUMP_HASHTABLE_STATS
-            ++probeCount;
-            HashTableStats::recordCollisionAtCount(probeCount);
-#endif
-            if (k == 0)
-                k = 1 | doubleHash(h);
-            i = (i + k) & sizeMask;
-        }
-
-        if (deletedEntry) {
-            initializeBucket(*deletedEntry);
-            entry = deletedEntry;
-            --m_deletedCount; 
-        }
-
-        HashTranslator::translate(*entry, key, extra);
-
-        ++m_keyCount;
-        
-        if (shouldExpand()) {
-            // FIXME: This makes an extra copy on expand. Probably not that bad since
-            // expand is rare, but would be better to have a version of expand that can
-            // follow a pivot entry and return the new position.
-            KeyType enteredKey = Extractor::extract(*entry);
-            expand();
-            pair<iterator, bool> p = std::make_pair(find(enteredKey), true);
-            ASSERT(p.first != end());
-            return p;
-        }
-        
-        internalCheckTableConsistency();
-        
-        return std::make_pair(makeKnownGoodIterator(entry), true);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    template<typename T, typename Extra, typename HashTranslator>
-    inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::addPassingHashCode(const T& key, const Extra& extra)
-    {
-        checkKey<T, HashTranslator>(key);
-
-        invalidateIterators();
-
-        if (!m_table)
-            expand();
-
-        internalCheckTableConsistency();
-
-        FullLookupType lookupResult = fullLookupForWriting<T, HashTranslator>(key);
-
-        ValueType* entry = lookupResult.first.first;
-        bool found = lookupResult.first.second;
-        unsigned h = lookupResult.second;
-        
-        if (found)
-            return std::make_pair(makeKnownGoodIterator(entry), false);
-        
-        if (isDeletedBucket(*entry)) {
-            initializeBucket(*entry);
-            --m_deletedCount;
-        }
-        
-        HashTranslator::translate(*entry, key, extra, h);
-        ++m_keyCount;
-        if (shouldExpand()) {
-            // FIXME: This makes an extra copy on expand. Probably not that bad since
-            // expand is rare, but would be better to have a version of expand that can
-            // follow a pivot entry and return the new position.
-            KeyType enteredKey = Extractor::extract(*entry);
-            expand();
-            pair<iterator, bool> p = std::make_pair(find(enteredKey), true);
-            ASSERT(p.first != end());
-            return p;
-        }
-
-        internalCheckTableConsistency();
-
-        return std::make_pair(makeKnownGoodIterator(entry), true);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::reinsert(ValueType& entry)
-    {
-        ASSERT(m_table);
-        ASSERT(!lookupForWriting(Extractor::extract(entry)).second);
-        ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).first)));
-#if DUMP_HASHTABLE_STATS
-        atomicIncrement(&HashTableStats::numReinserts);
-#endif
-
-        Mover<ValueType, Traits::needsDestruction>::move(entry, *lookupForWriting(Extractor::extract(entry)).first);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    template <typename T, typename HashTranslator> 
-    typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::find(const T& key)
-    {
-        if (!m_table)
-            return end();
-
-        ValueType* entry = lookup<T, HashTranslator>(key);
-        if (!entry)
-            return end();
-
-        return makeKnownGoodIterator(entry);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    template <typename T, typename HashTranslator> 
-    typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::const_iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::find(const T& key) const
-    {
-        if (!m_table)
-            return end();
-
-        ValueType* entry = const_cast<HashTable*>(this)->lookup<T, HashTranslator>(key);
-        if (!entry)
-            return end();
-
-        return makeKnownGoodConstIterator(entry);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    template <typename T, typename HashTranslator> 
-    bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::contains(const T& key) const
-    {
-        if (!m_table)
-            return false;
-
-        return const_cast<HashTable*>(this)->lookup<T, HashTranslator>(key);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeAndInvalidateWithoutEntryConsistencyCheck(ValueType* pos)
-    {
-        invalidateIterators();
-        remove(pos);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeAndInvalidate(ValueType* pos)
-    {
-        invalidateIterators();
-        internalCheckTableConsistency();
-        remove(pos);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(ValueType* pos)
-    {
-#if DUMP_HASHTABLE_STATS
-        atomicIncrement(&HashTableStats::numRemoves);
-#endif
-
-        deleteBucket(*pos);
-        ++m_deletedCount;
-        --m_keyCount;
-
-        if (shouldShrink())
-            shrink();
-
-        internalCheckTableConsistency();
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(iterator it)
-    {
-        if (it == end())
-            return;
-
-        removeAndInvalidate(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(iterator it)
-    {
-        if (it == end())
-            return;
-
-        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)
-    {
-        remove(find(key));
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::allocateTable(int size)
-    {
-        // would use a template member function with explicit specializations here, but
-        // gcc doesn't appear to support that
-        if (Traits::emptyValueIsZero)
-            return static_cast<ValueType*>(fastZeroedMalloc(size * sizeof(ValueType)));
-        ValueType* result = static_cast<ValueType*>(fastMalloc(size * sizeof(ValueType)));
-        for (int i = 0; i < size; i++)
-            initializeBucket(result[i]);
-        return result;
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::deallocateTable(ValueType* table, int size)
-    {
-        if (Traits::needsDestruction) {
-            for (int i = 0; i < size; ++i) {
-                if (!isDeletedBucket(table[i]))
-                    table[i].~ValueType();
-            }
-        }
-        fastFree(table);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::expand()
-    {
-        int newSize;
-        if (m_tableSize == 0)
-            newSize = m_minTableSize;
-        else if (mustRehashInPlace())
-            newSize = m_tableSize;
-        else
-            newSize = m_tableSize * 2;
-
-        rehash(newSize);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::rehash(int newTableSize)
-    {
-        internalCheckTableConsistencyExceptSize();
-
-        int oldTableSize = m_tableSize;
-        ValueType* oldTable = m_table;
-
-#if DUMP_HASHTABLE_STATS
-        if (oldTableSize != 0)
-            atomicIncrement(&HashTableStats::numRehashes);
-#endif
-
-        m_tableSize = newTableSize;
-        m_tableSizeMask = newTableSize - 1;
-        m_table = allocateTable(newTableSize);
-
-        for (int i = 0; i != oldTableSize; ++i)
-            if (!isEmptyOrDeletedBucket(oldTable[i]))
-                reinsert(oldTable[i]);
-
-        m_deletedCount = 0;
-
-        deallocateTable(oldTable, oldTableSize);
-
-        internalCheckTableConsistency();
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::clear()
-    {
-        invalidateIterators();
-        deallocateTable(m_table, m_tableSize);
-        m_table = 0;
-        m_tableSize = 0;
-        m_tableSizeMask = 0;
-        m_keyCount = 0;
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::HashTable(const HashTable& other)
-        : m_table(0)
-        , m_tableSize(0)
-        , m_tableSizeMask(0)
-        , m_keyCount(0)
-        , m_deletedCount(0)
-#if CHECK_HASHTABLE_ITERATORS
-        , m_iterators(0)
-#endif
-    {
-        // Copy the hash table the dumb way, by adding each element to the new table.
-        // It might be more efficient to copy the table slots, but it's not clear that efficiency is needed.
-        const_iterator end = other.end();
-        for (const_iterator it = other.begin(); it != end; ++it)
-            add(*it);
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::swap(HashTable& other)
-    {
-        invalidateIterators();
-        other.invalidateIterators();
-
-        ValueType* tmp_table = m_table;
-        m_table = other.m_table;
-        other.m_table = tmp_table;
-
-        int tmp_tableSize = m_tableSize;
-        m_tableSize = other.m_tableSize;
-        other.m_tableSize = tmp_tableSize;
-
-        int tmp_tableSizeMask = m_tableSizeMask;
-        m_tableSizeMask = other.m_tableSizeMask;
-        other.m_tableSizeMask = tmp_tableSizeMask;
-
-        int tmp_keyCount = m_keyCount;
-        m_keyCount = other.m_keyCount;
-        other.m_keyCount = tmp_keyCount;
-
-        int tmp_deletedCount = m_deletedCount;
-        m_deletedCount = other.m_deletedCount;
-        other.m_deletedCount = tmp_deletedCount;
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::operator=(const HashTable& other)
-    {
-        HashTable tmp(other);
-        swap(tmp);
-        return *this;
-    }
-
-#if !ASSERT_DISABLED
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkTableConsistency() const
-    {
-        checkTableConsistencyExceptSize();
-        ASSERT(!m_table || !shouldExpand());
-        ASSERT(!shouldShrink());
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkTableConsistencyExceptSize() const
-    {
-        if (!m_table)
-            return;
-
-        int count = 0;
-        int deletedCount = 0;
-        for (int j = 0; j < m_tableSize; ++j) {
-            ValueType* entry = m_table + j;
-            if (isEmptyBucket(*entry))
-                continue;
-
-            if (isDeletedBucket(*entry)) {
-                ++deletedCount;
-                continue;
-            }
-
-            const_iterator it = find(Extractor::extract(*entry));
-            ASSERT(entry == it.m_position);
-            ++count;
-
-            ValueCheck<Key>::checkConsistency(it->first);
-        }
-
-        ASSERT(count == m_keyCount);
-        ASSERT(deletedCount == m_deletedCount);
-        ASSERT(m_tableSize >= m_minTableSize);
-        ASSERT(m_tableSizeMask);
-        ASSERT(m_tableSize == m_tableSizeMask + 1);
-    }
-
-#endif // ASSERT_DISABLED
-
-#if CHECK_HASHTABLE_ITERATORS
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::invalidateIterators()
-    {
-        MutexLocker lock(m_mutex);
-        const_iterator* next;
-        for (const_iterator* p = m_iterators; p; p = next) {
-            next = p->m_next;
-            p->m_table = 0;
-            p->m_next = 0;
-            p->m_previous = 0;
-        }
-        m_iterators = 0;
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* table,
-        HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* it)
-    {
-        it->m_table = table;
-        it->m_previous = 0;
-
-        // Insert iterator at head of doubly-linked list of iterators.
-        if (!table) {
-            it->m_next = 0;
-        } else {
-            MutexLocker lock(table->m_mutex);
-            ASSERT(table->m_iterators != it);
-            it->m_next = table->m_iterators;
-            table->m_iterators = it;
-            if (it->m_next) {
-                ASSERT(!it->m_next->m_previous);
-                it->m_next->m_previous = it;
-            }
-        }
-    }
-
-    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
-    void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* it)
-    {
-        typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> HashTableType;
-        typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator;
-
-        // Delete iterator from doubly-linked list of iterators.
-        if (!it->m_table) {
-            ASSERT(!it->m_next);
-            ASSERT(!it->m_previous);
-        } else {
-            MutexLocker lock(it->m_table->m_mutex);
-            if (it->m_next) {
-                ASSERT(it->m_next->m_previous == it);
-                it->m_next->m_previous = it->m_previous;
-            }
-            if (it->m_previous) {
-                ASSERT(it->m_table->m_iterators != it);
-                ASSERT(it->m_previous->m_next == it);
-                it->m_previous->m_next = it->m_next;
-            } else {
-                ASSERT(it->m_table->m_iterators == it);
-                it->m_table->m_iterators = it->m_next;
-            }
-        }
-
-        it->m_table = 0;
-        it->m_next = 0;
-        it->m_previous = 0;
-    }
-
-#endif // CHECK_HASHTABLE_ITERATORS
-
-    // 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(); }
-        const ValueType& operator*() const { return *get(); }
-        const ValueType* operator->() const { return get(); }
-
-        HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        typename HashTableType::const_iterator m_impl;
-    };
-
-    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(); }
-        ValueType& operator*() const { return *get(); }
-        ValueType* operator->() const { return get(); }
-
-        HashTableIteratorAdapter& operator++() { ++m_impl; return *this; }
-        // postfix ++ intentionally omitted
-
-        operator HashTableConstIteratorAdapter<HashTableType, ValueType>() {
-            typename HashTableType::const_iterator i = m_impl;
-            return i;
-        }
-
-        typename HashTableType::iterator m_impl;
-    };
-
-    template<typename T, typename U>
-    inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
-    {
-        return a.m_impl == b.m_impl;
-    }
-
-    template<typename T, typename U>
-    inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
-
-    template<typename T, typename U>
-    inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
-    {
-        return a.m_impl == b.m_impl;
-    }
-
-    template<typename T, typename U>
-    inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b)
-    {
-        return a.m_impl != b.m_impl;
-    }
-
-} // namespace WTF
-
-#include "HashIterators.h"
-
-#endif // WTF_HashTable_h
diff --git a/wtf/HashTraits.h b/wtf/HashTraits.h
deleted file mode 100644 (file)
index fba5afe..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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_HashTraits_h
-#define WTF_HashTraits_h
-
-#include "HashFunctions.h"
-#include "TypeTraits.h"
-#include <utility>
-#include <limits>
-
-namespace WTF {
-
-    using std::pair;
-    using std::make_pair;
-
-    template<typename T> struct HashTraits;
-
-    template<bool isInteger, typename T> struct GenericHashTraitsBase;
-
-    template<typename T> struct GenericHashTraitsBase<false, T> {
-        static const bool emptyValueIsZero = false;
-        static const bool needsDestruction = true;
-    };
-
-    // Default integer traits disallow both 0 and -1 as keys (max value instead of -1 for unsigned).
-    template<typename T> struct GenericHashTraitsBase<true, T> {
-        static const bool emptyValueIsZero = true;
-        static const bool needsDestruction = false;
-        static void constructDeletedValue(T& slot) { slot = static_cast<T>(-1); }
-        static bool isDeletedValue(T value) { return value == static_cast<T>(-1); }
-    };
-
-    template<typename T> struct GenericHashTraits : GenericHashTraitsBase<IsInteger<T>::value, T> {
-        typedef T TraitType;
-        static T emptyValue() { return T(); }
-    };
-
-    template<typename T> struct HashTraits : GenericHashTraits<T> { };
-
-    template<typename T> struct FloatHashTraits : GenericHashTraits<T> {
-        static const bool needsDestruction = false;
-        static T emptyValue() { return std::numeric_limits<T>::infinity(); }
-        static void constructDeletedValue(T& slot) { slot = -std::numeric_limits<T>::infinity(); }
-        static bool isDeletedValue(T value) { return value == -std::numeric_limits<T>::infinity(); }
-    };
-
-    template<> struct HashTraits<float> : FloatHashTraits<float> { };
-    template<> struct HashTraits<double> : FloatHashTraits<double> { };
-
-    // Default unsigned traits disallow both 0 and max as keys -- use these traits to allow zero and disallow max - 1.
-    template<typename T> struct UnsignedWithZeroKeyHashTraits : GenericHashTraits<T> {
-        static const bool emptyValueIsZero = false;
-        static const bool needsDestruction = false;
-        static T emptyValue() { return std::numeric_limits<T>::max(); }
-        static void constructDeletedValue(T& slot) { slot = std::numeric_limits<T>::max() - 1; }
-        static bool isDeletedValue(T value) { return value == std::numeric_limits<T>::max() - 1; }
-    };
-
-    template<typename P> struct HashTraits<P*> : GenericHashTraits<P*> {
-        static const bool emptyValueIsZero = true;
-        static const bool needsDestruction = false;
-        static void constructDeletedValue(P*& slot) { slot = reinterpret_cast<P*>(-1); }
-        static bool isDeletedValue(P* value) { return value == reinterpret_cast<P*>(-1); }
-    };
-
-    template<typename T> struct SimpleClassHashTraits : GenericHashTraits<T> {
-        static const bool emptyValueIsZero = true;
-        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>
-    struct PairHashTraits : GenericHashTraits<pair<typename FirstTraitsArg::TraitType, typename SecondTraitsArg::TraitType> > {
-        typedef FirstTraitsArg FirstTraits;
-        typedef SecondTraitsArg SecondTraits;
-        typedef pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType> TraitType;
-
-        static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
-        static TraitType emptyValue() { return make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
-
-        static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
-
-        static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
-        static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
-    };
-
-    template<typename First, typename Second>
-    struct HashTraits<pair<First, Second> > : public PairHashTraits<HashTraits<First>, HashTraits<Second> > { };
-
-} // namespace WTF
-
-using WTF::HashTraits;
-using WTF::PairHashTraits;
-
-#endif // WTF_HashTraits_h
diff --git a/wtf/HexNumber.h b/wtf/HexNumber.h
deleted file mode 100644 (file)
index 8fd6032..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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
diff --git a/wtf/ListHashSet.h b/wtf/ListHashSet.h
deleted file mode 100644 (file)
index 25b73c1..0000000
+++ /dev/null
@@ -1,709 +0,0 @@
-/*
- * 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
- * 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_ListHashSet_h
-#define WTF_ListHashSet_h
-
-#include "Assertions.h"
-#include "HashSet.h"
-#include "OwnPtr.h"
-#include "PassOwnPtr.h"
-#include "StdLibExtras.h"
-
-namespace WTF {
-
-    // ListHashSet: Just like HashSet, this class provides a Set
-    // interface - a collection of unique objects with O(1) insertion,
-    // removal and test for containership. However, it also has an
-    // order - iterating it will always give back values in the order
-    // in which they are added.
-
-    // In theory it would be possible to add prepend, insertAfter
-    // and an append that moves the element to the end even if already present,
-    // but unclear yet if these are needed.
-
-    template<typename Value, size_t inlineCapacity, typename HashFunctions> class ListHashSet;
-
-    template<typename T> struct IdentityExtractor;
-
-    template<typename Value, size_t inlineCapacity, typename HashFunctions>
-    void deleteAllValues(const ListHashSet<Value, inlineCapacity, HashFunctions>&);
-
-    template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetIterator;
-    template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstIterator;
-
-    template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNode;
-    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 {
-        WTF_MAKE_FAST_ALLOCATED;
-    private:
-        typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
-        typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator;
-
-        typedef HashTraits<Node*> NodeTraits;
-        typedef ListHashSetNodeHashFunctions<ValueArg, inlineCapacity, HashArg> NodeHash;
-
-        typedef HashTable<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplType;
-        typedef HashTableIterator<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplTypeIterator;
-        typedef HashTableConstIterator<Node*, Node*, IdentityExtractor<Node*>, NodeHash, NodeTraits, NodeTraits> ImplTypeConstIterator;
-
-        typedef HashArg HashFunctions;
-
-    public:
-        typedef ValueArg ValueType;
-        typedef ListHashSetIterator<ValueType, inlineCapacity, HashArg> iterator;
-        typedef ListHashSetConstIterator<ValueType, inlineCapacity, HashArg> const_iterator;
-
-        friend class ListHashSetConstIterator<ValueType, inlineCapacity, HashArg>;
-
-        ListHashSet();
-        ListHashSet(const ListHashSet&);
-        ListHashSet& operator=(const ListHashSet&);
-        ~ListHashSet();
-
-        void swap(ListHashSet&);
-
-        int size() const;
-        int capacity() const;
-        bool isEmpty() const;
-
-        iterator begin();
-        iterator end();
-        const_iterator begin() const;
-        const_iterator end() const;
-
-        ValueType& first();
-        const ValueType& first() const;
-
-        ValueType& last();
-        const ValueType& last() const;
-        void removeLast();
-
-        iterator find(const ValueType&);
-        const_iterator find(const ValueType&) const;
-        bool contains(const ValueType&) const;
-
-        // An alternate version of find() that finds the object by hashing and comparing
-        // with some other type, to avoid the cost of type conversion.
-        // The HashTranslator interface is defined in HashSet.
-        template<typename T, typename HashTranslator> iterator find(const T&);
-        template<typename T, typename HashTranslator> const_iterator find(const T&) const;
-        template<typename T, typename HashTranslator> bool contains(const T&) const;
-
-        // the return value is a pair of an iterator to the new value's location, 
-        // and a bool that is true if an new entry was added
-        pair<iterator, bool> add(const ValueType&);
-
-        pair<iterator, bool> insertBefore(const ValueType& beforeValue, const ValueType& newValue);
-        pair<iterator, bool> insertBefore(iterator it, const ValueType&);
-
-        void remove(const ValueType&);
-        void remove(iterator);
-        void clear();
-
-    private:
-        void unlinkAndDelete(Node*);
-        void appendNode(Node*);
-        void insertNodeBefore(Node* beforeNode, Node* newNode);
-        void deleteAllNodes();
-        iterator makeIterator(Node*);
-        const_iterator makeConstIterator(Node*) const;
-
-        friend void deleteAllValues<>(const ListHashSet&);
-
-        ImplType m_impl;
-        Node* m_head;
-        Node* m_tail;
-        OwnPtr<NodeAllocator> m_allocator;
-    };
-
-    template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNodeAllocator {
-        typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
-        typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator;
-
-        ListHashSetNodeAllocator() 
-            : m_freeList(pool())
-            , m_isDoneWithInitialFreeList(false)
-        { 
-            memset(m_pool.pool, 0, sizeof(m_pool.pool));
-        }
-
-        Node* allocate()
-        { 
-            Node* result = m_freeList;
-
-            if (!result)
-                return static_cast<Node*>(fastMalloc(sizeof(Node)));
-
-            ASSERT(!result->m_isAllocated);
-
-            Node* next = result->m_next;
-            ASSERT(!next || !next->m_isAllocated);
-            if (!next && !m_isDoneWithInitialFreeList) {
-                next = result + 1;
-                if (next == pastPool()) {
-                    m_isDoneWithInitialFreeList = true;
-                    next = 0;
-                } else {
-                    ASSERT(inPool(next));
-                    ASSERT(!next->m_isAllocated);
-                }
-            }
-            m_freeList = next;
-
-            return result;
-        }
-
-        void deallocate(Node* node) 
-        {
-            if (inPool(node)) {
-#ifndef NDEBUG
-                node->m_isAllocated = false;
-#endif
-                node->m_next = m_freeList;
-                m_freeList = node;
-                return;
-            }
-
-            fastFree(node);
-        }
-
-    private:
-        Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.pool); }
-        Node* pastPool() { return pool() + m_poolSize; }
-
-        bool inPool(Node* node)
-        {
-            return node >= pool() && node < pastPool();
-        }
-
-        Node* m_freeList;
-        bool m_isDoneWithInitialFreeList;
-        static const size_t m_poolSize = inlineCapacity;
-        union {
-            char pool[sizeof(Node) * m_poolSize];
-            double forAlignment;
-        } m_pool;
-    };
-
-    template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNode {
-        typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator;
-
-        ListHashSetNode(ValueArg value)
-            : m_value(value)
-            , m_prev(0)
-            , m_next(0)
-#ifndef NDEBUG
-            , m_isAllocated(true)
-#endif
-        {
-        }
-
-        void* operator new(size_t, NodeAllocator* allocator)
-        {
-            return allocator->allocate();
-        }
-        void destroy(NodeAllocator* allocator)
-        {
-            this->~ListHashSetNode();
-            allocator->deallocate(this);
-        }
-
-        ValueArg m_value;
-        ListHashSetNode* m_prev;
-        ListHashSetNode* m_next;
-
-#ifndef NDEBUG
-        bool m_isAllocated;
-#endif
-    };
-
-    template<typename ValueArg, size_t inlineCapacity, typename HashArg> struct ListHashSetNodeHashFunctions {
-        typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
-        
-        static unsigned hash(Node* const& key) { return HashArg::hash(key->m_value); }
-        static bool equal(Node* const& a, Node* const& b) { return HashArg::equal(a->m_value, b->m_value); }
-        static const bool safeToCompareToEmptyOrDeleted = false;
-    };
-
-    template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetIterator {
-    private:
-        typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType;
-        typedef ListHashSetIterator<ValueArg, inlineCapacity, HashArg> iterator;
-        typedef ListHashSetConstIterator<ValueArg, inlineCapacity, HashArg> const_iterator;
-        typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
-        typedef ValueArg ValueType;
-        typedef ValueType& ReferenceType;
-        typedef ValueType* PointerType;
-
-        friend class ListHashSet<ValueArg, inlineCapacity, HashArg>;
-
-        ListHashSetIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { }
-
-    public:
-        ListHashSetIterator() { }
-
-        // default copy, assignment and destructor are OK
-
-        PointerType get() const { return const_cast<PointerType>(m_iterator.get()); }
-        ReferenceType operator*() const { return *get(); }
-        PointerType operator->() const { return get(); }
-
-        iterator& operator++() { ++m_iterator; return *this; }
-
-        // postfix ++ intentionally omitted
-
-        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; }
-
-        operator const_iterator() const { return m_iterator; }
-
-    private:
-        Node* node() { return m_iterator.node(); }
-
-        const_iterator m_iterator;
-    };
-
-    template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstIterator {
-    private:
-        typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType;
-        typedef ListHashSetIterator<ValueArg, inlineCapacity, HashArg> iterator;
-        typedef ListHashSetConstIterator<ValueArg, inlineCapacity, HashArg> const_iterator;
-        typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
-        typedef ValueArg ValueType;
-        typedef const ValueType& ReferenceType;
-        typedef const ValueType* PointerType;
-
-        friend class ListHashSet<ValueArg, inlineCapacity, HashArg>;
-        friend class ListHashSetIterator<ValueArg, inlineCapacity, HashArg>;
-
-        ListHashSetConstIterator(const ListHashSetType* set, Node* position)
-            : m_set(set)
-            , m_position(position)
-        {
-        }
-
-    public:
-        ListHashSetConstIterator()
-        {
-        }
-
-        PointerType get() const
-        {
-            return &m_position->m_value;
-        }
-        ReferenceType operator*() const { return *get(); }
-        PointerType operator->() const { return get(); }
-
-        const_iterator& operator++()
-        {
-            ASSERT(m_position != 0);
-            m_position = m_position->m_next;
-            return *this;
-        }
-
-        // postfix ++ intentionally omitted
-
-        const_iterator& operator--()
-        {
-            ASSERT(m_position != m_set->m_head);
-            if (!m_position)
-                m_position = m_set->m_tail;
-            else
-                m_position = m_position->m_prev;
-            return *this;
-        }
-
-        // postfix -- intentionally omitted
-
-        // Comparison.
-        bool operator==(const const_iterator& other) const
-        {
-            return m_position == other.m_position;
-        }
-        bool operator!=(const const_iterator& other) const
-        {
-            return m_position != other.m_position;
-        }
-
-    private:
-        Node* node() { return m_position; }
-
-        const ListHashSetType* m_set;
-        Node* m_position;
-    };
-
-
-    template<typename ValueType, size_t inlineCapacity, typename HashFunctions>
-    struct ListHashSetTranslator {
-    private:
-        typedef ListHashSetNode<ValueType, inlineCapacity> Node;
-        typedef ListHashSetNodeAllocator<ValueType, inlineCapacity> NodeAllocator;
-    public:
-        static unsigned hash(const ValueType& key) { return HashFunctions::hash(key); }
-        static bool equal(Node* const& a, const ValueType& b) { return HashFunctions::equal(a->m_value, b); }
-        static void translate(Node*& location, const ValueType& key, NodeAllocator* allocator)
-        {
-            location = new (allocator) Node(key);
-        }
-    };
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline ListHashSet<T, inlineCapacity, U>::ListHashSet()
-        : m_head(0)
-        , m_tail(0)
-        , m_allocator(adoptPtr(new NodeAllocator))
-    {
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline ListHashSet<T, inlineCapacity, U>::ListHashSet(const ListHashSet& other)
-        : m_head(0)
-        , m_tail(0)
-        , m_allocator(adoptPtr(new NodeAllocator))
-    {
-        const_iterator end = other.end();
-        for (const_iterator it = other.begin(); it != end; ++it)
-            add(*it);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline ListHashSet<T, inlineCapacity, U>& ListHashSet<T, inlineCapacity, U>::operator=(const ListHashSet& other)
-    {
-        ListHashSet tmp(other);
-        swap(tmp);
-        return *this;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline void ListHashSet<T, inlineCapacity, U>::swap(ListHashSet& other)
-    {
-        m_impl.swap(other.m_impl);
-        std::swap(m_head, other.m_head);
-        std::swap(m_tail, other.m_tail);
-        m_allocator.swap(other.m_allocator);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline ListHashSet<T, inlineCapacity, U>::~ListHashSet()
-    {
-        deleteAllNodes();
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline int ListHashSet<T, inlineCapacity, U>::size() const
-    {
-        return m_impl.size(); 
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline int ListHashSet<T, inlineCapacity, U>::capacity() const
-    {
-        return m_impl.capacity(); 
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline bool ListHashSet<T, inlineCapacity, U>::isEmpty() const
-    {
-        return m_impl.isEmpty(); 
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::begin()
-    {
-        return makeIterator(m_head); 
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::end()
-    {
-        return makeIterator(0);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::begin() const
-    {
-        return makeConstIterator(m_head); 
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::end() const
-    {
-        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)
-    {
-        typedef ListHashSetTranslator<ValueType, inlineCapacity, HashFunctions> Translator;
-        ImplTypeIterator it = m_impl.template find<ValueType, Translator>(value);
-        if (it == m_impl.end())
-            return end();
-        return makeIterator(*it); 
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::find(const ValueType& value) const
-    {
-        typedef ListHashSetTranslator<ValueType, inlineCapacity, HashFunctions> Translator;
-        ImplTypeConstIterator it = m_impl.template find<ValueType, Translator>(value);
-        if (it == m_impl.end())
-            return end();
-        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
-    {
-        typedef ListHashSetTranslator<ValueType, inlineCapacity, HashFunctions> Translator;
-        return m_impl.template contains<ValueType, Translator>(value);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    pair<typename ListHashSet<T, inlineCapacity, U>::iterator, bool> ListHashSet<T, inlineCapacity, U>::add(const ValueType &value)
-    {
-        typedef ListHashSetTranslator<ValueType, inlineCapacity, HashFunctions> Translator;
-        pair<typename ImplType::iterator, bool> result = m_impl.template add<ValueType, NodeAllocator*, Translator>(value, m_allocator.get());
-        if (result.second)
-            appendNode(*result.first);
-        return std::make_pair(makeIterator(*result.first), result.second);
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    pair<typename ListHashSet<T, inlineCapacity, U>::iterator, bool> ListHashSet<T, inlineCapacity, U>::insertBefore(iterator it, const ValueType& newValue)
-    {
-        typedef ListHashSetTranslator<ValueType, inlineCapacity, HashFunctions> Translator;
-        pair<typename ImplType::iterator, bool> result = m_impl.template add<ValueType, NodeAllocator*, Translator>(newValue, m_allocator.get());
-        if (result.second)
-            insertNodeBefore(it.node(), *result.first);
-        return std::make_pair(makeIterator(*result.first), result.second);
-
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    pair<typename ListHashSet<T, inlineCapacity, U>::iterator, bool> ListHashSet<T, inlineCapacity, U>::insertBefore(const ValueType& beforeValue, const ValueType& newValue)
-    {
-        return insertBefore(find(beforeValue), newValue); 
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline void ListHashSet<T, inlineCapacity, U>::remove(iterator it)
-    {
-        if (it == end())
-            return;
-        m_impl.remove(it.node());
-        unlinkAndDelete(it.node());
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline void ListHashSet<T, inlineCapacity, U>::remove(const ValueType& value)
-    {
-        remove(find(value));
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline void ListHashSet<T, inlineCapacity, U>::clear()
-    {
-        deleteAllNodes();
-        m_impl.clear(); 
-        m_head = 0;
-        m_tail = 0;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    void ListHashSet<T, inlineCapacity, U>::unlinkAndDelete(Node* node)
-    {
-        if (!node->m_prev) {
-            ASSERT(node == m_head);
-            m_head = node->m_next;
-        } else {
-            ASSERT(node != m_head);
-            node->m_prev->m_next = node->m_next;
-        }
-
-        if (!node->m_next) {
-            ASSERT(node == m_tail);
-            m_tail = node->m_prev;
-        } else {
-            ASSERT(node != m_tail);
-            node->m_next->m_prev = node->m_prev;
-        }
-
-        node->destroy(m_allocator.get());
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    void ListHashSet<T, inlineCapacity, U>::appendNode(Node* node)
-    {
-        node->m_prev = m_tail;
-        node->m_next = 0;
-
-        if (m_tail) {
-            ASSERT(m_head);
-            m_tail->m_next = node;
-        } else {
-            ASSERT(!m_head);
-            m_head = node;
-        }
-
-        m_tail = node;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    void ListHashSet<T, inlineCapacity, U>::insertNodeBefore(Node* beforeNode, Node* newNode)
-    {
-        if (!beforeNode)
-            return appendNode(newNode);
-        
-        newNode->m_next = beforeNode;
-        newNode->m_prev = beforeNode->m_prev;
-        if (beforeNode->m_prev)
-            beforeNode->m_prev->m_next = newNode;
-        beforeNode->m_prev = newNode;
-
-        if (!newNode->m_prev)
-            m_head = newNode;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    void ListHashSet<T, inlineCapacity, U>::deleteAllNodes()
-    {
-        if (!m_head)
-            return;
-
-        for (Node* node = m_head, *next = m_head->m_next; node; node = next, next = node ? node->m_next : 0)
-            node->destroy(m_allocator.get());
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline ListHashSetIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeIterator(Node* position) 
-    {
-        return ListHashSetIterator<T, inlineCapacity, U>(this, position); 
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline ListHashSetConstIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeConstIterator(Node* position) const
-    { 
-        return ListHashSetConstIterator<T, inlineCapacity, U>(this, position); 
-    }
-
-    template<bool, typename ValueType, typename HashTableType>
-    void deleteAllValues(HashTableType& collection)
-    {
-        typedef typename HashTableType::const_iterator iterator;
-        iterator end = collection.end();
-        for (iterator it = collection.begin(); it != end; ++it)
-            delete (*it)->m_value;
-    }
-
-    template<typename T, size_t inlineCapacity, typename U>
-    inline void deleteAllValues(const ListHashSet<T, inlineCapacity, U>& collection)
-    {
-        deleteAllValues<true, typename ListHashSet<T, inlineCapacity, U>::ValueType>(collection.m_impl);
-    }
-
-} // namespace WTF
-
-using WTF::ListHashSet;
-
-#endif /* WTF_ListHashSet_h */
diff --git a/wtf/ListRefPtr.h b/wtf/ListRefPtr.h
deleted file mode 100644 (file)
index 8bf6447..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *  Copyright (C) 2005, 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.
- *
- */
-
-#ifndef WTF_ListRefPtr_h
-#define WTF_ListRefPtr_h
-
-#include <wtf/RefPtr.h>
-
-namespace WTF {
-
-    // Specialized version of RefPtr desgined for use in singly-linked lists. 
-    // Derefs the list iteratively to avoid recursive derefing that can overflow the stack.
-    template <typename T> class ListRefPtr : public RefPtr<T> {
-    public:
-        ListRefPtr() : RefPtr<T>() {}
-        ListRefPtr(T* ptr) : RefPtr<T>(ptr) {}
-        ListRefPtr(const RefPtr<T>& o) : RefPtr<T>(o) {}
-        // see comment in PassRefPtr.h for why this takes const reference
-        template <typename U> ListRefPtr(const PassRefPtr<U>& o) : RefPtr<T>(o) {}
-        
-        ~ListRefPtr();
-        
-        ListRefPtr& operator=(T* optr) { RefPtr<T>::operator=(optr); return *this; }
-        ListRefPtr& operator=(const RefPtr<T>& o) { RefPtr<T>::operator=(o); return *this; }
-        ListRefPtr& operator=(const PassRefPtr<T>& o) { RefPtr<T>::operator=(o); return *this; }
-        template <typename U> ListRefPtr& operator=(const RefPtr<U>& o) { RefPtr<T>::operator=(o); return *this; }
-        template <typename U> ListRefPtr& operator=(const PassRefPtr<U>& o) { RefPtr<T>::operator=(o); return *this; }
-    };
-
-    // Remove inline for winscw compiler to prevent the compiler agressively resolving
-    // T::ref() in RefPtr<T>'s copy constructor.  The bug is reported at:
-    // https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=9812.
-    template <typename T> 
-#if !COMPILER(WINSCW)
-    inline
-#endif
-    ListRefPtr<T>::~ListRefPtr()
-    {
-        RefPtr<T> reaper = this->release();
-        while (reaper && reaper->hasOneRef())
-            reaper = reaper->releaseNext(); // implicitly protects reaper->next, then derefs reaper
-    }
-
-    template <typename T> inline T* getPtr(const ListRefPtr<T>& p)
-    {
-        return p.get();
-    }
-
-} // namespace WTF
-
-using WTF::ListRefPtr;
-
-#endif // WTF_ListRefPtr_h
diff --git a/wtf/Locker.h b/wtf/Locker.h
deleted file mode 100644 (file)
index c465b99..0000000
+++ /dev/null
@@ -1,48 +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.
- * 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 Locker_h
-#define Locker_h
-
-#include <wtf/Noncopyable.h>
-
-namespace WTF {
-
-template <typename T> class Locker {
-    WTF_MAKE_NONCOPYABLE(Locker);
-public:
-    Locker(T& lockable) : m_lockable(lockable) { m_lockable.lock(); }
-    ~Locker() { m_lockable.unlock(); }
-private:
-    T& m_lockable;
-};
-
-}
-
-using WTF::Locker;
-
-#endif
diff --git a/wtf/MD5.cpp b/wtf/MD5.cpp
deleted file mode 100644 (file)
index 07bbadd..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-// The original file was copied from sqlite, and was in the public domain.
-// Modifications Copyright 2006 Google Inc. All Rights Reserved
-/*
- * 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.
- */
-/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest.  This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, construct an
- * MD5 instance, call addBytes as needed on buffers full of bytes,
- * and then call checksum, which will fill a supplied 16-byte array
- * with the digest.
- */
-
-#include "config.h"
-#include "MD5.h"
-
-#include "Assertions.h"
-#ifndef NDEBUG
-#include "StringExtras.h"
-#include "text/CString.h"
-#endif
-#include <wtf/StdLibExtras.h>
-
-namespace WTF {
-
-#ifdef NDEBUG
-static inline void testMD5() { }
-#else
-// MD5 test case.
-static bool isTestMD5Done;
-
-static void expectMD5(CString input, CString expected)
-{
-    MD5 md5;
-    md5.addBytes(reinterpret_cast<const uint8_t*>(input.data()), input.length());
-    Vector<uint8_t, 16> digest;
-    md5.checksum(digest);
-    char* buf = 0;
-    CString actual = CString::newUninitialized(32, buf);
-    for (size_t i = 0; i < 16; i++) {
-        snprintf(buf, 3, "%02x", digest.at(i));
-        buf += 2;
-    }
-    ASSERT_WITH_MESSAGE(actual == expected, "input:%s[%lu] actual:%s expected:%s", input.data(), static_cast<unsigned long>(input.length()), actual.data(), expected.data());
-}
-
-static void testMD5()
-{
-    if (isTestMD5Done)
-        return;
-    isTestMD5Done = true;
-
-    // MD5 Test suite from http://www.ietf.org/rfc/rfc1321.txt
-    expectMD5("", "d41d8cd98f00b204e9800998ecf8427e");
-    expectMD5("a", "0cc175b9c0f1b6a831c399e269772661");
-    expectMD5("abc", "900150983cd24fb0d6963f7d28e17f72");
-    expectMD5("message digest", "f96b697d7cb7938d525a2f31aaf161d0");
-    expectMD5("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b");
-    expectMD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f");
-    expectMD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a");
-}
-#endif
-
-// Note: this code is harmless on little-endian machines.
-
-static void reverseBytes(uint8_t* buf, unsigned longs)
-{
-    ASSERT(longs > 0);
-    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_ptr<uint32_t *>(buf) = t;
-        buf += 4;
-    } while (--longs);
-}
-
-// The four core functions.
-// F1 is originally defined as (x & y | ~x & z), but optimized somewhat: 4 bit ops -> 3 bit ops.
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-// This is the central step in the MD5 algorithm.
-#define MD5STEP(f, w, x, y, z, data, s) \
-    (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
-
-static void MD5Transform(uint32_t buf[4], const uint32_t in[16])
-{
-    uint32_t a = buf[0];
-    uint32_t b = buf[1];
-    uint32_t c = buf[2];
-    uint32_t d = buf[3];
-
-    MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
-    MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
-    MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
-    MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
-    MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
-    MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
-    MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
-    MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
-    MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
-    MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
-    MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
-    MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
-    MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
-    MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
-    MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
-    MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
-
-    MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
-    MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
-    MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
-    MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
-    MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
-    MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
-    MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
-    MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
-    MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
-    MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
-    MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
-    MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
-    MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
-    MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
-    MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
-    MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
-
-    MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
-    MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
-    MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
-    MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
-    MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
-    MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
-    MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
-    MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
-    MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
-    MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
-    MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
-    MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
-    MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
-    MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
-    MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
-    MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
-
-    MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
-    MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
-    MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
-    MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
-    MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
-    MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
-    MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
-    MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
-    MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
-    MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
-    MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
-    MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
-    MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
-    MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
-    MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
-    MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
-
-    buf[0] += a;
-    buf[1] += b;
-    buf[2] += c;
-    buf[3] += d;
-}
-
-MD5::MD5()
-{
-    // FIXME: Move unit tests somewhere outside the constructor. See bug 55853.
-    testMD5();
-    m_buf[0] = 0x67452301;
-    m_buf[1] = 0xefcdab89;
-    m_buf[2] = 0x98badcfe;
-    m_buf[3] = 0x10325476;
-    m_bits[0] = 0;
-    m_bits[1] = 0;
-    memset(m_in, 0, sizeof(m_in));
-    ASSERT_WITH_MESSAGE(!(reinterpret_cast<uintptr_t>(m_in) % sizeof(uint32_t)), "alignment error of m_in");
-}
-
-void MD5::addBytes(const uint8_t* input, size_t length)
-{
-    const uint8_t* buf = input;
-
-    // Update bitcount
-    uint32_t t = m_bits[0];
-    m_bits[0] = t + (length << 3);
-    if (m_bits[0] < t)
-        m_bits[1]++; // Carry from low to high
-    m_bits[1] += length >> 29;
-
-    t = (t >> 3) & 0x3f; // Bytes already in shsInfo->data
-
-    // Handle any leading odd-sized chunks
-
-    if (t) {
-        uint8_t* p = m_in + t;
-
-        t = 64 - t;
-        if (length < t) {
-            memcpy(p, buf, length);
-            return;
-        }
-        memcpy(p, buf, t);
-        reverseBytes(m_in, 16);
-        MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t*>(m_in)); // m_in is 4-byte aligned.
-        buf += t;
-        length -= t;
-    }
-
-    // Process data in 64-byte chunks
-
-    while (length >= 64) {
-        memcpy(m_in, buf, 64);
-        reverseBytes(m_in, 16);
-        MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t*>(m_in)); // m_in is 4-byte aligned.
-        buf += 64;
-        length -= 64;
-    }
-
-    // Handle any remaining bytes of data.
-    memcpy(m_in, buf, length);
-}
-
-void MD5::checksum(Vector<uint8_t, 16>& digest)
-{
-    // Compute number of bytes mod 64
-    unsigned count = (m_bits[0] >> 3) & 0x3F;
-
-    // Set the first char of padding to 0x80.  This is safe since there is
-    // always at least one byte free
-    uint8_t* p = m_in + count;
-    *p++ = 0x80;
-
-    // Bytes of padding needed to make 64 bytes
-    count = 64 - 1 - count;
-
-    // Pad out to 56 mod 64
-    if (count < 8) {
-        // Two lots of padding:  Pad the first block to 64 bytes
-        memset(p, 0, count);
-        reverseBytes(m_in, 16);
-        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);
-    } else {
-        // Pad block to 56 bytes
-        memset(p, 0, count - 8);
-    }
-    reverseBytes(m_in, 14);
-
-    // Append length in bits and transform
-    // m_in is 4-byte aligned.
-    (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_ptr<uint32_t*>(m_in));
-    reverseBytes(reinterpret_cast<uint8_t*>(m_buf), 4);
-
-    // 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));
-}
-
-} // namespace WTF
diff --git a/wtf/MD5.h b/wtf/MD5.h
deleted file mode 100644 (file)
index 3caa810..0000000
--- a/wtf/MD5.h
+++ /dev/null
@@ -1,61 +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:
- *
- *     * 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_MD5_h
-#define WTF_MD5_h
-
-#include <wtf/Vector.h>
-
-namespace WTF {
-
-class MD5 {
-public:
-    MD5();
-
-    void addBytes(const Vector<uint8_t>& input)
-    {
-        addBytes(input.data(), input.size());
-    }
-    void addBytes(const uint8_t* input, size_t length);
-
-    // checksum has a side effect of resetting the state of the object.
-    void checksum(Vector<uint8_t, 16>&);
-
-private:
-    uint32_t m_buf[4];
-    uint32_t m_bits[2];
-    uint8_t m_in[64];
-};
-
-} // namespace WTF
-
-using WTF::MD5;
-
-#endif // WTF_MD5_h
diff --git a/wtf/MainThread.cpp b/wtf/MainThread.cpp
deleted file mode 100644 (file)
index 3229e5b..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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.
- */
-
-#include "config.h"
-#include "MainThread.h"
-
-#include "CurrentTime.h"
-#include "Deque.h"
-#include "StdLibExtras.h"
-#include "Threading.h"
-
-#include <wtf/iphone/WebCoreThread.h>
-
-#if PLATFORM(CHROMIUM)
-#error Chromium uses a different main thread implementation
-#endif
-
-namespace WTF {
-
-struct FunctionWithContext {
-    MainThreadFunction* function;
-    void* context;
-    ThreadCondition* syncFlag;
-
-    FunctionWithContext(MainThreadFunction* function = 0, void* context = 0, ThreadCondition* syncFlag = 0)
-        : function(function)
-        , context(context)
-        , syncFlag(syncFlag)
-    { 
-    }
-    bool operator == (const FunctionWithContext& o)
-    {
-        return function == o.function
-            && context == o.context
-            && syncFlag == o.syncFlag;
-    }
-};
-
-class FunctionWithContextFinder {
-public:
-    FunctionWithContextFinder(const FunctionWithContext& m) : m(m) {}
-    bool operator() (FunctionWithContext& o) { return o == m; }
-    FunctionWithContext m;
-};
-
-
-typedef Deque<FunctionWithContext> FunctionQueue;
-
-static bool callbacksPaused; // This global variable is only accessed from main thread.
-#if !PLATFORM(MAC) && !PLATFORM(QT)
-static ThreadIdentifier mainThreadIdentifier;
-#endif
-
-static Mutex& mainThreadFunctionQueueMutex()
-{
-    DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
-    return staticMutex;
-}
-
-static FunctionQueue& functionQueue()
-{
-    DEFINE_STATIC_LOCAL(FunctionQueue, staticFunctionQueue, ());
-    return staticFunctionQueue;
-}
-
-
-#if !PLATFORM(MAC)
-
-void initializeMainThread()
-{
-    static bool initializedMainThread;
-    if (initializedMainThread)
-        return;
-    initializedMainThread = true;
-
-#if !PLATFORM(QT)
-    mainThreadIdentifier = currentThread();
-#endif
-
-    mainThreadFunctionQueueMutex();
-    initializeMainThreadPlatform();
-}
-
-#else
-
-static pthread_once_t initializeMainThreadKeyOnce = PTHREAD_ONCE_INIT;
-
-static void initializeMainThreadOnce()
-{
-    mainThreadFunctionQueueMutex();
-    initializeMainThreadPlatform();
-}
-
-void initializeMainThread()
-{
-    pthread_once(&initializeMainThreadKeyOnce, initializeMainThreadOnce);
-}
-
-static void initializeMainThreadToProcessMainThreadOnce()
-{
-    mainThreadFunctionQueueMutex();
-    initializeMainThreadToProcessMainThreadPlatform();
-}
-
-void initializeMainThreadToProcessMainThread()
-{
-    pthread_once(&initializeMainThreadKeyOnce, initializeMainThreadToProcessMainThreadOnce);
-}
-#endif
-
-// 0.1 sec delays in UI is approximate threshold when they become noticeable. Have a limit that's half of that.
-static const double maxRunLoopSuspensionTime = 0.05;
-
-void dispatchFunctionsFromMainThread()
-{
-    ASSERT(isMainThread());
-
-    if (callbacksPaused)
-        return;
-
-    double startTime = currentTime();
-
-    FunctionWithContext invocation;
-    while (true) {
-        {
-            MutexLocker locker(mainThreadFunctionQueueMutex());
-            if (!functionQueue().size())
-                break;
-            invocation = functionQueue().takeFirst();
-        }
-
-        invocation.function(invocation.context);
-        if (invocation.syncFlag) {
-            MutexLocker locker(mainThreadFunctionQueueMutex());
-            invocation.syncFlag->signal();
-        }
-
-        // If we are running accumulated functions for too long so UI may become unresponsive, we need to
-        // yield so the user input can be processed. Otherwise user may not be able to even close the window.
-        // This code has effect only in case the scheduleDispatchFunctionsOnMainThread() is implemented in a way that
-        // allows input events to be processed before we are back here.
-        if (currentTime() - startTime > maxRunLoopSuspensionTime) {
-            scheduleDispatchFunctionsOnMainThread();
-            break;
-        }
-    }
-}
-
-void callOnMainThread(MainThreadFunction* function, void* context)
-{
-    ASSERT(function);
-    bool needToSchedule = false;
-    {
-        MutexLocker locker(mainThreadFunctionQueueMutex());
-        needToSchedule = functionQueue().size() == 0;
-        functionQueue().append(FunctionWithContext(function, context));
-    }
-    if (needToSchedule)
-        scheduleDispatchFunctionsOnMainThread();
-}
-
-void callOnMainThreadAndWait(MainThreadFunction* function, void* context)
-{
-    ASSERT(function);
-
-    if (isMainThread()) {
-        function(context);
-        return;
-    }
-
-    ThreadCondition syncFlag;
-    Mutex& functionQueueMutex = mainThreadFunctionQueueMutex();
-    MutexLocker locker(functionQueueMutex);
-    functionQueue().append(FunctionWithContext(function, context, &syncFlag));
-    if (functionQueue().size() == 1)
-        scheduleDispatchFunctionsOnMainThread();
-    syncFlag.wait(functionQueueMutex);
-}
-
-void cancelCallOnMainThread(MainThreadFunction* function, void* context)
-{
-    ASSERT(function);
-
-    MutexLocker locker(mainThreadFunctionQueueMutex());
-
-    FunctionWithContextFinder pred(FunctionWithContext(function, context));
-
-    while (true) {
-        // We must redefine 'i' each pass, because the itererator's operator= 
-        // requires 'this' to be valid, and remove() invalidates all iterators
-        FunctionQueue::iterator i(functionQueue().findIf(pred));
-        if (i == functionQueue().end())
-            break;
-        functionQueue().remove(i);
-    }
-}
-
-void setMainThreadCallbacksPaused(bool paused)
-{
-    ASSERT((isMainThread() || pthread_main_np()) && WebCoreWebThreadIsLockedOrDisabled());
-
-    if (callbacksPaused == paused)
-        return;
-
-    callbacksPaused = paused;
-
-    if (!callbacksPaused)
-        scheduleDispatchFunctionsOnMainThread();
-}
-
-#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(BREWMP)
-bool isMainThread()
-{
-    return currentThread() == mainThreadIdentifier;
-}
-#endif
-
-} // namespace WTF
diff --git a/wtf/MainThread.h b/wtf/MainThread.h
deleted file mode 100644 (file)
index 157e2cc..0000000
+++ /dev/null
@@ -1,72 +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.
- */
-
-#ifndef MainThread_h
-#define MainThread_h
-
-#include <stdint.h>
-
-namespace WTF {
-
-typedef uint32_t ThreadIdentifier;
-typedef void MainThreadFunction(void*);
-
-// Must be called from the main thread.
-void initializeMainThread();
-
-void callOnMainThread(MainThreadFunction*, void* context);
-void callOnMainThreadAndWait(MainThreadFunction*, void* context);
-void cancelCallOnMainThread(MainThreadFunction*, void* context);
-
-void setMainThreadCallbacksPaused(bool paused);
-
-bool isMainThread();
-bool isWebThread();
-
-// NOTE: these functions are internal to the callOnMainThread implementation.
-void initializeMainThreadPlatform();
-void scheduleDispatchFunctionsOnMainThread();
-void dispatchFunctionsFromMainThread();
-
-#if PLATFORM(MAC)
-// This version of initializeMainThread sets up the main thread as corresponding
-// to the process's main thread, and not necessarily the thread that calls this
-// function. It should only be used as a legacy aid for Mac WebKit.
-void initializeMainThreadToProcessMainThread();
-void initializeMainThreadToProcessMainThreadPlatform();
-#endif
-
-} // namespace WTF
-
-using WTF::callOnMainThread;
-using WTF::callOnMainThreadAndWait;
-using WTF::cancelCallOnMainThread;
-using WTF::setMainThreadCallbacksPaused;
-using WTF::isMainThread;
-#endif // MainThread_h
diff --git a/wtf/MallocZoneSupport.h b/wtf/MallocZoneSupport.h
deleted file mode 100644 (file)
index 4332e40..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 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:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must 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 MallocZoneSupport_h
-#define MallocZoneSupport_h
-
-#include <malloc/malloc.h>
-
-namespace WTF {
-
-class RemoteMemoryReader {
-    task_t m_task;
-    memory_reader_t* m_reader;
-
-public:
-    RemoteMemoryReader(task_t task, memory_reader_t* reader)
-        : m_task(task)
-        , m_reader(reader)
-    { }
-
-    void* operator()(vm_address_t address, size_t size) const
-    {
-        void* output;
-        kern_return_t err = (*m_reader)(m_task, address, size, static_cast<void**>(&output));
-        if (err)
-            output = 0;
-        return output;
-    }
-
-    template <typename T>
-    T* operator()(T* address, size_t size=sizeof(T)) const
-    {
-        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
-
-#endif // MallocZoneSupport_h
diff --git a/wtf/MathExtras.h b/wtf/MathExtras.h
deleted file mode 100644 (file)
index 6da125a..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008, 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 WTF_MathExtras_h
-#define WTF_MathExtras_h
-
-#include <algorithm>
-#include <cmath>
-#include <float.h>
-#include <limits>
-#include <stdlib.h>
-
-#if OS(SOLARIS)
-#include <ieeefp.h>
-#endif
-
-#if OS(OPENBSD)
-#include <sys/types.h>
-#include <machine/ieee.h>
-#endif
-
-#if COMPILER(MSVC)
-#if OS(WINCE)
-#include <stdlib.h>
-#endif
-#include <limits>
-#endif
-
-#ifndef M_PI
-const double piDouble = 3.14159265358979323846;
-const float piFloat = 3.14159265358979323846f;
-#else
-const double piDouble = M_PI;
-const float piFloat = static_cast<float>(M_PI);
-#endif
-
-#ifndef M_PI_2
-const double piOverTwoDouble = 1.57079632679489661923;
-const float piOverTwoFloat = 1.57079632679489661923f;
-#else
-const double piOverTwoDouble = M_PI_2;
-const float piOverTwoFloat = static_cast<float>(M_PI_2);
-#endif
-
-#ifndef M_PI_4
-const double piOverFourDouble = 0.785398163397448309616;
-const float piOverFourFloat = 0.785398163397448309616f;
-#else
-const double piOverFourDouble = M_PI_4;
-const float piOverFourFloat = static_cast<float>(M_PI_4);
-#endif
-
-#if OS(DARWIN)
-
-// Work around a bug in the Mac OS X libc where ceil(-0.1) return +0.
-inline double wtf_ceil(double x) { return copysign(ceil(x), x); }
-
-#define ceil(x) wtf_ceil(x)
-
-#endif
-
-#if OS(SOLARIS)
-
-#ifndef isfinite
-inline bool isfinite(double x) { return finite(x) && !isnand(x); }
-#endif
-#ifndef isinf
-inline bool isinf(double x) { return !finite(x) && !isnand(x); }
-#endif
-#ifndef signbit
-inline bool signbit(double x) { return copysign(1.0, x) < 0; }
-#endif
-
-#endif
-
-#if OS(OPENBSD)
-
-#ifndef isfinite
-inline bool isfinite(double x) { return finite(x); }
-#endif
-#ifndef signbit
-inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x; return p->dbl_sign; }
-#endif
-
-#endif
-
-#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)
-{
-    double integer = ceil(num);
-    if (num > 0)
-        return integer - num > 0.5 ? integer - 1.0 : integer;
-    return integer - num >= 0.5 ? integer - 1.0 : integer;
-}
-static float roundf(float num)
-{
-    float integer = ceilf(num);
-    if (num > 0)
-        return integer - num > 0.5f ? integer - 1.0f : integer;
-    return integer - num >= 0.5f ? integer - 1.0f : integer;
-}
-inline long long llround(double num) { return static_cast<long long>(round(num)); }
-inline long long llroundf(float num) { return static_cast<long long>(roundf(num)); }
-inline long lround(double num) { return static_cast<long>(round(num)); }
-inline long lroundf(float num) { return static_cast<long>(roundf(num)); }
-inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); }
-
-#endif
-
-#if COMPILER(MSVC)
-// The 64bit version of abs() is already defined in stdlib.h which comes with VC10
-#if COMPILER(MSVC9_OR_LOWER)
-inline long long abs(long long num) { return _abs64(num); }
-#endif
-
-inline bool isinf(double num) { return !_finite(num) && !_isnan(num); }
-inline bool isnan(double num) { return !!_isnan(num); }
-inline bool signbit(double num) { return _copysign(1.0, num) < 0; }
-
-inline double nextafter(double x, double y) { return _nextafter(x, y); }
-inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; }
-
-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)
-{
-    double posInf = std::numeric_limits<double>::infinity();
-    double negInf = -std::numeric_limits<double>::infinity();
-    double nan = std::numeric_limits<double>::quiet_NaN();
-
-    double result = nan;
-
-    if (x == posInf && y == posInf)
-        result = piOverFourDouble;
-    else if (x == posInf && y == negInf)
-        result = 3 * piOverFourDouble;
-    else if (x == negInf && y == posInf)
-        result = -piOverFourDouble;
-    else if (x == negInf && y == negInf)
-        result = -3 * piOverFourDouble;
-    else
-        result = ::atan2(x, y);
-
-    return result;
-}
-
-// Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN instead of x.
-inline double wtf_fmod(double x, double y) { return (!isinf(x) && isinf(y)) ? x : fmod(x, y); }
-
-// Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead of 1.
-inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); }
-
-#define atan2(x, y) wtf_atan2(x, y)
-#define fmod(x, y) wtf_fmod(x, y)
-#define pow(x, y) wtf_pow(x, y)
-
-#endif // COMPILER(MSVC)
-
-inline double deg2rad(double d)  { return d * piDouble / 180.0; }
-inline double rad2deg(double r)  { return r * 180.0 / piDouble; }
-inline double deg2grad(double d) { return d * 400.0 / 360.0; }
-inline double grad2deg(double g) { return g * 360.0 / 400.0; }
-inline double turn2deg(double t) { return t * 360.0; }
-inline double deg2turn(double d) { return d / 360.0; }
-inline double rad2grad(double r) { return r * 200.0 / piDouble; }
-inline double grad2rad(double g) { return g * piDouble / 200.0; }
-
-inline float deg2rad(float d)  { return d * piFloat / 180.0f; }
-inline float rad2deg(float r)  { return r * 180.0f / piFloat; }
-inline float deg2grad(float d) { return d * 400.0f / 360.0f; }
-inline float grad2deg(float g) { return g * 360.0f / 400.0f; }
-inline float turn2deg(float t) { return t * 360.0f; }
-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 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);
-}
-
-inline bool isWithinIntRange(float x)
-{
-    return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static_cast<float>(std::numeric_limits<int>::max());
-}
-
-#if !COMPILER(MSVC) && !(COMPILER(RVCT) && PLATFORM(BREWMP)) && !OS(SOLARIS) && !OS(SYMBIAN)
-using std::isfinite;
-using std::isinf;
-using std::isnan;
-using std::signbit;
-#endif
-
-#endif // #ifndef WTF_MathExtras_h
diff --git a/wtf/MessageQueue.h b/wtf/MessageQueue.h
deleted file mode 100644 (file)
index 3e48154..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009 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 MessageQueue_h
-#define MessageQueue_h
-
-#include <limits>
-#include <wtf/Assertions.h>
-#include <wtf/Deque.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/Threading.h>
-
-namespace WTF {
-
-    enum MessageQueueWaitResult {
-        MessageQueueTerminated,       // Queue was destroyed while waiting for message.
-        MessageQueueTimeout,          // Timeout was specified and it expired.
-        MessageQueueMessageReceived   // A message was successfully received and returned.
-    };
-
-    // 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 {
-        WTF_MAKE_NONCOPYABLE(MessageQueue);
-    public:
-        MessageQueue() : m_killed(false) { }
-        ~MessageQueue();
-
-        void append(PassOwnPtr<DataType>);
-        bool appendAndCheckEmpty(PassOwnPtr<DataType>);
-        void prepend(PassOwnPtr<DataType>);
-
-        PassOwnPtr<DataType> waitForMessage();
-        PassOwnPtr<DataType> tryGetMessage();
-        template<typename Predicate>
-        PassOwnPtr<DataType> waitForMessageFilteredWithTimeout(MessageQueueWaitResult&, Predicate&, double absoluteTime);
-
-        template<typename Predicate>
-        void removeIf(Predicate&);
-
-        void kill();
-        bool killed() const;
-
-        // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
-        bool isEmpty();
-
-        static double infiniteTime() { return std::numeric_limits<double>::max(); }
-
-    private:
-        static bool alwaysTruePredicate(DataType*) { return true; }
-
-        mutable Mutex m_mutex;
-        ThreadCondition m_condition;
-        Deque<DataType*> m_queue;
-        bool m_killed;
-    };
-
-    template<typename DataType>
-    MessageQueue<DataType>::~MessageQueue()
-    {
-        deleteAllValues(m_queue);
-    }
-
-    template<typename DataType>
-    inline void MessageQueue<DataType>::append(PassOwnPtr<DataType> message)
-    {
-        MutexLocker lock(m_mutex);
-        m_queue.append(message.leakPtr());
-        m_condition.signal();
-    }
-
-    // Returns true if the queue was empty before the item was added.
-    template<typename DataType>
-    inline bool MessageQueue<DataType>::appendAndCheckEmpty(PassOwnPtr<DataType> message)
-    {
-        MutexLocker lock(m_mutex);
-        bool wasEmpty = m_queue.isEmpty();
-        m_queue.append(message.leakPtr());
-        m_condition.signal();
-        return wasEmpty;
-    }
-
-    template<typename DataType>
-    inline void MessageQueue<DataType>::prepend(PassOwnPtr<DataType> message)
-    {
-        MutexLocker lock(m_mutex);
-        m_queue.prepend(message.leakPtr());
-        m_condition.signal();
-    }
-
-    template<typename DataType>
-    inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessage()
-    {
-        MessageQueueWaitResult exitReason; 
-        OwnPtr<DataType> result = waitForMessageFilteredWithTimeout(exitReason, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime());
-        ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived);
-        return result.release();
-    }
-
-    template<typename DataType>
-    template<typename Predicate>
-    inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessageFilteredWithTimeout(MessageQueueWaitResult& result, Predicate& predicate, double absoluteTime)
-    {
-        MutexLocker lock(m_mutex);
-        bool timedOut = false;
-
-        DequeConstIterator<DataType*> found = m_queue.end();
-        while (!m_killed && !timedOut && (found = m_queue.findIf(predicate)) == m_queue.end())
-            timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
-
-        ASSERT(!timedOut || absoluteTime != infiniteTime());
-
-        if (m_killed) {
-            result = MessageQueueTerminated;
-            return nullptr;
-        }
-
-        if (timedOut) {
-            result = MessageQueueTimeout;
-            return nullptr;
-        }
-
-        ASSERT(found != m_queue.end());
-        OwnPtr<DataType> message = adoptPtr(*found);
-        m_queue.remove(found);
-        result = MessageQueueMessageReceived;
-        return message.release();
-    }
-
-    template<typename DataType>
-    inline PassOwnPtr<DataType> MessageQueue<DataType>::tryGetMessage()
-    {
-        MutexLocker lock(m_mutex);
-        if (m_killed)
-            return nullptr;
-        if (m_queue.isEmpty())
-            return nullptr;
-
-        return adoptPtr(m_queue.takeFirst());
-    }
-
-    template<typename DataType>
-    template<typename Predicate>
-    inline void MessageQueue<DataType>::removeIf(Predicate& predicate)
-    {
-        MutexLocker lock(m_mutex);
-        // See bug 31657 for why this loop looks so weird
-        while (true) {
-            DequeConstIterator<DataType*> found = m_queue.findIf(predicate);
-            if (found == m_queue.end())
-                break;
-
-            DataType* message = *found;
-            m_queue.remove(found);
-            delete message;
-       }
-    }
-
-    template<typename DataType>
-    inline bool MessageQueue<DataType>::isEmpty()
-    {
-        MutexLocker lock(m_mutex);
-        if (m_killed)
-            return true;
-        return m_queue.isEmpty();
-    }
-
-    template<typename DataType>
-    inline void MessageQueue<DataType>::kill()
-    {
-        MutexLocker lock(m_mutex);
-        m_killed = true;
-        m_condition.broadcast();
-    }
-
-    template<typename DataType>
-    inline bool MessageQueue<DataType>::killed() const
-    {
-        MutexLocker lock(m_mutex);
-        return m_killed;
-    }
-} // namespace WTF
-
-using WTF::MessageQueue;
-// MessageQueueWaitResult enum and all its values.
-using WTF::MessageQueueWaitResult;
-using WTF::MessageQueueTerminated;
-using WTF::MessageQueueTimeout;
-using WTF::MessageQueueMessageReceived;
-
-#endif // MessageQueue_h
diff --git a/wtf/NonCopyingSort.h b/wtf/NonCopyingSort.h
deleted file mode 100644 (file)
index fd611bd..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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
diff --git a/wtf/Noncopyable.h b/wtf/Noncopyable.h
deleted file mode 100644 (file)
index cc6bc55..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *  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
- *  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_Noncopyable_h
-#define WTF_Noncopyable_h
-
-#ifndef __has_feature
-    #define __has_feature(x) 0
-#endif
-
-#if __has_feature(cxx_deleted_functions)
-    #define WTF_MAKE_NONCOPYABLE(ClassName) \
-        _Pragma("clang diagnostic push") \
-        _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") \
-        _Pragma("clang diagnostic ignored \"-Wc++0x-extensions\"") \
-        private: \
-            ClassName(const ClassName&) = delete; \
-            ClassName& operator=(const ClassName&) = delete; \
-        _Pragma("clang diagnostic pop")
-#else
-    #define WTF_MAKE_NONCOPYABLE(ClassName) \
-        private: \
-            ClassName(const ClassName&); \
-            ClassName& operator=(const ClassName&)
-#endif
-
-#endif // WTF_Noncopyable_h
diff --git a/wtf/NotFound.h b/wtf/NotFound.h
deleted file mode 100644 (file)
index 4263bce..0000000
+++ /dev/null
@@ -1,37 +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.
- */
-
-#ifndef NotFound_h
-#define NotFound_h
-
-namespace WTF {
-
-    const size_t notFound = static_cast<size_t>(-1);
-
-} // namespace WTF
-
-using WTF::notFound;
-
-#endif // NotFound_h
diff --git a/wtf/NullPtr.cpp b/wtf/NullPtr.cpp
deleted file mode 100644 (file)
index 224f1f1..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-
-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
deleted file mode 100644 (file)
index c0e7bd3..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-
-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
deleted file mode 100644 (file)
index ca93056..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index a6052ed..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 59bcdba..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index e7beb8a..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 7d86f6f..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 214a954..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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
diff --git a/wtf/OwnArrayPtr.h b/wtf/OwnArrayPtr.h
deleted file mode 100644 (file)
index 2828698..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- *  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
- *  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_OwnArrayPtr_h
-#define WTF_OwnArrayPtr_h
-
-#include "Assertions.h"
-#include "Noncopyable.h"
-#include "NullPtr.h"
-#include "PassOwnArrayPtr.h"
-#include <algorithm>
-
-namespace WTF {
-
-template<typename T> class PassOwnArrayPtr;
-template<typename T> PassOwnArrayPtr<T> adoptArrayPtr(T*);
-
-template <typename T> class OwnArrayPtr {
-public:
-    typedef T* PtrType;
-
-    OwnArrayPtr() : m_ptr(0) { }
-
-    // See comment in PassOwnArrayPtr.h for why this takes a const reference.
-    template<typename U> OwnArrayPtr(const PassOwnArrayPtr<U>& o);
-
-    // 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>&);
-
-    ~OwnArrayPtr() { deleteOwnedArrayPtr(m_ptr); }
-
-    PtrType get() const { return m_ptr; }
-
-    void clear();
-    PassOwnArrayPtr<T> release();
-    PtrType leakPtr() WARN_UNUSED_RETURN;
-
-    T& operator*() const { ASSERT(m_ptr); return *m_ptr; }
-    PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
-
-    T& operator[](std::ptrdiff_t i) const { ASSERT(m_ptr); ASSERT(i >= 0); return m_ptr[i]; }
-
-    bool operator!() const { return !m_ptr; }
-
-    // This conversion operator allows implicit conversion to bool but not to other integer types.
-#if COMPILER(WINSCW)
-    operator bool() const { return m_ptr; }
-#else
-    typedef T* OwnArrayPtr::*UnspecifiedBoolType;
-    operator UnspecifiedBoolType() const { return m_ptr ? &OwnArrayPtr::m_ptr : 0; }
-#endif
-
-    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); }
-
-#ifdef LOOSE_OWN_ARRAY_PTR
-    explicit OwnArrayPtr(PtrType ptr) : m_ptr(ptr) { }
-    void set(PtrType);
-#endif
-
-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 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
-
-using WTF::OwnArrayPtr;
-
-#endif // WTF_OwnArrayPtr_h
diff --git a/wtf/OwnFastMallocPtr.h b/wtf/OwnFastMallocPtr.h
deleted file mode 100644 (file)
index 9d4841a..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *  Copyright (C) 2006, 2007 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 OwnFastMallocPtr_h
-#define OwnFastMallocPtr_h
-
-#include "FastMalloc.h"
-
-namespace WTF {
-
-    template<class T> class OwnFastMallocPtr {
-        WTF_MAKE_NONCOPYABLE(OwnFastMallocPtr);
-    public:
-        explicit OwnFastMallocPtr(T* ptr) : m_ptr(ptr)
-        {
-        }
-
-        ~OwnFastMallocPtr()
-        {
-            fastFree(const_cast<void*>(static_cast<const void*>(const_cast<const T*>(m_ptr))));
-        }
-
-        T* get() const { return m_ptr; }
-        T* release() { T* ptr = m_ptr; m_ptr = 0; return ptr; }
-
-    private:
-        T* m_ptr;
-    };
-
-} // namespace WTF
-
-using WTF::OwnFastMallocPtr;
-
-#endif // OwnFastMallocPtr_h
diff --git a/wtf/OwnPtr.h b/wtf/OwnPtr.h
deleted file mode 100644 (file)
index f80ec54..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- *  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
- *  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_OwnPtr_h
-#define WTF_OwnPtr_h
-
-#include "Assertions.h"
-#include "NullPtr.h"
-#include "OwnPtrCommon.h"
-#include "TypeTraits.h"
-#include <algorithm>
-#include <memory>
-
-namespace WTF {
-
-    // Unlike most of our smart pointers, OwnPtr can take either the pointer type or the pointed-to type.
-
-    template<typename T> class PassOwnPtr;
-    template<typename T> PassOwnPtr<T> adoptPtr(T*);
-
-    template<typename T> class OwnPtr {
-    public:
-        typedef typename RemovePointer<T>::Type ValueType;
-        typedef ValueType* PtrType;
-
-        OwnPtr() : m_ptr(0) { }
-
-        // See comment in PassOwnPtr.h for why this takes a const reference.
-        template<typename U> OwnPtr(const PassOwnPtr<U>& o);
-
-        // This copy constructor is used implicitly by gcc when it generates
-        // transients for assigning a PassOwnPtr<T> object to a stack-allocated
-        // OwnPtr<T> object. It should never be called explicitly and gcc
-        // should optimize away the constructor when generating code.
-        OwnPtr(const OwnPtr<ValueType>&);
-
-        ~OwnPtr() { deleteOwnedPtr(m_ptr); }
-
-        PtrType get() const { return m_ptr; }
-
-        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; }
-
-        bool operator!() const { return !m_ptr; }
-
-        // This conversion operator allows implicit conversion to bool but not to other integer types.
-        typedef PtrType OwnPtr::*UnspecifiedBoolType;
-        operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : 0; }
-
-        OwnPtr& operator=(const PassOwnPtr<T>&);
-        OwnPtr& operator=(std::nullptr_t) { clear(); return *this; }
-        template<typename U> OwnPtr& operator=(const PassOwnPtr<U>&);
-
-        void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
-
-#ifdef LOOSE_OWN_PTR
-        explicit OwnPtr(PtrType ptr) : m_ptr(ptr) { }
-        void set(PtrType);
-#endif
-
-    private:
-        OwnPtr& operator=(const OwnPtr<T>&);
-
-        // We should never have two OwnPtrs for the same underlying object (otherwise we'll get
-        // double-destruction), so these equality operators should never be needed.
-        template<typename U> bool operator==(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
-        template<typename U> bool operator!=(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
-        template<typename U> bool operator==(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
-        template<typename U> bool operator!=(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
-
-        PtrType m_ptr;
-    };
-
-    template<typename T> template<typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o)
-        : m_ptr(o.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)
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = o.leakPtr();
-        ASSERT(!ptr || m_ptr != ptr);
-        deleteOwnedPtr(ptr);
-        return *this;
-    }
-
-    template<typename T> template<typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o)
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = o.leakPtr();
-        ASSERT(!ptr || m_ptr != ptr);
-        deleteOwnedPtr(ptr);
-        return *this;
-    }
-
-    template<typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b)
-    {
-        a.swap(b);
-    }
-
-    template<typename T, typename U> inline bool operator==(const OwnPtr<T>& a, U* b)
-    {
-        return a.get() == b; 
-    }
-
-    template<typename T, typename U> inline bool operator==(T* a, const OwnPtr<U>& b) 
-    {
-        return a == b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, U* b)
-    {
-        return a.get() != b; 
-    }
-
-    template<typename T, typename U> inline bool operator!=(T* a, const OwnPtr<U>& b)
-    {
-        return a != b.get(); 
-    }
-
-    template<typename T> inline typename OwnPtr<T>::PtrType getPtr(const OwnPtr<T>& p)
-    {
-        return p.get();
-    }
-
-} // namespace WTF
-
-using WTF::OwnPtr;
-
-#endif // WTF_OwnPtr_h
diff --git a/wtf/OwnPtrCommon.h b/wtf/OwnPtrCommon.h
deleted file mode 100644 (file)
index 19256ea..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Torch Mobile, Inc.
- * Copyright (C) 2010 Company 100 Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this 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_OwnPtrCommon_h
-#define WTF_OwnPtrCommon_h
-
-#if PLATFORM(WIN)
-typedef struct HBITMAP__* HBITMAP;
-typedef struct HBRUSH__* HBRUSH;
-typedef struct HDC__* HDC;
-typedef struct HFONT__* HFONT;
-typedef struct HPALETTE__* HPALETTE;
-typedef struct HPEN__* HPEN;
-typedef struct HRGN__* HRGN;
-#endif
-
-#if PLATFORM(BREWMP)
-// Forward delcarations at this point avoid the need to include BREW includes
-// in WTF headers.
-typedef struct _ISocket ISocket;
-typedef struct _IFileMgr IFileMgr;
-typedef struct _IFile IFile;
-typedef struct IBitmap IBitmap;
-typedef struct ISSL ISSL;
-typedef struct IMemGroup IMemGroup;
-typedef struct IMemSpace IMemSpace;
-#endif
-
-namespace WTF {
-
-    template <typename T> inline void deleteOwnedPtr(T* ptr)
-    {
-        typedef char known[sizeof(T) ? 1 : -1];
-        if (sizeof(known))
-            delete ptr;
-    }
-
-#if PLATFORM(WIN)
-    void deleteOwnedPtr(HBITMAP);
-    void deleteOwnedPtr(HBRUSH);
-    void deleteOwnedPtr(HDC);
-    void deleteOwnedPtr(HFONT);
-    void deleteOwnedPtr(HPALETTE);
-    void deleteOwnedPtr(HPEN);
-    void deleteOwnedPtr(HRGN);
-#endif
-
-#if PLATFORM(BREWMP)
-    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 // WTF_OwnPtrCommon_h
diff --git a/wtf/PageAllocation.h b/wtf/PageAllocation.h
deleted file mode 100644 (file)
index ff6f195..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 6f54710..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index c018dab..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index eba5b03..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 6fb68e5..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index e17c546..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 77783eb..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 2e0524d..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index e241b83..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 2aa44d5..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 687c771..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 706bd80..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 3f30924..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * 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
diff --git a/wtf/PassOwnPtr.h b/wtf/PassOwnPtr.h
deleted file mode 100644 (file)
index 3635f3c..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * 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 WTF_PassOwnPtr_h
-#define WTF_PassOwnPtr_h
-
-#include "Assertions.h"
-#include "NullPtr.h"
-#include "OwnPtrCommon.h"
-#include "TypeTraits.h"
-
-#if !PLATFORM(CHROMIUM) && !PLATFORM(WIN) && !PLATFORM(MAC) && !PLATFORM(QT)
-// Remove this once we make all WebKit code compatible with stricter rules about PassOwnPtr.
-#define LOOSE_PASS_OWN_PTR
-#endif
-
-namespace WTF {
-
-    // Unlike most of our smart pointers, PassOwnPtr can take either the pointer type or the pointed-to type.
-
-    template<typename T> class OwnPtr;
-    template<typename T> class PassOwnPtr;
-    template<typename T> PassOwnPtr<T> adoptPtr(T*);
-
-    template<typename T> class PassOwnPtr {
-    public:
-        typedef typename RemovePointer<T>::Type ValueType;
-        typedef ValueType* PtrType;
-
-        PassOwnPtr() : m_ptr(0) { }
-        PassOwnPtr(std::nullptr_t) : m_ptr(0) { }
-
-        // It somewhat breaks the type system to allow transfer of ownership out of
-        // a const PassOwnPtr. However, it makes it much easier to work with PassOwnPtr
-        // temporaries, and we don't have a need to use real const PassOwnPtrs anyway.
-        PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.leakPtr()) { }
-        template<typename U> PassOwnPtr(const PassOwnPtr<U>& o) : m_ptr(o.leakPtr()) { }
-
-        ~PassOwnPtr() { deleteOwnedPtr(m_ptr); }
-
-        PtrType get() const { return m_ptr; }
-
-        void clear();
-        PtrType leakPtr() const WARN_UNUSED_RETURN;
-
-        ValueType& 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.
-        typedef PtrType PassOwnPtr::*UnspecifiedBoolType;
-        operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; }
-
-        PassOwnPtr& operator=(const PassOwnPtr<T>&);
-#if !defined(LOOSE_PASS_OWN_PTR) || !HAVE(NULLPTR)
-        PassOwnPtr& operator=(std::nullptr_t) { clear(); return *this; }
-#endif
-        template<typename U> PassOwnPtr& operator=(const PassOwnPtr<U>&);
-
-        template<typename U> friend PassOwnPtr<U> adoptPtr(U*);
-
-#ifdef LOOSE_PASS_OWN_PTR
-        PassOwnPtr(PtrType ptr) : m_ptr(ptr) { }
-        PassOwnPtr& operator=(PtrType);
-#endif
-
-    private:
-#ifndef LOOSE_PASS_OWN_PTR
-        explicit PassOwnPtr(PtrType ptr) : m_ptr(ptr) { }
-#endif
-
-        // We should never have two OwnPtrs for the same underlying object (otherwise we'll get
-        // double-destruction), so these equality operators should never be needed.
-        template<typename U> bool operator==(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
-        template<typename U> bool operator!=(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
-        template<typename U> bool operator==(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
-        template<typename U> bool operator!=(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
-
-        mutable PtrType m_ptr;
-    };
-
-    template<typename T> inline void PassOwnPtr<T>::clear()
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = 0;
-        deleteOwnedPtr(ptr);
-    }
-
-    template<typename T> inline typename PassOwnPtr<T>::PtrType PassOwnPtr<T>::leakPtr() const
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = 0;
-        return ptr;
-    }
-
-#ifdef LOOSE_PASS_OWN_PTR
-    template<typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(PtrType optr)
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        ASSERT(!ptr || m_ptr != ptr);
-        if (ptr)
-            deleteOwnedPtr(ptr);
-        return *this;
-    }
-#endif
-
-    template<typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<T>& optr)
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = optr.leakPtr();
-        ASSERT(!ptr || m_ptr != ptr);
-        if (ptr)
-            deleteOwnedPtr(ptr);
-        return *this;
-    }
-
-    template<typename T> template<typename U> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<U>& optr)
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = optr.leakPtr();
-        ASSERT(!ptr || m_ptr != ptr);
-        if (ptr)
-            deleteOwnedPtr(ptr);
-        return *this;
-    }
-
-    template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) 
-    {
-        return a.get() == b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const OwnPtr<U>& b) 
-    {
-        return a.get() == b.get(); 
-    }
-    
-    template<typename T, typename U> inline bool operator==(const OwnPtr<T>& a, const PassOwnPtr<U>& b) 
-    {
-        return a.get() == b.get(); 
-    }
-    
-    template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b) 
-    {
-        return a.get() == b; 
-    }
-    
-    template<typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b) 
-    {
-        return a == b.get(); 
-    }
-    
-    template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) 
-    {
-        return a.get() != b.get(); 
-    }
-    
-    template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const OwnPtr<U>& b) 
-    {
-        return a.get() != b.get(); 
-    }
-    
-    template<typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, const PassOwnPtr<U>& b) 
-    {
-        return a.get() != b.get(); 
-    }
-    
-    template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b)
-    {
-        return a.get() != b; 
-    }
-    
-    template<typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b) 
-    {
-        return a != b.get(); 
-    }
-
-    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 adoptPtr(static_cast<T*>(p.leakPtr()));
-    }
-
-    template<typename T, typename U> inline PassOwnPtr<T> const_pointer_cast(const PassOwnPtr<U>& p) 
-    {
-        return adoptPtr(const_cast<T*>(p.leakPtr()));
-    }
-
-    template<typename T> inline T* getPtr(const PassOwnPtr<T>& p)
-    {
-        return p.get();
-    }
-
-} // namespace WTF
-
-using WTF::PassOwnPtr;
-using WTF::adoptPtr;
-using WTF::const_pointer_cast;
-using WTF::static_pointer_cast;
-
-#endif // WTF_PassOwnPtr_h
diff --git a/wtf/PassRefPtr.h b/wtf/PassRefPtr.h
deleted file mode 100644 (file)
index 7b4af6b..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- *  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
- *  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_PassRefPtr_h
-#define WTF_PassRefPtr_h
-
-#include "AlwaysInline.h"
-#include "NullPtr.h"
-
-namespace WTF {
-
-    template<typename T> class RefPtr;
-    template<typename T> class PassRefPtr;
-    template<typename T> PassRefPtr<T> adoptRef(T*);
-
-    inline void adopted(const void*) { }
-
-#if !COMPILER(WINSCW)
-#if !PLATFORM(QT)
-    #define REF_DEREF_INLINE ALWAYS_INLINE
-#else
-    // Using ALWAYS_INLINE broke the Qt build. This may be a GCC bug.
-    // See https://bugs.webkit.org/show_bug.cgi?id=37253 for details.
-    #define REF_DEREF_INLINE inline
-#endif
-#else
-    // No inlining for WINSCW compiler to prevent the compiler agressively resolving
-    // T::ref() and T::deref(), which will fail compiling when PassRefPtr<T> is used as
-    // a class member or function arguments before T is defined.
-    #define REF_DEREF_INLINE
-#endif
-
-    template<typename T> REF_DEREF_INLINE void refIfNotNull(T* ptr)
-    {
-        if (LIKELY(ptr != 0))
-            ptr->ref();
-    }
-
-    template<typename T> REF_DEREF_INLINE void derefIfNotNull(T* ptr)
-    {
-        if (LIKELY(ptr != 0))
-            ptr->deref();
-    }
-
-    #undef REF_DEREF_INLINE
-
-    template<typename T> class PassRefPtr {
-    public:
-        PassRefPtr() : m_ptr(0) { }
-        PassRefPtr(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 have a need to use real const PassRefPtrs anyway.
-        PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { }
-        template<typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.leakRef()) { }
-
-        ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
-
-        template<typename U> PassRefPtr(const RefPtr<U>&);
-        
-        T* get() const { return m_ptr; }
-
-        void clear();
-        T* leakRef() const WARN_UNUSED_RETURN;
-
-        T& operator*() const { return *m_ptr; }
-        T* operator->() const { return m_ptr; }
-
-        bool operator!() const { return !m_ptr; }
-
-        // This conversion operator allows implicit conversion to bool but not to other integer types.
-        typedef T* (PassRefPtr::*UnspecifiedBoolType);
-        operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
-
-        PassRefPtr& operator=(T*);
-        PassRefPtr& operator=(const PassRefPtr&);
-#if !HAVE(NULLPTR)
-        PassRefPtr& operator=(std::nullptr_t) { clear(); return *this; }
-#endif
-        template<typename U> PassRefPtr& operator=(const PassRefPtr<U>&);
-        template<typename U> PassRefPtr& operator=(const RefPtr<U>&);
-
-        friend PassRefPtr adoptRef<T>(T*);
-
-        // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
-        T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
-
-    private:
-        // adopting constructor
-        PassRefPtr(T* ptr, bool) : m_ptr(ptr) { }
-
-        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 leakRef()
-    // or clear().
-
-    // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However,
-    // if we use inheritance, GCC's optimizer fails to realize that destruction
-    // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the
-    // most important code from PassRefPtr.
-    template<typename T> class NonNullPassRefPtr {
-    public:
-        NonNullPassRefPtr(T* ptr)
-            : m_ptr(ptr)
-        {
-            ASSERT(m_ptr);
-            m_ptr->ref();
-        }
-
-        template<typename U> NonNullPassRefPtr(const RefPtr<U>& o)
-            : m_ptr(o.get())
-        {
-            ASSERT(m_ptr);
-            m_ptr->ref();
-        }
-
-        NonNullPassRefPtr(const NonNullPassRefPtr& o)
-            : m_ptr(o.leakRef())
-        {
-            ASSERT(m_ptr);
-        }
-
-        template<typename U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o)
-            : m_ptr(o.leakRef())
-        {
-            ASSERT(m_ptr);
-        }
-
-        template<typename U> NonNullPassRefPtr(const PassRefPtr<U>& o)
-            : m_ptr(o.leakRef())
-        {
-            ASSERT(m_ptr);
-        }
-
-        ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); }
-
-        T* get() const { return m_ptr; }
-
-        void clear();
-        T* leakRef() const WARN_UNUSED_RETURN { T* tmp = m_ptr; m_ptr = 0; return tmp; }
-
-        T& operator*() const { return *m_ptr; }
-        T* operator->() const { return m_ptr; }
-
-        // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
-        T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
-
-    private:
-        mutable T* m_ptr;
-    };
-
-    template<typename T> template<typename U> inline PassRefPtr<T>::PassRefPtr(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* ptr = m_ptr;
-        m_ptr = optr;
-        derefIfNotNull(ptr);
-        return *this;
-    }
-    
-    template<typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr)
-    {
-        refIfNotNull(optr);
-        T* ptr = m_ptr;
-        m_ptr = optr;
-        derefIfNotNull(ptr);
-        return *this;
-    }
-
-    template<typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<T>& ref)
-    {
-        T* ptr = m_ptr;
-        m_ptr = ref.leakRef();
-        derefIfNotNull(ptr);
-        return *this;
-    }
-    
-    template<typename T> template<typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<U>& ref)
-    {
-        T* ptr = m_ptr;
-        m_ptr = ref.leakRef();
-        derefIfNotNull(ptr);
-        return *this;
-    }
-    
-    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 
-    { 
-        return a.get() == b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b) 
-    { 
-        return a.get() == b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b) 
-    { 
-        return a.get() == b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b) 
-    { 
-        return a.get() == b; 
-    }
-    
-    template<typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b) 
-    {
-        return a == b.get(); 
-    }
-    
-    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 
-    { 
-        return a.get() != b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b) 
-    { 
-        return a.get() != b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b) 
-    { 
-        return a.get() != b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
-    {
-        return a.get() != b; 
-    }
-
-    template<typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b) 
-    { 
-        return a != b.get(); 
-    }
-    
-    template<typename T> inline PassRefPtr<T> adoptRef(T* p)
-    {
-        adopted(p);
-        return PassRefPtr<T>(p, true);
-    }
-
-    template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p) 
-    { 
-        return adoptRef(static_cast<T*>(p.leakRef())); 
-    }
-
-    template<typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p) 
-    { 
-        return adoptRef(const_cast<T*>(p.leakRef())); 
-    }
-
-    template<typename T> inline T* getPtr(const PassRefPtr<T>& p)
-    {
-        return p.get();
-    }
-
-    template<typename T> inline void NonNullPassRefPtr<T>::clear()
-    {
-        T* ptr = m_ptr;
-        m_ptr = 0;
-        derefIfNotNull(ptr);
-    }
-
-} // namespace WTF
-
-using WTF::PassRefPtr;
-using WTF::NonNullPassRefPtr;
-using WTF::adoptRef;
-using WTF::static_pointer_cast;
-using WTF::const_pointer_cast;
-
-#endif // WTF_PassRefPtr_h
diff --git a/wtf/PassTraits.h b/wtf/PassTraits.h
deleted file mode 100644 (file)
index 3462734..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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
diff --git a/wtf/Platform.h b/wtf/Platform.h
deleted file mode 100644 (file)
index 987cfbf..0000000
+++ /dev/null
@@ -1,1232 +0,0 @@
-/*
- * 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
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this 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_Platform_h
-#define WTF_Platform_h
-
-/* ==== PLATFORM handles OS, operating environment, graphics API, and
-   CPU. This macro will be phased out in favor of platform adaptation
-   macros, policy decision macros, and top-level port definitions. ==== */
-#define PLATFORM(WTF_FEATURE) (defined WTF_PLATFORM_##WTF_FEATURE  && WTF_PLATFORM_##WTF_FEATURE)
-
-
-/* ==== Platform adaptation macros: these describe properties of the target environment. ==== */
-
-/* COMPILER() - the compiler being used to build the project */
-#define COMPILER(WTF_FEATURE) (defined WTF_COMPILER_##WTF_FEATURE  && WTF_COMPILER_##WTF_FEATURE)
-/* CPU() - the target CPU architecture */
-#define CPU(WTF_FEATURE) (defined WTF_CPU_##WTF_FEATURE  && WTF_CPU_##WTF_FEATURE)
-/* HAVE() - specific system features (headers, functions or similar) that are present or not */
-#define HAVE(WTF_FEATURE) (defined HAVE_##WTF_FEATURE  && HAVE_##WTF_FEATURE)
-/* OS() - underlying operating system; only to be used for mandated low-level services like 
-   virtual memory, not to choose a GUI toolkit */
-#define OS(WTF_FEATURE) (defined WTF_OS_##WTF_FEATURE  && WTF_OS_##WTF_FEATURE)
-
-
-/* ==== Policy decision macros: these define policy choices for a particular port. ==== */
-
-/* USE() - use a particular third-party library or optional OS service */
-#define USE(WTF_FEATURE) (defined WTF_USE_##WTF_FEATURE  && WTF_USE_##WTF_FEATURE)
-/* ENABLE() - turn on a specific feature of WebKit */
-#define ENABLE(WTF_FEATURE) (defined ENABLE_##WTF_FEATURE  && ENABLE_##WTF_FEATURE)
-
-
-
-/* ==== COMPILER() - the compiler being used to build the project ==== */
-
-/* COMPILER(MSVC) Microsoft Visual C++ */
-/* COMPILER(MSVC7_OR_LOWER) Microsoft Visual C++ 2003 or lower*/
-/* COMPILER(MSVC9_OR_LOWER) Microsoft Visual C++ 2008 or lower*/
-#if defined(_MSC_VER)
-#define WTF_COMPILER_MSVC 1
-#if _MSC_VER < 1400
-#define WTF_COMPILER_MSVC7_OR_LOWER 1
-#elif _MSC_VER < 1600
-#define WTF_COMPILER_MSVC9_OR_LOWER 1
-#endif
-#endif
-
-/* COMPILER(RVCT)  - ARM RealView Compilation Tools */
-/* COMPILER(RVCT4_OR_GREATER) - ARM RealView Compilation Tools 4.0 or greater */
-#if defined(__CC_ARM) || defined(__ARMCC__)
-#define WTF_COMPILER_RVCT 1
-#define RVCT_VERSION_AT_LEAST(major, minor, patch, build) (__ARMCC_VERSION >= (major * 100000 + minor * 10000 + patch * 1000 + build))
-#else
-/* Define this for !RVCT compilers, just so we can write things like RVCT_VERSION_AT_LEAST(3, 0, 0, 0). */
-#define RVCT_VERSION_AT_LEAST(major, minor, patch, build) 0
-#endif
-
-/* COMPILER(GCCE) - GNU Compiler Collection for Embedded */
-#if defined(__GCCE__)
-#define WTF_COMPILER_GCCE 1
-#define GCCE_VERSION (__GCCE__ * 10000 + __GCCE_MINOR__ * 100 + __GCCE_PATCHLEVEL__)
-#define GCCE_VERSION_AT_LEAST(major, minor, patch) (GCCE_VERSION >= (major * 10000 + minor * 100 + patch))
-#endif
-
-/* COMPILER(GCC) - GNU Compiler Collection */
-/* --gnu option of the RVCT compiler also defines __GNUC__ */
-#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 */
-/* COMPILER(MINGW64) - mingw-w64 GCC - only used as additional check to exclude mingw.org specific functions */
-#if defined(__MINGW32__)
-#define WTF_COMPILER_MINGW 1
-#include <_mingw.h> /* private MinGW header */
-    #if defined(__MINGW64_VERSION_MAJOR) /* best way to check for mingw-w64 vs mingw.org */
-        #define WTF_COMPILER_MINGW64 1
-    #endif /* __MINGW64_VERSION_MAJOR */
-#endif /* __MINGW32__ */
-
-/* COMPILER(WINSCW) - CodeWarrior for Symbian emulator */
-#if defined(__WINSCW__)
-#define WTF_COMPILER_WINSCW 1
-/* cross-compiling, it is not really windows */
-#undef WIN32
-#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 ==== */
-
-/* This also defines CPU(BIG_ENDIAN) or CPU(MIDDLE_ENDIAN) or neither, as appropriate. */
-
-/* CPU(ALPHA) - DEC Alpha */
-#if defined(__alpha__)
-#define WTF_CPU_ALPHA 1
-#endif
-
-/* CPU(IA64) - Itanium / IA-64 */
-#if defined(__ia64__)
-#define WTF_CPU_IA64 1
-/* 32-bit mode on Itanium */
-#if !defined(__LP64__)
-#define WTF_CPU_IA64_32 1
-#endif
-#endif
-
-/* 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__) || defined(MIPS) || defined(_MIPS_)) \
-    && defined(_ABIO32)
-#define WTF_CPU_MIPS 1
-#if defined(__MIPSEB__)
-#define WTF_CPU_BIG_ENDIAN 1
-#endif
-#define WTF_MIPS_PIC (defined __PIC__)
-#define WTF_MIPS_ARCH __mips
-#define WTF_MIPS_ISA(v) (defined WTF_MIPS_ARCH && WTF_MIPS_ARCH == v)
-#define WTF_MIPS_ISA_AT_LEAST(v) (defined WTF_MIPS_ARCH && WTF_MIPS_ARCH >= v)
-#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 */
-#if   defined(__ppc__)     \
-    || defined(__PPC__)     \
-    || defined(__powerpc__) \
-    || defined(__powerpc)   \
-    || defined(__POWERPC__) \
-    || defined(_M_PPC)      \
-    || defined(__PPC)
-#define WTF_CPU_PPC 1
-#define WTF_CPU_BIG_ENDIAN 1
-#endif
-
-/* CPU(PPC64) - PowerPC 64-bit */
-#if   defined(__ppc64__) \
-    || defined(__PPC64__)
-#define WTF_CPU_PPC64 1
-#define WTF_CPU_BIG_ENDIAN 1
-#endif
-
-/* CPU(SH4) - SuperH SH-4 */
-#if defined(__SH4__)
-#define WTF_CPU_SH4 1
-#endif
-
-/* CPU(SPARC32) - SPARC 32-bit */
-#if defined(__sparc) && !defined(__arch64__) || defined(__sparcv8)
-#define WTF_CPU_SPARC32 1
-#define WTF_CPU_BIG_ENDIAN 1
-#endif
-
-/* CPU(SPARC64) - SPARC 64-bit */
-#if defined(__sparc__) && defined(__arch64__) || defined (__sparcv9)
-#define WTF_CPU_SPARC64 1
-#define WTF_CPU_BIG_ENDIAN 1
-#endif
-
-/* CPU(SPARC) - any SPARC, true for CPU(SPARC32) and CPU(SPARC64) */
-#if CPU(SPARC32) || CPU(SPARC64)
-#define WTF_CPU_SPARC 1
-#endif
-
-/* CPU(S390X) - S390 64-bit */
-#if defined(__s390x__)
-#define WTF_CPU_S390X 1
-#define WTF_CPU_BIG_ENDIAN 1
-#endif
-
-/* CPU(S390) - S390 32-bit */
-#if defined(__s390__)
-#define WTF_CPU_S390 1
-#define WTF_CPU_BIG_ENDIAN 1
-#endif
-
-/* CPU(X86) - i386 / x86 32-bit */
-#if   defined(__i386__) \
-    || defined(i386)     \
-    || defined(_M_IX86)  \
-    || defined(_X86_)    \
-    || defined(__THW_INTEL)
-#define WTF_CPU_X86 1
-#endif
-
-/* CPU(X86_64) - AMD64 / Intel64 / x86_64 64-bit */
-#if   defined(__x86_64__) \
-    || defined(_M_X64)
-#define WTF_CPU_X86_64 1
-#endif
-
-/* CPU(ARM) - ARM, any version*/
-#if   defined(arm) \
-    || defined(__arm__) \
-    || defined(ARM) \
-    || defined(_ARM_)
-#define WTF_CPU_ARM 1
-
-#if defined(__ARMEB__) || (COMPILER(RVCT) && defined(__BIG_ENDIAN))
-#define WTF_CPU_BIG_ENDIAN 1
-
-#elif !defined(__ARM_EABI__) \
-    && !defined(__EABI__) \
-    && !defined(__VFP_FP__) \
-    && !defined(_WIN32_WCE) \
-    && !defined(ANDROID)
-#define WTF_CPU_MIDDLE_ENDIAN 1
-
-#endif
-
-#define WTF_ARM_ARCH_AT_LEAST(N) (CPU(ARM) && WTF_ARM_ARCH_VERSION >= N)
-
-/* Set WTF_ARM_ARCH_VERSION */
-#if   defined(__ARM_ARCH_4__) \
-    || defined(__ARM_ARCH_4T__) \
-    || defined(__MARM_ARMV4__) \
-    || defined(_ARMV4I_)
-#define WTF_ARM_ARCH_VERSION 4
-
-#elif defined(__ARM_ARCH_5__) \
-    || defined(__ARM_ARCH_5T__) \
-    || 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__) \
-    || defined(__ARM_ARCH_6Z__) \
-    || defined(__ARM_ARCH_6ZK__) \
-    || defined(__ARM_ARCH_6T2__) \
-    || defined(__ARMV6__)
-#define WTF_ARM_ARCH_VERSION 6
-
-#elif defined(__ARM_ARCH_7A__) \
-    || defined(__ARM_ARCH_7F__) \
-    || defined(__ARM_ARCH_7R__) \
-    || defined(__ARM_ARCH_7S__)
-#define WTF_ARM_ARCH_VERSION 7
-
-/* RVCT sets _TARGET_ARCH_ARM */
-#elif defined(__TARGET_ARCH_ARM)
-#define WTF_ARM_ARCH_VERSION __TARGET_ARCH_ARM
-
-#if defined(__TARGET_ARCH_5E) \
-    || defined(__TARGET_ARCH_5TE) \
-    || defined(__TARGET_ARCH_5TEJ)
-/*ARMv5TE requires allocators to use aligned memory*/
-#define WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER 1
-#endif
-
-#else
-#define WTF_ARM_ARCH_VERSION 0
-
-#endif
-
-/* Set WTF_THUMB_ARCH_VERSION */
-#if   defined(__ARM_ARCH_4T__)
-#define WTF_THUMB_ARCH_VERSION 1
-
-#elif defined(__ARM_ARCH_5T__) \
-    || defined(__ARM_ARCH_5TE__) \
-    || defined(__ARM_ARCH_5TEJ__)
-#define WTF_THUMB_ARCH_VERSION 2
-
-#elif defined(__ARM_ARCH_6J__) \
-    || defined(__ARM_ARCH_6K__) \
-    || defined(__ARM_ARCH_6Z__) \
-    || defined(__ARM_ARCH_6ZK__) \
-    || defined(__ARM_ARCH_6M__)
-#define WTF_THUMB_ARCH_VERSION 3
-
-#elif defined(__ARM_ARCH_6T2__) \
-    || defined(__ARM_ARCH_7__) \
-    || defined(__ARM_ARCH_7A__) \
-    || defined(__ARM_ARCH_7F__) \
-    || defined(__ARM_ARCH_7R__) \
-    || defined(__ARM_ARCH_7M__) \
-    || defined(__ARM_ARCH_7S__)
-#define WTF_THUMB_ARCH_VERSION 4
-
-/* RVCT sets __TARGET_ARCH_THUMB */
-#elif defined(__TARGET_ARCH_THUMB)
-#define WTF_THUMB_ARCH_VERSION __TARGET_ARCH_THUMB
-
-#else
-#define WTF_THUMB_ARCH_VERSION 0
-#endif
-
-
-/* CPU(ARMV5_OR_LOWER) - ARM instruction set v5 or earlier */
-/* On ARMv5 and below the natural alignment is required. 
-   And there are some other differences for v5 or earlier. */
-#if !defined(ARMV5_OR_LOWER) && !WTF_ARM_ARCH_AT_LEAST(6)
-#define WTF_CPU_ARMV5_OR_LOWER 1
-#endif
-
-
-/* CPU(ARM_TRADITIONAL) - Thumb2 is not available, only traditional ARM (v4 or greater) */
-/* CPU(ARM_THUMB2) - Thumb2 instruction set is available */
-/* Only one of these will be defined. */
-#if !defined(WTF_CPU_ARM_TRADITIONAL) && !defined(WTF_CPU_ARM_THUMB2)
-#  if defined(thumb2) || defined(__thumb2__) \
-    || ((defined(__thumb) || defined(__thumb__)) && WTF_THUMB_ARCH_VERSION == 4)
-#    define WTF_CPU_ARM_TRADITIONAL 0
-#    define WTF_CPU_ARM_THUMB2 1
-#  elif WTF_ARM_ARCH_AT_LEAST(4)
-#    define WTF_CPU_ARM_TRADITIONAL 1
-#    define WTF_CPU_ARM_THUMB2 0
-#  else
-#    error "Not supported ARM architecture"
-#  endif
-#elif CPU(ARM_TRADITIONAL) && CPU(ARM_THUMB2) /* Sanity Check */
-#  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) */
-
-#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(ANDROID) - Android */
-#ifdef ANDROID
-#define WTF_OS_ANDROID 1
-#endif
-
-/* OS(AIX) - AIX */
-#ifdef _AIX
-#define WTF_OS_AIX 1
-#endif
-
-/* OS(DARWIN) - Any Darwin-based OS, including Mac OS X and iPhone OS */
-#ifdef __APPLE__
-#define WTF_OS_DARWIN 1
-
-/* FIXME: BUILDING_ON_.., and TARGETING... macros should be folded into the OS() system */
-#include <AvailabilityMacros.h>
-#if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
-#define BUILDING_ON_LEOPARD 1
-#elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
-#define BUILDING_ON_SNOW_LEOPARD 1
-#endif
-#if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
-#define TARGETING_LEOPARD 1
-#elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7
-#define TARGETING_SNOW_LEOPARD 1
-#endif
-#include <Availability.h>
-#include <TargetConditionals.h>
-
-#endif
-
-/* OS(IOS) - iOS */
-/* OS(MAC_OS_X) - Mac OS X (not including iOS) */
-#if OS(DARWIN) && ((defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED)  \
-    || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)                   \
-    || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR))
-#define WTF_OS_IOS 1
-#elif OS(DARWIN) && defined(TARGET_OS_MAC) && TARGET_OS_MAC
-#define WTF_OS_MAC_OS_X 1
-#endif
-
-/* OS(FREEBSD) - FreeBSD */
-#if defined(__FreeBSD__) || defined(__DragonFly__)
-#define WTF_OS_FREEBSD 1
-#endif
-
-/* OS(HAIKU) - Haiku */
-#ifdef __HAIKU__
-#define WTF_OS_HAIKU 1
-#endif
-
-/* OS(LINUX) - Linux */
-#ifdef __linux__
-#define WTF_OS_LINUX 1
-#endif
-
-/* OS(NETBSD) - NetBSD */
-#if defined(__NetBSD__)
-#define WTF_OS_NETBSD 1
-#endif
-
-/* OS(OPENBSD) - OpenBSD */
-#ifdef __OpenBSD__
-#define WTF_OS_OPENBSD 1
-#endif
-
-/* OS(QNX) - QNX */
-#if defined(__QNXNTO__)
-#define WTF_OS_QNX 1
-#endif
-
-/* OS(SOLARIS) - Solaris */
-#if defined(sun) || defined(__sun)
-#define WTF_OS_SOLARIS 1
-#endif
-
-/* OS(WINCE) - Windows CE; note that for this platform OS(WINDOWS) is also defined */
-#if defined(_WIN32_WCE)
-#define WTF_OS_WINCE 1
-#endif
-
-/* OS(WINDOWS) - Any version of Windows */
-#if defined(WIN32) || defined(_WIN32)
-#define WTF_OS_WINDOWS 1
-#endif
-
-/* OS(SYMBIAN) - Symbian */
-#if defined (__SYMBIAN32__)
-#define WTF_OS_SYMBIAN 1
-#endif
-
-/* OS(UNIX) - Any Unix-like system */
-#if   OS(AIX)              \
-    || OS(ANDROID)          \
-    || OS(DARWIN)           \
-    || OS(FREEBSD)          \
-    || OS(HAIKU)            \
-    || OS(LINUX)            \
-    || OS(NETBSD)           \
-    || OS(OPENBSD)          \
-    || OS(QNX)              \
-    || OS(SOLARIS)          \
-    || OS(SYMBIAN)          \
-    || defined(unix)        \
-    || defined(__unix)      \
-    || defined(__unix__)
-#define WTF_OS_UNIX 1
-#endif
-
-/* Operating environments */
-
-/* FIXME: these are all mixes of OS, operating environment and policy choices. */
-/* PLATFORM(CHROMIUM) */
-/* PLATFORM(QT) */
-/* PLATFORM(WX) */
-/* PLATFORM(GTK) */
-/* PLATFORM(HAIKU) */
-/* PLATFORM(MAC) */
-/* PLATFORM(WIN) */
-#if defined(BUILDING_CHROMIUM__)
-#define WTF_PLATFORM_CHROMIUM 1
-#elif defined(BUILDING_QT__)
-#define WTF_PLATFORM_QT 1
-#elif defined(BUILDING_WX__)
-#define WTF_PLATFORM_WX 1
-#elif defined(BUILDING_GTK__)
-#define WTF_PLATFORM_GTK 1
-#elif defined(BUILDING_HAIKU__)
-#define WTF_PLATFORM_HAIKU 1
-#elif defined(BUILDING_BREWMP__)
-#define WTF_PLATFORM_BREWMP 1
-#if defined(AEE_SIMULATOR)
-#define WTF_PLATFORM_BREWMP_SIMULATOR 1
-#else
-#define WTF_PLATFORM_BREWMP_SIMULATOR 0
-#endif
-#undef WTF_OS_WINDOWS
-#undef WTF_PLATFORM_WIN
-#elif OS(DARWIN)
-#define WTF_PLATFORM_MAC 1
-#elif OS(WINDOWS)
-#define WTF_PLATFORM_WIN 1
-#endif
-
-/* PLATFORM(IOS) */
-/* FIXME: this is sometimes used as an OS switch and sometimes for higher-level things */
-#if (defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
-#define WTF_PLATFORM_IOS 1
-#endif
-
-/* PLATFORM(IOS_SIMULATOR) */
-#if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
-#define WTF_PLATFORM_IOS 1
-#define WTF_PLATFORM_IOS_SIMULATOR 1
-#else
-#define WTF_PLATFORM_IOS_SIMULATOR 0
-#endif
-
-#if !defined(WTF_PLATFORM_IOS)
-#define WTF_PLATFORM_IOS 0
-#endif
-
-/* Graphics engines */
-
-/* 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
-
-/* USE(SKIA) for Win/Linux, CG for Mac */
-#if PLATFORM(CHROMIUM)
-#if OS(DARWIN)
-#define WTF_USE_CG 1
-#define WTF_USE_ATSUI 1
-#define WTF_USE_CORE_TEXT 1
-#define WTF_USE_ICCJPEG 1
-#else
-#define WTF_USE_SKIA 1
-#define WTF_USE_CHROMIUM_NET 1
-#endif
-#endif
-
-#if PLATFORM(BREWMP)
-#define WTF_USE_SKIA 1
-#endif
-
-#if PLATFORM(GTK)
-#define WTF_USE_CAIRO 1
-#endif
-
-
-#if OS(WINCE)
-#include <ce_time.h>
-#define WTF_USE_MERSENNE_TWISTER_19937 1
-#endif
-
-#if PLATFORM(QT) && OS(UNIX) && !OS(SYMBIAN) && !OS(DARWIN)
-#define WTF_USE_PTHREAD_BASED_QT 1
-#endif
-
-#if (PLATFORM(GTK) || PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || (PLATFORM(QT) && (OS(DARWIN) || USE(PTHREAD_BASED_QT)) && !ENABLE(SINGLE_THREADED))) && !defined(ENABLE_JSC_MULTIPLE_THREADS)
-#define ENABLE_JSC_MULTIPLE_THREADS 1
-#endif
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-#define ENABLE_WTF_MULTIPLE_THREADS 1
-#endif
-
-/* On Windows, use QueryPerformanceCounter by default */
-#if OS(WINDOWS)
-#define WTF_USE_QUERY_PERFORMANCE_COUNTER  1
-#endif
-
-#if OS(WINCE) && !PLATFORM(QT)
-#define NOMINMAX       /* Windows min and max conflict with standard macros */
-#define NOSHLWAPI      /* shlwapi.h not available on WinCe */
-
-/* MSDN documentation says these functions are provided with uspce.lib.  But we cannot find this file. */
-#define __usp10__      /* disable "usp10.h" */
-
-#define _INC_ASSERT    /* disable "assert.h" */
-#define assert(x)
-
-#endif  /* OS(WINCE) && !PLATFORM(QT) */
-
-#if PLATFORM(QT)
-#define WTF_USE_QT4_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
-#define WTF_USE_ICU_UNICODE 1
-#endif
-
-
-#if PLATFORM(CHROMIUM) && OS(DARWIN)
-#define WTF_USE_CF 1
-#define WTF_USE_PTHREADS 1
-#define HAVE_PTHREAD_RWLOCK 1
-#endif
-
-#define DONT_FINALIZE_ON_MAIN_THREAD 1
-
-#if PLATFORM(BREWMP)
-#define ENABLE_SINGLE_THREADED 1
-#endif
-
-#if PLATFORM(QT) && OS(DARWIN)
-#define WTF_USE_CF 1
-#endif
-
-#if OS(DARWIN) && !PLATFORM(GTK) && !PLATFORM(QT)
-#define ENABLE_PURGEABLE_MEMORY 1
-#endif
-
-#define ENABLE_CONTEXT_MENUS 0
-#define ENABLE_DISK_IMAGE_CACHE 1
-#define ENABLE_DRAG_SUPPORT 0
-#define ENABLE_DATA_TRANSFER_ITEMS 0
-#define ENABLE_FTPDIR 1
-#define ENABLE_GEOLOCATION 1
-#define ENABLE_GEOLOCATION_PERMISSION_CACHE 1
-#define ENABLE_ICONDATABASE 0
-#define ENABLE_JAVA_BRIDGE 0
-#define ENABLE_NETSCAPE_PLUGIN_API 0
-#define ENABLE_ORIENTATION_EVENTS 1
-#define ENABLE_REPAINT_THROTTLING 1
-#define ENABLE_RESPECT_EXIF_ORIENTATION 1
-#define ENABLE_WEB_ARCHIVE 1
-#define HAVE_CFNETWORK_DATA_ARRAY_CALLBACK 1
-#define HAVE_PTHREAD_RWLOCK 1
-#define HAVE_READLINE 1
-#define HAVE_RUNLOOP_TIMER 0
-#define WTF_USE_CF 1
-#define WTF_USE_CFNETWORK 1
-#define WTF_USE_PTHREADS 1
-#define WTF_USE_WEB_THREAD 1
-
-#undef ENABLE_PURGEABLE_MEMORY
-
-#if defined(WTF_ARM_ARCH_VERSION) && WTF_ARM_ARCH_VERSION == 6
-#define ENABLE_INSPECTOR 0
-#define ENABLE_PURGEABLE_MEMORY 0
-#else
-#define ENABLE_INSPECTOR 1
-#define ENABLE_PURGEABLE_MEMORY 1
-#endif
-
-#if defined(WTF_ARM_ARCH_VERSION) && WTF_ARM_ARCH_VERSION >= 7
-    // ARMv7;
-    #define WTF_USE_JSVALUE32_64 1
-    #define ENABLE_INTERPRETER 1
-    #define ENABLE_JIT 1
-    #define ENABLE_YARR 1
-    #define ENABLE_YARR_JIT 1
-#else
-    // ARMv6; never use the JIT, use JSVALUE32_64 only if compiling with llvm.
-    #define ENABLE_JIT 0
-    #define ENABLE_YARR 0
-    #define ENABLE_YARR_JIT 0
-    /* FIXME: <rdar://problem/7478149> gcc-4.2 compiler bug with USE(JSVALUE32_64) and armv6 target */
-    #ifdef __llvm__
-    #define WTF_USE_JSVALUE32_64 1
-    #else
-    #define WTF_USE_JSVALUE32 1
-    #endif
-#endif
-
-#undef ENABLE_WEBGL
-#if defined(WTF_ARM_ARCH_VERSION) && WTF_ARM_ARCH_VERSION == 6
-#define ENABLE_WEBGL 0
-#else
-#define ENABLE_WEBGL 1
-#endif
-
-
-#if PLATFORM(ANDROID)
-#define WTF_USE_PTHREADS 1
-#define USE_SYSTEM_MALLOC 1
-#define ENABLE_JAVA_BRIDGE 1
-#define LOG_DISABLED 1
-/* Prevents Webkit from drawing the caret in textfields and textareas
-   This prevents unnecessary invals. */
-#define ENABLE_TEXT_CARET 1
-#define ENABLE_JAVASCRIPT_DEBUGGER 0
-#if !defined(ENABLE_JIT) && !ENABLE(ANDROID_JSC_JIT)
-#define ENABLE_JIT 0
-#endif
-#endif
-
-#if PLATFORM(WIN) && !OS(WINCE)
-#define WTF_USE_CF 1
-#define WTF_USE_PTHREADS 0
-#endif
-
-#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !defined(WIN_CAIRO)
-#define WTF_USE_CFNETWORK 1
-#endif
-
-#define WTF_USE_CFURLCACHE 1
-#define WTF_USE_CFURLSTORAGESESSIONS 1
-
-#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(QT)
-#define ENABLE_WEB_ARCHIVE 1
-#endif
-
-#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !defined(WIN_CAIRO) && !PLATFORM(QT)
-#define ENABLE_FULLSCREEN_API 1
-#endif
-
-#if PLATFORM(WX)
-#define ENABLE_ASSEMBLER 1
-#define ENABLE_GLOBAL_FASTMALLOC_NEW 0
-#if OS(DARWIN)
-#define WTF_USE_CF 1
-#define WTF_USE_CORE_TEXT 1
-#define ENABLE_WEB_ARCHIVE 1
-#endif
-#endif
-
-#if PLATFORM(GTK)
-#if HAVE(PTHREAD_H)
-#define WTF_USE_PTHREADS 1
-#define HAVE_PTHREAD_RWLOCK 1
-#endif
-#endif
-
-#if PLATFORM(HAIKU)
-#define HAVE_POSIX_MEMALIGN 1
-#define WTF_USE_CURL 1
-#define WTF_USE_PTHREADS 1
-#define HAVE_PTHREAD_RWLOCK 1
-#define USE_SYSTEM_MALLOC 1
-#define ENABLE_NETSCAPE_PLUGIN_API 0
-#endif
-
-#if PLATFORM(BREWMP)
-#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 OS(UNIX) && !OS(SYMBIAN)
-#define HAVE_SIGNAL_H 1
-#endif
-
-#if !defined(HAVE_STRNSTR)
-#if OS(DARWIN) || OS(FREEBSD)
-#define HAVE_STRNSTR 1
-#endif
-#endif
-
-#if !OS(WINDOWS) && !OS(SOLARIS) && !OS(QNX) \
-    && !OS(SYMBIAN) && !OS(HAIKU) && !OS(RVCT) \
-    && !OS(ANDROID) && !PLATFORM(BREWMP)
-#define HAVE_TM_GMTOFF 1
-#define HAVE_TM_ZONE 1
-#define HAVE_TIMEGM 1
-#endif
-
-#if OS(DARWIN)
-
-#define HAVE_ERRNO_H 1
-#define HAVE_LANGINFO_H 1
-#define HAVE_MMAP 1
-#define HAVE_MERGESORT 1
-#define HAVE_SBRK 1
-#define HAVE_STRINGS_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
-
-#ifndef TARGETING_LEOPARD
-
-#define HAVE_DISPATCH_H 1
-#define HAVE_HOSTED_CORE_ANIMATION 1
-
-
-#endif
-
-#define HAVE_MADV_FREE 1
-#define HAVE_PTHREAD_SETNAME_NP 1
-
-#elif OS(WINDOWS)
-
-#if OS(WINCE)
-#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
-
-#elif OS(SYMBIAN)
-
-#define HAVE_ERRNO_H 1
-#define HAVE_MMAP 0
-#define HAVE_SBRK 1
-
-#define HAVE_SYS_TIME_H 1
-#define HAVE_STRINGS_H 1
-
-#if !COMPILER(RVCT)
-#define HAVE_SYS_PARAM_H 1
-#endif
-
-#elif PLATFORM(BREWMP)
-
-#define HAVE_ERRNO_H 1
-
-#elif OS(QNX)
-
-#define HAVE_ERRNO_H 1
-#define HAVE_MMAP 1
-#define HAVE_SBRK 1
-#define HAVE_STRINGS_H 1
-#define HAVE_SYS_PARAM_H 1
-#define HAVE_SYS_TIME_H 1
-
-#elif OS(ANDROID)
-
-#define HAVE_ERRNO_H 1
-#define HAVE_LANGINFO_H 0
-#define HAVE_MMAP 1
-#define HAVE_SBRK 1
-#define HAVE_STRINGS_H 1
-#define HAVE_SYS_PARAM_H 1
-#define HAVE_SYS_TIME_H 1
-
-#else
-
-/* FIXME: is this actually used or do other platforms generate their own config.h? */
-
-#define HAVE_ERRNO_H 1
-/* As long as Haiku doesn't have a complete support of locale this will be disabled. */
-#if !OS(HAIKU)
-#define HAVE_LANGINFO_H 1
-#endif
-#define HAVE_MMAP 1
-#define HAVE_SBRK 1
-#define HAVE_STRINGS_H 1
-#define HAVE_SYS_PARAM_H 1
-#define HAVE_SYS_TIME_H 1
-
-#endif
-
-/* ENABLE macro defaults */
-
-#if PLATFORM(QT)
-/* We must not customize the global operator new and delete for the Qt port. */
-#define ENABLE_GLOBAL_FASTMALLOC_NEW 0
-#if !OS(UNIX) || OS(SYMBIAN)
-#define USE_SYSTEM_MALLOC 1
-#endif
-#endif
-
-/* fastMalloc match validation allows for runtime verification that
-   new is matched by delete, fastMalloc is matched by fastFree, etc. */
-#if !defined(ENABLE_FAST_MALLOC_MATCH_VALIDATION)
-#define ENABLE_FAST_MALLOC_MATCH_VALIDATION 0
-#endif
-
-#if !defined(ENABLE_ICONDATABASE)
-#define ENABLE_ICONDATABASE 1
-#endif
-
-#if !defined(ENABLE_DATABASE)
-#define ENABLE_DATABASE 1
-#endif
-
-#if !defined(ENABLE_JAVASCRIPT_DEBUGGER)
-#define ENABLE_JAVASCRIPT_DEBUGGER 1
-#endif
-
-#if !defined(ENABLE_FTPDIR)
-#define ENABLE_FTPDIR 1
-#endif
-
-#if !defined(ENABLE_CONTEXT_MENUS)
-#define ENABLE_CONTEXT_MENUS 1
-#endif
-
-#if !defined(ENABLE_DISK_IMAGE_CACHE)
-#define ENABLE_DISK_IMAGE_CACHE 0
-#endif
-
-#if !defined(ENABLE_DRAG_SUPPORT)
-#define ENABLE_DRAG_SUPPORT 1
-#endif
-
-#if !defined(ENABLE_DATA_TRANSFER_ITEMS)
-#define ENABLE_DATA_TRANSFER_ITEMS 0
-#endif
-
-#if !defined(ENABLE_DASHBOARD_SUPPORT)
-#define ENABLE_DASHBOARD_SUPPORT 0
-#endif
-
-#if !defined(ENABLE_GEOLOCATION_PERMISSION_CACHE)
-#define ENABLE_GEOLOCATION_PERMISSION_CACHE 0
-#endif
-
-#if !defined(ENABLE_INSPECTOR)
-#define ENABLE_INSPECTOR 1
-#endif
-
-#if !defined(ENABLE_JAVA_BRIDGE)
-#define ENABLE_JAVA_BRIDGE 0
-#endif
-
-#if !defined(ENABLE_NETSCAPE_PLUGIN_API)
-#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(WTF_USE_PLUGIN_HOST_PROCESS)
-#define WTF_USE_PLUGIN_HOST_PROCESS 0
-#endif
-
-#if !defined(ENABLE_ORIENTATION_EVENTS)
-#define ENABLE_ORIENTATION_EVENTS 0
-#endif
-
-#if !defined(ENABLE_RESPECT_EXIF_ORIENTATION)
-#define ENABLE_RESPECT_EXIF_ORIENTATION 0
-#endif
-
-#if !defined(ENABLE_OPCODE_STATS)
-#define ENABLE_OPCODE_STATS 0
-#endif
-
-#if !defined(ENABLE_GLOBAL_FASTMALLOC_NEW)
-#define ENABLE_GLOBAL_FASTMALLOC_NEW 1
-#endif
-
-#define ENABLE_DEBUG_WITH_BREAKPOINT 0
-#define ENABLE_SAMPLING_COUNTERS 0
-#define ENABLE_SAMPLING_FLAGS 0
-#define ENABLE_OPCODE_SAMPLING 0
-#define ENABLE_CODEBLOCK_SAMPLING 0
-#if ENABLE(CODEBLOCK_SAMPLING) && !ENABLE(OPCODE_SAMPLING)
-#error "CODEBLOCK_SAMPLING requires OPCODE_SAMPLING"
-#endif
-#if ENABLE(OPCODE_SAMPLING) || ENABLE(SAMPLING_FLAGS)
-#define ENABLE_SAMPLING_THREAD 1
-#endif
-
-#if !defined(ENABLE_GEOLOCATION)
-#define ENABLE_GEOLOCATION 0
-#endif
-
-#if !defined(ENABLE_GESTURE_RECOGNIZER)
-#define ENABLE_GESTURE_RECOGNIZER 0
-#endif
-
-#if !defined(ENABLE_NOTIFICATIONS)
-#define ENABLE_NOTIFICATIONS 0
-#endif
-
-#define ENABLE_TEXT_CARET 0
-
-#if !defined(ENABLE_TEXT_CARET)
-#define ENABLE_TEXT_CARET 1
-#endif
-
-#if !defined(ENABLE_ON_FIRST_TEXTAREA_FOCUS_SELECT_ALL)
-#define ENABLE_ON_FIRST_TEXTAREA_FOCUS_SELECT_ALL 0
-#endif
-
-#if !defined(ENABLE_FULLSCREEN_API)
-#define ENABLE_FULLSCREEN_API 0
-#endif
-
-#if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32_64)
-#if (CPU(X86_64) && (OS(UNIX) || OS(WINDOWS))) \
-    || (CPU(IA64) && !CPU(IA64_32)) \
-    || CPU(ALPHA) \
-    || CPU(SPARC64) \
-    || CPU(S390X) \
-    || CPU(PPC64)
-#define WTF_USE_JSVALUE64 1
-#else
-#define WTF_USE_JSVALUE32_64 1
-#endif
-#endif /* !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32_64) */
-
-#if !defined(ENABLE_REPAINT_THROTTLING)
-#define ENABLE_REPAINT_THROTTLING 0
-#endif
-
-/* 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
-
-/* JIT is not implemented for 64 bit on MSVC */
-#if !defined(ENABLE_JIT) && COMPILER(MSVC) && CPU(X86_64)
-#define ENABLE_JIT 0
-#endif
-
-/* 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
-
-/* 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
-
-/* Ensure that either the JIT or the interpreter has been enabled. */
-#if !defined(ENABLE_INTERPRETER) && !ENABLE(JIT)
-#define ENABLE_INTERPRETER 1
-#endif
-#if !(ENABLE(JIT) || ENABLE(INTERPRETER))
-#error You have to have at least one execution model enabled to build JSC
-#endif
-
-#if CPU(SH4) && PLATFORM(QT)
-#define ENABLE_JIT 1
-#define ENABLE_YARR 1
-#define ENABLE_YARR_JIT 1
-#define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1
-#define ENABLE_ASSEMBLER 1
-#endif
-
-/* Configure the JIT */
-#if ENABLE(JIT)
-    #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)
-#define JSC_HOST_CALL __fastcall
-#elif CPU(X86) && COMPILER(GCC)
-#define JSC_HOST_CALL __attribute__ ((fastcall))
-#else
-#define JSC_HOST_CALL
-#endif
-
-/* Configure the interpreter */
-#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(4, 0, 0, 0) && defined(__GNUC__))
-#define HAVE_COMPUTED_GOTO 1
-#endif
-#if HAVE(COMPUTED_GOTO) && ENABLE(INTERPRETER)
-#define ENABLE_COMPUTED_GOTO_INTERPRETER 1
-#endif
-
-/* Regular Expression Tracing - Set to 1 to trace RegExp's in jsc.  Results dumped at exit */
-#define ENABLE_REGEXP_TRACING 0
-
-/* Yet Another Regex Runtime - turned on by default for JIT enabled ports. */
-#if PLATFORM(CHROMIUM)
-#define ENABLE_YARR_JIT 0
-
-#elif ENABLE(JIT) && !defined(ENABLE_YARR_JIT)
-#define ENABLE_YARR_JIT 1
-
-/* Setting this flag compares JIT results with interpreter results. */
-#define ENABLE_YARR_JIT_DEBUG 0
-#endif
-
-#if ENABLE(JIT) || ENABLE(YARR_JIT)
-#define ENABLE_ASSEMBLER 1
-#endif
-
-/* Pick which allocator to use; we only need an executable allocator if the assembler is compiled in.
-   On x86-64 we use a single fixed mmap, on other platforms we mmap on demand. */
-#if ENABLE(ASSEMBLER)
-#define ENABLE_EXECUTABLE_ALLOCATOR_FIXED 1
-#endif
-
-#if !defined(ENABLE_PAN_SCROLLING) && OS(WINDOWS)
-#define ENABLE_PAN_SCROLLING 1
-#endif
-
-#if !defined(ENABLE_SMOOTH_SCROLLING)
-#define ENABLE_SMOOTH_SCROLLING 0
-#endif
-
-#if !defined(ENABLE_WEB_ARCHIVE)
-#define ENABLE_WEB_ARCHIVE 0
-#endif
-
-/* Use the QXmlStreamReader implementation for XMLDocumentParser */
-/* Use the QXmlQuery implementation for XSLTProcessor */
-#if PLATFORM(QT)
-#define WTF_USE_QXMLSTREAM 1
-#define WTF_USE_QXMLQUERY 1
-#endif
-
-#if PLATFORM(MAC)
-/* Complex text framework */
-#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
-#endif
-
-/* Accelerated compositing */
-#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT) || (PLATFORM(WIN) && !OS(WINCE) &&!defined(WIN_CAIRO))
-#define WTF_USE_ACCELERATED_COMPOSITING 1
-#endif
-
-#if (PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)) || PLATFORM(IOS)
-#define WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK 1
-#endif
-
-
-#if COMPILER(GCC)
-#define WARN_UNUSED_RETURN __attribute__ ((warn_unused_result))
-#else
-#define WARN_UNUSED_RETURN
-#endif
-
-#if !ENABLE(NETSCAPE_PLUGIN_API) || (ENABLE(NETSCAPE_PLUGIN_API) && ((OS(UNIX) && (PLATFORM(QT) || PLATFORM(WX))) || PLATFORM(GTK)))
-#define ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH 1
-#endif
-
-/* Set up a define for a common error that is intended to cause a build error -- thus the space after Error. */
-#define WTF_PLATFORM_CFNETWORK Error USE_macro_should_be_used_with_CFNETWORK
-
-#define ENABLE_JSC_ZOMBIES 0
-
-/* FIXME: Eventually we should enable this for all platforms and get rid of the define. */
-#define WTF_USE_PLATFORM_STRATEGIES 1
-
-#if PLATFORM(WIN)
-#define WTF_USE_CROSS_PLATFORM_CONTEXT_MENUS 1
-#endif
-
-/* Geolocation request policy. pre-emptive policy is to acquire user permission before acquiring location.
-   Client based implementations will have option to choose between pre-emptive and nonpre-emptive permission policy.
-   pre-emptive permission policy is enabled by default for all client-based implementations. */
-#if ENABLE(CLIENT_BASED_GEOLOCATION)
-#define WTF_USE_PREEMPT_GEOLOCATION_PERMISSION 1
-#endif
-
-#if CPU(ARM_THUMB2)
-#define ENABLE_BRANCH_COMPACTION 1
-#endif
-
-#if !defined(ENABLE_THREADING_OPENMP) && defined(_OPENMP)
-#define ENABLE_THREADING_OPENMP 1
-#endif
-
-#if !defined(ENABLE_PARALLEL_JOBS) && !ENABLE(SINGLE_THREADED) && (ENABLE(THREADING_GENERIC) || ENABLE(THREADING_LIBDISPATCH) || ENABLE(THREADING_OPENMP))
-#define ENABLE_PARALLEL_JOBS 1
-#endif
-
-#if ENABLE(GLIB_SUPPORT)
-#include "GTypedefs.h"
-#endif
-
-/* FIXME: This define won't be needed once #27551 is fully landed. However, 
-   since most ports try to support sub-project independence, adding new headers
-   to WTF causes many ports to break, and so this way we can address the build
-   breakages one port at a time. */
-#define WTF_USE_EXPORT_MACROS 0
-
-#if (PLATFORM(QT) && !OS(SYMBIAN)) || PLATFORM(GTK)
-#define WTF_USE_UNIX_DOMAIN_SOCKETS 1
-#endif
-
-#ifndef NDEBUG
-#ifndef ENABLE_GC_VALIDATION
-#define ENABLE_GC_VALIDATION 1
-#endif
-#endif
-
-#endif /* WTF_Platform_h */
diff --git a/wtf/PossiblyNull.h b/wtf/PossiblyNull.h
deleted file mode 100644 (file)
index 79c4d82..0000000
+++ /dev/null
@@ -1,59 +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 PossiblyNull_h
-#define PossiblyNull_h
-
-#include "Assertions.h"
-
-namespace WTF {
-
-template <typename T> struct PossiblyNull {
-    PossiblyNull(T data)
-        : m_data(data)
-    {
-    }
-    PossiblyNull(const PossiblyNull<T>& source)
-        : m_data(source.m_data)
-    {
-        source.m_data = 0;
-    }
-    ~PossiblyNull() { ASSERT(!m_data); }
-    bool getValue(T& out) WARN_UNUSED_RETURN;
-private:
-    mutable T m_data;
-};
-
-template <typename T> bool PossiblyNull<T>::getValue(T& out)
-{
-    out = m_data;
-    bool result = !!m_data;
-    m_data = 0;
-    return result;
-}
-
-}
-
-#endif
diff --git a/wtf/RandomNumber.cpp b/wtf/RandomNumber.cpp
deleted file mode 100644 (file)
index 490c591..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- *           (C) 2008, 2009 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. 
- */
-
-#include "config.h"
-#include "RandomNumber.h"
-
-#include "CryptographicallyRandomNumber.h"
-#include "RandomNumberSeed.h"
-
-#include <limits>
-#include <limits.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#if USE(MERSENNE_TWISTER_19937)
-extern "C" {
-#include "mt19937ar.c"
-}
-#endif
-
-#if PLATFORM(BREWMP)
-#include <AEEAppGen.h>
-#include <AEESource.h>
-#include <AEEStdLib.h>
-#include <wtf/brew/RefPtrBrew.h>
-#include <wtf/brew/ShellBrew.h>
-#endif
-
-namespace WTF {
-
-double randomNumber()
-{
-#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
-    // 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).
-
-#if !ENABLE(WTF_MULTIPLE_THREADS)
-    static bool s_initialized = false;
-    if (!s_initialized) {
-        initializeRandomNumberGenerator();
-        s_initialized = true;
-    }
-#endif
-
-#if USE(MERSENNE_TWISTER_19937)
-    return genrand_res53();
-#elif PLATFORM(BREWMP)
-    uint32_t bits;
-    // 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
-    uint32_t part1 = rand() & (RAND_MAX - 1);
-    uint32_t part2 = rand() & (RAND_MAX - 1);
-    // rand only provides 31 bits, and the low order bits of that aren't very random
-    // so we take the high 26 bits of part 1, and the high 27 bits of part2.
-    part1 >>= 5; // drop the low 5 bits
-    part2 >>= 4; // drop the low 4 bits
-    uint64_t fullRandom = part1;
-    fullRandom <<= 27;
-    fullRandom |= part2;
-
-    // Mask off the low 53bits
-    fullRandom &= (1LL << 53) - 1;
-    return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
-#endif
-#endif
-}
-
-}
diff --git a/wtf/RandomNumber.h b/wtf/RandomNumber.h
deleted file mode 100644 (file)
index f2e7e8f..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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_RandomNumber_h
-#define WTF_RandomNumber_h
-
-namespace WTF {
-
-    // Returns a pseudo-random number in the range [0, 1), attempts to be
-    // cryptographically secure if possible on the target platform
-    double randomNumber();
-
-}
-
-using WTF::randomNumber;
-
-#endif
diff --git a/wtf/RandomNumberSeed.h b/wtf/RandomNumberSeed.h
deleted file mode 100644 (file)
index 0703abf..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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_RandomNumberSeed_h
-#define WTF_RandomNumberSeed_h
-
-#include <stdlib.h>
-#include <time.h>
-
-#if HAVE(SYS_TIME_H)
-#include <sys/time.h>
-#endif
-
-#if OS(UNIX)
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
-#if USE(MERSENNE_TWISTER_19937)
-extern "C" {
-void init_by_array(unsigned long init_key[],int key_length);
-}
-#endif
-
-// Internal JavaScriptCore usage only
-namespace WTF {
-
-inline void initializeRandomNumberGenerator()
-{
-#if OS(DARWIN)
-    // On Darwin we use arc4random which initialises itself.
-#elif OS(WINCE)
-    // initialize rand()
-    srand(GetTickCount());
-#elif COMPILER(MSVC) && defined(_CRT_RAND_S)
-    // On Windows we use rand_s which initialises itself
-#elif PLATFORM(BREWMP)
-    // On Brew MP we use AEECLSID_RANDOM which initialises itself
-#elif OS(UNIX)
-    // srandomdev is not guaranteed to exist on linux so we use this poor seed, this should be improved
-    timeval time;
-    gettimeofday(&time, 0);
-    srandom(static_cast<unsigned>(time.tv_usec * getpid()));
-#else
-    srand(static_cast<unsigned>(time(0)));
-#endif
-
-#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
diff --git a/wtf/RefCounted.h b/wtf/RefCounted.h
deleted file mode 100644 (file)
index 12b670e..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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
- * 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 RefCounted_h
-#define RefCounted_h
-
-#include "Assertions.h"
-#include "FastAllocBase.h"
-#include "Noncopyable.h"
-
-namespace WTF {
-
-// This base class holds the non-template methods and attributes.
-// The RefCounted class inherits from it reducing the template bloat
-// generated by the compiler (technique called template hoisting).
-class RefCountedBase {
-public:
-    void ref()
-    {
-        ASSERT(!m_deletionHasBegun);
-        ASSERT(!m_adoptionIsRequired);
-        ++m_refCount;
-    }
-
-    bool hasOneRef() const
-    {
-        ASSERT(!m_deletionHasBegun);
-        return m_refCount == 1;
-    }
-
-    int refCount() const
-    {
-        return m_refCount;
-    }
-
-    void relaxAdoptionRequirement()
-    {
-#ifndef NDEBUG
-        ASSERT(!m_deletionHasBegun);
-        ASSERT(m_adoptionIsRequired);
-        m_adoptionIsRequired = false;
-#endif
-    }
-
-    // Helper for generating JIT code. Please do not use for non-JIT purposes.
-    const int* addressOfCount() const
-    {
-        return &m_refCount;
-    }
-
-protected:
-    RefCountedBase()
-        : m_refCount(1)
-#ifndef NDEBUG
-        , m_deletionHasBegun(false)
-        , m_adoptionIsRequired(true)
-#endif
-    {
-    }
-
-    ~RefCountedBase()
-    {
-        ASSERT(m_deletionHasBegun);
-        ASSERT(!m_adoptionIsRequired);
-    }
-
-    // Returns whether the pointer should be freed or not.
-    bool derefBase()
-    {
-        ASSERT(!m_deletionHasBegun);
-        ASSERT(!m_adoptionIsRequired);
-
-        ASSERT(m_refCount > 0);
-        if (m_refCount == 1) {
-#ifndef NDEBUG
-            m_deletionHasBegun = true;
-#endif
-            return true;
-        }
-
-        --m_refCount;
-        return false;
-    }
-
-#ifndef NDEBUG
-    bool deletionHasBegun() const
-    {
-        return m_deletionHasBegun;
-    }
-#endif
-
-private:
-    template<typename T> friend class CrossThreadRefCounted;
-
-#ifndef NDEBUG
-    friend void adopted(RefCountedBase*);
-#endif
-
-    int m_refCount;
-#ifndef NDEBUG
-    bool m_deletionHasBegun;
-    bool m_adoptionIsRequired;
-#endif
-};
-
-#ifndef NDEBUG
-
-inline void adopted(RefCountedBase* object)
-{
-    if (!object)
-        return;
-    ASSERT(!object->m_deletionHasBegun);
-    object->m_adoptionIsRequired = false;
-}
-
-#endif
-
-template<typename T> class RefCounted : public RefCountedBase {
-    WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED;
-public:
-    void deref()
-    {
-        if (derefBase())
-            delete static_cast<T*>(this);
-    }
-
-protected:
-    RefCounted() { }
-    ~RefCounted()
-    {
-    }
-};
-
-template<typename T> class RefCountedCustomAllocated : public RefCountedBase {
-    WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated);
-
-public:
-    void deref()
-    {
-        if (derefBase())
-            delete static_cast<T*>(this);
-    }
-
-protected:
-    ~RefCountedCustomAllocated()
-    {
-    }
-};
-
-} // namespace WTF
-
-using WTF::RefCounted;
-using WTF::RefCountedCustomAllocated;
-
-#endif // RefCounted_h
diff --git a/wtf/RefCountedLeakCounter.cpp b/wtf/RefCountedLeakCounter.cpp
deleted file mode 100644 (file)
index 08b32ab..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- *  Copyright (C) 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 "RefCountedLeakCounter.h"
-
-#include <wtf/HashCountedSet.h>
-
-namespace WTF {
-
-#ifdef NDEBUG
-
-void RefCountedLeakCounter::suppressMessages(const char*) { }
-void RefCountedLeakCounter::cancelMessageSuppression(const char*) { }
-
-RefCountedLeakCounter::RefCountedLeakCounter(const char*) { }
-RefCountedLeakCounter::~RefCountedLeakCounter() { }
-
-void RefCountedLeakCounter::increment() { }
-void RefCountedLeakCounter::decrement() { }
-
-#else
-
-#define LOG_CHANNEL_PREFIX Log
-static WTFLogChannel LogRefCountedLeaks = { 0x00000000, "", WTFLogChannelOn };
-
-typedef HashCountedSet<const char*, PtrHash<const char*> > ReasonSet;
-static ReasonSet* leakMessageSuppressionReasons;
-
-void RefCountedLeakCounter::suppressMessages(const char* reason)
-{
-    if (!leakMessageSuppressionReasons)
-        leakMessageSuppressionReasons = new ReasonSet;
-    leakMessageSuppressionReasons->add(reason);
-}
-
-void RefCountedLeakCounter::cancelMessageSuppression(const char* reason)
-{
-    ASSERT(leakMessageSuppressionReasons);
-    ASSERT(leakMessageSuppressionReasons->contains(reason));
-    leakMessageSuppressionReasons->remove(reason);
-}
-
-RefCountedLeakCounter::RefCountedLeakCounter(const char* description)
-    : m_description(description)
-{
-}    
-
-RefCountedLeakCounter::~RefCountedLeakCounter()
-{
-    static bool loggedSuppressionReason;
-    if (m_count) {
-        if (!leakMessageSuppressionReasons || leakMessageSuppressionReasons->isEmpty())
-            LOG(RefCountedLeaks, "LEAK: %u %s", m_count, m_description);
-        else if (!loggedSuppressionReason) {
-            // This logs only one reason. Later we could change it so we log all the reasons.
-            LOG(RefCountedLeaks, "No leak checking done: %s", leakMessageSuppressionReasons->begin()->first);
-            loggedSuppressionReason = true;
-        }
-    }
-}
-
-void RefCountedLeakCounter::increment()
-{
-#if ENABLE(WTF_MULTIPLE_THREADS)
-    atomicIncrement(&m_count);
-#else
-    ++m_count;
-#endif
-}
-
-void RefCountedLeakCounter::decrement()
-{
-#if ENABLE(WTF_MULTIPLE_THREADS)
-    atomicDecrement(&m_count);
-#else
-    --m_count;
-#endif
-}
-
-#endif
-
-} // namespace WTF
diff --git a/wtf/RefCountedLeakCounter.h b/wtf/RefCountedLeakCounter.h
deleted file mode 100644 (file)
index 57cc283..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  Copyright (C) 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 RefCountedLeakCounter_h
-#define RefCountedLeakCounter_h
-#include "Assertions.h"
-#include "Threading.h"
-
-namespace WTF {
-    
-    struct RefCountedLeakCounter {
-        static void suppressMessages(const char*);
-        static void cancelMessageSuppression(const char*);
-        
-        explicit RefCountedLeakCounter(const char* description);
-        ~RefCountedLeakCounter();
-
-        void increment();
-        void decrement();
-
-#ifndef NDEBUG
-    private:
-        volatile int m_count;
-        const char* m_description;
-#endif
-    };
-
-}  // namespace WTF
-
-#endif
diff --git a/wtf/RefPtr.h b/wtf/RefPtr.h
deleted file mode 100644 (file)
index 353bd35..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- *  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
- *  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.
- *
- */
-
-// RefPtr and PassRefPtr are documented at http://webkit.org/coding/RefPtr.html
-
-#ifndef WTF_RefPtr_h
-#define WTF_RefPtr_h
-
-#include <algorithm>
-#include "FastAllocBase.h"
-#include "PassRefPtr.h"
-
-namespace WTF {
-
-    enum PlacementNewAdoptType { PlacementNewAdopt };
-
-    template<typename T> class PassRefPtr;
-    template<typename T> class NonNullPassRefPtr;
-
-    enum HashTableDeletedValueType { HashTableDeletedValue };
-
-    template<typename T> class RefPtr {
-        WTF_MAKE_FAST_ALLOCATED;
-    public:
-        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.
-        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(); }
-
-        ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); }
-
-        T* get() const { return m_ptr; }
-        
-        void clear();
-        PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }
-
-        T& operator*() const { return *m_ptr; }
-        ALWAYS_INLINE 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.
-        typedef T* (RefPtr::*UnspecifiedBoolType);
-        operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; }
-        
-        RefPtr& operator=(const RefPtr&);
-        RefPtr& operator=(T*);
-        RefPtr& operator=(const PassRefPtr<T>&);
-        RefPtr& operator=(const NonNullPassRefPtr<T>&);
-#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&);
-
-        static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
-
-    private:
-        T* m_ptr;
-    };
-    
-    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.leakRef())
-    {
-    }
-
-    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* ptr = m_ptr;
-        m_ptr = optr;
-        derefIfNotNull(ptr);
-        return *this;
-    }
-    
-    template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o)
-    {
-        T* optr = o.get();
-        refIfNotNull(optr);
-        T* ptr = m_ptr;
-        m_ptr = optr;
-        derefIfNotNull(ptr);
-        return *this;
-    }
-    
-    template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr)
-    {
-        refIfNotNull(optr);
-        T* ptr = m_ptr;
-        m_ptr = optr;
-        derefIfNotNull(ptr);
-        return *this;
-    }
-
-    template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o)
-    {
-        T* ptr = m_ptr;
-        m_ptr = o.leakRef();
-        derefIfNotNull(ptr);
-        return *this;
-    }
-
-    template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<T>& o)
-    {
-        T* ptr = m_ptr;
-        m_ptr = o.leakRef();
-        derefIfNotNull(ptr);
-        return *this;
-    }
-
-    template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o)
-    {
-        T* ptr = m_ptr;
-        m_ptr = o.leakRef();
-        derefIfNotNull(ptr);
-        return *this;
-    }
-
-    template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<U>& o)
-    {
-        T* ptr = m_ptr;
-        m_ptr = o.leakRef();
-        derefIfNotNull(ptr);
-        return *this;
-    }
-
-    template<class T> inline void RefPtr<T>::swap(RefPtr<T>& o)
-    {
-        std::swap(m_ptr, o.m_ptr);
-    }
-
-    template<class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b)
-    {
-        a.swap(b);
-    }
-
-    template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
-    { 
-        return a.get() == b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b)
-    { 
-        return a.get() == b; 
-    }
-    
-    template<typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b) 
-    {
-        return a == b.get(); 
-    }
-    
-    template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
-    { 
-        return a.get() != b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b)
-    {
-        return a.get() != b; 
-    }
-
-    template<typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b)
-    { 
-        return a != b.get(); 
-    }
-    
-    template<typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p)
-    { 
-        return RefPtr<T>(static_cast<T*>(p.get())); 
-    }
-
-    template<typename T, typename U> inline RefPtr<T> const_pointer_cast(const RefPtr<U>& p)
-    { 
-        return RefPtr<T>(const_cast<T*>(p.get())); 
-    }
-
-    template<typename T> inline T* getPtr(const RefPtr<T>& p)
-    {
-        return p.get();
-    }
-
-} // namespace WTF
-
-using WTF::RefPtr;
-using WTF::static_pointer_cast;
-using WTF::const_pointer_cast;
-
-#endif // WTF_RefPtr_h
diff --git a/wtf/RefPtrHashMap.h b/wtf/RefPtrHashMap.h
deleted file mode 100644 (file)
index dbeabfa..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * 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 RefPtrHashMap_h
-#define RefPtrHashMap_h
-
-namespace WTF {
-
-    // This specialization is a direct copy of HashMap, with overloaded functions
-    // to allow for lookup by pointer instead of RefPtr, avoiding ref-count churn.
-    
-    // FIXME: Find a better way that doesn't require an entire copy of the HashMap template.
-    
-    template<typename RawKeyType, typename ValueType, typename ValueTraits, typename HashFunctions>
-    struct RefPtrHashMapRawKeyTranslator {
-        typedef typename ValueType::first_type KeyType;
-        typedef typename ValueType::second_type MappedType;
-        typedef typename ValueTraits::FirstTraits KeyTraits;
-        typedef typename ValueTraits::SecondTraits MappedTraits;
-
-        static unsigned hash(RawKeyType key) { return HashFunctions::hash(key); }
-        static bool equal(const KeyType& a, RawKeyType b) { return HashFunctions::equal(a, b); }
-        static void translate(ValueType& location, RawKeyType key, const MappedType& mapped)
-        {
-            location.first = key;
-            location.second = mapped;
-        }
-    };
-
-    template<typename T, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
-    class HashMap<RefPtr<T>, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> {
-        WTF_MAKE_FAST_ALLOCATED;
-    private:
-        typedef KeyTraitsArg KeyTraits;
-        typedef MappedTraitsArg MappedTraits;
-        typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits;
-
-    public:
-        typedef typename KeyTraits::TraitType KeyType;
-        typedef T* RawKeyType;
-        typedef typename MappedTraits::TraitType MappedType;
-        typedef typename ValueTraits::TraitType ValueType;
-
-    private:
-        typedef HashArg HashFunctions;
-
-        typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>,
-            HashFunctions, ValueTraits, KeyTraits> HashTableType;
-
-        typedef RefPtrHashMapRawKeyTranslator<RawKeyType, ValueType, ValueTraits, HashFunctions>
-            RawKeyTranslator;
-
-    public:
-        typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
-        typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
-
-        void swap(HashMap&);
-
-        int size() const;
-        int capacity() const;
-        bool isEmpty() const;
-
-        // iterators iterate over pairs of keys and values
-        iterator begin();
-        iterator end();
-        const_iterator begin() const;
-        const_iterator end() const;
-
-        iterator find(const KeyType&);
-        iterator find(RawKeyType);
-        const_iterator find(const KeyType&) const;
-        const_iterator find(RawKeyType) const;
-        bool contains(const KeyType&) const;
-        bool contains(RawKeyType) const;
-        MappedType get(const KeyType&) const;
-        MappedType get(RawKeyType) const;
-        MappedType inlineGet(RawKeyType) const;
-
-        // replaces value but not key if key is already present
-        // return value is a pair of the iterator to the key location, 
-        // and a boolean that's true if a new value was actually added
-        pair<iterator, bool> set(const KeyType&, const MappedType&); 
-        pair<iterator, bool> set(RawKeyType, const MappedType&); 
-
-        // does nothing if key is already present
-        // return value is a pair of the iterator to the key location, 
-        // and a boolean that's true if a new value was actually added
-        pair<iterator, bool> add(const KeyType&, const MappedType&); 
-        pair<iterator, bool> add(RawKeyType, const MappedType&); 
-
-        void remove(const KeyType&);
-        void remove(RawKeyType);
-        void remove(iterator);
-        void clear();
-
-        MappedType take(const KeyType&); // efficient combination of get with remove
-        MappedType take(RawKeyType); // efficient combination of get with remove
-
-    private:
-        pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&);
-        pair<iterator, bool> inlineAdd(RawKeyType, const MappedType&);
-
-        HashTableType m_impl;
-    };
-    
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void HashMap<RefPtr<T>, U, V, W, X>::swap(HashMap& other)
-    {
-        m_impl.swap(other.m_impl); 
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline int HashMap<RefPtr<T>, U, V, W, X>::size() const
-    {
-        return m_impl.size(); 
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline int HashMap<RefPtr<T>, U, V, W, X>::capacity() const
-    { 
-        return m_impl.capacity(); 
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline bool HashMap<RefPtr<T>, U, V, W, X>::isEmpty() const
-    {
-        return m_impl.isEmpty();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::begin()
-    {
-        return m_impl.begin();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::end()
-    {
-        return m_impl.end();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::begin() const
-    {
-        return m_impl.begin();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::end() const
-    {
-        return m_impl.end();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key)
-    {
-        return m_impl.find(key);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key)
-    {
-        return m_impl.template find<RawKeyType, RawKeyTranslator>(key);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key) const
-    {
-        return m_impl.find(key);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key) const
-    {
-        return m_impl.template find<RawKeyType, RawKeyTranslator>(key);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(const KeyType& key) const
-    {
-        return m_impl.contains(key);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(RawKeyType key) const
-    {
-        return m_impl.template contains<RawKeyType, RawKeyTranslator>(key);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
-    HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped) 
-    {
-        typedef HashMapTranslator<ValueType, ValueTraits, HashFunctions> TranslatorType;
-        return m_impl.template add<KeyType, MappedType, TranslatorType>(key, mapped);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
-    HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(RawKeyType key, const MappedType& mapped) 
-    {
-        return m_impl.template add<RawKeyType, MappedType, RawKeyTranslator>(key, mapped);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
-    HashMap<RefPtr<T>, U, V, W, X>::set(const KeyType& key, const MappedType& mapped) 
-    {
-        pair<iterator, bool> result = inlineAdd(key, mapped);
-        if (!result.second) {
-            // add call above didn't change anything, so set the mapped value
-            result.first->second = mapped;
-        }
-        return result;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
-    HashMap<RefPtr<T>, U, V, W, X>::set(RawKeyType key, const MappedType& mapped) 
-    {
-        pair<iterator, bool> result = inlineAdd(key, mapped);
-        if (!result.second) {
-            // add call above didn't change anything, so set the mapped value
-            result.first->second = mapped;
-        }
-        return result;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
-    HashMap<RefPtr<T>, U, V, W, X>::add(const KeyType& key, const MappedType& mapped)
-    {
-        return inlineAdd(key, mapped);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool>
-    HashMap<RefPtr<T>, U, V, W, X>::add(RawKeyType key, const MappedType& mapped)
-    {
-        return inlineAdd(key, mapped);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename MappedTraits>
-    typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
-    HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(const KeyType& key) const
-    {
-        ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key);
-        if (!entry)
-            return MappedTraits::emptyValue();
-        return entry->second;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename MappedTraits>
-    typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
-    inline HashMap<RefPtr<T>, U, V, W, MappedTraits>::inlineGet(RawKeyType key) const
-    {
-        ValueType* entry = const_cast<HashTableType&>(m_impl).template lookup<RawKeyType, RawKeyTranslator>(key);
-        if (!entry)
-            return MappedTraits::emptyValue();
-        return entry->second;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename MappedTraits>
-    typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
-    HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(RawKeyType key) const
-    {
-        return inlineGet(key);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void HashMap<RefPtr<T>, U, V, W, X>::remove(iterator it)
-    {
-        if (it.m_impl == m_impl.end())
-            return;
-        m_impl.internalCheckTableConsistency();
-        m_impl.removeWithoutEntryConsistencyCheck(it.m_impl);
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void HashMap<RefPtr<T>, U, V, W, X>::remove(const KeyType& key)
-    {
-        remove(find(key));
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void HashMap<RefPtr<T>, U, V, W, X>::remove(RawKeyType key)
-    {
-        remove(find(key));
-    }
-
-    template<typename T, typename U, typename V, typename W, typename X>
-    inline void HashMap<RefPtr<T>, U, V, W, X>::clear()
-    {
-        m_impl.clear();
-    }
-
-    template<typename T, typename U, typename V, typename W, typename MappedTraits>
-    typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
-    HashMap<RefPtr<T>, U, V, W, MappedTraits>::take(const KeyType& key)
-    {
-        // This can probably be made more efficient to avoid ref/deref churn.
-        iterator it = find(key);
-        if (it == end())
-            return MappedTraits::emptyValue();
-        typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType result = it->second;
-        remove(it);
-        return result;
-    }
-
-    template<typename T, typename U, typename V, typename W, typename MappedTraits>
-    typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType
-    HashMap<RefPtr<T>, U, V, W, MappedTraits>::take(RawKeyType key)
-    {
-        // This can probably be made more efficient to avoid ref/deref churn.
-        iterator it = find(key);
-        if (it == end())
-            return MappedTraits::emptyValue();
-        typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedType result = it->second;
-        remove(it);
-        return result;
-    }
-
-} // namespace WTF
-
-#endif // RefPtrHashMap_h
diff --git a/wtf/RetainPtr.h b/wtf/RetainPtr.h
deleted file mode 100644 (file)
index a716390..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- *  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
- *  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 RetainPtr_h
-#define RetainPtr_h
-
-#include "HashTraits.h"
-#include "NullPtr.h"
-#include "TypeTraits.h"
-#include <algorithm>
-
-#if USE(CF)
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-
-#ifdef __OBJC__
-#import <Foundation/Foundation.h>
-#endif
-
-namespace WTF {
-
-    // Unlike most most of our smart pointers, RetainPtr can take either the pointer type or the pointed-to type,
-    // so both RetainPtr<NSDictionary> and RetainPtr<CFDictionaryRef> will work.
-
-    enum AdoptCFTag { AdoptCF };
-    enum AdoptNSTag { AdoptNS };
-    
-#ifdef __OBJC__
-    inline void adoptNSReference(id ptr)
-    {
-        if (ptr) {
-            CFRetain(ptr);
-            [ptr release];
-        }
-    }
-#endif
-
-    template<typename T> class RetainPtr {
-    public:
-        typedef typename RemovePointer<T>::Type ValueType;
-        typedef ValueType* PtrType;
-
-        RetainPtr() : m_ptr(0) {}
-        RetainPtr(PtrType ptr) : m_ptr(ptr) { if (ptr) CFRetain(ptr); }
-
-        RetainPtr(AdoptCFTag, PtrType ptr) : m_ptr(ptr) { }
-        RetainPtr(AdoptNSTag, PtrType ptr) : m_ptr(ptr) { adoptNSReference(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); }
-        
-        template<typename U> RetainPtr(const RetainPtr<U>&);
-        
-        PtrType get() const { return m_ptr; }
-
-        void clear();
-        PtrType leakRef() WARN_UNUSED_RETURN;
-
-        PtrType 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.
-        typedef PtrType RetainPtr::*UnspecifiedBoolType;
-        operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; }
-        
-        RetainPtr& operator=(const RetainPtr&);
-        template<typename U> RetainPtr& operator=(const RetainPtr<U>&);
-        RetainPtr& operator=(PtrType);
-        template<typename U> RetainPtr& operator=(U*);
-#if !HAVE(NULLPTR)
-        RetainPtr& operator=(std::nullptr_t) { clear(); return *this; }
-#endif
-
-        void adoptCF(PtrType);
-        void adoptNS(PtrType);
-        
-        void swap(RetainPtr&);
-
-        // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
-        PtrType releaseRef() { return leakRef(); }
-
-    private:
-        static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
-
-        PtrType m_ptr;
-    };
-    
-    template<typename T> 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)
-            CFRetain(optr);
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
-        return *this;
-    }
-    
-    template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o)
-    {
-        PtrType optr = o.get();
-        if (optr)
-            CFRetain(optr);
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
-        return *this;
-    }
-    
-    template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr)
-    {
-        if (optr)
-            CFRetain(optr);
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
-        return *this;
-    }
-
-    template<typename T> inline void RetainPtr<T>::adoptCF(PtrType optr)
-    {
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
-    }
-
-    template<typename T> inline void RetainPtr<T>::adoptNS(PtrType optr)
-    {
-        adoptNSReference(optr);
-        
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
-    }
-    
-    template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr)
-    {
-        if (optr)
-            CFRetain(optr);
-        PtrType ptr = m_ptr;
-        m_ptr = optr;
-        if (ptr)
-            CFRelease(ptr);
-        return *this;
-    }
-
-    template<typename T> inline void RetainPtr<T>::swap(RetainPtr<T>& o)
-    {
-        std::swap(m_ptr, o.m_ptr);
-    }
-
-    template<typename T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b)
-    {
-        a.swap(b);
-    }
-
-    template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b)
-    { 
-        return a.get() == b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b)
-    { 
-        return a.get() == b; 
-    }
-    
-    template<typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b) 
-    {
-        return a == b.get(); 
-    }
-    
-    template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b)
-    { 
-        return a.get() != b.get(); 
-    }
-
-    template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b)
-    {
-        return a.get() != b; 
-    }
-
-    template<typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b)
-    { 
-        return a != b.get(); 
-    }
-    
-    template<typename P> struct HashTraits<RetainPtr<P> > : SimpleClassHashTraits<RetainPtr<P> > { };
-    
-    template<typename P> struct PtrHash<RetainPtr<P> > : PtrHash<P*> {
-        using PtrHash<P*>::hash;
-        static unsigned hash(const RetainPtr<P>& key) { return hash(key.get()); }
-        using PtrHash<P*>::equal;
-        static bool equal(const RetainPtr<P>& a, const RetainPtr<P>& b) { return a == b; }
-        static bool equal(P* a, const RetainPtr<P>& b) { return a == b; }
-        static bool equal(const RetainPtr<P>& a, P* b) { return a == b; }
-    };
-    
-    template<typename P> struct DefaultHash<RetainPtr<P> > { typedef PtrHash<RetainPtr<P> > Hash; };
-
-} // namespace WTF
-
-using WTF::AdoptCF;
-using WTF::AdoptNS;
-using WTF::RetainPtr;
-
-#endif // WTF_RetainPtr_h
diff --git a/wtf/SHA1.cpp b/wtf/SHA1.cpp
deleted file mode 100644 (file)
index e76f6ac..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index dad6dc8..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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/SegmentedVector.h b/wtf/SegmentedVector.h
deleted file mode 100644 (file)
index b1cbc4d..0000000
+++ /dev/null
@@ -1,255 +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.
- * 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 SegmentedVector_h
-#define SegmentedVector_h
-
-#include <wtf/Vector.h>
-
-namespace WTF {
-
-    // An iterator for SegmentedVector. It supports only the pre ++ operator
-    template <typename T, size_t SegmentSize> class SegmentedVector;
-    template <typename T, size_t SegmentSize> class SegmentedVectorIterator {
-    private:
-        friend class SegmentedVector<T, SegmentSize>;
-    public:
-        typedef SegmentedVectorIterator<T, SegmentSize> Iterator;
-
-        ~SegmentedVectorIterator() { }
-
-        T& operator*() const { return m_vector.m_segments.at(m_segment)->at(m_index); }
-        T* operator->() const { return &m_vector.m_segments.at(m_segment)->at(m_index); }
-
-        // Only prefix ++ operator supported
-        Iterator& operator++()
-        {
-            ASSERT(m_index != SegmentSize);
-            ++m_index;
-            if (m_index >= m_vector.m_segments.at(m_segment)->size())  {
-                if (m_segment + 1 < m_vector.m_segments.size()) {
-                    ASSERT(m_vector.m_segments.at(m_segment)->size() > 0);
-                    ++m_segment;
-                    m_index = 0;
-                } else {
-                    // Points to the "end" symbol
-                    m_segment = 0;
-                    m_index = SegmentSize;
-                }
-            }
-            return *this;
-        }
-
-        bool operator==(const Iterator& other) const
-        {
-            return (m_index == other.m_index && m_segment = other.m_segment && &m_vector == &other.m_vector);
-        }
-
-        bool operator!=(const Iterator& other) const
-        {
-            return (m_index != other.m_index || m_segment != other.m_segment || &m_vector != &other.m_vector);
-        }
-
-        SegmentedVectorIterator& operator=(const SegmentedVectorIterator<T, SegmentSize>& other)
-        {
-            m_vector = other.m_vector;
-            m_segment = other.m_segment;
-            m_index = other.m_index;
-            return *this;
-        }
-
-    private:
-        SegmentedVectorIterator(SegmentedVector<T, SegmentSize>& vector, size_t segment, size_t index)
-            : m_vector(vector)
-            , m_segment(segment)
-            , m_index(index)
-        {
-        }
-
-        SegmentedVector<T, SegmentSize>& m_vector;
-        size_t m_segment;
-        size_t m_index;
-    };
-
-    // SegmentedVector is just like Vector, but it doesn't move the values
-    // stored in its buffer when it grows. Therefore, it is safe to keep
-    // pointers into a SegmentedVector.
-    template <typename T, size_t SegmentSize> class SegmentedVector {
-        friend class SegmentedVectorIterator<T, SegmentSize>;
-    public:
-        typedef SegmentedVectorIterator<T, SegmentSize> Iterator;
-
-        SegmentedVector()
-            : m_size(0)
-        {
-            m_segments.append(&m_inlineSegment);
-        }
-
-        ~SegmentedVector()
-        {
-            deleteAllSegments();
-        }
-
-        size_t size() const { return m_size; }
-        bool isEmpty() const { return !size(); }
-
-        T& at(size_t index)
-        {
-            if (index < SegmentSize)
-                return m_inlineSegment[index];
-            return segmentFor(index)->at(subscriptFor(index));
-        }
-
-        T& operator[](size_t index)
-        {
-            return at(index);
-        }
-
-        T& last()
-        {
-            return at(size() - 1);
-        }
-
-        template <typename U> void append(const U& value)
-        {
-            ++m_size;
-
-            if (m_size <= SegmentSize) {
-                m_inlineSegment.uncheckedAppend(value);
-                return;
-            }
-
-            if (!segmentExistsFor(m_size - 1))
-                m_segments.append(new Segment);
-            segmentFor(m_size - 1)->uncheckedAppend(value);
-        }
-
-        T& alloc()
-        {
-            append<T>(T());
-            return last();
-        }
-
-        void removeLast()
-        {
-            if (m_size <= SegmentSize)
-                m_inlineSegment.removeLast();
-            else
-                segmentFor(m_size - 1)->removeLast();
-            --m_size;
-        }
-
-        void grow(size_t size)
-        {
-            ASSERT(size > m_size);
-            ensureSegmentsFor(size);
-            m_size = size;
-        }
-
-        void clear()
-        {
-            deleteAllSegments();
-            m_segments.resize(1);
-            m_inlineSegment.clear();
-            m_size = 0;
-        }
-
-        Iterator begin()
-        {
-            return Iterator(*this, 0, m_size ? 0 : SegmentSize);
-        }
-
-        Iterator end()
-        {
-            return Iterator(*this, 0, SegmentSize);
-        }
-
-    private:
-        typedef Vector<T, SegmentSize> Segment;
-
-        void deleteAllSegments()
-        {
-            // Skip the first segment, because it's our inline segment, which was
-            // not created by new.
-            for (size_t i = 1; i < m_segments.size(); i++)
-                delete m_segments[i];
-        }
-
-        bool segmentExistsFor(size_t index)
-        {
-            return index / SegmentSize < m_segments.size();
-        }
-
-        Segment* segmentFor(size_t index)
-        {
-            return m_segments[index / SegmentSize];
-        }
-
-        size_t subscriptFor(size_t index)
-        {
-            return index % SegmentSize;
-        }
-
-        void ensureSegmentsFor(size_t size)
-        {
-            size_t segmentCount = m_size / SegmentSize;
-            if (m_size % SegmentSize)
-                ++segmentCount;
-            segmentCount = std::max<size_t>(segmentCount, 1); // We always have at least our inline segment.
-
-            size_t neededSegmentCount = size / SegmentSize;
-            if (size % SegmentSize)
-                ++neededSegmentCount;
-
-            // Fill up to N - 1 segments.
-            size_t end = neededSegmentCount - 1;
-            for (size_t i = segmentCount - 1; i < end; ++i)
-                ensureSegment(i, SegmentSize);
-
-            // Grow segment N to accomodate the remainder.
-            ensureSegment(end, subscriptFor(size - 1) + 1);
-        }
-
-        void ensureSegment(size_t segmentIndex, size_t size)
-        {
-            ASSERT(segmentIndex <= m_segments.size());
-            if (segmentIndex == m_segments.size())
-                m_segments.append(new Segment);
-            m_segments[segmentIndex]->grow(size);
-        }
-
-        size_t m_size;
-        Segment m_inlineSegment;
-        Vector<Segment*, 32> m_segments;
-    };
-
-} // namespace WTF
-
-using WTF::SegmentedVector;
-
-#endif // SegmentedVector_h
diff --git a/wtf/SentinelLinkedList.h b/wtf/SentinelLinkedList.h
deleted file mode 100644 (file)
index 610d2d2..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index c00bf36..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index 4e481bb..0000000
+++ /dev/null
@@ -1,57 +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:
- *
- *     * 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
deleted file mode 100644 (file)
index f2ed57d..0000000
+++ /dev/null
@@ -1,304 +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 "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
deleted file mode 100644 (file)
index dc93f90..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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
diff --git a/wtf/StaticConstructors.h b/wtf/StaticConstructors.h
deleted file mode 100644 (file)
index 8b2df9d..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Computer, 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 StaticConstructors_h
-#define StaticConstructors_h
-
-// We need to avoid having static constructors. We achieve this
-// with two separate methods for GCC and MSVC. Both methods prevent the static
-// initializers from being registered and called on program startup. On GCC, we
-// declare the global objects with a different type that can be POD default
-// initialized by the linker/loader. On MSVC we use a special compiler feature
-// to have the CRT ignore our static initializers. The constructors will never
-// be called and the objects will be left uninitialized.
-//
-// With both of these approaches, we must define and explicitly call an init
-// routine that uses placement new to create the objects and overwrite the
-// uninitialized placeholders.
-//
-// This is not completely portable, but is what we have for now without
-// changing how a lot of code accesses these global objects.
-
-#ifdef SKIP_STATIC_CONSTRUCTORS_ON_MSVC
-// - Assume that all includes of this header want ALL of their static
-//   initializers ignored. This is currently the case. This means that if
-//   a .cc includes this header (or it somehow gets included), all static
-//   initializers after the include will not be executed.
-// - We do this with a pragma, so that all of the static initializer pointers
-//   go into our own section, and the CRT won't call them. Eventually it would
-//   be nice if the section was discarded, because we don't want the pointers.
-//   See: http://msdn.microsoft.com/en-us/library/7977wcck(VS.80).aspx
-#pragma warning(disable:4075)
-#pragma init_seg(".unwantedstaticinits")
-#endif
-
-#ifndef SKIP_STATIC_CONSTRUCTORS_ON_GCC
-    // Define an global in the normal way.
-#if COMPILER(MSVC7_OR_LOWER)
-#define DEFINE_GLOBAL(type, name) \
-    const type name;
-#elif COMPILER(WINSCW)
-#define DEFINE_GLOBAL(type, name, arg...) \
-    const type name;
-#else
-#define DEFINE_GLOBAL(type, name, ...) \
-    const type name;
-#endif
-
-#else
-// Define an correctly-sized array of pointers to avoid static initialization.
-// Use an array of pointers instead of an array of char in case there is some alignment issue.
-#if COMPILER(MSVC7_OR_LOWER)
-#define DEFINE_GLOBAL(type, name) \
-    void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)];
-#elif COMPILER(WINSCW)
-#define DEFINE_GLOBAL(type, name, arg...) \
-    void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)];
-#else
-#define DEFINE_GLOBAL(type, name, ...) \
-    void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)];
-#endif
-#endif
-
-#endif // StaticConstructors_h
diff --git a/wtf/StdLibExtras.h b/wtf/StdLibExtras.h
deleted file mode 100644 (file)
index a8582e9..0000000
+++ /dev/null
@@ -1,167 +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. 
- */
-
-#ifndef WTF_StdLibExtras_h
-#define WTF_StdLibExtras_h
-
-#include <wtf/Assertions.h>
-
-// Use these to declare and define a static local variable (static T;) so that
-//  it is leaked so that its destructors are not called at exit. Using this
-//  macro also allows workarounds a compiler bug present in Apple's version of GCC 4.0.1.
-#ifndef DEFINE_STATIC_LOCAL
-#if COMPILER(GCC) && defined(__APPLE_CC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 1
-#define DEFINE_STATIC_LOCAL(type, name, arguments) \
-    static type* name##Ptr = new type arguments; \
-    type& name = *name##Ptr
-#else
-#define DEFINE_STATIC_LOCAL(type, name, arguments) \
-    static type& name = *new type arguments
-#endif
-#endif
-
-// OBJECT_OFFSETOF: Like the C++ offsetof macro, but you can use it with classes.
-// The magic number 0x4000 is insignificant. We use it to avoid using NULL, since
-// NULL can cause compiler problems, especially in cases of multiple inheritance.
-#define OBJECT_OFFSETOF(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000)
-
-// STRINGIZE: Can convert any value to quoted string, even expandable macros
-#define STRINGIZE(exp) #exp
-#define STRINGIZE_VALUE_OF(exp) STRINGIZE(exp)
-
-/*
- * The reinterpret_cast<Type1*>([pointer to Type2]) expressions - where
- * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC:
- * increases required alignment of target type.
- *
- * An implicit or an extra static_cast<void*> bypasses the warning.
- * For more info see the following bugzilla entries:
- * - https://bugs.webkit.org/show_bug.cgi?id=38045
- * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976
- */
-#if (CPU(ARM) || CPU(MIPS)) && COMPILER(GCC)
-template<typename Type>
-bool isPointerTypeAlignmentOkay(Type* ptr)
-{
-    return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type));
-}
-
-template<typename TypePtr>
-TypePtr reinterpret_cast_ptr(void* ptr)
-{
-    ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
-    return reinterpret_cast<TypePtr>(ptr);
-}
-
-template<typename TypePtr>
-TypePtr reinterpret_cast_ptr(const void* ptr)
-{
-    ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
-    return reinterpret_cast<TypePtr>(ptr);
-}
-#else
-#define reinterpret_cast_ptr reinterpret_cast
-#endif
-
-namespace WTF {
-
-/*
- * C++'s idea of a reinterpret_cast lacks sufficient cojones.
- */
-template<typename TO, typename FROM>
-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);
-
-    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
-
-using WTF::binarySearch;
-using WTF::bitwise_cast;
-
-#endif // WTF_StdLibExtras_h
diff --git a/wtf/StringExtras.cpp b/wtf/StringExtras.cpp
deleted file mode 100644 (file)
index 1b96417..0000000
+++ /dev/null
@@ -1,62 +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 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"
-
-#if COMPILER(RVCT) && __ARMCC_VERSION < 400000
-
-#include "StringExtras.h"
-
-#include "ASCIICType.h"
-
-int strcasecmp(const char* s1, const char* s2)
-{
-    while (toASCIIUpper(*s1) == toASCIIUpper(*s2)) {
-        if (*s1 == '\0')
-            return 0;
-        s1++;
-        s2++;
-    }
-
-    return toASCIIUpper(*s1) - toASCIIUpper(*s2);
-}
-
-int strncasecmp(const char* s1, const char* s2, size_t len)
-{
-    while (len > 0 && toASCIIUpper(*s1) == toASCIIUpper(*s2)) {
-        if (*s1 == '\0')
-            return 0;
-        s1++;
-        s2++;
-        len--;
-    }
-
-    if (!len)
-        return 0;
-
-    return toASCIIUpper(*s1) - toASCIIUpper(*s2);
-}
-
-#endif
diff --git a/wtf/StringExtras.h b/wtf/StringExtras.h
deleted file mode 100644 (file)
index 371e33b..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this 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_StringExtras_h
-#define WTF_StringExtras_h
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#if HAVE(STRINGS_H) 
-#include <strings.h> 
-#endif 
-
-#if COMPILER(MSVC)
-// FIXME: why a COMPILER check instead of OS? also, these should be HAVE checks
-
-inline int snprintf(char* buffer, size_t count, const char* format, ...) 
-{
-    int result;
-    va_list 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;
-}
-
-inline double wtf_vsnprintf(char* buffer, size_t count, const char* format, va_list 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;
-}
-
-// 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)
-
-inline int strnicmp(const char* string1, const char* string2, size_t count)
-{
-    return _strnicmp(string1, string2, count);
-}
-
-inline int stricmp(const char* string1, const char* string2)
-{
-    return _stricmp(string1, string2);
-}
-
-inline char* strdup(const char* strSource)
-{
-    return _strdup(strSource);
-}
-
-#endif
-
-inline int strncasecmp(const char* s1, const char* s2, size_t len)
-{
-    return _strnicmp(s1, s2, len);
-}
-
-inline int strcasecmp(const char* s1, const char* s2)
-{
-    return _stricmp(s1, s2);
-}
-
-#endif
-
-#if !HAVE(STRNSTR)
-
-inline char* strnstr(const char* buffer, const char* target, size_t bufferLength)
-{
-    size_t targetLength = strlen(target);
-    if (targetLength == 0)
-        return const_cast<char*>(buffer);
-    for (const char* start = buffer; *start && start + targetLength <= buffer + bufferLength; start++) {
-        if (*start == *target && strncmp(start + 1, target + 1, targetLength - 1) == 0)
-            return const_cast<char*>(start);
-    }
-    return 0;
-}
-
-#endif
-
-#if COMPILER(RVCT) && __ARMCC_VERSION < 400000
-
-int strcasecmp(const char* s1, const char* s2);
-int strncasecmp(const char* s1, const char* s2, size_t len);
-
-#endif
-
-#endif // WTF_StringExtras_h
diff --git a/wtf/StringHasher.h b/wtf/StringHasher.h
deleted file mode 100644 (file)
index 5a2c36c..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * 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
diff --git a/wtf/TCPackedCache.h b/wtf/TCPackedCache.h
deleted file mode 100644 (file)
index 0464f8f..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright (c) 2007, 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.
-
-// ---
-// Author: Geoff Pike
-//
-// This file provides a minimal cache that can hold a <key, value> pair
-// with little if any wasted space.  The types of the key and value
-// must be unsigned integral types or at least have unsigned semantics
-// for >>, casting, and similar operations.
-//
-// Synchronization is not provided.  However, the cache is implemented
-// as an array of cache entries whose type is chosen at compile time.
-// If a[i] is atomic on your hardware for the chosen array type then
-// raciness will not necessarily lead to bugginess.  The cache entries
-// must be large enough to hold a partial key and a value packed
-// together.  The partial keys are bit strings of length
-// kKeybits - kHashbits, and the values are bit strings of length kValuebits.
-//
-// In an effort to use minimal space, every cache entry represents
-// some <key, value> pair; the class provides no way to mark a cache
-// entry as empty or uninitialized.  In practice, you may want to have
-// reserved keys or values to get around this limitation.  For example, in
-// tcmalloc's PageID-to-sizeclass cache, a value of 0 is used as
-// "unknown sizeclass."
-//
-// Usage Considerations
-// --------------------
-//
-// kHashbits controls the size of the cache.  The best value for
-// kHashbits will of course depend on the application.  Perhaps try
-// tuning the value of kHashbits by measuring different values on your
-// favorite benchmark.  Also remember not to be a pig; other
-// programs that need resources may suffer if you are.
-//
-// The main uses for this class will be when performance is
-// critical and there's a convenient type to hold the cache's
-// entries.  As described above, the number of bits required
-// for a cache entry is (kKeybits - kHashbits) + kValuebits.  Suppose
-// kKeybits + kValuebits is 43.  Then it probably makes sense to
-// chose kHashbits >= 11 so that cache entries fit in a uint32.
-//
-// On the other hand, suppose kKeybits = kValuebits = 64.  Then
-// using this class may be less worthwhile.  You'll probably
-// be using 128 bits for each entry anyway, so maybe just pick
-// a hash function, H, and use an array indexed by H(key):
-//    void Put(K key, V value) { a_[H(key)] = pair<K, V>(key, value); }
-//    V GetOrDefault(K key, V default) { const pair<K, V> &p = a_[H(key)]; ... }
-//    etc.
-//
-// Further Details
-// ---------------
-//
-// For caches used only by one thread, the following is true:
-// 1. For a cache c,
-//      (c.Put(key, value), c.GetOrDefault(key, 0)) == value
-//    and
-//      (c.Put(key, value), <...>, c.GetOrDefault(key, 0)) == value
-//    if the elided code contains no c.Put calls.
-//
-// 2. Has(key) will return false if no <key, value> pair with that key
-//    has ever been Put.  However, a newly initialized cache will have
-//    some <key, value> pairs already present.  When you create a new
-//    cache, you must specify an "initial value."  The initialization
-//    procedure is equivalent to Clear(initial_value), which is
-//    equivalent to Put(k, initial_value) for all keys k from 0 to
-//    2^kHashbits - 1.
-//
-// 3. If key and key' differ then the only way Put(key, value) may
-//    cause Has(key') to change is that Has(key') may change from true to
-//    false. Furthermore, a Put() call that doesn't change Has(key')
-//    doesn't change GetOrDefault(key', ...) either.
-//
-// Implementation details:
-//
-// This is a direct-mapped cache with 2^kHashbits entries;
-// the hash function simply takes the low bits of the key.
-// So, we don't have to store the low bits of the key in the entries.
-// Instead, an entry is the high bits of a key and a value, packed
-// together.  E.g., a 20 bit key and a 7 bit value only require
-// a uint16 for each entry if kHashbits >= 11.
-//
-// Alternatives to this scheme will be added as needed.
-
-#ifndef TCMALLOC_PACKED_CACHE_INL_H__
-#define TCMALLOC_PACKED_CACHE_INL_H__
-
-#ifndef WTF_CHANGES
-#include "base/basictypes.h"  // for COMPILE_ASSERT
-#include "base/logging.h"     // for DCHECK
-#endif
-
-#ifndef DCHECK_EQ
-#define DCHECK_EQ(val1, val2) ASSERT((val1) == (val2))
-#endif
-
-// A safe way of doing "(1 << n) - 1" -- without worrying about overflow
-// Note this will all be resolved to a constant expression at compile-time
-#define N_ONES_(IntType, N)                                     \
-  ( (N) == 0 ? 0 : ((static_cast<IntType>(1) << ((N)-1))-1 +    \
-                    (static_cast<IntType>(1) << ((N)-1))) )
-
-// The types K and V provide upper bounds on the number of valid keys
-// and values, but we explicitly require the keys to be less than
-// 2^kKeybits and the values to be less than 2^kValuebits.  The size of
-// the table is controlled by kHashbits, and the type of each entry in
-// the cache is T.  See also the big comment at the top of the file.
-template <int kKeybits, typename T>
-class PackedCache {
- public:
-  typedef uintptr_t K;
-  typedef size_t V;
-  static const size_t kHashbits = 12;
-  static const size_t kValuebits = 8;
-
-  explicit PackedCache(V initial_value) {
-    COMPILE_ASSERT(kKeybits <= sizeof(K) * 8, key_size);
-    COMPILE_ASSERT(kValuebits <= sizeof(V) * 8, value_size);
-    COMPILE_ASSERT(kHashbits <= kKeybits, hash_function);
-    COMPILE_ASSERT(kKeybits - kHashbits + kValuebits <= kTbits,
-                   entry_size_must_be_big_enough);
-    Clear(initial_value);
-  }
-
-  void Put(K key, V value) {
-    DCHECK_EQ(key, key & kKeyMask);
-    DCHECK_EQ(value, value & kValueMask);
-    array_[Hash(key)] = static_cast<T>(KeyToUpper(key) | value);
-  }
-
-  bool Has(K key) const {
-    DCHECK_EQ(key, key & kKeyMask);
-    return KeyMatch(array_[Hash(key)], key);
-  }
-
-  V GetOrDefault(K key, V default_value) const {
-    // As with other code in this class, we touch array_ as few times
-    // as we can.  Assuming entries are read atomically (e.g., their
-    // type is uintptr_t on most hardware) then certain races are
-    // harmless.
-    DCHECK_EQ(key, key & kKeyMask);
-    T entry = array_[Hash(key)];
-    return KeyMatch(entry, key) ? EntryToValue(entry) : default_value;
-  }
-
-  void Clear(V value) {
-    DCHECK_EQ(value, value & kValueMask);
-    for (int i = 0; i < 1 << kHashbits; i++) {
-      array_[i] = static_cast<T>(value);
-    }
-  }
-
- private:
-  // We are going to pack a value and the upper part of a key into
-  // an entry of type T.  The UPPER type is for the upper part of a key,
-  // after the key has been masked and shifted for inclusion in an entry.
-  typedef T UPPER;
-
-  static V EntryToValue(T t) { return t & kValueMask; }
-
-  static UPPER EntryToUpper(T t) { return t & kUpperMask; }
-
-  // If v is a V and u is an UPPER then you can create an entry by
-  // doing u | v.  kHashbits determines where in a K to find the upper
-  // part of the key, and kValuebits determines where in the entry to put
-  // it.
-  static UPPER KeyToUpper(K k) {
-    const int shift = kHashbits - kValuebits;
-    // Assume kHashbits >= kValuebits. It would be easy to lift this assumption.
-    return static_cast<T>(k >> shift) & kUpperMask;
-  }
-
-  // This is roughly the inverse of KeyToUpper().  Some of the key has been
-  // thrown away, since KeyToUpper() masks off the low bits of the key.
-  static K UpperToPartialKey(UPPER u) {
-    DCHECK_EQ(u, u & kUpperMask);
-    const int shift = kHashbits - kValuebits;
-    // Assume kHashbits >= kValuebits. It would be easy to lift this assumption.
-    return static_cast<K>(u) << shift;
-  }
-
-  static size_t Hash(K key) {
-    return static_cast<size_t>(key) & N_ONES_(size_t, kHashbits);
-  }
-
-  // Does the entry's partial key match the relevant part of the given key?
-  static bool KeyMatch(T entry, K key) {
-    return ((KeyToUpper(key) ^ entry) & kUpperMask) == 0;
-  }
-
-  static const size_t kTbits = 8 * sizeof(T);
-  static const int kUpperbits = kKeybits - kHashbits;
-
-  // For masking a K.
-  static const K kKeyMask = N_ONES_(K, kKeybits);
-
-  // For masking a T.
-  static const T kUpperMask = N_ONES_(T, kUpperbits) << kValuebits;
-
-  // For masking a V or a T.
-  static const V kValueMask = N_ONES_(V, kValuebits);
-
-  T array_[1 << kHashbits];
-};
-
-#undef N_ONES_
-
-#endif  // TCMALLOC_PACKED_CACHE_INL_H__
diff --git a/wtf/TCPageMap.h b/wtf/TCPageMap.h
deleted file mode 100644 (file)
index 99bdc40..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright (c) 2005, 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.
-
-// ---
-// Author: Sanjay Ghemawat <opensource@google.com>
-//
-// A data structure used by the caching malloc.  It maps from page# to
-// a pointer that contains info about that page.  We use two
-// representations: one for 32-bit addresses, and another for 64 bit
-// addresses.  Both representations provide the same interface.  The
-// first representation is implemented as a flat array, the seconds as
-// a three-level radix tree that strips away approximately 1/3rd of
-// the bits every time.
-//
-// The BITS parameter should be the number of bits required to hold
-// a page number.  E.g., with 32 bit pointers and 4K pages (i.e.,
-// page offset fits in lower 12 bits), BITS == 20.
-
-#ifndef TCMALLOC_PAGEMAP_H__
-#define TCMALLOC_PAGEMAP_H__
-
-#if HAVE(STDINT_H)
-#include <stdint.h>
-#elif HAVE(INTTYPES_H)
-#include <inttypes.h>
-#else
-#include <sys/types.h>
-#endif
-
-#include <string.h>
-#include "Assertions.h"
-
-// Single-level array
-template <int BITS>
-class TCMalloc_PageMap1 {
- private:
-  void** array_;
-
- public:
-  typedef uintptr_t Number;
-
-  void init(void* (*allocator)(size_t)) {
-    array_ = reinterpret_cast<void**>((*allocator)(sizeof(void*) << BITS));
-    memset(array_, 0, sizeof(void*) << BITS);
-  }
-
-  // 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, size_t) {
-    // Nothing to do since flat array was allocate at start
-    return true;
-  }
-
-  void PreallocateMoreMemory() {}
-
-  // REQUIRES "k" is in range "[0,2^BITS-1]".
-  // REQUIRES "k" has been ensured before.
-  //
-  // Return the current value for KEY.  Returns "Value()" if not
-  // yet set.
-  void* get(Number k) const {
-    return array_[k];
-  }
-
-  // REQUIRES "k" is in range "[0,2^BITS-1]".
-  // REQUIRES "k" has been ensured before.
-  //
-  // Sets the value for KEY.
-  void set(Number k, void* v) {
-    array_[k] = v;
-  }
-};
-
-// Two-level radix tree
-template <int BITS>
-class TCMalloc_PageMap2 {
- private:
-  // Put 32 entries in the root and (2^BITS)/32 entries in each leaf.
-  static const int ROOT_BITS = 5;
-  static const int ROOT_LENGTH = 1 << ROOT_BITS;
-
-  static const int LEAF_BITS = BITS - ROOT_BITS;
-  static const int LEAF_LENGTH = 1 << LEAF_BITS;
-
-  // Leaf node
-  struct Leaf {
-    void* values[LEAF_LENGTH];
-  };
-
-  Leaf* root_[ROOT_LENGTH];             // Pointers to 32 child nodes
-  void* (*allocator_)(size_t);          // Memory allocator
-
- public:
-  typedef uintptr_t Number;
-
-  void init(void* (*allocator)(size_t)) {
-    allocator_ = allocator;
-    memset(root_, 0, sizeof(root_));
-  }
-
-  void* get(Number k) const {
-    ASSERT(k >> BITS == 0);
-    const Number i1 = k >> LEAF_BITS;
-    const Number i2 = k & (LEAF_LENGTH-1);
-    return root_[i1]->values[i2];
-  }
-
-  void set(Number k, void* v) {
-    ASSERT(k >> BITS == 0);
-    const Number i1 = k >> LEAF_BITS;
-    const Number i2 = k & (LEAF_LENGTH-1);
-    root_[i1]->values[i2] = v;
-  }
-
-  bool Ensure(Number start, size_t n) {
-    for (Number key = start; key <= start + n - 1; ) {
-      const Number i1 = key >> LEAF_BITS;
-
-      // Make 2nd level node if necessary
-      if (root_[i1] == NULL) {
-        Leaf* leaf = reinterpret_cast<Leaf*>((*allocator_)(sizeof(Leaf)));
-        if (leaf == NULL) return false;
-        memset(leaf, 0, sizeof(*leaf));
-        root_[i1] = leaf;
-      }
-
-      // Advance key past whatever is covered by this leaf node
-      key = ((key >> LEAF_BITS) + 1) << LEAF_BITS;
-    }
-    return true;
-  }
-
-  void PreallocateMoreMemory() {
-    // Allocate enough to keep track of all possible pages
-    Ensure(0, 1 << BITS);
-  }
-
-#ifdef WTF_CHANGES
-  template<class Visitor, class MemoryReader>
-  void visitValues(Visitor& visitor, const MemoryReader& reader)
-  {
-    for (int i = 0; i < ROOT_LENGTH; i++) {
-      if (!root_[i])
-        continue;
-
-      Leaf* l = reader(reinterpret_cast<Leaf*>(root_[i]));
-      for (int j = 0; j < LEAF_LENGTH; j += visitor.visit(l->values[j]))
-        ;
-    }
-  }
-
-  template<class Visitor, class MemoryReader>
-  void visitAllocations(Visitor& visitor, const MemoryReader&) {
-    for (int i = 0; i < ROOT_LENGTH; i++) {
-      if (root_[i])
-        visitor.visit(root_[i], sizeof(Leaf));
-    }
-  }
-#endif
-};
-
-// Three-level radix tree
-template <int BITS>
-class TCMalloc_PageMap3 {
- private:
-  // How many bits should we consume at each interior level
-  static const int INTERIOR_BITS = (BITS + 2) / 3; // Round-up
-  static const int INTERIOR_LENGTH = 1 << INTERIOR_BITS;
-
-  // How many bits should we consume at leaf level
-  static const int LEAF_BITS = BITS - 2*INTERIOR_BITS;
-  static const int LEAF_LENGTH = 1 << LEAF_BITS;
-
-  // Interior node
-  struct Node {
-    Node* ptrs[INTERIOR_LENGTH];
-  };
-
-  // Leaf node
-  struct Leaf {
-    void* values[LEAF_LENGTH];
-  };
-
-  Node* root_;                          // Root of radix tree
-  void* (*allocator_)(size_t);          // Memory allocator
-
-  Node* NewNode() {
-    Node* result = reinterpret_cast<Node*>((*allocator_)(sizeof(Node)));
-    if (result != NULL) {
-      memset(result, 0, sizeof(*result));
-    }
-    return result;
-  }
-
- public:
-  typedef uintptr_t Number;
-
-  void init(void* (*allocator)(size_t)) {
-    allocator_ = allocator;
-    root_ = NewNode();
-  }
-
-  void* get(Number k) const {
-    ASSERT(k >> BITS == 0);
-    const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS);
-    const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1);
-    const Number i3 = k & (LEAF_LENGTH-1);
-    return reinterpret_cast<Leaf*>(root_->ptrs[i1]->ptrs[i2])->values[i3];
-  }
-
-  void set(Number k, void* v) {
-    ASSERT(k >> BITS == 0);
-    const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS);
-    const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1);
-    const Number i3 = k & (LEAF_LENGTH-1);
-    reinterpret_cast<Leaf*>(root_->ptrs[i1]->ptrs[i2])->values[i3] = v;
-  }
-
-  bool Ensure(Number start, size_t n) {
-    for (Number key = start; key <= start + n - 1; ) {
-      const Number i1 = key >> (LEAF_BITS + INTERIOR_BITS);
-      const Number i2 = (key >> LEAF_BITS) & (INTERIOR_LENGTH-1);
-
-      // Make 2nd level node if necessary
-      if (root_->ptrs[i1] == NULL) {
-        Node* n = NewNode();
-        if (n == NULL) return false;
-        root_->ptrs[i1] = n;
-      }
-
-      // Make leaf node if necessary
-      if (root_->ptrs[i1]->ptrs[i2] == NULL) {
-        Leaf* leaf = reinterpret_cast<Leaf*>((*allocator_)(sizeof(Leaf)));
-        if (leaf == NULL) return false;
-        memset(leaf, 0, sizeof(*leaf));
-        root_->ptrs[i1]->ptrs[i2] = reinterpret_cast<Node*>(leaf);
-      }
-
-      // Advance key past whatever is covered by this leaf node
-      key = ((key >> LEAF_BITS) + 1) << LEAF_BITS;
-    }
-    return true;
-  }
-
-  void PreallocateMoreMemory() {
-  }
-
-#ifdef WTF_CHANGES
-  template<class Visitor, class MemoryReader>
-  void visitValues(Visitor& visitor, const MemoryReader& reader) {
-    Node* root = reader(root_);
-    for (int i = 0; i < INTERIOR_LENGTH; i++) {
-      if (!root->ptrs[i])
-        continue;
-
-      Node* n = reader(root->ptrs[i]);
-      for (int j = 0; j < INTERIOR_LENGTH; j++) {
-        if (!n->ptrs[j])
-          continue;
-
-        Leaf* l = reader(reinterpret_cast<Leaf*>(n->ptrs[j]));
-        for (int k = 0; k < LEAF_LENGTH; k += visitor.visit(l->values[k]))
-          ;
-      }
-    }
-  }
-
-  template<class Visitor, class MemoryReader>
-  void visitAllocations(Visitor& visitor, const MemoryReader& reader) {
-    visitor.visit(root_, sizeof(Node));
-
-    Node* root = reader(root_);
-    for (int i = 0; i < INTERIOR_LENGTH; i++) {
-      if (!root->ptrs[i])
-        continue;
-
-      visitor.visit(root->ptrs[i], sizeof(Node));
-      Node* n = reader(root->ptrs[i]);
-      for (int j = 0; j < INTERIOR_LENGTH; j++) {
-        if (!n->ptrs[j])
-          continue;
-
-        visitor.visit(n->ptrs[j], sizeof(Leaf));
-      }
-    }
-  }
-#endif
-};
-
-#endif  // TCMALLOC_PAGEMAP_H__
diff --git a/wtf/TCSpinLock.h b/wtf/TCSpinLock.h
deleted file mode 100644 (file)
index 81b7d0c..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-// 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
-// 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.
-
-// ---
-// Author: Sanjay Ghemawat <opensource@google.com>
-
-#ifndef TCMALLOC_INTERNAL_SPINLOCK_H__
-#define TCMALLOC_INTERNAL_SPINLOCK_H__
-
-#if (CPU(X86) || CPU(X86_64) || CPU(PPC)) && (COMPILER(GCC) || COMPILER(MSVC))
-
-#include <time.h>       /* For nanosleep() */
-
-#if HAVE(STDINT_H)
-#include <stdint.h>
-#elif HAVE(INTTYPES_H)
-#include <inttypes.h>
-#else
-#include <sys/types.h>
-#endif
-
-#if OS(WINDOWS)
-#ifndef WIN32_LEAN_AND_MEAN
-#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);
-
-// The following is a struct so that it can be initialized at compile time
-struct TCMalloc_SpinLock {
-
-  inline void Lock() {
-    int r;
-#if COMPILER(GCC)
-#if CPU(X86) || CPU(X86_64)
-    __asm__ __volatile__
-      ("xchgl %0, %1"
-       : "=r"(r), "=m"(lockword_)
-       : "0"(1), "m"(lockword_)
-       : "memory");
-#else
-    volatile unsigned int *lockword_ptr = &lockword_;
-    __asm__ __volatile__
-        ("1: lwarx %0, 0, %1\n\t"
-         "stwcx. %2, 0, %1\n\t"
-         "bne- 1b\n\t"
-         "isync"
-         : "=&r" (r), "=r" (lockword_ptr)
-         : "r" (1), "1" (lockword_ptr)
-         : "memory");
-#endif
-#elif COMPILER(MSVC)
-    __asm {
-        mov eax, this    ; store &lockword_ (which is this+0) in eax
-        mov ebx, 1       ; store 1 in ebx
-        xchg [eax], ebx  ; exchange lockword_ and 1
-        mov r, ebx       ; store old value of lockword_ in r
-    }
-#endif
-    if (r) TCMalloc_SlowLock(&lockword_);
-  }
-
-  inline void Unlock() {
-#if COMPILER(GCC)
-#if CPU(X86) || CPU(X86_64)
-    __asm__ __volatile__
-      ("movl $0, %0"
-       : "=m"(lockword_)
-       : "m" (lockword_)
-       : "memory");
-#else
-    __asm__ __volatile__
-      ("isync\n\t"
-       "eieio\n\t"
-       "stw %1, %0"
-#if OS(DARWIN) || CPU(PPC)
-       : "=o" (lockword_)
-#else
-       : "=m" (lockword_) 
-#endif
-       : "r" (0)
-       : "memory");
-#endif
-#elif COMPILER(MSVC)
-      __asm {
-          mov eax, this  ; store &lockword_ (which is this+0) in eax
-          mov [eax], 0   ; set lockword_ to 0
-      }
-#endif
-  }
-    // Report if we think the lock can be held by this thread.
-    // When the lock is truly held by the invoking thread
-    // we will always return true.
-    // Indended to be used as CHECK(lock.IsHeld());
-    inline bool IsHeld() const {
-        return lockword_ != 0;
-    }
-
-    inline void Init() { lockword_ = 0; }
-
-    volatile unsigned int lockword_;
-};
-
-#define SPINLOCK_INITIALIZER { 0 }
-
-static void TCMalloc_SlowLock(volatile unsigned int* lockword) {
-// Yield immediately since fast path failed
-#if OS(WINDOWS)
-  Sleep(0);
-#else
-  sched_yield();
-#endif
-  while (true) {
-    int r;
-#if COMPILER(GCC)
-#if CPU(X86) || CPU(X86_64)
-    __asm__ __volatile__
-      ("xchgl %0, %1"
-       : "=r"(r), "=m"(*lockword)
-       : "0"(1), "m"(*lockword)
-       : "memory");
-
-#else
-    int tmp = 1;
-    __asm__ __volatile__
-        ("1: lwarx %0, 0, %1\n\t"
-         "stwcx. %2, 0, %1\n\t"
-         "bne- 1b\n\t"
-         "isync"
-         : "=&r" (r), "=r" (lockword)
-         : "r" (tmp), "1" (lockword)
-         : "memory");
-#endif
-#elif COMPILER(MSVC)
-    __asm {
-        mov eax, lockword     ; assign lockword into eax
-        mov ebx, 1            ; assign 1 into ebx
-        xchg [eax], ebx       ; exchange *lockword and 1
-        mov r, ebx            ; store old value of *lockword in r
-    }
-#endif
-    if (!r) {
-      return;
-    }
-
-    // This code was adapted from the ptmalloc2 implementation of
-    // spinlocks which would sched_yield() upto 50 times before
-    // sleeping once for a few milliseconds.  Mike Burrows suggested
-    // just doing one sched_yield() outside the loop and always
-    // sleeping after that.  This change helped a great deal on the
-    // performance of spinlocks under high contention.  A test program
-    // with 10 threads on a dual Xeon (four virtual processors) went
-    // from taking 30 seconds to 16 seconds.
-
-    // Sleep for a few milliseconds
-#if OS(WINDOWS)
-    Sleep(2);
-#else
-    struct timespec tm;
-    tm.tv_sec = 0;
-    tm.tv_nsec = 2000001;
-    nanosleep(&tm, NULL);
-#endif
-  }
-}
-
-#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>
-
-// Portable version
-struct TCMalloc_SpinLock {
-  pthread_mutex_t private_lock_;
-
-  inline void Init() {
-    if (pthread_mutex_init(&private_lock_, NULL) != 0) CRASH();
-  }
-  inline void Finalize() {
-    if (pthread_mutex_destroy(&private_lock_) != 0) CRASH();
-  }
-  inline void Lock() {
-    if (pthread_mutex_lock(&private_lock_) != 0) CRASH();
-  }
-  inline void Unlock() {
-    if (pthread_mutex_unlock(&private_lock_) != 0) CRASH();
-  }
-  bool IsHeld() {
-    if (pthread_mutex_trylock(&private_lock_))
-      return true;
-
-    Unlock();
-    return false;
-  }
-};
-
-#define SPINLOCK_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
-
-#endif
-
-// Corresponding locker object that arranges to acquire a spinlock for
-// the duration of a C++ scope.
-class TCMalloc_SpinLockHolder {
- private:
-  TCMalloc_SpinLock* lock_;
- public:
-  inline explicit TCMalloc_SpinLockHolder(TCMalloc_SpinLock* l)
-    : lock_(l) { l->Lock(); }
-  inline ~TCMalloc_SpinLockHolder() { lock_->Unlock(); }
-};
-
-// Short-hands for convenient use by tcmalloc.cc
-typedef TCMalloc_SpinLock SpinLock;
-typedef TCMalloc_SpinLockHolder SpinLockHolder;
-
-#endif  // TCMALLOC_INTERNAL_SPINLOCK_H__
diff --git a/wtf/TCSystemAlloc.cpp b/wtf/TCSystemAlloc.cpp
deleted file mode 100644 (file)
index 3cb59e8..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-// Copyright (c) 2005, 2007, 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.
-
-// ---
-// Author: Sanjay Ghemawat
-
-#include "config.h"
-#if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC)
-#include "TCSystemAlloc.h"
-
-#include <algorithm>
-#include "Assertions.h"
-#include "TCSpinLock.h"
-#include "UnusedParam.h"
-#include "VMTags.h"
-
-#if HAVE(STDINT_H)
-#include <stdint.h>
-#elif HAVE(INTTYPES_H)
-#include <inttypes.h>
-#else
-#include <sys/types.h>
-#endif
-
-#if OS(WINDOWS)
-#include "windows.h"
-#else
-#include <errno.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#endif
-
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-using namespace std;
-
-// Structure for discovering alignment
-union MemoryAligner {
-  void*  p;
-  double d;
-  size_t s;
-};
-
-static SpinLock spinlock = SPINLOCK_INITIALIZER;
-
-// Page size is initialized on demand
-static size_t pagesize = 0;
-
-// Configuration parameters.
-//
-// if use_devmem is true, either use_sbrk or use_mmap must also be true.
-// For 2.2 kernels, it looks like the sbrk address space (500MBish) and
-// the mmap address space (1300MBish) are disjoint, so we need both allocators
-// to get as much virtual memory as possible.
-#ifndef WTF_CHANGES
-static bool use_devmem = false;
-#endif
-
-#if HAVE(SBRK)
-static bool use_sbrk = false;
-#endif
-
-#if HAVE(MMAP)
-static bool use_mmap = true;
-#endif 
-
-#if HAVE(VIRTUALALLOC)
-static bool use_VirtualAlloc = true;
-#endif
-
-// Flags to keep us from retrying allocators that failed.
-static bool devmem_failure = false;
-static bool sbrk_failure = false;
-static bool mmap_failure = false;
-static bool VirtualAlloc_failure = false;
-
-#ifndef WTF_CHANGES
-DEFINE_int32(malloc_devmem_start, 0,
-             "Physical memory starting location in MB for /dev/mem allocation."
-             "  Setting this to 0 disables /dev/mem allocation");
-DEFINE_int32(malloc_devmem_limit, 0,
-             "Physical memory limit location in MB for /dev/mem allocation."
-             "  Setting this to 0 means no limit.");
-#else
-static const int32_t FLAGS_malloc_devmem_start = 0;
-static const int32_t FLAGS_malloc_devmem_limit = 0;
-#endif
-
-#if HAVE(SBRK)
-
-static void* TrySbrk(size_t size, size_t *actual_size, size_t alignment) {
-  size = ((size + alignment - 1) / alignment) * alignment;
-  
-  // could theoretically return the "extra" bytes here, but this
-  // is simple and correct.
-  if (actual_size) 
-    *actual_size = size;
-    
-  void* result = sbrk(size);
-  if (result == reinterpret_cast<void*>(-1)) {
-    sbrk_failure = true;
-    return NULL;
-  }
-
-  // Is it aligned?
-  uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
-  if ((ptr & (alignment-1)) == 0)  return result;
-
-  // Try to get more memory for alignment
-  size_t extra = alignment - (ptr & (alignment-1));
-  void* r2 = sbrk(extra);
-  if (reinterpret_cast<uintptr_t>(r2) == (ptr + size)) {
-    // Contiguous with previous result
-    return reinterpret_cast<void*>(ptr + extra);
-  }
-
-  // Give up and ask for "size + alignment - 1" bytes so
-  // that we can find an aligned region within it.
-  result = sbrk(size + alignment - 1);
-  if (result == reinterpret_cast<void*>(-1)) {
-    sbrk_failure = true;
-    return NULL;
-  }
-  ptr = reinterpret_cast<uintptr_t>(result);
-  if ((ptr & (alignment-1)) != 0) {
-    ptr += alignment - (ptr & (alignment-1));
-  }
-  return reinterpret_cast<void*>(ptr);
-}
-
-#endif /* HAVE(SBRK) */
-
-#if HAVE(MMAP)
-
-static void* TryMmap(size_t size, size_t *actual_size, size_t alignment) {
-  // Enforce page alignment
-  if (pagesize == 0) pagesize = getpagesize();
-  if (alignment < pagesize) alignment = pagesize;
-  size = ((size + alignment - 1) / alignment) * alignment;
-  
-  // could theoretically return the "extra" bytes here, but this
-  // is simple and correct.
-  if (actual_size) 
-    *actual_size = size;
-    
-  // Ask for extra memory if alignment > pagesize
-  size_t extra = 0;
-  if (alignment > pagesize) {
-    extra = alignment - pagesize;
-  }
-  void* result = mmap(NULL, size + extra,
-                      PROT_READ | PROT_WRITE,
-                      MAP_PRIVATE|MAP_ANONYMOUS,
-                      VM_TAG_FOR_TCMALLOC_MEMORY, 0);
-  if (result == reinterpret_cast<void*>(MAP_FAILED)) {
-    mmap_failure = true;
-    return NULL;
-  }
-
-  // Adjust the return memory so it is aligned
-  uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
-  size_t adjust = 0;
-  if ((ptr & (alignment - 1)) != 0) {
-    adjust = alignment - (ptr & (alignment - 1));
-  }
-
-  // Return the unused memory to the system
-  if (adjust > 0) {
-    munmap(reinterpret_cast<void*>(ptr), adjust);
-  }
-  if (adjust < extra) {
-    munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust);
-  }
-
-  ptr += adjust;
-  return reinterpret_cast<void*>(ptr);
-}
-
-#endif /* HAVE(MMAP) */
-
-#if HAVE(VIRTUALALLOC)
-
-static void* TryVirtualAlloc(size_t size, size_t *actual_size, size_t alignment) {
-  // Enforce page alignment
-  if (pagesize == 0) {
-    SYSTEM_INFO system_info;
-    GetSystemInfo(&system_info);
-    pagesize = system_info.dwPageSize;
-  }
-
-  if (alignment < pagesize) alignment = pagesize;
-  size = ((size + alignment - 1) / alignment) * alignment;
-
-  // could theoretically return the "extra" bytes here, but this
-  // is simple and correct.
-  if (actual_size) 
-    *actual_size = size;
-    
-  // Ask for extra memory if alignment > pagesize
-  size_t extra = 0;
-  if (alignment > pagesize) {
-    extra = alignment - pagesize;
-  }
-  void* result = VirtualAlloc(NULL, size + extra,
-                              MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, 
-                              PAGE_READWRITE);
-
-  if (result == NULL) {
-    VirtualAlloc_failure = true;
-    return NULL;
-  }
-
-  // Adjust the return memory so it is aligned
-  uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
-  size_t adjust = 0;
-  if ((ptr & (alignment - 1)) != 0) {
-    adjust = alignment - (ptr & (alignment - 1));
-  }
-
-  // Return the unused memory to the system - we'd like to release but the best we can do
-  // is decommit, since Windows only lets you free the whole allocation.
-  if (adjust > 0) {
-    VirtualFree(reinterpret_cast<void*>(ptr), adjust, MEM_DECOMMIT);
-  }
-  if (adjust < extra) {
-    VirtualFree(reinterpret_cast<void*>(ptr + adjust + size), extra-adjust, MEM_DECOMMIT);
-  }
-
-  ptr += adjust;
-  return reinterpret_cast<void*>(ptr);
-}
-
-#endif /* HAVE(MMAP) */
-
-#ifndef WTF_CHANGES
-static void* TryDevMem(size_t size, size_t *actual_size, size_t alignment) {
-  static bool initialized = false;
-  static off_t physmem_base;  // next physical memory address to allocate
-  static off_t physmem_limit; // maximum physical address allowed
-  static int physmem_fd;      // file descriptor for /dev/mem
-  
-  // Check if we should use /dev/mem allocation.  Note that it may take
-  // a while to get this flag initialized, so meanwhile we fall back to
-  // the next allocator.  (It looks like 7MB gets allocated before
-  // this flag gets initialized -khr.)
-  if (FLAGS_malloc_devmem_start == 0) {
-    // NOTE: not a devmem_failure - we'd like TCMalloc_SystemAlloc to
-    // try us again next time.
-    return NULL;
-  }
-  
-  if (!initialized) {
-    physmem_fd = open("/dev/mem", O_RDWR);
-    if (physmem_fd < 0) {
-      devmem_failure = true;
-      return NULL;
-    }
-    physmem_base = FLAGS_malloc_devmem_start*1024LL*1024LL;
-    physmem_limit = FLAGS_malloc_devmem_limit*1024LL*1024LL;
-    initialized = true;
-  }
-  
-  // Enforce page alignment
-  if (pagesize == 0) pagesize = getpagesize();
-  if (alignment < pagesize) alignment = pagesize;
-  size = ((size + alignment - 1) / alignment) * alignment;
-    
-  // could theoretically return the "extra" bytes here, but this
-  // is simple and correct.
-  if (actual_size)
-    *actual_size = size;
-    
-  // Ask for extra memory if alignment > pagesize
-  size_t extra = 0;
-  if (alignment > pagesize) {
-    extra = alignment - pagesize;
-  }
-  
-  // check to see if we have any memory left
-  if (physmem_limit != 0 && physmem_base + size + extra > physmem_limit) {
-    devmem_failure = true;
-    return NULL;
-  }
-  void *result = mmap(0, size + extra, PROT_READ | PROT_WRITE,
-                      MAP_SHARED, physmem_fd, physmem_base);
-  if (result == reinterpret_cast<void*>(MAP_FAILED)) {
-    devmem_failure = true;
-    return NULL;
-  }
-  uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
-  
-  // Adjust the return memory so it is aligned
-  size_t adjust = 0;
-  if ((ptr & (alignment - 1)) != 0) {
-    adjust = alignment - (ptr & (alignment - 1));
-  }
-  
-  // Return the unused virtual memory to the system
-  if (adjust > 0) {
-    munmap(reinterpret_cast<void*>(ptr), adjust);
-  }
-  if (adjust < extra) {
-    munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust);
-  }
-  
-  ptr += adjust;
-  physmem_base += adjust + size;
-  
-  return reinterpret_cast<void*>(ptr);
-}
-#endif
-
-void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, size_t alignment) {
-  // Discard requests that overflow
-  if (size + alignment < size) return NULL;
-    
-  SpinLockHolder lock_holder(&spinlock);
-
-  // Enforce minimum alignment
-  if (alignment < sizeof(MemoryAligner)) alignment = sizeof(MemoryAligner);
-
-  // Try twice, once avoiding allocators that failed before, and once
-  // more trying all allocators even if they failed before.
-  for (int i = 0; i < 2; i++) {
-
-#ifndef WTF_CHANGES
-    if (use_devmem && !devmem_failure) {
-      void* result = TryDevMem(size, actual_size, alignment);
-      if (result != NULL) return result;
-    }
-#endif
-    
-#if HAVE(SBRK)
-    if (use_sbrk && !sbrk_failure) {
-      void* result = TrySbrk(size, actual_size, alignment);
-      if (result != NULL) return result;
-    }
-#endif
-
-#if HAVE(MMAP)    
-    if (use_mmap && !mmap_failure) {
-      void* result = TryMmap(size, actual_size, alignment);
-      if (result != NULL) return result;
-    }
-#endif
-
-#if HAVE(VIRTUALALLOC)
-    if (use_VirtualAlloc && !VirtualAlloc_failure) {
-      void* result = TryVirtualAlloc(size, actual_size, alignment);
-      if (result != NULL) return result;
-    }
-#endif
-
-    // nothing worked - reset failure flags and try again
-    devmem_failure = false;
-    sbrk_failure = false;
-    mmap_failure = false;
-    VirtualAlloc_failure = false;
-  }
-  return NULL;
-}
-
-#if HAVE(MADV_FREE_REUSE)
-
-void TCMalloc_SystemRelease(void* start, size_t length)
-{
-    while (madvise(start, length, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
-}
-
-#elif HAVE(MADV_FREE) || HAVE(MADV_DONTNEED)
-
-void TCMalloc_SystemRelease(void* start, size_t length)
-{
-    // MADV_FREE clears the modified bit on pages, which allows
-    // them to be discarded immediately.
-#if HAVE(MADV_FREE)
-    const int advice = MADV_FREE;
-#else
-    const int advice = MADV_DONTNEED;
-#endif
-  if (FLAGS_malloc_devmem_start) {
-    // It's not safe to use MADV_DONTNEED if we've been mapping
-    // /dev/mem for heap memory
-    return;
-  }
-  if (pagesize == 0) pagesize = getpagesize();
-  const size_t pagemask = pagesize - 1;
-
-  size_t new_start = reinterpret_cast<size_t>(start);
-  size_t end = new_start + length;
-  size_t new_end = end;
-
-  // Round up the starting address and round down the ending address
-  // to be page aligned:
-  new_start = (new_start + pagesize - 1) & ~pagemask;
-  new_end = new_end & ~pagemask;
-
-  ASSERT((new_start & pagemask) == 0);
-  ASSERT((new_end & pagemask) == 0);
-  ASSERT(new_start >= reinterpret_cast<size_t>(start));
-  ASSERT(new_end <= end);
-
-  if (new_end > new_start) {
-    // Note -- ignoring most return codes, because if this fails it
-    // doesn't matter...
-    while (madvise(reinterpret_cast<char*>(new_start), new_end - new_start,
-                   advice) == -1 &&
-           errno == EAGAIN) {
-      // NOP
-    }
-  }
-}
-
-#elif HAVE(MMAP)
-
-void TCMalloc_SystemRelease(void* start, size_t length)
-{
-  void* newAddress = mmap(start, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
-  // If the mmap failed then that's ok, we just won't return the memory to the system.
-  ASSERT_UNUSED(newAddress, newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED));
-}
-
-#elif HAVE(VIRTUALALLOC)
-
-void TCMalloc_SystemRelease(void* start, size_t length)
-{
-    if (VirtualFree(start, length, MEM_DECOMMIT))
-        return;
-
-    // The decommit may fail if the memory region consists of allocations
-    // from more than one call to VirtualAlloc.  In this case, fall back to
-    // using VirtualQuery to retrieve the allocation boundaries and decommit
-    // them each individually.
-
-    char* ptr = static_cast<char*>(start);
-    char* end = ptr + length;
-    MEMORY_BASIC_INFORMATION info;
-    while (ptr < end) {
-        size_t resultSize = VirtualQuery(ptr, &info, sizeof(info));
-        ASSERT_UNUSED(resultSize, resultSize == sizeof(info));
-
-        size_t decommitSize = min<size_t>(info.RegionSize, end - ptr);
-        BOOL success = VirtualFree(ptr, decommitSize, MEM_DECOMMIT);
-        ASSERT_UNUSED(success, success);
-        ptr += decommitSize;
-    }
-}
-
-#else
-
-// Platforms that don't support returning memory use an empty inline version of TCMalloc_SystemRelease
-// declared in TCSystemAlloc.h
-
-#endif
-
-#if HAVE(MADV_FREE_REUSE)
-
-void TCMalloc_SystemCommit(void* start, size_t length)
-{
-    while (madvise(start, length, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { }
-}
-
-#elif HAVE(VIRTUALALLOC)
-
-void TCMalloc_SystemCommit(void* start, size_t length)
-{
-    if (VirtualAlloc(start, length, MEM_COMMIT, PAGE_READWRITE) == start)
-        return;
-
-    // The commit may fail if the memory region consists of allocations
-    // from more than one call to VirtualAlloc.  In this case, fall back to
-    // using VirtualQuery to retrieve the allocation boundaries and commit them
-    // each individually.
-
-    char* ptr = static_cast<char*>(start);
-    char* end = ptr + length;
-    MEMORY_BASIC_INFORMATION info;
-    while (ptr < end) {
-        size_t resultSize = VirtualQuery(ptr, &info, sizeof(info));
-        ASSERT_UNUSED(resultSize, resultSize == sizeof(info));
-
-        size_t commitSize = min<size_t>(info.RegionSize, end - ptr);
-        void* newAddress = VirtualAlloc(ptr, commitSize, MEM_COMMIT, PAGE_READWRITE);
-        ASSERT_UNUSED(newAddress, newAddress == ptr);
-        ptr += commitSize;
-    }
-}
-
-#else
-
-// Platforms that don't need to explicitly commit memory use an empty inline version of TCMalloc_SystemCommit
-// declared in TCSystemAlloc.h
-
-#endif
-
-#endif // #if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC)
-
diff --git a/wtf/TCSystemAlloc.h b/wtf/TCSystemAlloc.h
deleted file mode 100644 (file)
index 1c67788..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2005, 2007, 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.
-
-// ---
-// Author: Sanjay Ghemawat
-//
-// Routine that uses sbrk/mmap to allocate memory from the system.
-// Useful for implementing malloc.
-
-#ifndef TCMALLOC_SYSTEM_ALLOC_H__
-#define TCMALLOC_SYSTEM_ALLOC_H__
-
-// REQUIRES: "alignment" is a power of two or "0" to indicate default alignment
-//
-// Allocate and return "N" bytes of zeroed memory.
-//
-// If actual_bytes is NULL then the returned memory is exactly the
-// requested size.  If actual bytes is non-NULL then the allocator
-// may optionally return more bytes than asked for (i.e. return an
-// entire "huge" page if a huge page allocator is in use).
-//
-// The returned pointer is a multiple of "alignment" if non-zero.
-//
-// Returns NULL when out of memory.
-extern void* TCMalloc_SystemAlloc(size_t bytes, size_t *actual_bytes,
-                                  size_t alignment = 0);
-
-// This call is a hint to the operating system that the pages
-// contained in the specified range of memory will not be used for a
-// while, and can be released for use by other processes or the OS.
-// Pages which are released in this way may be destroyed (zeroed) by
-// the OS.  The benefit of this function is that it frees memory for
-// use by the system, the cost is that the pages are faulted back into
-// the address space next time they are touched, which can impact
-// performance.  (Only pages fully covered by the memory region will
-// be released, partial pages will not.)
-extern void TCMalloc_SystemRelease(void* start, size_t length);
-
-extern void TCMalloc_SystemCommit(void* start, size_t length);
-
-#if !HAVE(MADV_FREE_REUSE) && !HAVE(MADV_DONTNEED) && !HAVE(MMAP) && !HAVE(VIRTUALALLOC)
-inline void TCMalloc_SystemRelease(void*, size_t) { }
-#endif
-
-#if !HAVE(VIRTUALALLOC) && !HAVE(MADV_FREE_REUSE)
-inline void TCMalloc_SystemCommit(void*, size_t) { }
-#endif
-
-#endif /* TCMALLOC_SYSTEM_ALLOC_H__ */
diff --git a/wtf/ThreadFunctionInvocation.h b/wtf/ThreadFunctionInvocation.h
deleted file mode 100644 (file)
index f1e1472..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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
diff --git a/wtf/ThreadIdentifierDataPthreads.cpp b/wtf/ThreadIdentifierDataPthreads.cpp
deleted file mode 100644 (file)
index 042d49e..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2009 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"
-
-#if USE(PTHREADS)
-
-#include "ThreadIdentifierDataPthreads.h"
-
-#include "Threading.h"
-
-namespace WTF {
-
-pthread_key_t ThreadIdentifierData::m_key;
-
-void clearPthreadHandleForIdentifier(ThreadIdentifier);
-
-ThreadIdentifierData::~ThreadIdentifierData()
-{
-    clearPthreadHandleForIdentifier(m_identifier);
-}
-
-ThreadIdentifier ThreadIdentifierData::identifier()
-{
-    initializeKeyOnce();
-    ThreadIdentifierData* threadIdentifierData = static_cast<ThreadIdentifierData*>(pthread_getspecific(m_key));
-
-    return threadIdentifierData ? threadIdentifierData->m_identifier : 0;
-}
-
-void ThreadIdentifierData::initialize(ThreadIdentifier id)
-{
-    ASSERT(!identifier());
-
-    initializeKeyOnce();
-    pthread_setspecific(m_key, new ThreadIdentifierData(id));
-}
-
-void ThreadIdentifierData::destruct(void* data)
-{
-    ThreadIdentifierData* threadIdentifierData = static_cast<ThreadIdentifierData*>(data);
-    ASSERT(threadIdentifierData);
-
-    if (threadIdentifierData->m_isDestroyedOnce) {
-        delete threadIdentifierData;
-        return;
-    }
-
-    threadIdentifierData->m_isDestroyedOnce = true;
-    // Re-setting the value for key causes another destruct() call after all other thread-specific destructors were called.
-    pthread_setspecific(m_key, threadIdentifierData);
-}
-
-void ThreadIdentifierData::initializeKeyOnceHelper()
-{
-    if (pthread_key_create(&m_key, destruct))
-        CRASH();
-}
-
-void ThreadIdentifierData::initializeKeyOnce()
-{
-    static pthread_once_t onceControl = PTHREAD_ONCE_INIT;
-    if (pthread_once(&onceControl, initializeKeyOnceHelper))
-        CRASH();
-}
-
-} // namespace WTF
-
-#endif // USE(PTHREADS)
-
diff --git a/wtf/ThreadIdentifierDataPthreads.h b/wtf/ThreadIdentifierDataPthreads.h
deleted file mode 100644 (file)
index ed1ba2c..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2009 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 ThreadIdentifierDataPthreads_h
-#define ThreadIdentifierDataPthreads_h
-
-#include <wtf/Threading.h>
-
-namespace WTF {
-
-// Holds ThreadIdentifier in the thread-specific storage and employs pthreads-specific 2-pass destruction to reliably remove
-// ThreadIdentifier from threadMap. It assumes regular ThreadSpecific types don't use multiple-pass destruction.
-class ThreadIdentifierData {
-    WTF_MAKE_NONCOPYABLE(ThreadIdentifierData);
-public:
-    ~ThreadIdentifierData();
-
-    // Creates and puts an instance of ThreadIdentifierData into thread-specific storage.
-    static void initialize(ThreadIdentifier identifier);
-
-    // Returns 0 if thread-specific storage was not initialized.
-    static ThreadIdentifier identifier();
-
-private:
-    ThreadIdentifierData(ThreadIdentifier identifier)
-        : m_identifier(identifier)
-        , m_isDestroyedOnce(false)
-    {
-    }
-
-    // This thread-specific destructor is called 2 times when thread terminates:
-    // - first, when all the other thread-specific destructors are called, it simply remembers it was 'destroyed once'
-    // and re-sets itself into the thread-specific slot to make Pthreads to call it again later.
-    // - second, after all thread-specific destructors were invoked, it gets called again - this time, we remove the
-    // ThreadIdentifier from the threadMap, completing the cleanup.
-    static void destruct(void* data);
-
-    static void initializeKeyOnceHelper();
-    static void initializeKeyOnce();
-
-    ThreadIdentifier m_identifier;
-    bool m_isDestroyedOnce;
-    static pthread_key_t m_key;
-};
-
-} // namespace WTF
-
-#endif // ThreadIdentifierDataPthreads_h
-
-
diff --git a/wtf/ThreadSafeRefCounted.h b/wtf/ThreadSafeRefCounted.h
deleted file mode 100644 (file)
index ca11db3..0000000
+++ /dev/null
@@ -1,153 +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 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/ThreadSpecific.h b/wtf/ThreadSpecific.h
deleted file mode 100644 (file)
index 0aeee13..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Jian Li <jianli@chromium.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must 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.
- */
-
-/* Thread local storage is implemented by using either pthread API or Windows
- * native API. There is subtle semantic discrepancy for the cleanup function
- * implementation as noted below:
- *   @ In pthread implementation, the destructor function will be called
- *     repeatedly if there is still non-NULL value associated with the function.
- *   @ In Windows native implementation, the destructor function will be called
- *     only once.
- * This semantic discrepancy does not impose any problem because nowhere in
- * WebKit the repeated call bahavior is utilized.
- */
-
-#ifndef WTF_ThreadSpecific_h
-#define WTF_ThreadSpecific_h
-
-#include <wtf/Noncopyable.h>
-
-#if USE(PTHREADS)
-#include <pthread.h>
-#elif PLATFORM(QT)
-#include <QThreadStorage>
-#elif PLATFORM(GTK)
-#include <glib.h>
-#elif OS(WINDOWS)
-#include <windows.h>
-#endif
-
-namespace WTF {
-
-#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) && OS(WINDOWS)
-// ThreadSpecificThreadExit should be called each time when a thread is detached.
-// This is done automatically for threads created with WTF::createThread.
-void ThreadSpecificThreadExit();
-#endif
-
-template<typename T> class ThreadSpecific {
-    WTF_MAKE_NONCOPYABLE(ThreadSpecific);
-public:
-    ThreadSpecific();
-    T* operator->();
-    operator T*();
-    T& operator*();
-
-    void replace(T*);
-
-private:
-#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) && OS(WINDOWS)
-    friend void ThreadSpecificThreadExit();
-#endif
-
-    // Not implemented. It's technically possible to destroy a thread specific key, but one would need
-    // to make sure that all values have been destroyed already (usually, that all threads that used it
-    // have exited). It's unlikely that any user of this call will be in that situation - and having
-    // a destructor defined can be confusing, given that it has such strong pre-requisites to work correctly.
-    ~ThreadSpecific();
-    
-    T* get();
-    void set(T*);
-    void static destroy(void* ptr);
-
-#if USE(PTHREADS) || PLATFORM(QT) || 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); }
-#endif
-
-        T* value;
-        ThreadSpecific<T>* owner;
-#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK)
-        void (*destructor)(void*);
-#endif
-    };
-#endif
-
-#if ENABLE(SINGLE_THREADED)
-    T* m_value;
-#else
-#if USE(PTHREADS)
-    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
-#endif
-};
-
-#if ENABLE(SINGLE_THREADED)
-template<typename T>
-inline ThreadSpecific<T>::ThreadSpecific()
-    : m_value(0)
-{
-}
-
-template<typename T>
-inline T* ThreadSpecific<T>::get()
-{
-    return m_value;
-}
-
-template<typename T>
-inline void ThreadSpecific<T>::set(T* ptr)
-{
-    ASSERT(!get());
-    m_value = ptr;
-}
-#else
-#if USE(PTHREADS)
-template<typename T>
-inline ThreadSpecific<T>::ThreadSpecific()
-{
-    int error = pthread_key_create(&m_key, destroy);
-    if (error)
-        CRASH();
-}
-
-template<typename T>
-inline T* ThreadSpecific<T>::get()
-{
-    Data* data = static_cast<Data*>(pthread_getspecific(m_key));
-    return data ? data->value : 0;
-}
-
-template<typename T>
-inline void ThreadSpecific<T>::set(T* ptr)
-{
-    ASSERT(!get());
-    pthread_setspecific(m_key, new Data(ptr, this));
-}
-
-#elif PLATFORM(QT)
-
-template<typename T>
-inline ThreadSpecific<T>::ThreadSpecific()
-{
-}
-
-template<typename T>
-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()
-{
-    g_static_private_init(&m_key);
-}
-
-template<typename T>
-inline T* ThreadSpecific<T>::get()
-{
-    Data* data = static_cast<Data*>(g_static_private_get(&m_key));
-    return data ? data->value : 0;
-}
-
-template<typename T>
-inline void ThreadSpecific<T>::set(T* ptr)
-{
-    ASSERT(!get());
-    Data* data = new Data(ptr, this);
-    g_static_private_set(&m_key, data, destroy);
-}
-
-#elif OS(WINDOWS)
-
-// TLS_OUT_OF_INDEXES is not defined on WinCE.
-#ifndef TLS_OUT_OF_INDEXES
-#define TLS_OUT_OF_INDEXES 0xffffffff
-#endif
-
-// The maximum number of TLS keys that can be created. For simplification, we assume that:
-// 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies.
-// 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough.
-const int kMaxTlsKeySize = 256;
-
-long& tlsKeyCount();
-DWORD* tlsKeys();
-
-template<typename T>
-inline ThreadSpecific<T>::ThreadSpecific()
-    : m_index(-1)
-{
-    DWORD tlsKey = TlsAlloc();
-    if (tlsKey == TLS_OUT_OF_INDEXES)
-        CRASH();
-
-    m_index = InterlockedIncrement(&tlsKeyCount()) - 1;
-    if (m_index >= kMaxTlsKeySize)
-        CRASH();
-    tlsKeys()[m_index] = tlsKey;
-}
-
-template<typename T>
-inline ThreadSpecific<T>::~ThreadSpecific()
-{
-    // Does not invoke destructor functions. They will be called from ThreadSpecificThreadExit when the thread is detached.
-    TlsFree(tlsKeys()[m_index]);
-}
-
-template<typename T>
-inline T* ThreadSpecific<T>::get()
-{
-    Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index]));
-    return data ? data->value : 0;
-}
-
-template<typename T>
-inline void ThreadSpecific<T>::set(T* ptr)
-{
-    ASSERT(!get());
-    Data* data = new Data(ptr, this);
-    data->destructor = &ThreadSpecific<T>::destroy;
-    TlsSetValue(tlsKeys()[m_index], data);
-}
-
-#else
-#error ThreadSpecific is not implemented for this platform.
-#endif
-#endif
-
-template<typename T>
-inline void ThreadSpecific<T>::destroy(void* ptr)
-{
-#if !ENABLE(SINGLE_THREADED)
-    Data* data = static_cast<Data*>(ptr);
-
-#if USE(PTHREADS)
-    // 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
-    data->owner->m_key.setLocalData(data);
-#endif
-
-    data->value->~T();
-    fastFree(data->value);
-
-#if USE(PTHREADS)
-    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
-#error ThreadSpecific is not implemented for this platform.
-#endif
-
-#if !PLATFORM(QT)
-    delete data;
-#endif
-#endif
-}
-
-template<typename T>
-inline ThreadSpecific<T>::operator T*()
-{
-    T* ptr = static_cast<T*>(get());
-    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*>(fastZeroedMalloc(sizeof(T)));
-        set(ptr);
-        new (ptr) T;
-    }
-    return ptr;
-}
-
-template<typename T>
-inline T* ThreadSpecific<T>::operator->()
-{
-    return operator T*();
-}
-
-template<typename T>
-inline T& ThreadSpecific<T>::operator*()
-{
-    return *operator T*();
-}
-
-template<typename T>
-inline void ThreadSpecific<T>::replace(T* newPtr)
-{
-    ASSERT(newPtr);
-    Data* data = static_cast<Data*>(pthread_getspecific(m_key));
-    ASSERT(data);
-    data->value->~T();
-    fastFree(data->value);
-    data->value = newPtr;
-}
-
-}
-
-#endif
diff --git a/wtf/ThreadSpecificWin.cpp b/wtf/ThreadSpecificWin.cpp
deleted file mode 100644 (file)
index d72996a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2009 Jian Li <jianli@chromium.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.
- *
- */
-
-#include "config.h"
-
-#include "ThreadSpecific.h"
-
-#if USE(PTHREADS)
-#error This file should not be compiled by ports that do not use Windows native ThreadSpecific implementation.
-#endif
-
-namespace WTF {
-
-long& tlsKeyCount()
-{
-    static long count;
-    return count;
-}
-
-DWORD* tlsKeys()
-{
-    static DWORD keys[kMaxTlsKeySize];
-    return keys;
-}
-
-void ThreadSpecificThreadExit()
-{
-    for (long i = 0; i < tlsKeyCount(); i++) {
-        // The layout of ThreadSpecific<T>::Data does not depend on T. So we are safe to do the static cast to ThreadSpecific<int> in order to access its data member.
-        ThreadSpecific<int>::Data* data = static_cast<ThreadSpecific<int>::Data*>(TlsGetValue(tlsKeys()[i]));
-        if (data)
-            data->destructor(data);
-    }
-}
-
-} // namespace WTF
diff --git a/wtf/Threading.cpp b/wtf/Threading.cpp
deleted file mode 100644 (file)
index f2e0565..0000000
+++ /dev/null
@@ -1,100 +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 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 "Threading.h"
-
-#include <string.h>
-
-namespace WTF {
-
-struct NewThreadContext {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
-    NewThreadContext(ThreadFunction entryPoint, void* data, const char* name)
-        : entryPoint(entryPoint)
-        , data(data)
-        , name(name)
-    {
-    }
-
-    ThreadFunction entryPoint;
-    void* data;
-    const char* name;
-
-    Mutex creationMutex;
-};
-
-static void* threadEntryPoint(void* contextData)
-{
-    NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData);
-
-    // Block until our creating thread has completed any extra setup work, including
-    // establishing ThreadIdentifier.
-    {
-        MutexLocker locker(context->creationMutex);
-    }
-
-    initializeCurrentThreadInternal(context->name);
-
-    // Grab the info that we need out of the context, then deallocate it.
-    ThreadFunction entryPoint = context->entryPoint;
-    void* data = context->data;
-    delete context;
-
-    return entryPoint(data);
-}
-
-ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name)
-{
-    // Visual Studio has a 31-character limit on thread names. Longer names will
-    // be truncated silently, but we'd like callers to know about the limit.
-#if !LOG_DISABLED
-    if (strlen(name) > 31)
-        LOG_ERROR("Thread name \"%s\" is longer than 31 characters and will be truncated by Visual Studio", name);
-#endif
-
-    NewThreadContext* context = new NewThreadContext(entryPoint, data, name);
-
-    // Prevent the thread body from executing until we've established the thread identifier.
-    MutexLocker locker(context->creationMutex);
-
-    return createThreadInternal(threadEntryPoint, context, name);
-}
-
-#if PLATFORM(MAC) || PLATFORM(WIN)
-
-// This function is deprecated but needs to be kept around for backward
-// compatibility. Use the 3-argument version of createThread above.
-
-ThreadIdentifier createThread(ThreadFunction entryPoint, void* data);
-
-ThreadIdentifier createThread(ThreadFunction entryPoint, void* data)
-{
-    return createThread(entryPoint, data, 0);
-}
-#endif
-
-} // namespace WTF
diff --git a/wtf/Threading.h b/wtf/Threading.h
deleted file mode 100644 (file)
index b6f8c24..0000000
+++ /dev/null
@@ -1,118 +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 Threading_h
-#define Threading_h
-
-#include "Platform.h"
-
-#include <stdint.h>
-#include <wtf/Assertions.h>
-#include <wtf/Atomics.h>
-#include <wtf/Locker.h>
-#include <wtf/MainThread.h>
-#include <wtf/Noncopyable.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).
-#define AtomicallyInitializedStatic(T, name) \
-    WTF::lockAtomicallyInitializedStaticMutex(); \
-    static T name; \
-    WTF::unlockAtomicallyInitializedStaticMutex();
-
-namespace WTF {
-
-typedef uint32_t ThreadIdentifier;
-typedef void* (*ThreadFunction)(void* argument);
-
-// This function must be called from the main thread. It is safe to call it repeatedly.
-// Darwin is an exception to this rule: it is OK to call it from any thread, the only 
-// requirement is that the calls are not reentrant.
-void initializeThreading();
-
-// Returns 0 if thread creation failed.
-// The thread name must be a literal since on some platforms it's passed in to the thread.
-ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName);
-
-// Internal platform-specific createThread implementation.
-ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadName);
-
-// Called in the thread during initialization.
-// Helpful for platforms where the thread name must be set from within the thread.
-void initializeCurrentThreadInternal(const char* threadName);
-
-ThreadIdentifier currentThread();
-int waitForThreadCompletion(ThreadIdentifier, void**);
-void detachThread(ThreadIdentifier);
-
-void yield();
-
-void lockAtomicallyInitializedStaticMutex();
-void unlockAtomicallyInitializedStaticMutex();
-
-} // namespace WTF
-
-using WTF::ThreadIdentifier;
-using WTF::createThread;
-using WTF::currentThread;
-using WTF::detachThread;
-using WTF::waitForThreadCompletion;
-using WTF::yield;
-
-#endif // Threading_h
diff --git a/wtf/ThreadingNone.cpp b/wtf/ThreadingNone.cpp
deleted file mode 100644 (file)
index 2e8a259..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#include "config.h"
-#include "Threading.h"
-
-#if ENABLE(SINGLE_THREADED)
-
-namespace WTF {
-
-void initializeThreading() { }
-ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return ThreadIdentifier(); }
-void initializeCurrentThreadInternal(const char*) { }
-int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; }
-void detachThread(ThreadIdentifier) { }
-ThreadIdentifier currentThread() { return ThreadIdentifier(); }
-bool isMainThread() { return true; }
-
-Mutex::Mutex() { }
-Mutex::~Mutex() { }
-void Mutex::lock() { }
-bool Mutex::tryLock() { return false; }
-void Mutex::unlock() { }
-
-ThreadCondition::ThreadCondition() { }
-ThreadCondition::~ThreadCondition() { }
-void ThreadCondition::wait(Mutex&) { }
-bool ThreadCondition::timedWait(Mutex&, double) { return false; }
-void ThreadCondition::signal() { }
-void ThreadCondition::broadcast() { }
-
-void lockAtomicallyInitializedStaticMutex() { }
-void unlockAtomicallyInitializedStaticMutex() { }
-
-} // namespace WebCore
-
-#endif
diff --git a/wtf/ThreadingPrimitives.h b/wtf/ThreadingPrimitives.h
deleted file mode 100644 (file)
index 831a99e..0000000
+++ /dev/null
@@ -1,169 +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.
- *
- */
-
-#ifndef ThreadingPrimitives_h
-#define ThreadingPrimitives_h
-
-#include "Platform.h"
-
-#include <wtf/Assertions.h>
-#include <wtf/FastAllocBase.h>
-#include <wtf/Locker.h>
-#include <wtf/Noncopyable.h>
-
-#if OS(WINDOWS)
-#include <windows.h>
-#endif
-
-#if USE(PTHREADS)
-#include <pthread.h>
-#elif PLATFORM(GTK)
-#include "GOwnPtr.h"
-#endif
-
-#if PLATFORM(QT)
-#include <qglobal.h>
-QT_BEGIN_NAMESPACE
-class QMutex;
-class QWaitCondition;
-QT_END_NAMESPACE
-#endif
-
-namespace WTF {
-
-#if USE(PTHREADS)
-typedef pthread_mutex_t PlatformMutex;
-#if HAVE(PTHREAD_RWLOCK)
-typedef pthread_rwlock_t PlatformReadWriteLock;
-#else
-typedef void* PlatformReadWriteLock;
-#endif
-typedef pthread_cond_t PlatformCondition;
-#elif PLATFORM(GTK)
-typedef GOwnPtr<GMutex> PlatformMutex;
-typedef void* PlatformReadWriteLock; // FIXME: Implement.
-typedef GOwnPtr<GCond> PlatformCondition;
-#elif PLATFORM(QT)
-typedef QT_PREPEND_NAMESPACE(QMutex)* PlatformMutex;
-typedef void* PlatformReadWriteLock; // FIXME: Implement.
-typedef QT_PREPEND_NAMESPACE(QWaitCondition)* PlatformCondition;
-#elif OS(WINDOWS)
-struct PlatformMutex {
-    CRITICAL_SECTION m_internalMutex;
-    size_t m_recursionCount;
-};
-typedef void* PlatformReadWriteLock; // FIXME: Implement.
-struct PlatformCondition {
-    size_t m_waitersGone;
-    size_t m_waitersBlocked;
-    size_t m_waitersToUnblock; 
-    HANDLE m_blockLock;
-    HANDLE m_blockQueue;
-    HANDLE m_unblockLock;
-
-    bool timedWait(PlatformMutex&, DWORD durationMilliseconds);
-    void signal(bool unblockAll);
-};
-#else
-typedef void* PlatformMutex;
-typedef void* PlatformReadWriteLock;
-typedef void* PlatformCondition;
-#endif
-    
-class Mutex {
-    WTF_MAKE_NONCOPYABLE(Mutex); WTF_MAKE_FAST_ALLOCATED;
-public:
-    Mutex();
-    ~Mutex();
-
-    void lock();
-    bool tryLock();
-    void unlock();
-
-public:
-    PlatformMutex& impl() { return m_mutex; }
-private:
-    PlatformMutex m_mutex;
-};
-
-typedef Locker<Mutex> MutexLocker;
-
-class ReadWriteLock {
-    WTF_MAKE_NONCOPYABLE(ReadWriteLock);
-public:
-    ReadWriteLock();
-    ~ReadWriteLock();
-
-    void readLock();
-    bool tryReadLock();
-
-    void writeLock();
-    bool tryWriteLock();
-    
-    void unlock();
-
-private:
-    PlatformReadWriteLock m_readWriteLock;
-};
-
-class ThreadCondition {
-    WTF_MAKE_NONCOPYABLE(ThreadCondition);
-public:
-    ThreadCondition();
-    ~ThreadCondition();
-    
-    void wait(Mutex& mutex);
-    // Returns true if the condition was signaled before absoluteTime, false if the absoluteTime was reached or is in the past.
-    // The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime().
-    bool timedWait(Mutex&, double absoluteTime);
-    void signal();
-    void broadcast();
-    
-private:
-    PlatformCondition m_condition;
-};
-
-#if OS(WINDOWS)
-// The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime().
-// Returns an interval in milliseconds suitable for passing to one of the Win32 wait functions (e.g., ::WaitForSingleObject).
-DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime);
-#endif
-
-} // namespace WTF
-
-using WTF::Mutex;
-using WTF::MutexLocker;
-using WTF::ThreadCondition;
-
-#if OS(WINDOWS)
-using WTF::absoluteTimeToWaitTimeoutInterval;
-#endif
-
-#endif // ThreadingPrimitives_h
diff --git a/wtf/ThreadingPthreads.cpp b/wtf/ThreadingPthreads.cpp
deleted file mode 100644 (file)
index 916aa36..0000000
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Copyright (C) 2007, 2009 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.
- */
-
-#include "config.h"
-#include "Threading.h"
-
-#if USE(PTHREADS)
-
-#include "CurrentTime.h"
-#include "HashMap.h"
-#include "MainThread.h"
-#include "RandomNumberSeed.h"
-#include "StdLibExtras.h"
-#include "ThreadIdentifierDataPthreads.h"
-#include "ThreadSpecific.h"
-#include "UnusedParam.h"
-#include <errno.h>
-
-#if !COMPILER(MSVC)
-#include <limits.h>
-#include <sched.h>
-#include <sys/time.h>
-#endif
-
-#if OS(ANDROID)
-#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 {
-
-typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap;
-
-static Mutex* atomicallyInitializedStaticMutex;
-
-void clearPthreadHandleForIdentifier(ThreadIdentifier);
-
-static Mutex& threadMapMutex()
-{
-    DEFINE_STATIC_LOCAL(Mutex, mutex, ());
-    return mutex;
-}
-
-void initializeThreading()
-{
-    if (atomicallyInitializedStaticMutex)
-        return;
-
-    atomicallyInitializedStaticMutex = new Mutex;
-    threadMapMutex();
-    initializeRandomNumberGenerator();
-}
-
-void lockAtomicallyInitializedStaticMutex()
-{
-    ASSERT(atomicallyInitializedStaticMutex);
-    atomicallyInitializedStaticMutex->lock();
-}
-
-void unlockAtomicallyInitializedStaticMutex()
-{
-    atomicallyInitializedStaticMutex->unlock();
-}
-
-static ThreadMap& threadMap()
-{
-    DEFINE_STATIC_LOCAL(ThreadMap, map, ());
-    return map;
-}
-
-static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle)
-{
-    MutexLocker locker(threadMapMutex());
-
-    ThreadMap::iterator i = threadMap().begin();
-    for (; i != threadMap().end(); ++i) {
-        if (pthread_equal(i->second, pthreadHandle))
-            return i->first;
-    }
-
-    return 0;
-}
-
-static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle)
-{
-    ASSERT(!identifierByPthreadHandle(pthreadHandle));
-
-    MutexLocker locker(threadMapMutex());
-
-    static ThreadIdentifier identifierCount = 1;
-
-    threadMap().add(identifierCount, pthreadHandle);
-
-    return identifierCount++;
-}
-
-static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id)
-{
-    MutexLocker locker(threadMapMutex());
-
-    return threadMap().get(id);
-}
-
-void clearPthreadHandleForIdentifier(ThreadIdentifier id)
-{
-    MutexLocker locker(threadMapMutex());
-
-    ASSERT(threadMap().contains(id));
-
-    threadMap().remove(id);
-}
-
-#if OS(ANDROID)
-static void* runThreadWithRegistration(void* arg)
-{
-    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(arg));
-    JavaVM* vm = JSC::Bindings::getJavaVM();
-    JNIEnv* env;
-    void* ret = 0;
-    if (vm->AttachCurrentThread(&env, 0) == JNI_OK) {
-        ret = invocation->function(invocation->data);
-        vm->DetachCurrentThread();
-    }
-    return ret;
-}
-
-ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
-{
-    pthread_t threadHandle;
-
-    // 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);
-        return 0;
-    }
-
-    // The thread will take ownership of invocation.
-    invocation.leakPtr();
-
-    return establishIdentifierForPthreadHandle(threadHandle);
-}
-#else
-ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
-{
-    pthread_t threadHandle;
-    if (pthread_create(&threadHandle, 0, entryPoint, data)) {
-        LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
-        return 0;
-    }
-
-    return establishIdentifierForPthreadHandle(threadHandle);
-}
-#endif
-
-void initializeCurrentThreadInternal(const char* threadName)
-{
-#if HAVE(PTHREAD_SETNAME_NP)
-    pthread_setname_np(threadName);
-#else
-    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);
-}
-
-int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
-{
-    ASSERT(threadID);
-
-    pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
-    if (!pthreadHandle)
-        return 0;
-
-    int joinResult = pthread_join(pthreadHandle, result);
-    if (joinResult == EDEADLK)
-        LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
-
-    return joinResult;
-}
-
-void detachThread(ThreadIdentifier threadID)
-{
-    ASSERT(threadID);
-
-    pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID);
-    if (!pthreadHandle)
-        return;
-
-    pthread_detach(pthreadHandle);
-}
-
-void yield()
-{
-    sched_yield();
-}
-
-ThreadIdentifier currentThread()
-{
-    ThreadIdentifier id = ThreadIdentifierData::identifier();
-    if (id)
-        return id;
-
-    // Not a WTF-created thread, ThreadIdentifier is not established yet.
-    id = establishIdentifierForPthreadHandle(pthread_self());
-    ThreadIdentifierData::initialize(id);
-    return id;
-}
-
-Mutex::Mutex()
-{
-    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()
-{
-    pthread_mutex_destroy(&m_mutex);
-}
-
-void Mutex::lock()
-{
-    int result = pthread_mutex_lock(&m_mutex);
-    ASSERT_UNUSED(result, !result);
-}
-
-bool Mutex::tryLock()
-{
-    int result = pthread_mutex_trylock(&m_mutex);
-
-    if (result == 0)
-        return true;
-    if (result == EBUSY)
-        return false;
-
-    ASSERT_NOT_REACHED();
-    return false;
-}
-
-void Mutex::unlock()
-{
-    int result = pthread_mutex_unlock(&m_mutex);
-    ASSERT_UNUSED(result, !result);
-}
-
-#if HAVE(PTHREAD_RWLOCK)
-ReadWriteLock::ReadWriteLock()
-{
-    pthread_rwlock_init(&m_readWriteLock, NULL);
-}
-
-ReadWriteLock::~ReadWriteLock()
-{
-    pthread_rwlock_destroy(&m_readWriteLock);
-}
-
-void ReadWriteLock::readLock()
-{
-    int result = pthread_rwlock_rdlock(&m_readWriteLock);
-    ASSERT_UNUSED(result, !result);
-}
-
-bool ReadWriteLock::tryReadLock()
-{
-    int result = pthread_rwlock_tryrdlock(&m_readWriteLock);
-
-    if (result == 0)
-        return true;
-    if (result == EBUSY || result == EAGAIN)
-        return false;
-
-    ASSERT_NOT_REACHED();
-    return false;
-}
-
-void ReadWriteLock::writeLock()
-{
-    int result = pthread_rwlock_wrlock(&m_readWriteLock);
-    ASSERT_UNUSED(result, !result);
-}
-
-bool ReadWriteLock::tryWriteLock()
-{
-    int result = pthread_rwlock_trywrlock(&m_readWriteLock);
-
-    if (result == 0)
-        return true;
-    if (result == EBUSY || result == EAGAIN)
-        return false;
-
-    ASSERT_NOT_REACHED();
-    return false;
-}
-
-void ReadWriteLock::unlock()
-{
-    int result = pthread_rwlock_unlock(&m_readWriteLock);
-    ASSERT_UNUSED(result, !result);
-}
-#endif  // HAVE(PTHREAD_RWLOCK)
-
-ThreadCondition::ThreadCondition()
-{ 
-    pthread_cond_init(&m_condition, NULL);
-}
-
-ThreadCondition::~ThreadCondition()
-{
-    pthread_cond_destroy(&m_condition);
-}
-    
-void ThreadCondition::wait(Mutex& mutex)
-{
-    int result = pthread_cond_wait(&m_condition, &mutex.impl());
-    ASSERT_UNUSED(result, !result);
-}
-
-bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
-{
-    if (absoluteTime < currentTime())
-        return false;
-
-    if (absoluteTime > INT_MAX) {
-        wait(mutex);
-        return true;
-    }
-
-    int timeSeconds = static_cast<int>(absoluteTime);
-    int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9);
-
-    timespec targetTime;
-    targetTime.tv_sec = timeSeconds;
-    targetTime.tv_nsec = timeNanoseconds;
-
-    return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0;
-}
-
-void ThreadCondition::signal()
-{
-    int result = pthread_cond_signal(&m_condition);
-    ASSERT_UNUSED(result, !result);
-}
-
-void ThreadCondition::broadcast()
-{
-    int result = pthread_cond_broadcast(&m_condition);
-    ASSERT_UNUSED(result, !result);
-}
-
-} // namespace WTF
-
-#endif // USE(PTHREADS)
diff --git a/wtf/ThreadingWin.cpp b/wtf/ThreadingWin.cpp
deleted file mode 100644 (file)
index c452205..0000000
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Google Inc. All rights reserved.
- * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must 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.
- */
-
-/*
- * There are numerous academic and practical works on how to implement pthread_cond_wait/pthread_cond_signal/pthread_cond_broadcast
- * functions on Win32. Here is one example: http://www.cs.wustl.edu/~schmidt/win32-cv-1.html which is widely credited as a 'starting point'
- * of modern attempts. There are several more or less proven implementations, one in Boost C++ library (http://www.boost.org) and another
- * in pthreads-win32 (http://sourceware.org/pthreads-win32/).
- *
- * The number of articles and discussions is the evidence of significant difficulties in implementing these primitives correctly.
- * The brief search of revisions, ChangeLog entries, discussions in comp.programming.threads and other places clearly documents
- * numerous pitfalls and performance problems the authors had to overcome to arrive to the suitable implementations.
- * Optimally, WebKit would use one of those supported/tested libraries directly. To roll out our own implementation is impractical,
- * if even for the lack of sufficient testing. However, a faithful reproduction of the code from one of the popular supported
- * libraries seems to be a good compromise.
- *
- * The early Boost implementation (http://www.boxbackup.org/trac/browser/box/nick/win/lib/win32/boost_1_32_0/libs/thread/src/condition.cpp?rev=30)
- * is identical to pthreads-win32 (http://sourceware.org/cgi-bin/cvsweb.cgi/pthreads/pthread_cond_wait.c?rev=1.10&content-type=text/x-cvsweb-markup&cvsroot=pthreads-win32).
- * Current Boost uses yet another (although seemingly equivalent) algorithm which came from their 'thread rewrite' effort.
- *
- * This file includes timedWait/signal/broadcast implementations translated to WebKit coding style from the latest algorithm by
- * Alexander Terekhov and Louis Thomas, as captured here: http://sourceware.org/cgi-bin/cvsweb.cgi/pthreads/pthread_cond_wait.c?rev=1.10&content-type=text/x-cvsweb-markup&cvsroot=pthreads-win32
- * It replaces the implementation of their previous algorithm, also documented in the same source above.
- * The naming and comments are left very close to original to enable easy cross-check.
- *
- * The corresponding Pthreads-win32 License is included below, and CONTRIBUTORS file which it refers to is added to
- * source directory (as CONTRIBUTORS.pthreads-win32).
- */
-
-/*
- *      Pthreads-win32 - POSIX Threads Library for Win32
- *      Copyright(C) 1998 John E. Bossom
- *      Copyright(C) 1999,2005 Pthreads-win32 contributors
- *
- *      Contact Email: rpj@callisto.canberra.edu.au
- *
- *      The current list of contributors is contained
- *      in the file CONTRIBUTORS included with the source
- *      code distribution. The list can also be seen at the
- *      following World Wide Web location:
- *      http://sources.redhat.com/pthreads-win32/contributors.html
- *
- *      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 in the file COPYING.LIB;
- *      if not, write to the Free Software Foundation, Inc.,
- *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include "config.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 !OS(WINCE)
-#include <process.h>
-#endif
-
-#if HAVE(ERRNO_H)
-#include <errno.h>
-#endif
-
-namespace WTF {
-
-// MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadNameInternal all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
-static const DWORD MS_VC_EXCEPTION = 0x406D1388;
-
-#pragma pack(push, 8)
-typedef struct tagTHREADNAME_INFO {
-    DWORD dwType; // must be 0x1000
-    LPCSTR szName; // pointer to name (in user addr space)
-    DWORD dwThreadID; // thread ID (-1=caller thread)
-    DWORD dwFlags; // reserved for future use, must be zero
-} THREADNAME_INFO;
-#pragma pack(pop)
-
-void initializeCurrentThreadInternal(const char* szThreadName)
-{
-    THREADNAME_INFO info;
-    info.dwType = 0x1000;
-    info.szName = szThreadName;
-    info.dwThreadID = GetCurrentThreadId();
-    info.dwFlags = 0;
-
-    __try {
-        RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info));
-    } __except (EXCEPTION_CONTINUE_EXECUTION) {
-    }
-}
-
-static Mutex* atomicallyInitializedStaticMutex;
-
-void lockAtomicallyInitializedStaticMutex()
-{
-    ASSERT(atomicallyInitializedStaticMutex);
-    atomicallyInitializedStaticMutex->lock();
-}
-
-void unlockAtomicallyInitializedStaticMutex()
-{
-    atomicallyInitializedStaticMutex->unlock();
-}
-
-static Mutex& threadMapMutex()
-{
-    static Mutex mutex;
-    return mutex;
-}
-
-void initializeThreading()
-{
-    if (atomicallyInitializedStaticMutex)
-        return;
-
-    atomicallyInitializedStaticMutex = new Mutex;
-    threadMapMutex();
-    initializeRandomNumberGenerator();
-}
-
-static HashMap<DWORD, HANDLE>& threadMap()
-{
-    static HashMap<DWORD, HANDLE> map;
-    return map;
-}
-
-static void storeThreadHandleByIdentifier(DWORD threadID, HANDLE threadHandle)
-{
-    MutexLocker locker(threadMapMutex());
-    ASSERT(!threadMap().contains(threadID));
-    threadMap().add(threadID, threadHandle);
-}
-
-static HANDLE threadHandleForIdentifier(ThreadIdentifier id)
-{
-    MutexLocker locker(threadMapMutex());
-    return threadMap().get(id);
-}
-
-static void clearThreadHandleForIdentifier(ThreadIdentifier id)
-{
-    MutexLocker locker(threadMapMutex());
-    ASSERT(threadMap().contains(id));
-    threadMap().remove(id);
-}
-
-static unsigned __stdcall wtfThreadEntryPoint(void* param)
-{
-    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(param));
-    void* result = invocation->function(invocation->data);
-
-#if !USE(PTHREADS) && OS(WINDOWS)
-    // Do the TLS cleanup.
-    ThreadSpecificThreadExit();
-#endif
-
-    return reinterpret_cast<unsigned>(result);
-}
-
-ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char* threadName)
-{
-    unsigned threadIdentifier = 0;
-    ThreadIdentifier threadID = 0;
-    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data));
-#if OS(WINCE)
-    // This is safe on WINCE, since CRT is in the core and innately multithreaded.
-    // On desktop Windows, need to use _beginthreadex (not available on WinCE) if using any CRT functions
-    HANDLE threadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)wtfThreadEntryPoint, invocation.get(), 0, (LPDWORD)&threadIdentifier);
-#else
-    HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation.get(), 0, &threadIdentifier));
-#endif
-    if (!threadHandle) {
-#if OS(WINCE)
-        LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, ::GetLastError());
-#elif !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);
-#endif
-        return 0;
-    }
-
-    // The thread will take ownership of invocation.
-    invocation.leakPtr();
-
-    threadID = static_cast<ThreadIdentifier>(threadIdentifier);
-    storeThreadHandleByIdentifier(threadIdentifier, threadHandle);
-
-    return threadID;
-}
-
-int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
-{
-    ASSERT(threadID);
-    
-    HANDLE threadHandle = threadHandleForIdentifier(threadID);
-    if (!threadHandle)
-        LOG_ERROR("ThreadIdentifier %u did not correspond to an active thread when trying to quit", threadID);
-    DWORD joinResult = WaitForSingleObject(threadHandle, INFINITE);
-    if (joinResult == WAIT_FAILED)
-        LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);
-
-    CloseHandle(threadHandle);
-    clearThreadHandleForIdentifier(threadID);
-
-    return joinResult;
-}
-
-void detachThread(ThreadIdentifier threadID)
-{
-    ASSERT(threadID);
-
-    HANDLE threadHandle = threadHandleForIdentifier(threadID);
-    if (threadHandle)
-        CloseHandle(threadHandle);
-    clearThreadHandleForIdentifier(threadID);
-}
-
-void yield()
-{
-    ::Sleep(1);
-}
-
-ThreadIdentifier currentThread()
-{
-    return static_cast<ThreadIdentifier>(GetCurrentThreadId());
-}
-
-Mutex::Mutex()
-{
-    m_mutex.m_recursionCount = 0;
-    InitializeCriticalSection(&m_mutex.m_internalMutex);
-}
-
-Mutex::~Mutex()
-{
-    DeleteCriticalSection(&m_mutex.m_internalMutex);
-}
-
-void Mutex::lock()
-{
-    EnterCriticalSection(&m_mutex.m_internalMutex);
-    ++m_mutex.m_recursionCount;
-}
-    
-bool Mutex::tryLock()
-{
-    // This method is modeled after the behavior of pthread_mutex_trylock,
-    // which will return an error if the lock is already owned by the
-    // current thread.  Since the primitive Win32 'TryEnterCriticalSection'
-    // treats this as a successful case, it changes the behavior of several
-    // tests in WebKit that check to see if the current thread already
-    // owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord)
-    DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex);
-    
-    if (result != 0) {       // We got the lock
-        // If this thread already had the lock, we must unlock and
-        // return false so that we mimic the behavior of POSIX's
-        // pthread_mutex_trylock:
-        if (m_mutex.m_recursionCount > 0) {
-            LeaveCriticalSection(&m_mutex.m_internalMutex);
-            return false;
-        }
-
-        ++m_mutex.m_recursionCount;
-        return true;
-    }
-
-    return false;
-}
-
-void Mutex::unlock()
-{
-    --m_mutex.m_recursionCount;
-    LeaveCriticalSection(&m_mutex.m_internalMutex);
-}
-
-bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMilliseconds)
-{
-    // Enter the wait state.
-    DWORD res = WaitForSingleObject(m_blockLock, INFINITE);
-    ASSERT(res == WAIT_OBJECT_0);
-    ++m_waitersBlocked;
-    res = ReleaseSemaphore(m_blockLock, 1, 0);
-    ASSERT(res);
-
-    --mutex.m_recursionCount;
-    LeaveCriticalSection(&mutex.m_internalMutex);
-
-    // Main wait - use timeout.
-    bool timedOut = (WaitForSingleObject(m_blockQueue, durationMilliseconds) == WAIT_TIMEOUT);
-
-    res = WaitForSingleObject(m_unblockLock, INFINITE);
-    ASSERT(res == WAIT_OBJECT_0);
-
-    int signalsLeft = m_waitersToUnblock;
-
-    if (m_waitersToUnblock)
-        --m_waitersToUnblock;
-    else if (++m_waitersGone == (INT_MAX / 2)) { // timeout/canceled or spurious semaphore
-        // timeout or spurious wakeup occured, normalize the m_waitersGone count
-        // this may occur if many calls to wait with a timeout are made and
-        // no call to notify_* is made
-        res = WaitForSingleObject(m_blockLock, INFINITE);
-        ASSERT(res == WAIT_OBJECT_0);
-        m_waitersBlocked -= m_waitersGone;
-        res = ReleaseSemaphore(m_blockLock, 1, 0);
-        ASSERT(res);
-        m_waitersGone = 0;
-    }
-
-    res = ReleaseMutex(m_unblockLock);
-    ASSERT(res);
-
-    if (signalsLeft == 1) {
-        res = ReleaseSemaphore(m_blockLock, 1, 0); // Open the gate.
-        ASSERT(res);
-    }
-
-    EnterCriticalSection (&mutex.m_internalMutex);
-    ++mutex.m_recursionCount;
-
-    return !timedOut;
-}
-
-void PlatformCondition::signal(bool unblockAll)
-{
-    unsigned signalsToIssue = 0;
-
-    DWORD res = WaitForSingleObject(m_unblockLock, INFINITE);
-    ASSERT(res == WAIT_OBJECT_0);
-
-    if (m_waitersToUnblock) { // the gate is already closed
-        if (!m_waitersBlocked) { // no-op
-            res = ReleaseMutex(m_unblockLock);
-            ASSERT(res);
-            return;
-        }
-
-        if (unblockAll) {
-            signalsToIssue = m_waitersBlocked;
-            m_waitersToUnblock += m_waitersBlocked;
-            m_waitersBlocked = 0;
-        } else {
-            signalsToIssue = 1;
-            ++m_waitersToUnblock;
-            --m_waitersBlocked;
-        }
-    } else if (m_waitersBlocked > m_waitersGone) {
-        res = WaitForSingleObject(m_blockLock, INFINITE); // Close the gate.
-        ASSERT(res == WAIT_OBJECT_0);
-        if (m_waitersGone != 0) {
-            m_waitersBlocked -= m_waitersGone;
-            m_waitersGone = 0;
-        }
-        if (unblockAll) {
-            signalsToIssue = m_waitersBlocked;
-            m_waitersToUnblock = m_waitersBlocked;
-            m_waitersBlocked = 0;
-        } else {
-            signalsToIssue = 1;
-            m_waitersToUnblock = 1;
-            --m_waitersBlocked;
-        }
-    } else { // No-op.
-        res = ReleaseMutex(m_unblockLock);
-        ASSERT(res);
-        return;
-    }
-
-    res = ReleaseMutex(m_unblockLock);
-    ASSERT(res);
-
-    if (signalsToIssue) {
-        res = ReleaseSemaphore(m_blockQueue, signalsToIssue, 0);
-        ASSERT(res);
-    }
-}
-
-static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1);
-
-ThreadCondition::ThreadCondition()
-{
-    m_condition.m_waitersGone = 0;
-    m_condition.m_waitersBlocked = 0;
-    m_condition.m_waitersToUnblock = 0;
-    m_condition.m_blockLock = CreateSemaphore(0, 1, 1, 0);
-    m_condition.m_blockQueue = CreateSemaphore(0, 0, MaxSemaphoreCount, 0);
-    m_condition.m_unblockLock = CreateMutex(0, 0, 0);
-
-    if (!m_condition.m_blockLock || !m_condition.m_blockQueue || !m_condition.m_unblockLock) {
-        if (m_condition.m_blockLock)
-            CloseHandle(m_condition.m_blockLock);
-        if (m_condition.m_blockQueue)
-            CloseHandle(m_condition.m_blockQueue);
-        if (m_condition.m_unblockLock)
-            CloseHandle(m_condition.m_unblockLock);
-    }
-}
-
-ThreadCondition::~ThreadCondition()
-{
-    CloseHandle(m_condition.m_blockLock);
-    CloseHandle(m_condition.m_blockQueue);
-    CloseHandle(m_condition.m_unblockLock);
-}
-
-void ThreadCondition::wait(Mutex& mutex)
-{
-    m_condition.timedWait(mutex.impl(), INFINITE);
-}
-
-bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
-{
-    DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime);
-
-    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 m_condition.timedWait(mutex.impl(), interval);
-}
-
-void ThreadCondition::signal()
-{
-    m_condition.signal(false); // Unblock only 1 thread.
-}
-
-void ThreadCondition::broadcast()
-{
-    m_condition.signal(true); // Unblock all threads.
-}
-
-DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime)
-{
-    double currentTime = WTF::currentTime();
-
-    // Time is in the past - return immediately.
-    if (absoluteTime < currentTime)
-        return 0;
-
-    // Time is too far in the future (and would overflow unsigned long) - wait forever.
-    if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0)
-        return INFINITE;
-
-    return static_cast<DWORD>((absoluteTime - currentTime) * 1000.0);
-}
-
-} // namespace WTF
diff --git a/wtf/TypeTraits.cpp b/wtf/TypeTraits.cpp
deleted file mode 100644 (file)
index afeaa5e..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
- /*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009, 2010 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.
- *
- */
-
-#include "config.h"
-#include "TypeTraits.h"
-
-#include "Assertions.h"
-
-namespace WTF {
-
-COMPILE_ASSERT(IsInteger<bool>::value, WTF_IsInteger_bool_true);
-COMPILE_ASSERT(IsInteger<char>::value, WTF_IsInteger_char_true);
-COMPILE_ASSERT(IsInteger<signed char>::value, WTF_IsInteger_signed_char_true);
-COMPILE_ASSERT(IsInteger<unsigned char>::value, WTF_IsInteger_unsigned_char_true);
-COMPILE_ASSERT(IsInteger<short>::value, WTF_IsInteger_short_true);
-COMPILE_ASSERT(IsInteger<unsigned short>::value, WTF_IsInteger_unsigned_short_true);
-COMPILE_ASSERT(IsInteger<int>::value, WTF_IsInteger_int_true);
-COMPILE_ASSERT(IsInteger<unsigned int>::value, WTF_IsInteger_unsigned_int_true);
-COMPILE_ASSERT(IsInteger<long>::value, WTF_IsInteger_long_true);
-COMPILE_ASSERT(IsInteger<unsigned long>::value, WTF_IsInteger_unsigned_long_true);
-COMPILE_ASSERT(IsInteger<long long>::value, WTF_IsInteger_long_long_true);
-COMPILE_ASSERT(IsInteger<unsigned long long>::value, WTF_IsInteger_unsigned_long_long_true);
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-COMPILE_ASSERT(IsInteger<wchar_t>::value, WTF_IsInteger_wchar_t_true);
-#endif
-COMPILE_ASSERT(!IsInteger<char*>::value, WTF_IsInteger_char_pointer_false);
-COMPILE_ASSERT(!IsInteger<const char*>::value, WTF_IsInteger_const_char_pointer_false);
-COMPILE_ASSERT(!IsInteger<volatile char*>::value, WTF_IsInteger_volatile_char_pointer_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<unsigned char>::value, WTF_IsPod_unsigned_char_true);
-COMPILE_ASSERT(IsPod<short>::value, WTF_IsPod_short_true);
-COMPILE_ASSERT(IsPod<unsigned short>::value, WTF_IsPod_unsigned_short_true);
-COMPILE_ASSERT(IsPod<int>::value, WTF_IsPod_int_true);
-COMPILE_ASSERT(IsPod<unsigned int>::value, WTF_IsPod_unsigned_int_true);
-COMPILE_ASSERT(IsPod<long>::value, WTF_IsPod_long_true);
-COMPILE_ASSERT(IsPod<unsigned long>::value, WTF_IsPod_unsigned_long_true);
-COMPILE_ASSERT(IsPod<long long>::value, WTF_IsPod_long_long_true);
-COMPILE_ASSERT(IsPod<unsigned long long>::value, WTF_IsPod_unsigned_long_long_true);
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-COMPILE_ASSERT(IsPod<wchar_t>::value, WTF_IsPod_wchar_t_true);
-#endif
-COMPILE_ASSERT(IsPod<char*>::value, WTF_IsPod_char_pointer_true);
-COMPILE_ASSERT(IsPod<const char*>::value, WTF_IsPod_const_char_pointer_true);
-COMPILE_ASSERT(IsPod<volatile char*>::value, WTF_IsPod_volatile_char_pointer_true);
-COMPILE_ASSERT(IsPod<double>::value, WTF_IsPod_double_true);
-COMPILE_ASSERT(IsPod<long double>::value, WTF_IsPod_long_double_true);
-COMPILE_ASSERT(IsPod<float>::value, WTF_IsPod_float_true);
-COMPILE_ASSERT(!IsPod<IsPod<bool> >::value, WTF_IsPod_struct_false);
-
-enum IsConvertibleToIntegerCheck { };
-COMPILE_ASSERT(IsConvertibleToInteger<IsConvertibleToIntegerCheck>::value, WTF_IsConvertibleToInteger_enum_true);
-COMPILE_ASSERT(IsConvertibleToInteger<bool>::value, WTF_IsConvertibleToInteger_bool_true);
-COMPILE_ASSERT(IsConvertibleToInteger<char>::value, WTF_IsConvertibleToInteger_char_true);
-COMPILE_ASSERT(IsConvertibleToInteger<signed char>::value, WTF_IsConvertibleToInteger_signed_char_true);
-COMPILE_ASSERT(IsConvertibleToInteger<unsigned char>::value, WTF_IsConvertibleToInteger_unsigned_char_true);
-COMPILE_ASSERT(IsConvertibleToInteger<short>::value, WTF_IsConvertibleToInteger_short_true);
-COMPILE_ASSERT(IsConvertibleToInteger<unsigned short>::value, WTF_IsConvertibleToInteger_unsigned_short_true);
-COMPILE_ASSERT(IsConvertibleToInteger<int>::value, WTF_IsConvertibleToInteger_int_true);
-COMPILE_ASSERT(IsConvertibleToInteger<unsigned int>::value, WTF_IsConvertibleToInteger_unsigned_int_true);
-COMPILE_ASSERT(IsConvertibleToInteger<long>::value, WTF_IsConvertibleToInteger_long_true);
-COMPILE_ASSERT(IsConvertibleToInteger<unsigned long>::value, WTF_IsConvertibleToInteger_unsigned_long_true);
-COMPILE_ASSERT(IsConvertibleToInteger<long long>::value, WTF_IsConvertibleToInteger_long_long_true);
-COMPILE_ASSERT(IsConvertibleToInteger<unsigned long long>::value, WTF_IsConvertibleToInteger_unsigned_long_long_true);
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-COMPILE_ASSERT(IsConvertibleToInteger<wchar_t>::value, WTF_IsConvertibleToInteger_wchar_t_true);
-#endif
-COMPILE_ASSERT(IsConvertibleToInteger<double>::value, WTF_IsConvertibleToInteger_double_true);
-COMPILE_ASSERT(IsConvertibleToInteger<long double>::value, WTF_IsConvertibleToInteger_long_double_true);
-COMPILE_ASSERT(IsConvertibleToInteger<float>::value, WTF_IsConvertibleToInteger_float_true);
-COMPILE_ASSERT(!IsConvertibleToInteger<char*>::value, WTF_IsConvertibleToInteger_char_pointer_false);
-COMPILE_ASSERT(!IsConvertibleToInteger<const char*>::value, WTF_IsConvertibleToInteger_const_char_pointer_false);
-COMPILE_ASSERT(!IsConvertibleToInteger<volatile char*>::value, WTF_IsConvertibleToInteger_volatile_char_pointer_false);
-COMPILE_ASSERT(!IsConvertibleToInteger<IsConvertibleToInteger<bool> >::value, WTF_IsConvertibleToInteger_struct_false);
-
-COMPILE_ASSERT((IsSameType<bool, bool>::value), WTF_IsSameType_bool_true);
-COMPILE_ASSERT((IsSameType<int*, int*>::value), WTF_IsSameType_int_pointer_true);
-COMPILE_ASSERT((!IsSameType<int, int*>::value), WTF_IsSameType_int_int_pointer_false);
-COMPILE_ASSERT((!IsSameType<bool, const bool>::value), WTF_IsSameType_const_change_false);
-COMPILE_ASSERT((!IsSameType<bool, volatile bool>::value), WTF_IsSameType_volatile_change_false);
-
-template <typename T>
-class TestBaseClass {
-};
-
-class TestDerivedClass : public TestBaseClass<int> {
-};
-
-COMPILE_ASSERT((IsSubclass<TestDerivedClass, TestBaseClass<int> >::value), WTF_Test_IsSubclass_Derived_From_Base);
-COMPILE_ASSERT((!IsSubclass<TestBaseClass<int>, TestDerivedClass>::value), WTF_Test_IsSubclass_Base_From_Derived);
-COMPILE_ASSERT((IsSubclassOfTemplate<TestDerivedClass, TestBaseClass>::value), WTF_Test_IsSubclassOfTemplate_Base_From_Derived);
-COMPILE_ASSERT((IsSameType<RemoveTemplate<TestBaseClass<int>, TestBaseClass>::Type, int>::value), WTF_Test_RemoveTemplate);
-COMPILE_ASSERT((IsSameType<RemoveTemplate<int, TestBaseClass>::Type, int>::value), WTF_Test_RemoveTemplate_WithoutTemplate);
-
-
-COMPILE_ASSERT((IsSameType<bool, RemoveConst<const bool>::Type>::value), WTF_test_RemoveConst_const_bool);
-COMPILE_ASSERT((!IsSameType<bool, RemoveConst<volatile bool>::Type>::value), WTF_test_RemoveConst_volatile_bool);
-
-COMPILE_ASSERT((IsSameType<bool, RemoveVolatile<bool>::Type>::value), WTF_test_RemoveVolatile_bool);
-COMPILE_ASSERT((!IsSameType<bool, RemoveVolatile<const bool>::Type>::value), WTF_test_RemoveVolatile_const_bool);
-COMPILE_ASSERT((IsSameType<bool, RemoveVolatile<volatile bool>::Type>::value), WTF_test_RemoveVolatile_volatile_bool);
-
-COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<bool>::Type>::value), WTF_test_RemoveConstVolatile_bool);
-COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<const bool>::Type>::value), WTF_test_RemoveConstVolatile_const_bool);
-COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<volatile bool>::Type>::value), WTF_test_RemoveConstVolatile_volatile_bool);
-COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<const volatile bool>::Type>::value), WTF_test_RemoveConstVolatile_const_volatile_bool);
-
-COMPILE_ASSERT((IsSameType<int, RemovePointer<int>::Type>::value), WTF_Test_RemovePointer_int);
-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
diff --git a/wtf/TypeTraits.h b/wtf/TypeTraits.h
deleted file mode 100644 (file)
index 6c7466a..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
- /*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009, 2010 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 TypeTraits_h
-#define TypeTraits_h
-
-#include "Platform.h"
-
-#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 {
-
-    // The following are provided in this file:
-    //
-    //   IsInteger<T>::value
-    //   IsPod<T>::value, see the definition for a note about its limitations
-    //   IsConvertibleToInteger<T>::value
-    //
-    //   IsSameType<T, U>::value
-    //
-    //   RemovePointer<T>::Type
-    //   RemoveReference<T>::Type
-    //   RemoveConst<T>::Type
-    //   RemoveVolatile<T>::Type
-    //   RemoveConstVolatile<T>::Type
-    //
-    //   COMPILE_ASSERT's in TypeTraits.cpp illustrate their usage and what they do.
-
-    template<typename T> struct IsInteger           { static const bool value = false; };
-    template<> struct IsInteger<bool>               { static const bool value = true; };
-    template<> struct IsInteger<char>               { static const bool value = true; };
-    template<> struct IsInteger<signed char>        { static const bool value = true; };
-    template<> struct IsInteger<unsigned char>      { static const bool value = true; };
-    template<> struct IsInteger<short>              { static const bool value = true; };
-    template<> struct IsInteger<unsigned short>     { static const bool value = true; };
-    template<> struct IsInteger<int>                { static const bool value = true; };
-    template<> struct IsInteger<unsigned int>       { static const bool value = true; };
-    template<> struct IsInteger<long>               { static const bool value = true; };
-    template<> struct IsInteger<unsigned long>      { static const bool value = true; };
-    template<> struct IsInteger<long long>          { static const bool value = true; };
-    template<> struct IsInteger<unsigned long long> { static const bool value = true; };
-#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
-    template<> struct IsInteger<wchar_t>            { static const bool value = true; };
-#endif
-
-    template<typename T> struct IsFloatingPoint     { static const bool value = false; };
-    template<> struct IsFloatingPoint<float>        { static const bool value = true; };
-    template<> struct IsFloatingPoint<double>       { static const bool value = true; };
-    template<> struct IsFloatingPoint<long double>  { static const bool value = true; };
-
-    template<typename T> struct IsArithmetic     { static const bool value = IsInteger<T>::value || IsFloatingPoint<T>::value; };
-
-    // IsPod is misnamed as it doesn't cover all plain old data (pod) types.
-    // Specifically, it doesn't allow for enums or for structs.
-    template <typename T> struct IsPod           { static const bool value = IsArithmetic<T>::value; };
-    template <typename P> struct IsPod<P*>       { static const bool value = true; };
-
-    template<typename T> class IsConvertibleToInteger {
-        // Avoid "possible loss of data" warning when using Microsoft's C++ compiler
-        // by not converting int's to doubles.
-        template<bool performCheck, typename U> class IsConvertibleToDouble;
-        template<typename U> class IsConvertibleToDouble<false, U> {
-        public:
-            static const bool value = false;
-        };
-
-        template<typename U> class IsConvertibleToDouble<true, U> {
-            typedef char YesType;
-            struct NoType {
-                char padding[8];
-            };
-
-            static YesType floatCheck(long double);
-            static NoType floatCheck(...);
-            static T& t;
-        public:
-            static const bool value = sizeof(floatCheck(t)) == sizeof(YesType);
-        };
-
-    public:
-        static const bool value = IsInteger<T>::value || IsConvertibleToDouble<!IsInteger<T>::value, T>::value;
-    };
-
-    template <typename T, typename U> struct IsSameType {
-        static const bool value = false;
-    };
-
-    template <typename T> struct IsSameType<T, T> {
-        static const bool value = true;
-    };
-
-    template <typename T, typename U> class IsSubclass {
-        typedef char YesType;
-        struct NoType {
-            char padding[8];
-        };
-
-        static YesType subclassCheck(U*);
-        static NoType subclassCheck(...);
-        static T* t;
-    public:
-        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
-    };
-
-    template <typename T, template<class V> class U> class IsSubclassOfTemplate {
-        typedef char YesType;
-        struct NoType {
-            char padding[8];
-        };
-
-        template<typename W> static YesType subclassCheck(U<W>*);
-        static NoType subclassCheck(...);
-        static T* t;
-    public:
-        static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType);
-    };
-
-    template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate {
-        typedef T Type;
-    };
-
-    template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate<OuterTemplate<T>, OuterTemplate> {
-        typedef T Type;
-    };
-
-    template <typename T> struct RemoveConst {
-        typedef T Type;
-    };
-
-    template <typename T> struct RemoveConst<const T> {
-        typedef T Type;
-    };
-
-    template <typename T> struct RemoveVolatile {
-        typedef T Type;
-    };
-
-    template <typename T> struct RemoveVolatile<volatile T> {
-        typedef T Type;
-    };
-
-    template <typename T> struct RemoveConstVolatile {
-        typedef typename RemoveVolatile<typename RemoveConst<T>::Type>::Type Type;
-    };
-
-    template <typename T> struct RemovePointer {
-        typedef T Type;
-    };
-
-    template <typename T> struct RemovePointer<T*> {
-        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.
-    // VC10 (VS2010) and later support C++ TR1 type_traits in the std::tr1 namespace.
-    template<typename T> struct HasTrivialConstructor : public std::tr1::has_trivial_constructor<T> { };
-    template<typename T> struct HasTrivialDestructor : public std::tr1::has_trivial_destructor<T> { };
-
-#else
-
-    // This compiler doesn't provide type traits, so we provide basic HasTrivialConstructor
-    // and HasTrivialDestructor definitions. The definitions here include most built-in
-    // scalar types but do not include POD structs and classes. For the intended purposes of
-    // type_traits this results correct but potentially less efficient code.
-    template <typename T, T v>
-    struct IntegralConstant {
-        static const T value = v;
-        typedef T value_type;
-        typedef IntegralConstant<T, v> type;
-    };
-
-    typedef IntegralConstant<bool, true>  true_type;
-    typedef IntegralConstant<bool, false> false_type;
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER)
-    // VC8 (VS2005) and later have built-in compiler support for HasTrivialConstructor / HasTrivialDestructor,
-    // but for some unexplained reason it doesn't work on built-in types.
-    template <typename T> struct HasTrivialConstructor : public IntegralConstant<bool, __has_trivial_constructor(T)>{ };
-    template <typename T> struct HasTrivialDestructor : public IntegralConstant<bool, __has_trivial_destructor(T)>{ };
-#else
-    template <typename T> struct HasTrivialConstructor : public false_type{ };
-    template <typename T> struct HasTrivialDestructor : public false_type{ };
-#endif
-
-    template <typename T> struct HasTrivialConstructor<T*> : public true_type{ };
-    template <typename T> struct HasTrivialDestructor<T*> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<float> : public true_type{ };
-    template <> struct HasTrivialConstructor<const float> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile float> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile float> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<double> : public true_type{ };
-    template <> struct HasTrivialConstructor<const double> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile double> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile double> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<long double> : public true_type{ };
-    template <> struct HasTrivialConstructor<const long double> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile long double> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile long double> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<unsigned char> : public true_type{ };
-    template <> struct HasTrivialConstructor<const unsigned char> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile unsigned char> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile unsigned char> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<unsigned short> : public true_type{ };
-    template <> struct HasTrivialConstructor<const unsigned short> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile unsigned short> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile unsigned short> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<unsigned int> : public true_type{ };
-    template <> struct HasTrivialConstructor<const unsigned int> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile unsigned int> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile unsigned int> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<unsigned long> : public true_type{ };
-    template <> struct HasTrivialConstructor<const unsigned long> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile unsigned long> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile unsigned long> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<unsigned long long> : public true_type{ };
-    template <> struct HasTrivialConstructor<const unsigned long long> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile unsigned long long> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile unsigned long long> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<signed char> : public true_type{ };
-    template <> struct HasTrivialConstructor<const signed char> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile signed char> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile signed char> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<signed short> : public true_type{ };
-    template <> struct HasTrivialConstructor<const signed short> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile signed short> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile signed short> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<signed int> : public true_type{ };
-    template <> struct HasTrivialConstructor<const signed int> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile signed int> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile signed int> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<signed long> : public true_type{ };
-    template <> struct HasTrivialConstructor<const signed long> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile signed long> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile signed long> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<signed long long> : public true_type{ };
-    template <> struct HasTrivialConstructor<const signed long long> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile signed long long> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile signed long long> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<bool> : public true_type{ };
-    template <> struct HasTrivialConstructor<const bool> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile bool> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile bool> : public true_type{ };
-
-    template <> struct HasTrivialConstructor<char> : public true_type{ };
-    template <> struct HasTrivialConstructor<const char> : public true_type{ };
-    template <> struct HasTrivialConstructor<volatile char> : public true_type{ };
-    template <> struct HasTrivialConstructor<const volatile char> : public true_type{ };
-
-    #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
-        template <> struct HasTrivialConstructor<wchar_t> : public true_type{ };
-        template <> struct HasTrivialConstructor<const wchar_t> : public true_type{ };
-        template <> struct HasTrivialConstructor<volatile wchar_t> : public true_type{ };
-        template <> struct HasTrivialConstructor<const volatile wchar_t> : public true_type{ };
-    #endif
-
-    template <> struct HasTrivialDestructor<float> : public true_type{ };
-    template <> struct HasTrivialDestructor<const float> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile float> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile float> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<double> : public true_type{ };
-    template <> struct HasTrivialDestructor<const double> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile double> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile double> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<long double> : public true_type{ };
-    template <> struct HasTrivialDestructor<const long double> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile long double> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile long double> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<unsigned char> : public true_type{ };
-    template <> struct HasTrivialDestructor<const unsigned char> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile unsigned char> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile unsigned char> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<unsigned short> : public true_type{ };
-    template <> struct HasTrivialDestructor<const unsigned short> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile unsigned short> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile unsigned short> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<unsigned int> : public true_type{ };
-    template <> struct HasTrivialDestructor<const unsigned int> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile unsigned int> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile unsigned int> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<unsigned long> : public true_type{ };
-    template <> struct HasTrivialDestructor<const unsigned long> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile unsigned long> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile unsigned long> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<unsigned long long> : public true_type{ };
-    template <> struct HasTrivialDestructor<const unsigned long long> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile unsigned long long> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile unsigned long long> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<signed char> : public true_type{ };
-    template <> struct HasTrivialDestructor<const signed char> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile signed char> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile signed char> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<signed short> : public true_type{ };
-    template <> struct HasTrivialDestructor<const signed short> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile signed short> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile signed short> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<signed int> : public true_type{ };
-    template <> struct HasTrivialDestructor<const signed int> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile signed int> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile signed int> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<signed long> : public true_type{ };
-    template <> struct HasTrivialDestructor<const signed long> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile signed long> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile signed long> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<signed long long> : public true_type{ };
-    template <> struct HasTrivialDestructor<const signed long long> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile signed long long> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile signed long long> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<bool> : public true_type{ };
-    template <> struct HasTrivialDestructor<const bool> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile bool> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile bool> : public true_type{ };
-
-    template <> struct HasTrivialDestructor<char> : public true_type{ };
-    template <> struct HasTrivialDestructor<const char> : public true_type{ };
-    template <> struct HasTrivialDestructor<volatile char> : public true_type{ };
-    template <> struct HasTrivialDestructor<const volatile char> : public true_type{ };
-
-    #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
-        template <> struct HasTrivialDestructor<wchar_t> : public true_type{ };
-        template <> struct HasTrivialDestructor<const wchar_t> : public true_type{ };
-        template <> struct HasTrivialDestructor<volatile wchar_t> : public true_type{ };
-        template <> struct HasTrivialDestructor<const volatile wchar_t> : public true_type{ };
-    #endif
-
-#endif  // __GLIBCXX__, etc.
-
-} // namespace WTF
-
-#endif // TypeTraits_h
diff --git a/wtf/UnusedParam.h b/wtf/UnusedParam.h
deleted file mode 100644 (file)
index 6ff6fd8..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  Copyright (C) 2006 Apple Computer, 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_UnusedParam_h
-#define WTF_UnusedParam_h
-
-/* 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. */
-
-#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 */
diff --git a/wtf/VMTags.h b/wtf/VMTags.h
deleted file mode 100644 (file)
index 117bc37..0000000
+++ /dev/null
@@ -1,75 +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 VMTags_h
-#define VMTags_h
-
-// On Mac OS X, the VM subsystem allows tagging memory requested from mmap and vm_map
-// in order to aid tools that inspect system memory use. 
-#if OS(DARWIN)
-
-#include <mach/vm_statistics.h>
-
-#if defined(VM_MEMORY_TCMALLOC)
-#define VM_TAG_FOR_TCMALLOC_MEMORY VM_MAKE_TAG(VM_MEMORY_TCMALLOC)
-#else
-#define VM_TAG_FOR_TCMALLOC_MEMORY VM_MAKE_TAG(53)
-#endif // defined(VM_MEMORY_TCMALLOC)
-
-#if defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
-#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
-#else
-#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(64)
-#endif // defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR)
-
-#if defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE)
-#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE)
-#else
-#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(65)
-#endif // defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE)
-
-#if defined(VM_MEMORY_JAVASCRIPT_CORE)
-#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_CORE)
-#else
-#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(63)
-#endif // defined(VM_MEMORY_JAVASCRIPT_CORE)
-
-#if defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
-#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
-#else
-#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(69)
-#endif // defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS)
-
-#else // OS(DARWIN)
-
-#define VM_TAG_FOR_TCMALLOC_MEMORY -1
-#define VM_TAG_FOR_COLLECTOR_MEMORY -1
-#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1
-#define VM_TAG_FOR_REGISTERFILE_MEMORY -1
-#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY -1
-
-#endif // OS(DARWIN)
-
-#endif // VMTags_h
diff --git a/wtf/ValueCheck.h b/wtf/ValueCheck.h
deleted file mode 100644 (file)
index 2a86eb0..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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 ValueCheck_h
-#define ValueCheck_h
-
-#include <wtf/FastMalloc.h>
-
-namespace WTF {
-
-template<typename T> struct ValueCheck {
-    typedef T TraitType;
-    static void checkConsistency(const T&) { }
-};
-
-#if !ASSERT_DISABLED
-template<typename P> struct ValueCheck<P*> {
-    typedef P* TraitType;
-    static void checkConsistency(const P* p)
-    {
-        if (!p)
-            return;
-        ASSERT(fastMallocSize(p));
-        ValueCheck<P>::checkConsistency(*p);
-    }
-};
-#endif
-
-}
-
-#endif // ValueCheck_h
diff --git a/wtf/Vector.h b/wtf/Vector.h
deleted file mode 100644 (file)
index d5805cc..0000000
+++ /dev/null
@@ -1,1177 +0,0 @@
-/*
- *  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_Vector_h
-#define WTF_Vector_h
-
-#include "FastAllocBase.h"
-#include "Noncopyable.h"
-#include "NotFound.h"
-#include "StdLibExtras.h"
-#include "ValueCheck.h"
-#include "VectorTraits.h"
-#include <limits>
-#include <utility>
-#include <wtf/Alignment.h>
-
-#if PLATFORM(QT)
-#include <QDataStream>
-#endif
-
-namespace WTF {
-
-    using std::min;
-    using std::max;
-
-    #if COMPILER(GCC) && !COMPILER(INTEL) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303)
-        typedef char __attribute__((__may_alias__)) AlignedBufferChar; 
-    #else
-        typedef char AlignedBufferChar; 
-    #endif
-
-    template <size_t size, size_t alignment> struct AlignedBuffer;
-    template <size_t size> struct AlignedBuffer<size, 1> { AlignedBufferChar buffer[size]; };
-    template <size_t size> struct AlignedBuffer<size, 2> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 2);  };
-    template <size_t size> struct AlignedBuffer<size, 4> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 4);  };
-    template <size_t size> struct AlignedBuffer<size, 8> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 8);  };
-    template <size_t size> struct AlignedBuffer<size, 16> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 16); };
-    template <size_t size> struct AlignedBuffer<size, 32> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); };
-    template <size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); };
-
-    template <size_t size, size_t alignment>
-    void swap(AlignedBuffer<size, alignment>& a, AlignedBuffer<size, alignment>& b)
-    {
-        for (size_t i = 0; i < size; ++i)
-            std::swap(a.buffer[i], b.buffer[i]);
-    }
-
-    template <bool needsDestruction, typename T>
-    struct VectorDestructor;
-
-    template<typename T>
-    struct VectorDestructor<false, T>
-    {
-        static void destruct(T*, T*) {}
-    };
-
-    template<typename T>
-    struct VectorDestructor<true, T>
-    {
-        static void destruct(T* begin, T* end) 
-        {
-            for (T* cur = begin; cur != end; ++cur)
-                cur->~T();
-        }
-    };
-
-    template <bool needsInitialization, bool canInitializeWithMemset, typename T>
-    struct VectorInitializer;
-
-    template<bool ignore, typename T>
-    struct VectorInitializer<false, ignore, T>
-    {
-        static void initialize(T*, T*) {}
-    };
-
-    template<typename T>
-    struct VectorInitializer<true, false, T>
-    {
-        static void initialize(T* begin, T* end) 
-        {
-            for (T* cur = begin; cur != end; ++cur)
-                new (cur) T;
-        }
-    };
-
-    template<typename T>
-    struct VectorInitializer<true, true, T>
-    {
-        static void initialize(T* begin, T* end) 
-        {
-            memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin));
-        }
-    };
-
-    template <bool canMoveWithMemcpy, typename T>
-    struct VectorMover;
-
-    template<typename T>
-    struct VectorMover<false, T>
-    {
-        static void move(const T* src, const T* srcEnd, T* dst)
-        {
-            while (src != srcEnd) {
-                new (dst) T(*src);
-#if COMPILER(SUNCC) && __SUNPRO_CC <= 0x590
-                const_cast<T*>(src)->~T(); // Work around obscure SunCC 12 compiler bug.
-#else
-                src->~T();
-#endif
-                ++dst;
-                ++src;
-            }
-        }
-        static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
-        {
-            if (src > dst)
-                move(src, srcEnd, dst);
-            else {
-                T* dstEnd = dst + (srcEnd - src);
-                while (src != srcEnd) {
-                    --srcEnd;
-                    --dstEnd;
-                    new (dstEnd) T(*srcEnd);
-                    srcEnd->~T();
-                }
-            }
-        }
-    };
-
-    template<typename T>
-    struct VectorMover<true, T>
-    {
-        static void move(const T* src, const T* srcEnd, T* dst) 
-        {
-            memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
-        }
-        static void moveOverlapping(const T* src, const T* srcEnd, T* dst) 
-        {
-            memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
-        }
-    };
-
-    template <bool canCopyWithMemcpy, typename T>
-    struct VectorCopier;
-
-    template<typename T>
-    struct VectorCopier<false, T>
-    {
-        static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) 
-        {
-            while (src != srcEnd) {
-                new (dst) T(*src);
-                ++dst;
-                ++src;
-            }
-        }
-    };
-
-    template<typename T>
-    struct VectorCopier<true, T>
-    {
-        static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) 
-        {
-            memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
-        }
-    };
-
-    template <bool canFillWithMemset, typename T>
-    struct VectorFiller;
-
-    template<typename T>
-    struct VectorFiller<false, T>
-    {
-        static void uninitializedFill(T* dst, T* dstEnd, const T& val) 
-        {
-            while (dst != dstEnd) {
-                new (dst) T(val);
-                ++dst;
-            }
-        }
-    };
-
-    template<typename T>
-    struct VectorFiller<true, T>
-    {
-        static void uninitializedFill(T* dst, T* dstEnd, const T& val) 
-        {
-            ASSERT(sizeof(T) == sizeof(char));
-            memset(dst, val, dstEnd - dst);
-        }
-    };
-    
-    template<bool canCompareWithMemcmp, typename T>
-    struct VectorComparer;
-    
-    template<typename T>
-    struct VectorComparer<false, T>
-    {
-        static bool compare(const T* a, const T* b, size_t size)
-        {
-            for (size_t i = 0; i < size; ++i)
-                if (a[i] != b[i])
-                    return false;
-            return true;
-        }
-    };
-
-    template<typename T>
-    struct VectorComparer<true, T>
-    {
-        static bool compare(const T* a, const T* b, size_t size)
-        {
-            return memcmp(a, b, sizeof(T) * size) == 0;
-        }
-    };
-    
-    template<typename T>
-    struct VectorTypeOperations
-    {
-        static void destruct(T* begin, T* end)
-        {
-            VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
-        }
-
-        static void initialize(T* begin, T* end)
-        {
-            VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
-        }
-
-        static void move(const T* src, const T* srcEnd, T* dst)
-        {
-            VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
-        }
-
-        static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
-        {
-            VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
-        }
-
-        static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
-        {
-            VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
-        }
-
-        static void uninitializedFill(T* dst, T* dstEnd, const T& val)
-        {
-            VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
-        }
-        
-        static bool compare(const T* a, const T* b, size_t size)
-        {
-            return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size);
-        }
-    };
-
-    template<typename T>
-    class VectorBufferBase {
-        WTF_MAKE_NONCOPYABLE(VectorBufferBase);
-    public:
-        void allocateBuffer(size_t newCapacity)
-        {
-            ASSERT(newCapacity);
-            m_capacity = newCapacity;
-            if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
-                CRASH();
-            m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
-        }
-
-        bool tryAllocateBuffer(size_t newCapacity)
-        {
-            ASSERT(newCapacity);
-            if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
-                return false;
-
-            T* newBuffer;
-            if (tryFastMalloc(newCapacity * sizeof(T)).getValue(newBuffer)) {
-                m_capacity = newCapacity;
-                m_buffer = newBuffer;
-                return true;
-            }
-            return false;
-        }
-
-        void deallocateBuffer(T* bufferToDeallocate)
-        {
-            if (m_buffer == bufferToDeallocate) {
-                m_buffer = 0;
-                m_capacity = 0;
-            }
-            fastFree(bufferToDeallocate);
-        }
-
-        T* buffer() { return m_buffer; }
-        const T* buffer() const { return m_buffer; }
-        T** bufferSlot() { return &m_buffer; }
-        size_t capacity() const { return m_capacity; }
-
-        T* releaseBuffer()
-        {
-            T* buffer = m_buffer;
-            m_buffer = 0;
-            m_capacity = 0;
-            return buffer;
-        }
-
-    protected:
-        VectorBufferBase()
-            : m_buffer(0)
-            , m_capacity(0)
-        {
-        }
-
-        VectorBufferBase(T* buffer, size_t capacity)
-            : m_buffer(buffer)
-            , m_capacity(capacity)
-        {
-        }
-
-        ~VectorBufferBase()
-        {
-            // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here.
-        }
-
-        T* m_buffer;
-        size_t m_capacity;
-    };
-
-    template<typename T, size_t inlineCapacity>
-    class VectorBuffer;
-
-    template<typename T>
-    class VectorBuffer<T, 0> : private VectorBufferBase<T> {
-    private:
-        typedef VectorBufferBase<T> Base;
-    public:
-        VectorBuffer()
-        {
-        }
-
-        VectorBuffer(size_t 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()
-        {
-            deallocateBuffer(buffer());
-        }
-        
-        void swap(VectorBuffer<T, 0>& other)
-        {
-            std::swap(m_buffer, other.m_buffer);
-            std::swap(m_capacity, other.m_capacity);
-        }
-        
-        void restoreInlineBufferIfNeeded() { }
-
-        using Base::allocateBuffer;
-        using Base::tryAllocateBuffer;
-        using Base::deallocateBuffer;
-
-        using Base::buffer;
-        using Base::bufferSlot;
-        using Base::capacity;
-
-        using Base::releaseBuffer;
-    private:
-        using Base::m_buffer;
-        using Base::m_capacity;
-    };
-
-    template<typename T, size_t inlineCapacity>
-    class VectorBuffer : private VectorBufferBase<T> {
-        WTF_MAKE_NONCOPYABLE(VectorBuffer);
-    private:
-        typedef VectorBufferBase<T> Base;
-    public:
-        VectorBuffer()
-            : Base(inlineBuffer(), inlineCapacity)
-        {
-        }
-
-        VectorBuffer(size_t capacity)
-            : Base(inlineBuffer(), inlineCapacity)
-        {
-            if (capacity > inlineCapacity)
-                Base::allocateBuffer(capacity);
-        }
-
-        ~VectorBuffer()
-        {
-            deallocateBuffer(buffer());
-        }
-
-        void allocateBuffer(size_t newCapacity)
-        {
-            // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks.
-            if (newCapacity > inlineCapacity)
-                Base::allocateBuffer(newCapacity);
-            else {
-                m_buffer = inlineBuffer();
-                m_capacity = inlineCapacity;
-            }
-        }
-
-        bool tryAllocateBuffer(size_t newCapacity)
-        {
-            if (newCapacity > inlineCapacity)
-                return Base::tryAllocateBuffer(newCapacity);
-            m_buffer = inlineBuffer();
-            m_capacity = inlineCapacity;
-            return true;
-        }
-
-        void deallocateBuffer(T* bufferToDeallocate)
-        {
-            if (bufferToDeallocate == inlineBuffer())
-                return;
-            Base::deallocateBuffer(bufferToDeallocate);
-        }
-        
-        void swap(VectorBuffer<T, inlineCapacity>& other)
-        {
-            if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) {
-                WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
-                std::swap(m_capacity, other.m_capacity);
-            } else if (buffer() == inlineBuffer()) {
-                m_buffer = other.m_buffer;
-                other.m_buffer = other.inlineBuffer();
-                WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
-                std::swap(m_capacity, other.m_capacity);
-            } else if (other.buffer() == other.inlineBuffer()) {
-                other.m_buffer = m_buffer;
-                m_buffer = inlineBuffer();
-                WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
-                std::swap(m_capacity, other.m_capacity);
-            } else {
-                std::swap(m_buffer, other.m_buffer);
-                std::swap(m_capacity, other.m_capacity);
-            }
-        }
-
-        void restoreInlineBufferIfNeeded()
-        {
-            if (m_buffer)
-                return;
-            m_buffer = inlineBuffer();
-            m_capacity = inlineCapacity;
-        }
-
-        using Base::buffer;
-        using Base::bufferSlot;
-        using Base::capacity;
-
-        T* releaseBuffer()
-        {
-            if (buffer() == inlineBuffer())
-                return 0;
-            return Base::releaseBuffer();
-        }
-
-    private:
-        using Base::m_buffer;
-        using Base::m_capacity;
-
-        static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
-        T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); }
-
-        AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
-    };
-
-    template<typename T, size_t inlineCapacity = 0>
-    class Vector {
-        WTF_MAKE_FAST_ALLOCATED;
-    private:
-        typedef VectorBuffer<T, inlineCapacity> Buffer;
-        typedef VectorTypeOperations<T> TypeOperations;
-
-    public:
-        typedef T ValueType;
-
-        typedef T* iterator;
-        typedef const T* const_iterator;
-
-        Vector() 
-            : m_size(0)
-        {
-        }
-        
-        explicit Vector(size_t size) 
-            : m_size(size)
-            , m_buffer(size)
-        {
-            if (begin())
-                TypeOperations::initialize(begin(), end());
-        }
-
-        ~Vector()
-        {
-            if (m_size) shrink(0);
-        }
-
-        Vector(const Vector&);
-        template<size_t otherCapacity> 
-        Vector(const Vector<T, otherCapacity>&);
-
-        Vector& operator=(const Vector&);
-        template<size_t otherCapacity> 
-        Vector& operator=(const Vector<T, otherCapacity>&);
-
-        size_t size() const { return m_size; }
-        size_t capacity() const { return m_buffer.capacity(); }
-        bool isEmpty() const { return !size(); }
-
-        T& at(size_t i) 
-        { 
-            ASSERT(i < size());
-            return m_buffer.buffer()[i]; 
-        }
-        const T& at(size_t i) const 
-        {
-            ASSERT(i < size());
-            return m_buffer.buffer()[i]; 
-        }
-
-        T& operator[](size_t i) { return at(i); }
-        const T& operator[](size_t i) const { return at(i); }
-
-        T* data() { return m_buffer.buffer(); }
-        const T* data() const { return m_buffer.buffer(); }
-        T** dataSlot() { return m_buffer.bufferSlot(); }
-
-        iterator begin() { return data(); }
-        iterator end() { return begin() + m_size; }
-        const_iterator begin() const { return data(); }
-        const_iterator end() const { return begin() + m_size; }
-        
-        T& first() { return at(0); }
-        const T& first() const { return at(0); }
-        T& last() { return at(size() - 1); }
-        const T& last() const { return at(size() - 1); }
-
-        template<typename U> bool contains(const U&) const;
-        template<typename U> size_t find(const U&) const;
-        template<typename U> size_t reverseFind(const U&) const;
-
-        void shrink(size_t size);
-        void grow(size_t size);
-        void resize(size_t size);
-        void reserveCapacity(size_t newCapacity);
-        bool tryReserveCapacity(size_t newCapacity);
-        void reserveInitialCapacity(size_t initialCapacity);
-        void shrinkCapacity(size_t newCapacity);
-        void shrinkToFit() { shrinkCapacity(size()); }
-
-        void clear() { shrinkCapacity(0); }
-
-        template<typename U> void append(const U*, size_t);
-        template<typename U> void append(const U&);
-        template<typename U> void uncheckedAppend(const U& val);
-        template<size_t otherCapacity> void append(const Vector<T, otherCapacity>&);
-        template<typename U> bool tryAppend(const U*, size_t);
-
-        template<typename U> void insert(size_t position, const U*, size_t);
-        template<typename U> void insert(size_t position, const U&);
-        template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&);
-
-        template<typename U> void prepend(const U*, size_t);
-        template<typename U> void prepend(const U&);
-        template<typename U, size_t c> void prepend(const Vector<U, c>&);
-
-        void remove(size_t position);
-        void remove(size_t position, size_t length);
-
-        void removeLast() 
-        {
-            ASSERT(!isEmpty());
-            shrink(size() - 1); 
-        }
-
-        Vector(size_t size, const T& val)
-            : m_size(size)
-            , m_buffer(size)
-        {
-            if (begin())
-                TypeOperations::uninitializedFill(begin(), end(), val);
-        }
-
-        void fill(const T&, size_t);
-        void fill(const T& val) { fill(val, size()); }
-
-        template<typename Iterator> void appendRange(Iterator start, Iterator end);
-
-        T* releaseBuffer();
-
-        void swap(Vector<T, inlineCapacity>& other)
-        {
-            std::swap(m_size, other.m_size);
-            m_buffer.swap(other.m_buffer);
-        }
-
-        void reverse();
-
-        void checkConsistency();
-
-    private:
-        void expandCapacity(size_t newMinCapacity);
-        const T* expandCapacity(size_t newMinCapacity, const T*);
-        bool tryExpandCapacity(size_t newMinCapacity);
-        const T* tryExpandCapacity(size_t newMinCapacity, const T*);
-        template<typename U> U* expandCapacity(size_t newMinCapacity, U*); 
-
-        size_t m_size;
-        Buffer m_buffer;
-    };
-
-#if PLATFORM(QT)
-    template<typename T>
-    QDataStream& operator<<(QDataStream& stream, const Vector<T>& data)
-    {
-        stream << qint64(data.size());
-        foreach (const T& i, data)
-            stream << i;
-        return stream;
-    }
-
-    template<typename T>
-    QDataStream& operator>>(QDataStream& stream, Vector<T>& data)
-    {
-        data.clear();
-        qint64 count;
-        T item;
-        stream >> count;
-        data.reserveCapacity(count);
-        for (qint64 i = 0; i < count; ++i) {
-            stream >> item;
-            data.append(item);
-        }
-        return stream;
-    }
-#endif
-
-    template<typename T, size_t inlineCapacity>
-    Vector<T, inlineCapacity>::Vector(const Vector& other)
-        : m_size(other.size())
-        , m_buffer(other.capacity())
-    {
-        if (begin())
-            TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
-    }
-
-    template<typename T, size_t inlineCapacity>
-    template<size_t otherCapacity> 
-    Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
-        : m_size(other.size())
-        , m_buffer(other.capacity())
-    {
-        if (begin())
-            TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
-    }
-
-    template<typename T, size_t inlineCapacity>
-    Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other)
-    {
-        if (&other == this)
-            return *this;
-        
-        if (size() > other.size())
-            shrink(other.size());
-        else if (other.size() > capacity()) {
-            clear();
-            reserveCapacity(other.size());
-            if (!begin())
-                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();
-
-        return *this;
-    }
-
-    inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; }
-
-    template<typename T, size_t inlineCapacity>
-    template<size_t otherCapacity> 
-    Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
-    {
-        // If 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()) {
-            clear();
-            reserveCapacity(other.size());
-            if (!begin())
-                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();
-
-        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
-    {
-        for (size_t i = 0; i < size(); ++i) {
-            if (at(i) == value)
-                return i;
-        }
-        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)
-    {
-        if (size() > newSize)
-            shrink(newSize);
-        else if (newSize > capacity()) {
-            clear();
-            reserveCapacity(newSize);
-            if (!begin())
-                return;
-        }
-        
-        std::fill(begin(), end(), val);
-        TypeOperations::uninitializedFill(end(), begin() + newSize, val);
-        m_size = newSize;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    template<typename Iterator>
-    void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end)
-    {
-        for (Iterator it = start; it != end; ++it)
-            append(*it);
-    }
-
-    template<typename T, size_t inlineCapacity>
-    void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
-    {
-        reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
-    }
-    
-    template<typename T, size_t inlineCapacity>
-    const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr)
-    {
-        if (ptr < begin() || ptr >= end()) {
-            expandCapacity(newMinCapacity);
-            return ptr;
-        }
-        size_t index = ptr - begin();
-        expandCapacity(newMinCapacity);
-        return begin() + index;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    bool Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity)
-    {
-        return tryReserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
-    }
-    
-    template<typename T, size_t inlineCapacity>
-    const T* Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity, const T* ptr)
-    {
-        if (ptr < begin() || ptr >= end()) {
-            if (!tryExpandCapacity(newMinCapacity))
-                return 0;
-            return ptr;
-        }
-        size_t index = ptr - begin();
-        if (!tryExpandCapacity(newMinCapacity))
-            return 0;
-        return begin() + index;
-    }
-
-    template<typename T, size_t inlineCapacity> template<typename U>
-    inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr)
-    {
-        expandCapacity(newMinCapacity);
-        return ptr;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void Vector<T, inlineCapacity>::resize(size_t size)
-    {
-        if (size <= m_size)
-            TypeOperations::destruct(begin() + size, end());
-        else {
-            if (size > capacity())
-                expandCapacity(size);
-            if (begin())
-                TypeOperations::initialize(end(), begin() + size);
-        }
-        
-        m_size = size;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    void Vector<T, inlineCapacity>::shrink(size_t size)
-    {
-        ASSERT(size <= m_size);
-        TypeOperations::destruct(begin() + size, end());
-        m_size = size;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    void Vector<T, inlineCapacity>::grow(size_t size)
-    {
-        ASSERT(size >= m_size);
-        if (size > capacity())
-            expandCapacity(size);
-        if (begin())
-            TypeOperations::initialize(end(), begin() + size);
-        m_size = size;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
-    {
-        if (newCapacity <= capacity())
-            return;
-        T* oldBuffer = begin();
-        T* oldEnd = end();
-        m_buffer.allocateBuffer(newCapacity);
-        if (begin())
-            TypeOperations::move(oldBuffer, oldEnd, begin());
-        m_buffer.deallocateBuffer(oldBuffer);
-    }
-    
-    template<typename T, size_t inlineCapacity>
-    bool Vector<T, inlineCapacity>::tryReserveCapacity(size_t newCapacity)
-    {
-        if (newCapacity <= capacity())
-            return true;
-        T* oldBuffer = begin();
-        T* oldEnd = end();
-        if (!m_buffer.tryAllocateBuffer(newCapacity))
-            return false;
-        ASSERT(begin());
-        TypeOperations::move(oldBuffer, oldEnd, begin());
-        m_buffer.deallocateBuffer(oldBuffer);
-        return true;
-    }
-    
-    template<typename T, size_t inlineCapacity>
-    inline void Vector<T, inlineCapacity>::reserveInitialCapacity(size_t initialCapacity)
-    {
-        ASSERT(!m_size);
-        ASSERT(capacity() == inlineCapacity);
-        if (initialCapacity > inlineCapacity)
-            m_buffer.allocateBuffer(initialCapacity);
-    }
-    
-    template<typename T, size_t inlineCapacity>
-    void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity)
-    {
-        if (newCapacity >= capacity())
-            return;
-
-        if (newCapacity < size()) 
-            shrink(newCapacity);
-
-        T* oldBuffer = begin();
-        if (newCapacity > 0) {
-            T* oldEnd = end();
-            m_buffer.allocateBuffer(newCapacity);
-            if (begin() != oldBuffer)
-                TypeOperations::move(oldBuffer, oldEnd, begin());
-        }
-
-        m_buffer.deallocateBuffer(oldBuffer);
-        m_buffer.restoreInlineBufferIfNeeded();
-    }
-
-    // Templatizing these is better than just letting the conversion happen implicitly,
-    // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
-    // without refcount thrash.
-
-    template<typename T, size_t inlineCapacity> template<typename U>
-    void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
-    {
-        size_t newSize = m_size + dataSize;
-        if (newSize > capacity()) {
-            data = expandCapacity(newSize, data);
-            if (!begin())
-                return;
-        }
-        if (newSize < m_size)
-            CRASH();
-        T* dest = end();
-        for (size_t i = 0; i < dataSize; ++i)
-            new (&dest[i]) T(data[i]);
-        m_size = newSize;
-    }
-
-    template<typename T, size_t inlineCapacity> template<typename U>
-    bool Vector<T, inlineCapacity>::tryAppend(const U* data, size_t dataSize)
-    {
-        size_t newSize = m_size + dataSize;
-        if (newSize > capacity()) {
-            data = tryExpandCapacity(newSize, data);
-            if (!data)
-                return false;
-            ASSERT(begin());
-        }
-        if (newSize < m_size)
-            return false;
-        T* dest = end();
-        for (size_t i = 0; i < dataSize; ++i)
-            new (&dest[i]) T(data[i]);
-        m_size = newSize;
-        return true;
-    }
-
-    template<typename T, size_t inlineCapacity> template<typename U>
-    ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val)
-    {
-        const U* ptr = &val;
-        if (size() == capacity()) {
-            ptr = expandCapacity(size() + 1, ptr);
-            if (!begin())
-                return;
-        }
-            
-#if COMPILER(MSVC7_OR_LOWER)
-        // FIXME: MSVC7 generates compilation errors when trying to assign
-        // a pointer to a Vector of its base class (i.e. can't downcast). So far
-        // I've been unable to determine any logical reason for this, so I can
-        // only assume it is a bug with the compiler. Casting is a bad solution,
-        // however, because it subverts implicit conversions, so a better 
-        // one is needed. 
-        new (end()) T(static_cast<T>(*ptr));
-#else
-        new (end()) T(*ptr);
-#endif
-        ++m_size;
-    }
-
-    // This version of append saves a branch in the case where you know that the
-    // vector's capacity is large enough for the append to succeed.
-
-    template<typename T, size_t inlineCapacity> template<typename U>
-    inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val)
-    {
-        ASSERT(size() < capacity());
-        const U* ptr = &val;
-        new (end()) T(*ptr);
-        ++m_size;
-    }
-
-    // This method should not be called append, a better name would be appendElements.
-    // It could also be eliminated entirely, and call sites could just use
-    // appendRange(val.begin(), val.end()).
-    template<typename T, size_t inlineCapacity> template<size_t otherCapacity>
-    inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity>& val)
-    {
-        append(val.begin(), val.size());
-    }
-
-    template<typename T, size_t inlineCapacity> template<typename U>
-    void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize)
-    {
-        ASSERT(position <= size());
-        size_t newSize = m_size + dataSize;
-        if (newSize > capacity()) {
-            data = expandCapacity(newSize, data);
-            if (!begin())
-                return;
-        }
-        if (newSize < m_size)
-            CRASH();
-        T* spot = begin() + position;
-        TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
-        for (size_t i = 0; i < dataSize; ++i)
-            new (&spot[i]) T(data[i]);
-        m_size = newSize;
-    }
-     
-    template<typename T, size_t inlineCapacity> template<typename U>
-    inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
-    {
-        ASSERT(position <= size());
-        const U* data = &val;
-        if (size() == capacity()) {
-            data = expandCapacity(size() + 1, data);
-            if (!begin())
-                return;
-        }
-        T* spot = begin() + position;
-        TypeOperations::moveOverlapping(spot, end(), spot + 1);
-        new (spot) T(*data);
-        ++m_size;
-    }
-   
-    template<typename T, size_t inlineCapacity> template<typename U, size_t c>
-    inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val)
-    {
-        insert(position, val.begin(), val.size());
-    }
-
-    template<typename T, size_t inlineCapacity> template<typename U>
-    void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize)
-    {
-        insert(0, data, dataSize);
-    }
-
-    template<typename T, size_t inlineCapacity> template<typename U>
-    inline void Vector<T, inlineCapacity>::prepend(const U& val)
-    {
-        insert(0, val);
-    }
-   
-    template<typename T, size_t inlineCapacity> template<typename U, size_t c>
-    inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val)
-    {
-        insert(0, val.begin(), val.size());
-    }
-    
-    template<typename T, size_t inlineCapacity>
-    inline void Vector<T, inlineCapacity>::remove(size_t position)
-    {
-        ASSERT(position < size());
-        T* spot = begin() + position;
-        spot->~T();
-        TypeOperations::moveOverlapping(spot + 1, end(), spot);
-        --m_size;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length)
-    {
-        ASSERT(position < size());
-        ASSERT(position + length <= size());
-        T* beginSpot = begin() + position;
-        T* endSpot = beginSpot + length;
-        TypeOperations::destruct(beginSpot, endSpot); 
-        TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
-        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()
-    {
-        T* buffer = m_buffer.releaseBuffer();
-        if (inlineCapacity && !buffer && m_size) {
-            // If the vector had some data, but no buffer to release,
-            // that means it was using the inline buffer. In that case,
-            // we create a brand new buffer so the caller always gets one.
-            size_t bytes = m_size * sizeof(T);
-            buffer = static_cast<T*>(fastMalloc(bytes));
-            memcpy(buffer, data(), bytes);
-        }
-        m_size = 0;
-        return buffer;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void Vector<T, inlineCapacity>::checkConsistency()
-    {
-#if !ASSERT_DISABLED
-        for (size_t i = 0; i < size(); ++i)
-            ValueCheck<T>::checkConsistency(at(i));
-#endif
-    }
-
-    template<typename T, size_t inlineCapacity>
-    void deleteAllValues(const Vector<T, inlineCapacity>& collection)
-    {
-        typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
-        iterator end = collection.end();
-        for (iterator it = collection.begin(); it != end; ++it)
-            delete *it;
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
-    {
-        a.swap(b);
-    }
-
-    template<typename T, size_t inlineCapacity>
-    bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
-    {
-        if (a.size() != b.size())
-            return false;
-
-        return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
-    }
-
-    template<typename T, size_t inlineCapacity>
-    inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
-    {
-        return !(a == b);
-    }
-
-#if !ASSERT_DISABLED
-    template<typename T> struct ValueCheck<Vector<T> > {
-        typedef Vector<T> TraitType;
-        static void checkConsistency(const Vector<T>& v)
-        {
-            v.checkConsistency();
-        }
-    };
-#endif
-
-} // namespace WTF
-
-using WTF::Vector;
-
-#endif // WTF_Vector_h
diff --git a/wtf/VectorTraits.h b/wtf/VectorTraits.h
deleted file mode 100644 (file)
index 6777c9e..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 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_VectorTraits_h
-#define WTF_VectorTraits_h
-
-#include "OwnPtr.h"
-#include "RefPtr.h"
-#include "TypeTraits.h"
-#include <utility>
-#include <memory>
-
-using std::pair;
-
-namespace WTF {
-
-    template<bool isPod, typename T>
-    struct VectorTraitsBase;
-
-    template<typename T>
-    struct VectorTraitsBase<false, T>
-    {
-        static const bool needsDestruction = true;
-        static const bool needsInitialization = true;
-        static const bool canInitializeWithMemset = false;
-        static const bool canMoveWithMemcpy = false;
-        static const bool canCopyWithMemcpy = false;
-        static const bool canFillWithMemset = false;
-        static const bool canCompareWithMemcmp = false;
-    };
-
-    template<typename T>
-    struct VectorTraitsBase<true, T>
-    {
-        static const bool needsDestruction = false;
-        static const bool needsInitialization = false;
-        static const bool canInitializeWithMemset = false;
-        static const bool canMoveWithMemcpy = true;
-        static const bool canCopyWithMemcpy = true;
-        static const bool canFillWithMemset = sizeof(T) == sizeof(char);
-        static const bool canCompareWithMemcmp = true;
-    };
-
-    template<typename T>
-    struct VectorTraits : VectorTraitsBase<IsPod<T>::value, T> { };
-
-    struct SimpleClassVectorTraits : VectorTraitsBase<false, void>
-    {
-        static const bool canInitializeWithMemset = true;
-        static const bool canMoveWithMemcpy = true;
-        static const bool canCompareWithMemcmp = true;
-    };
-
-    // we know OwnPtr and RefPtr are simple enough that initializing to 0 and moving with memcpy
-    // (and then not destructing the original) will totally work
-    template<typename P>
-    struct VectorTraits<RefPtr<P> > : SimpleClassVectorTraits { };
-
-    template<typename P>
-    struct VectorTraits<OwnPtr<P> > : SimpleClassVectorTraits { };
-
-    template<typename First, typename Second>
-    struct VectorTraits<pair<First, Second> >
-    {
-        typedef VectorTraits<First> FirstTraits;
-        typedef VectorTraits<Second> SecondTraits;
-
-        static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
-        static const bool needsInitialization = FirstTraits::needsInitialization || SecondTraits::needsInitialization;
-        static const bool canInitializeWithMemset = FirstTraits::canInitializeWithMemset && SecondTraits::canInitializeWithMemset;
-        static const bool canMoveWithMemcpy = FirstTraits::canMoveWithMemcpy && SecondTraits::canMoveWithMemcpy;
-        static const bool canCopyWithMemcpy = FirstTraits::canCopyWithMemcpy && SecondTraits::canCopyWithMemcpy;
-        static const bool canFillWithMemset = false;
-        static const bool canCompareWithMemcmp = FirstTraits::canCompareWithMemcmp && SecondTraits::canCompareWithMemcmp;
-    };
-
-} // namespace WTF
-
-using WTF::VectorTraits;
-using WTF::SimpleClassVectorTraits;
-
-#endif // WTF_VectorTraits_h
diff --git a/wtf/WTFThreadData.cpp b/wtf/WTFThreadData.cpp
deleted file mode 100644 (file)
index 64624b5..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this 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 "WTFThreadData.h"
-
-namespace WTF {
-
-#if WTFTHREADDATA_MULTITHREADED
-ThreadSpecific<WTFThreadData>* WTFThreadData::staticData;
-#else
-WTFThreadData* WTFThreadData::staticData;
-#endif
-
-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;
-    else
-        m_defaultIdentifierTable = new JSC::IdentifierTable();
-
-    m_currentIdentifierTable = m_defaultIdentifierTable;
-#endif
-}
-
-WTFThreadData::~WTFThreadData()
-{
-    if (m_atomicStringTableDestructor)
-        m_atomicStringTableDestructor(m_atomicStringTable);
-#if USE(JSC)
-    delete m_defaultIdentifierTable;
-#endif
-}
-
-}
diff --git a/wtf/WTFThreadData.h b/wtf/WTFThreadData.h
deleted file mode 100644 (file)
index 243aa91..0000000
+++ /dev/null
@@ -1,170 +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 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 WTFThreadData_h
-#define WTFThreadData_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.
-// However this check was not correct anyway, re this comment:
-//    // FIXME: Workers are not necessarily the only feature that make per-thread global data necessary.
-//    // We need to check for e.g. database objects manipulating strings on secondary threads.
-// Always enabling this is safe, and should be a better option until we can come up
-// with a better define.
-#define WTFTHREADDATA_MULTITHREADED 1
-
-#if WTFTHREADDATA_MULTITHREADED
-#include <wtf/ThreadSpecific.h>
-#include <wtf/Threading.h>
-#endif
-
-#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 {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
-    ~IdentifierTable();
-
-    std::pair<HashSet<StringImpl*>::iterator, bool> add(StringImpl* value);
-    template<typename U, typename V>
-    std::pair<HashSet<StringImpl*>::iterator, bool> add(U value);
-
-    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; }
-
-private:
-    HashSet<StringImpl*> m_table;
-    LiteralIdentifierTable m_literalTable;
-};
-
-}
-#endif
-
-namespace WTF {
-
-class AtomicStringTable;
-
-typedef void (*AtomicStringTableDestructor)(AtomicStringTable*);
-
-class WTFThreadData {
-    WTF_MAKE_NONCOPYABLE(WTFThreadData);
-public:
-    WTFThreadData();
-    ~WTFThreadData();
-
-    AtomicStringTable* atomicStringTable()
-    {
-        return m_atomicStringTable;
-    }
-
-#if USE(JSC)
-    JSC::IdentifierTable* currentIdentifierTable()
-    {
-        return m_currentIdentifierTable;
-    }
-
-    JSC::IdentifierTable* setCurrentIdentifierTable(JSC::IdentifierTable* identifierTable)
-    {
-        JSC::IdentifierTable* oldIdentifierTable = m_currentIdentifierTable;
-        m_currentIdentifierTable = identifierTable;
-        return oldIdentifierTable;
-    }
-
-    void resetCurrentIdentifierTable()
-    {
-        m_currentIdentifierTable = m_defaultIdentifierTable;
-    }
-
-    const StackBounds& stack() const
-    {
-        return m_stackBounds;
-    }
-#endif
-
-private:
-    AtomicStringTable* m_atomicStringTable;
-    AtomicStringTableDestructor m_atomicStringTableDestructor;
-
-#if USE(JSC)
-    JSC::IdentifierTable* m_defaultIdentifierTable;
-    JSC::IdentifierTable* m_currentIdentifierTable;
-    StackBounds m_stackBounds;
-#endif
-
-#if WTFTHREADDATA_MULTITHREADED
-    static JS_EXPORTDATA ThreadSpecific<WTFThreadData>* staticData;
-#else
-    static JS_EXPORTDATA WTFThreadData* staticData;
-#endif
-    friend WTFThreadData& wtfThreadData();
-    friend class AtomicStringTable;
-};
-
-inline WTFThreadData& wtfThreadData()
-{
-#if WTFTHREADDATA_MULTITHREADED
-    // WRT WebCore:
-    //    WTFThreadData is used on main thread before it could possibly be used
-    //    on secondary ones, so there is no need for synchronization here.
-    // WRT JavaScriptCore:
-    //    wtfThreadData() is initially called from initializeThreading(), ensuring
-    //    this is initially called in a pthread_once locked context.
-    if (!WTFThreadData::staticData)
-        WTFThreadData::staticData = new ThreadSpecific<WTFThreadData>;
-    return **WTFThreadData::staticData;
-#else
-    if (!WTFThreadData::staticData) {
-        WTFThreadData::staticData = static_cast<WTFThreadData*>(fastMalloc(sizeof(WTFThreadData)));
-        // WTFThreadData constructor indirectly uses staticData, so we need to set up the memory before invoking it.
-        new (WTFThreadData::staticData) WTFThreadData;
-    }
-    return *WTFThreadData::staticData;
-#endif
-}
-
-} // namespace WTF
-
-using WTF::WTFThreadData;
-using WTF::wtfThreadData;
-
-#endif // WTFThreadData_h
diff --git a/wtf/android/AndroidThreading.h b/wtf/android/AndroidThreading.h
deleted file mode 100644 (file)
index 27f548c..0000000
+++ /dev/null
@@ -1,39 +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.
- */
-
-#ifndef AndroidThreading_h
-#define AndroidThreading_h
-
-namespace WTF {
-
-// An interface to the embedding layer, which provides threading support.
-class AndroidThreading {
-public:
-    static void scheduleDispatchFunctionsOnMainThread();
-};
-
-} // namespace WTF
-
-#endif // AndroidThreading_h
diff --git a/wtf/android/MainThreadAndroid.cpp b/wtf/android/MainThreadAndroid.cpp
deleted file mode 100644 (file)
index 5e5f7b1..0000000
+++ /dev/null
@@ -1,42 +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.
- */
-
-#include "config.h"
-#include "MainThread.h"
-
-#include "AndroidThreading.h"
-
-namespace WTF {
-
-void initializeMainThreadPlatform()
-{
-}
-
-void scheduleDispatchFunctionsOnMainThread()
-{
-    AndroidThreading::scheduleDispatchFunctionsOnMainThread();
-}
-
-} // namespace WTF
diff --git a/wtf/brew/MainThreadBrew.cpp b/wtf/brew/MainThreadBrew.cpp
deleted file mode 100644 (file)
index 2690ea5..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2009 Company 100, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must 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 "MainThread.h"
-
-namespace WTF {
-
-void initializeMainThreadPlatform()
-{
-    // not implemented
-}
-
-void scheduleDispatchFunctionsOnMainThread()
-{
-    // not implemented
-}
-
-} // namespace WTF
-
diff --git a/wtf/brew/OwnPtrBrew.cpp b/wtf/brew/OwnPtrBrew.cpp
deleted file mode 100644 (file)
index ce10fc3..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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 "OwnPtr.h"
-
-#include <AEEBitmap.h>
-#include <AEEFile.h>
-#include <AEEIMemGroup.h>
-#include <AEEIMemSpace.h>
-#include <AEENet.h>
-#include <AEESSL.h>
-#include <AEEStdLib.h>
-
-namespace WTF {
-
-void deleteOwnedPtr(IFileMgr* ptr)
-{
-    if (ptr)
-        IFILEMGR_Release(ptr);
-}
-
-void deleteOwnedPtr(IFile* ptr)
-{
-    if (ptr)
-        IFILE_Release(ptr);
-}
-
-void deleteOwnedPtr(IBitmap* ptr)
-{
-    if (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
deleted file mode 100644 (file)
index 40e257b..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *  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
diff --git a/wtf/brew/ShellBrew.h b/wtf/brew/ShellBrew.h
deleted file mode 100644 (file)
index 8047631..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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. 
- * 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 ShellBrew_h
-#define ShellBrew_h
-
-#include <AEEAppGen.h>
-#include <AEEStdLib.h>
-
-#include <wtf/Assertions.h>
-#include <wtf/PassOwnPtr.h>
-#include <wtf/RefPtr.h>
-
-namespace WTF {
-
-template <typename T>
-static inline PassOwnPtr<T> createInstance(AEECLSID cls)
-{
-    T* instance = 0;
-
-    IShell* shell = reinterpret_cast<AEEApplet*>(GETAPPINSTANCE())->m_pIShell;
-    ISHELL_CreateInstance(shell, cls, reinterpret_cast<void**>(&instance));
-    ASSERT(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;
-using WTF::createRefPtrInstance;
-
-#endif // ShellBrew_h
diff --git a/wtf/brew/StringBrew.cpp b/wtf/brew/StringBrew.cpp
deleted file mode 100644 (file)
index d8f2e59..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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
diff --git a/wtf/brew/SystemMallocBrew.h b/wtf/brew/SystemMallocBrew.h
deleted file mode 100644 (file)
index c973b30..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010 Company 100, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must 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 SystemMallocBrew_h
-#define SystemMallocBrew_h
-
-#include <AEEStdLib.h>
-
-static inline void* mallocBrew(size_t n)
-{
-    // By default, memory allocated using MALLOC() is initialized
-    // to zero. This behavior can be disabled by performing a bitwise
-    // OR of the flag ALLOC_NO_ZMEM with the dwSize parameter.
-    return MALLOC(n | ALLOC_NO_ZMEM);
-}
-
-static inline void* callocBrew(size_t numElements, size_t elementSize)
-{
-    return MALLOC(numElements * elementSize);
-}
-
-static inline void freeBrew(void* p)
-{
-    return FREE(p);
-}
-
-static inline void* reallocBrew(void* p, size_t n)
-{
-    return REALLOC(p, n | ALLOC_NO_ZMEM);
-}
-
-// Use MALLOC macro instead of the standard malloc function.
-// Although RVCT provides malloc, we can't use it in BREW
-// because the loader does not initialize the base address properly.
-#define malloc(n) mallocBrew(n)
-#define calloc(n, s) callocBrew(n, s)
-#define realloc(p, n) reallocBrew(p, n)
-#define free(p) freeBrew(p)
-
-#endif // SystemMallocBrew_h
diff --git a/wtf/chromium/ChromiumThreading.h b/wtf/chromium/ChromiumThreading.h
deleted file mode 100644 (file)
index 3938621..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-* Copyright (C) 2009 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 ChromiumThreading_h
-#define ChromiumThreading_h
-
-namespace WTF {
-
-// An interface to the embedding layer, which provides threading support.
-class ChromiumThreading {
-public:
-    static void callOnMainThread(void (*func)(void*), void* context);
-};
-
-} // namespace WTF
-
-#endif // ChromiumThreading_h
diff --git a/wtf/chromium/MainThreadChromium.cpp b/wtf/chromium/MainThreadChromium.cpp
deleted file mode 100644 (file)
index 9e6592b..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-* Copyright (C) 2009 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 "MainThread.h"
-
-#include "Assertions.h"
-#include "ChromiumThreading.h"
-#include "Threading.h"
-
-namespace WTF {
-
-static ThreadIdentifier mainThreadIdentifier;
-
-void initializeMainThread()
-{
-    static bool initializedMainThread;
-    if (initializedMainThread)
-        return;
-    initializedMainThread = true;
-
-    mainThreadIdentifier = currentThread();
-}
-
-void callOnMainThread(MainThreadFunction* function, void* context)
-{
-    ChromiumThreading::callOnMainThread(function, context);
-}
-
-void callOnMainThreadAndWait(MainThreadFunction*, void*)
-{
-    ASSERT_NOT_REACHED();
-}
-
-void setMainThreadCallbacksPaused(bool)
-{
-    ASSERT_NOT_REACHED();
-}
-
-bool isMainThread()
-{
-    return currentThread() == mainThreadIdentifier;
-}
-
-} // namespace WTF
-
diff --git a/wtf/dtoa.cpp b/wtf/dtoa.cpp
deleted file mode 100644 (file)
index b162543..0000000
+++ /dev/null
@@ -1,1834 +0,0 @@
-/****************************************************************
- *
- * The author of this software is David M. Gay.
- *
- * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
- * 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
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- *
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- ***************************************************************/
-
-/* 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
- * before invoking strtod or dtoa.  If the machine uses (the equivalent
- * of) Intel 80x87 arithmetic, the call
- *    _control87(PC_53, MCW_PC);
- * does this with many compilers.  Whether this or another call is
- * appropriate depends on the compiler; for this to work, it may be
- * necessary to #include "float.h" or another system-dependent header
- * file.
- */
-
-/* strtod for IEEE-arithmetic machines.
- *
- * This strtod returns a nearest machine number to the input decimal
- * string (or sets errno to ERANGE).  With IEEE arithmetic, ties are
- * broken by the IEEE round-even rule.  Otherwise ties are broken by
- * biased rounding (add half and chop).
- *
- * Inspired loosely by William D. Clinger's paper "How to Read Floating
- * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
- *
- * Modifications:
- *
- *    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
- *        much larger than 22 (the maximum integer k for which
- *        we can represent 10^k exactly), we may be able to
- *        compute (d*10^k) * 10^(e-k) with just one roundoff.
- *    3. Rather than a bit-at-a-time adjustment of the binary
- *        result in the hard case, we use floating-point
- *        arithmetic to determine the adjustment to within
- *        one bit; only in really hard cases do we need to
- *        compute a second residual.
- *    4. Because of 3., we don't need a large table of powers of 10
- *        for ten-to-e (just some small tables, e.g. of 10^k
- *        for 0 <= k <= 22).
- */
-
-#include "config.h"
-#include "dtoa.h"
-
-#if HAVE(ERRNO_H)
-#include <errno.h>
-#endif
-#include <float.h>
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wtf/AlwaysInline.h>
-#include <wtf/Assertions.h>
-#include <wtf/DecimalNumber.h>
-#include <wtf/FastMalloc.h>
-#include <wtf/MathExtras.h>
-#include <wtf/Threading.h>
-#include <wtf/UnusedParam.h>
-#include <wtf/Vector.h>
-
-#if COMPILER(MSVC)
-#pragma warning(disable: 4244)
-#pragma warning(disable: 4245)
-#pragma warning(disable: 4554)
-#endif
-
-namespace WTF {
-
-#if ENABLE(WTF_MULTIPLE_THREADS)
-Mutex* s_dtoaP5Mutex;
-#endif
-
-typedef union {
-    double d;
-    uint32_t L[2];
-} U;
-
-#if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN)
-#define word0(x) (x)->L[0]
-#define word1(x) (x)->L[1]
-#else
-#define word0(x) (x)->L[1]
-#define word1(x) (x)->L[0]
-#endif
-#define dval(x) (x)->d
-
-/* The following definition of Storeinc is appropriate for MIPS processors.
- * An alternative that might be better on some machines is
- *  *p++ = high << 16 | low & 0xffff;
- */
-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
-    p16[1] = high;
-    p16[0] = low;
-#endif
-    return p + 1;
-}
-
-#define Exp_shift  20
-#define Exp_shift1 20
-#define Exp_msk1    0x100000
-#define Exp_msk11   0x100000
-#define Exp_mask  0x7ff00000
-#define P 53
-#define Bias 1023
-#define Emin (-1022)
-#define Exp_1  0x3ff00000
-#define Exp_11 0x3ff00000
-#define Ebits 11
-#define Frac_mask  0xfffff
-#define Frac_mask1 0xfffff
-#define Ten_pmax 22
-#define Bletch 0x10
-#define Bndry_mask  0xfffff
-#define Bndry_mask1 0xfffff
-#define LSB 1
-#define Sign_bit 0x80000000
-#define Log2P 1
-#define Tiny0 0
-#define Tiny1 1
-#define Quick_max 14
-#define Int_max 14
-
-#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
-
-#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
-
-struct BigInt {
-    BigInt() : sign(0) { }
-    int sign;
-
-    void clear()
-    {
-        sign = 0;
-        m_words.clear();
-    }
-
-    size_t size() const
-    {
-        return m_words.size();
-    }
-
-    void resize(size_t s)
-    {
-        m_words.resize(s);
-    }
-
-    uint32_t* words()
-    {
-        return m_words.data();
-    }
-
-    const uint32_t* words() const
-    {
-        return m_words.data();
-    }
-
-    void append(uint32_t w)
-    {
-        m_words.append(w);
-    }
-
-    Vector<uint32_t, 16> m_words;
-};
-
-static void multadd(BigInt& b, int m, int a)    /* multiply by m and add a */
-{
-#ifdef USE_LONG_LONG
-    unsigned long long carry;
-#else
-    uint32_t carry;
-#endif
-
-    int wds = b.size();
-    uint32_t* x = b.words();
-    int i = 0;
-    carry = a;
-    do {
-#ifdef USE_LONG_LONG
-        unsigned long long y = *x * (unsigned long long)m + carry;
-        carry = y >> 32;
-        *x++ = (uint32_t)y & 0xffffffffUL;
-#else
-        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);
-#endif
-    } while (++i < wds);
-
-    if (carry)
-        b.append((uint32_t)carry);
-}
-
-static void s2b(BigInt& b, const char* s, int nd0, int nd, uint32_t y9)
-{
-    b.sign = 0;
-    b.resize(1);
-    b.words()[0] = y9;
-
-    int i = 9;
-    if (9 < nd0) {
-        s += 9;
-        do {
-            multadd(b, 10, *s++ - '0');
-        } while (++i < nd0);
-        s++;
-    } else
-        s += 10;
-    for (; i < nd; i++)
-        multadd(b, 10, *s++ - '0');
-}
-
-static int hi0bits(uint32_t x)
-{
-    int k = 0;
-
-    if (!(x & 0xffff0000)) {
-        k = 16;
-        x <<= 16;
-    }
-    if (!(x & 0xff000000)) {
-        k += 8;
-        x <<= 8;
-    }
-    if (!(x & 0xf0000000)) {
-        k += 4;
-        x <<= 4;
-    }
-    if (!(x & 0xc0000000)) {
-        k += 2;
-        x <<= 2;
-    }
-    if (!(x & 0x80000000)) {
-        k++;
-        if (!(x & 0x40000000))
-            return 32;
-    }
-    return k;
-}
-
-static int lo0bits(uint32_t* y)
-{
-    int k;
-    uint32_t x = *y;
-
-    if (x & 7) {
-        if (x & 1)
-            return 0;
-        if (x & 2) {
-            *y = x >> 1;
-            return 1;
-        }
-        *y = x >> 2;
-        return 2;
-    }
-    k = 0;
-    if (!(x & 0xffff)) {
-        k = 16;
-        x >>= 16;
-    }
-    if (!(x & 0xff)) {
-        k += 8;
-        x >>= 8;
-    }
-    if (!(x & 0xf)) {
-        k += 4;
-        x >>= 4;
-    }
-    if (!(x & 0x3)) {
-        k += 2;
-        x >>= 2;
-    }
-    if (!(x & 1)) {
-        k++;
-        x >>= 1;
-        if (!x)
-            return 32;
-    }
-    *y = x;
-    return k;
-}
-
-static void i2b(BigInt& b, int i)
-{
-    b.sign = 0;
-    b.resize(1);
-    b.words()[0] = i;
-}
-
-static void mult(BigInt& aRef, const BigInt& bRef)
-{
-    const BigInt* a = &aRef;
-    const BigInt* b = &bRef;
-    BigInt c;
-    int wa, wb, wc;
-    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;
-#else
-    uint32_t carry, z;
-#endif
-
-    if (a->size() < b->size()) {
-        const BigInt* tmp = a;
-        a = b;
-        b = tmp;
-    }
-
-    wa = a->size();
-    wb = b->size();
-    wc = wa + wb;
-    c.resize(wc);
-
-    for (xc = c.words(), xa = xc + wc; xc < xa; xc++)
-        *xc = 0;
-    xa = a->words();
-    xae = xa + wa;
-    xb = b->words();
-    xbe = xb + wb;
-    xc0 = c.words();
-#ifdef USE_LONG_LONG
-    for (; xb < xbe; xc0++) {
-        if ((y = *xb++)) {
-            x = xa;
-            xc = xc0;
-            carry = 0;
-            do {
-                z = *x++ * (unsigned long long)y + *xc + carry;
-                carry = z >> 32;
-                *xc++ = (uint32_t)z & 0xffffffffUL;
-            } while (x < xae);
-            *xc = (uint32_t)carry;
-        }
-    }
-#else
-    for (; xb < xbe; xb++, xc0++) {
-        if ((y = *xb & 0xffff)) {
-            x = xa;
-            xc = xc0;
-            carry = 0;
-            do {
-                z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
-                carry = z >> 16;
-                uint32_t z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
-                carry = z2 >> 16;
-                xc = storeInc(xc, z2, z);
-            } while (x < xae);
-            *xc = carry;
-        }
-        if ((y = *xb >> 16)) {
-            x = xa;
-            xc = xc0;
-            carry = 0;
-            uint32_t z2 = *xc;
-            do {
-                z = (*x & 0xffff) * y + (*xc >> 16) + carry;
-                carry = z >> 16;
-                xc = storeInc(xc, z, z2);
-                z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
-                carry = z2 >> 16;
-            } while (x < xae);
-            *xc = z2;
-        }
-    }
-#endif
-    for (xc0 = c.words(), xc = xc0 + wc; wc > 0 && !*--xc; --wc) { }
-    c.resize(wc);
-    aRef = c;
-}
-
-struct P5Node {
-    WTF_MAKE_NONCOPYABLE(P5Node); WTF_MAKE_FAST_ALLOCATED;
-public:
-    P5Node() { }
-    BigInt val;
-    P5Node* next;
-};
-
-static P5Node* p5s;
-static int p5sCount;
-
-static ALWAYS_INLINE void pow5mult(BigInt& b, int k)
-{
-    static int p05[3] = { 5, 25, 125 };
-
-    if (int i = k & 3)
-        multadd(b, p05[i - 1], 0);
-
-    if (!(k >>= 2))
-        return;
-
-#if ENABLE(WTF_MULTIPLE_THREADS)
-    s_dtoaP5Mutex->lock();
-#endif
-    P5Node* p5 = p5s;
-
-    if (!p5) {
-        /* first time */
-        p5 = new P5Node;
-        i2b(p5->val, 625);
-        p5->next = 0;
-        p5s = p5;
-        p5sCount = 1;
-    }
-
-    int p5sCountLocal = p5sCount;
-#if ENABLE(WTF_MULTIPLE_THREADS)
-    s_dtoaP5Mutex->unlock();
-#endif
-    int p5sUsed = 0;
-
-    for (;;) {
-        if (k & 1)
-            mult(b, p5->val);
-
-        if (!(k >>= 1))
-            break;
-
-        if (++p5sUsed == p5sCountLocal) {
-#if ENABLE(WTF_MULTIPLE_THREADS)
-            s_dtoaP5Mutex->lock();
-#endif
-            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);
-                ++p5sCount;
-            }
-
-            p5sCountLocal = p5sCount;
-#if ENABLE(WTF_MULTIPLE_THREADS)
-            s_dtoaP5Mutex->unlock();
-#endif
-        }
-        p5 = p5->next;
-    }
-}
-
-static ALWAYS_INLINE void lshift(BigInt& b, int k)
-{
-    int n = k >> 5;
-
-    int origSize = b.size();
-    int n1 = n + origSize + 1;
-
-    if (k &= 0x1f)
-        b.resize(b.size() + n + 1);
-    else
-        b.resize(b.size() + n);
-
-    const uint32_t* srcStart = b.words();
-    uint32_t* dstStart = b.words();
-    const uint32_t* src = srcStart + origSize - 1;
-    uint32_t* dst = dstStart + n1 - 1;
-    if (k) {
-        uint32_t hiSubword = 0;
-        int s = 32 - k;
-        for (; src >= srcStart; --src) {
-            *dst-- = hiSubword | *src >> s;
-            hiSubword = *src << k;
-        }
-        *dst = hiSubword;
-        ASSERT(dst == dstStart + n);
-
-        b.resize(origSize + n + !!b.words()[n1 - 1]);
-    }
-    else {
-        do {
-            *--dst = *src--;
-        } while (src >= srcStart);
-    }
-    for (dst = dstStart + n; dst != dstStart; )
-        *--dst = 0;
-
-    ASSERT(b.size() <= 1 || b.words()[b.size() - 1]);
-}
-
-static int cmp(const BigInt& a, const BigInt& b)
-{
-    const uint32_t *xa, *xa0, *xb, *xb0;
-    int i, j;
-
-    i = a.size();
-    j = b.size();
-    ASSERT(i <= 1 || a.words()[i - 1]);
-    ASSERT(j <= 1 || b.words()[j - 1]);
-    if (i -= j)
-        return i;
-    xa0 = a.words();
-    xa = xa0 + j;
-    xb0 = b.words();
-    xb = xb0 + j;
-    for (;;) {
-        if (*--xa != *--xb)
-            return *xa < *xb ? -1 : 1;
-        if (xa <= xa0)
-            break;
-    }
-    return 0;
-}
-
-static ALWAYS_INLINE void diff(BigInt& c, const BigInt& aRef, const BigInt& bRef)
-{
-    const BigInt* a = &aRef;
-    const BigInt* b = &bRef;
-    int i, wa, wb;
-    uint32_t* xc;
-
-    i = cmp(*a, *b);
-    if (!i) {
-        c.sign = 0;
-        c.resize(1);
-        c.words()[0] = 0;
-        return;
-    }
-    if (i < 0) {
-        const BigInt* tmp = a;
-        a = b;
-        b = tmp;
-        i = 1;
-    } else
-        i = 0;
-
-    wa = a->size();
-    const uint32_t* xa = a->words();
-    const uint32_t* xae = xa + wa;
-    wb = b->size();
-    const uint32_t* xb = b->words();
-    const uint32_t* xbe = xb + wb;
-
-    c.resize(wa);
-    c.sign = i;
-    xc = c.words();
-#ifdef USE_LONG_LONG
-    unsigned long long borrow = 0;
-    do {
-        unsigned long long y = (unsigned long long)*xa++ - *xb++ - borrow;
-        borrow = y >> 32 & (uint32_t)1;
-        *xc++ = (uint32_t)y & 0xffffffffUL;
-    } while (xb < xbe);
-    while (xa < xae) {
-        unsigned long long y = *xa++ - borrow;
-        borrow = y >> 32 & (uint32_t)1;
-        *xc++ = (uint32_t)y & 0xffffffffUL;
-    }
-#else
-    uint32_t borrow = 0;
-    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;
-        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;
-        xc = storeInc(xc, z, y);
-    }
-#endif
-    while (!*--xc)
-        wa--;
-    c.resize(wa);
-}
-
-static double ulp(U *x)
-{
-    register int32_t L;
-    U u;
-
-    L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1;
-        word0(&u) = L;
-        word1(&u) = 0;
-    return dval(&u);
-}
-
-static double b2d(const BigInt& a, int* e)
-{
-    const uint32_t* xa;
-    const uint32_t* xa0;
-    uint32_t w;
-    uint32_t y;
-    uint32_t z;
-    int k;
-    U d;
-
-#define d0 word0(&d)
-#define d1 word1(&d)
-
-    xa0 = a.words();
-    xa = xa0 + a.size();
-    y = *--xa;
-    ASSERT(y);
-    k = hi0bits(y);
-    *e = 32 - k;
-    if (k < Ebits) {
-        d0 = Exp_1 | (y >> (Ebits - k));
-        w = xa > xa0 ? *--xa : 0;
-        d1 = (y << (32 - Ebits + k)) | (w >> (Ebits - k));
-        goto returnD;
-    }
-    z = xa > xa0 ? *--xa : 0;
-    if (k -= Ebits) {
-        d0 = Exp_1 | (y << k) | (z >> (32 - k));
-        y = xa > xa0 ? *--xa : 0;
-        d1 = (z << k) | (y >> (32 - k));
-    } else {
-        d0 = Exp_1 | y;
-        d1 = z;
-    }
-returnD:
-#undef d0
-#undef d1
-    return dval(&d);
-}
-
-static ALWAYS_INLINE void d2b(BigInt& b, U* d, int* e, int* bits)
-{
-    int de, k;
-    uint32_t* x;
-    uint32_t y, z;
-    int i;
-#define d0 word0(d)
-#define d1 word1(d)
-
-    b.sign = 0;
-    b.resize(1);
-    x = b.words();
-
-    z = d0 & Frac_mask;
-    d0 &= 0x7fffffff;    /* clear sign bit, which we ignore */
-    if ((de = (int)(d0 >> Exp_shift)))
-        z |= Exp_msk1;
-    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;
-        }
-
-        i = b.size();
-    } else {
-        k = lo0bits(&z);
-        x[0] = z;
-        i = 1;
-        b.resize(1);
-        k += 32;
-    }
-    if (de) {
-        *e = de - Bias - (P - 1) + k;
-        *bits = P - k;
-    } else {
-        *e = de - Bias - (P - 1) + 1 + k;
-        *bits = (32 * i) - hi0bits(x[i - 1]);
-    }
-}
-#undef d0
-#undef d1
-
-static double ratio(const BigInt& a, const BigInt& b)
-{
-    U da, db;
-    int k, ka, kb;
-
-    dval(&da) = b2d(a, &ka);
-    dval(&db) = b2d(b, &kb);
-    k = ka - kb + 32 * (a.size() - b.size());
-    if (k > 0)
-        word0(&da) += k * Exp_msk1;
-    else {
-        k = -k;
-        word0(&db) += k * Exp_msk1;
-    }
-    return dval(&da) / dval(&db);
-}
-
-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
-};
-
-static const double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
-static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
-    9007199254740992. * 9007199254740992.e-256
-    /* = 2^106 * 1e-256 */
-};
-
-/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
-/* flag unnecessarily.  It leads to a song and dance at the end of strtod. */
-#define Scale_Bit 0x10
-#define n_bigtens 5
-
-double strtod(const char* s00, char** se)
-{
-    int scale;
-    int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
-        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;
-
-    sign = nz0 = nz = 0;
-    dval(&rv) = 0;
-    for (s = s00; ; s++) {
-        switch (*s) {
-        case '-':
-            sign = 1;
-            /* no break */
-        case '+':
-            if (*++s)
-                goto break2;
-            /* no break */
-        case 0:
-            goto ret0;
-        case '\t':
-        case '\n':
-        case '\v':
-        case '\f':
-        case '\r':
-        case ' ':
-            continue;
-        default:
-            goto break2;
-        }
-    }
-break2:
-    if (*s == '0') {
-        nz0 = 1;
-        while (*++s == '0') { }
-        if (!*s)
-            goto ret;
-    }
-    s0 = s;
-    y = z = 0;
-    for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
-        if (nd < 9)
-            y = (10 * y) + c - '0';
-        else if (nd < 16)
-            z = (10 * z) + c - '0';
-    nd0 = nd;
-    if (c == '.') {
-        c = *++s;
-        if (!nd) {
-            for (; c == '0'; c = *++s)
-                nz++;
-            if (c > '0' && c <= '9') {
-                s0 = s;
-                nf += nz;
-                nz = 0;
-                goto haveDig;
-            }
-            goto digDone;
-        }
-        for (; c >= '0' && c <= '9'; c = *++s) {
-haveDig:
-            nz++;
-            if (c -= '0') {
-                nf += nz;
-                for (i = 1; i < nz; i++)
-                    if (nd++ < 9)
-                        y *= 10;
-                    else if (nd <= DBL_DIG + 1)
-                        z *= 10;
-                if (nd++ < 9)
-                    y = (10 * y) + c;
-                else if (nd <= DBL_DIG + 1)
-                    z = (10 * z) + c;
-                nz = 0;
-            }
-        }
-    }
-digDone:
-    e = 0;
-    if (c == 'e' || c == 'E') {
-        if (!nd && !nz && !nz0)
-            goto ret0;
-        s00 = s;
-        esign = 0;
-        switch (c = *++s) {
-        case '-':
-            esign = 1;
-        case '+':
-            c = *++s;
-        }
-        if (c >= '0' && c <= '9') {
-            while (c == '0')
-                c = *++s;
-            if (c > '0' && c <= '9') {
-                L = c - '0';
-                s1 = s;
-                while ((c = *++s) >= '0' && c <= '9')
-                    L = (10 * L) + c - '0';
-                if (s - s1 > 8 || L > 19999)
-                    /* Avoid confusion from exponents
-                     * so large that e might overflow.
-                     */
-                    e = 19999; /* safe for 16 bit ints */
-                else
-                    e = (int)L;
-                if (esign)
-                    e = -e;
-            } else
-                e = 0;
-        } else
-            s = s00;
-    }
-    if (!nd) {
-        if (!nz && !nz0) {
-ret0:
-            s = s00;
-            sign = 0;
-        }
-        goto ret;
-    }
-    e1 = e -= nf;
-
-    /* Now we have nd0 digits, starting at s0, followed by a
-     * decimal point, followed by nd-nd0 digits.  The number we're
-     * after is the integer represented by those digits times
-     * 10**e */
-
-    if (!nd0)
-        nd0 = nd;
-    k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
-    dval(&rv) = y;
-    if (k > 9)
-        dval(&rv) = tens[k - 9] * dval(&rv) + z;
-    if (nd <= DBL_DIG) {
-        if (!e)
-            goto ret;
-        if (e > 0) {
-            if (e <= Ten_pmax) {
-                /* rv = */ rounded_product(dval(&rv), tens[e]);
-                goto ret;
-            }
-            i = DBL_DIG - nd;
-            if (e <= Ten_pmax + i) {
-                /* A fancier test would sometimes let us do
-                 * this for larger i values.
-                 */
-                e -= i;
-                dval(&rv) *= tens[i];
-                /* rv = */ rounded_product(dval(&rv), tens[e]);
-                goto ret;
-            }
-        } else if (e >= -Ten_pmax) {
-            /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
-            goto ret;
-        }
-    }
-    e1 += nd - k;
-
-    scale = 0;
-
-    /* Get starting approximation = rv * 10**e1 */
-
-    if (e1 > 0) {
-        if ((i = e1 & 15))
-            dval(&rv) *= tens[i];
-        if (e1 &= ~15) {
-            if (e1 > DBL_MAX_10_EXP) {
-ovfl:
-#if HAVE(ERRNO_H)
-                errno = ERANGE;
-#endif
-                /* Can't trust HUGE_VAL */
-                word0(&rv) = Exp_mask;
-                word1(&rv) = 0;
-                goto ret;
-            }
-            e1 >>= 4;
-            for (j = 0; e1 > 1; j++, e1 >>= 1)
-                if (e1 & 1)
-                    dval(&rv) *= bigtens[j];
-        /* The last multiplication could overflow. */
-            word0(&rv) -= P * Exp_msk1;
-            dval(&rv) *= bigtens[j];
-            if ((z = word0(&rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P))
-                goto ovfl;
-            if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) {
-                /* set to largest number */
-                /* (Can't trust DBL_MAX) */
-                word0(&rv) = Big0;
-                word1(&rv) = Big1;
-            } else
-                word0(&rv) += P * Exp_msk1;
-        }
-    } else if (e1 < 0) {
-        e1 = -e1;
-        if ((i = e1 & 15))
-            dval(&rv) /= tens[i];
-        if (e1 >>= 4) {
-            if (e1 >= 1 << n_bigtens)
-                goto undfl;
-            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; clear j low bits */
-                if (j >= 32) {
-                    word1(&rv) = 0;
-                    if (j >= 53)
-                        word0(&rv) = (P + 2) * Exp_msk1;
-                    else
-                        word0(&rv) &= 0xffffffff << (j - 32);
-                } else
-                    word1(&rv) &= 0xffffffff << j;
-            }
-                if (!dval(&rv)) {
-undfl:
-                    dval(&rv) = 0.;
-#if HAVE(ERRNO_H)
-                    errno = ERANGE;
-#endif
-                    goto ret;
-                }
-        }
-    }
-
-    /* Now the hard part -- adjusting rv to the correct value.*/
-
-    /* Put digits into bd: true value = bd * 10^e */
-
-    s2b(bd0, s0, nd0, nd, y);
-
-    for (;;) {
-        bd = bd0;
-        d2b(bb, &rv, &bbe, &bbbits);    /* rv = bb * 2^bbe */
-        i2b(bs, 1);
-
-        if (e >= 0) {
-            bb2 = bb5 = 0;
-            bd2 = bd5 = e;
-        } else {
-            bb2 = bb5 = -e;
-            bd2 = bd5 = 0;
-        }
-        if (bbe >= 0)
-            bb2 += bbe;
-        else
-            bd2 -= bbe;
-        bs2 = bb2;
-        j = bbe - scale;
-        i = j + bbbits - 1;    /* logb(rv) */
-        if (i < Emin)    /* denormal */
-            j += P - Emin;
-        else
-            j = P + 1 - bbbits;
-        bb2 += j;
-        bd2 += j;
-        bd2 += scale;
-        i = bb2 < bd2 ? bb2 : bd2;
-        if (i > bs2)
-            i = bs2;
-        if (i > 0) {
-            bb2 -= i;
-            bd2 -= i;
-            bs2 -= i;
-        }
-        if (bb5 > 0) {
-            pow5mult(bs, bb5);
-            mult(bb, bs);
-        }
-        if (bb2 > 0)
-            lshift(bb, bb2);
-        if (bd5 > 0)
-            pow5mult(bd, bd5);
-        if (bd2 > 0)
-            lshift(bd, bd2);
-        if (bs2 > 0)
-            lshift(bs, bs2);
-        diff(delta, bb, bd);
-        dsign = delta.sign;
-        delta.sign = 0;
-        i = cmp(delta, bs);
-
-        if (i < 0) {
-            /* Error is less than half an ulp -- check for
-             * special case of mantissa a power of two.
-             */
-            if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
-             || (word0(&rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1
-                ) {
-                break;
-            }
-            if (!delta.words()[0] && delta.size() <= 1) {
-                /* exact result */
-                break;
-            }
-            lshift(delta, Log2P);
-            if (cmp(delta, bs) > 0)
-                goto dropDown;
-            break;
-        }
-        if (!i) {
-            /* exactly half-way between */
-            if (dsign) {
-                if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
-                 &&  word1(&rv) == (
-            (scale && (y = word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1)
-        ? (0xffffffff & (0xffffffff << (2 * P + 1 - (y >> Exp_shift)))) :
-                           0xffffffff)) {
-                    /*boundary case -- increment exponent*/
-                    word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1;
-                    word1(&rv) = 0;
-                    dsign = 0;
-                    break;
-                }
-            } else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
-dropDown:
-                /* boundary case -- decrement exponent */
-                if (scale) {
-                    L = word0(&rv) & Exp_mask;
-                    if (L <= (2 * P + 1) * Exp_msk1) {
-                        if (L > (P + 2) * Exp_msk1)
-                            /* round even ==> */
-                            /* accept rv */
-                            break;
-                        /* rv = smallest denormal */
-                        goto undfl;
-                    }
-                }
-                L = (word0(&rv) & Exp_mask) - Exp_msk1;
-                word0(&rv) = L | Bndry_mask1;
-                word1(&rv) = 0xffffffff;
-                break;
-            }
-            if (!(word1(&rv) & LSB))
-                break;
-            if (dsign)
-                dval(&rv) += ulp(&rv);
-            else {
-                dval(&rv) -= ulp(&rv);
-                if (!dval(&rv))
-                    goto undfl;
-            }
-            dsign = 1 - dsign;
-            break;
-        }
-        if ((aadj = ratio(delta, bs)) <= 2.) {
-            if (dsign)
-                aadj = aadj1 = 1.;
-            else if (word1(&rv) || word0(&rv) & Bndry_mask) {
-                if (word1(&rv) == Tiny1 && !word0(&rv))
-                    goto undfl;
-                aadj = 1.;
-                aadj1 = -1.;
-            } else {
-                /* special case -- power of FLT_RADIX to be */
-                /* rounded down... */
-
-                if (aadj < 2. / FLT_RADIX)
-                    aadj = 1. / FLT_RADIX;
-                else
-                    aadj *= 0.5;
-                aadj1 = -aadj;
-            }
-        } else {
-            aadj *= 0.5;
-            aadj1 = dsign ? aadj : -aadj;
-        }
-        y = word0(&rv) & Exp_mask;
-
-        /* Check for overflow */
-
-        if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) {
-            dval(&rv0) = dval(&rv);
-            word0(&rv) -= P * Exp_msk1;
-            adj.d = aadj1 * ulp(&rv);
-            dval(&rv) += adj.d;
-            if ((word0(&rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) {
-                if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
-                    goto ovfl;
-                word0(&rv) = Big0;
-                word1(&rv) = Big1;
-                goto cont;
-            }
-            word0(&rv) += P * Exp_msk1;
-        } else {
-            if (scale && y <= 2 * P * Exp_msk1) {
-                if (aadj <= 0x7fffffff) {
-                    if ((z = (uint32_t)aadj) <= 0)
-                        z = 1;
-                    aadj = z;
-                    aadj1 = dsign ? aadj : -aadj;
-                }
-                dval(&aadj2) = aadj1;
-                word0(&aadj2) += (2 * P + 1) * Exp_msk1 - y;
-                aadj1 = dval(&aadj2);
-            }
-            adj.d = aadj1 * ulp(&rv);
-            dval(&rv) += adj.d;
-        }
-        z = word0(&rv) & Exp_mask;
-        if (!scale && y == z) {
-            /* Can we stop now? */
-            L = (int32_t)aadj;
-            aadj -= L;
-            /* The tolerances below are conservative. */
-            if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
-                if (aadj < .4999999 || aadj > .5000001)
-                    break;
-            } else if (aadj < .4999999 / FLT_RADIX)
-                break;
-        }
-cont:
-        {}
-    }
-    if (scale) {
-        word0(&rv0) = Exp_1 - 2 * P * Exp_msk1;
-        word1(&rv0) = 0;
-        dval(&rv) *= dval(&rv0);
-#if HAVE(ERRNO_H)
-        /* try to avoid the bug of testing an 8087 register value */
-        if (!word0(&rv) && !word1(&rv))
-            errno = ERANGE;
-#endif
-    }
-ret:
-    if (se)
-        *se = const_cast<char*>(s);
-    return sign ? -dval(&rv) : dval(&rv);
-}
-
-static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S)
-{
-    size_t n;
-    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;
-    uint32_t si, z, zs;
-#endif
-    ASSERT(b.size() <= 1 || b.words()[b.size() - 1]);
-    ASSERT(S.size() <= 1 || S.words()[S.size() - 1]);
-
-    n = S.size();
-    ASSERT_WITH_MESSAGE(b.size() <= n, "oversize b in quorem");
-    if (b.size() < n)
-        return 0;
-    sx = S.words();
-    sxe = sx + --n;
-    bx = b.words();
-    bxe = bx + n;
-    q = *bxe / (*sxe + 1);    /* ensure q <= true quotient */
-    ASSERT_WITH_MESSAGE(q <= 9, "oversized quotient in quorem");
-    if (q) {
-        borrow = 0;
-        carry = 0;
-        do {
-#ifdef USE_LONG_LONG
-            ys = *sx++ * (unsigned long long)q + carry;
-            carry = ys >> 32;
-            y = *bx - (ys & 0xffffffffUL) - borrow;
-            borrow = y >> 32 & (uint32_t)1;
-            *bx++ = (uint32_t)y & 0xffffffffUL;
-#else
-            si = *sx++;
-            ys = (si & 0xffff) * q + carry;
-            zs = (si >> 16) * q + (ys >> 16);
-            carry = zs >> 16;
-            y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
-            borrow = (y & 0x10000) >> 16;
-            z = (*bx >> 16) - (zs & 0xffff) - borrow;
-            borrow = (z & 0x10000) >> 16;
-            bx = storeInc(bx, z, y);
-#endif
-        } while (sx <= sxe);
-        if (!*bxe) {
-            bx = b.words();
-            while (--bxe > bx && !*bxe)
-                --n;
-            b.resize(n);
-        }
-    }
-    if (cmp(b, S) >= 0) {
-        q++;
-        borrow = 0;
-        carry = 0;
-        bx = b.words();
-        sx = S.words();
-        do {
-#ifdef USE_LONG_LONG
-            ys = *sx++ + carry;
-            carry = ys >> 32;
-            y = *bx - (ys & 0xffffffffUL) - borrow;
-            borrow = y >> 32 & (uint32_t)1;
-            *bx++ = (uint32_t)y & 0xffffffffUL;
-#else
-            si = *sx++;
-            ys = (si & 0xffff) + carry;
-            zs = (si >> 16) + (ys >> 16);
-            carry = zs >> 16;
-            y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
-            borrow = (y & 0x10000) >> 16;
-            z = (*bx >> 16) - (zs & 0xffff) - borrow;
-            borrow = (z & 0x10000) >> 16;
-            bx = storeInc(bx, z, y);
-#endif
-        } while (sx <= sxe);
-        bx = b.words();
-        bxe = bx + n;
-        if (!*bxe) {
-            while (--bxe > bx && !*bxe)
-                --n;
-            b.resize(n);
-        }
-    }
-    return q;
-}
-
-/* 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. 112-126].
- *
- * Modifications:
- *    1. Rather than iterating, we use a simple numeric overestimate
- *       to determine k = floor(log10(d)).  We scale relevant
- *       quantities using O(log2(k)) rather than O(k) multiplications.
- *    2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
- *       try to generate digits strictly left to right.  Instead, we
- *       compute with fewer bits and propagate the carry if necessary
- *       when rounding the final digit up.  This is often faster.
- *    3. Under the assumption that input will be rounded nearest,
- *       mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
- *       That is, we allow equality in stopping tests when the
- *       round-nearest rule will give the same floating-point value
- *       as would satisfaction of the stopping test with strict
- *       inequality.
- *    4. We remove common factors of powers of 2 from relevant
- *       quantities.
- *    5. When converting floating-point integers less than 1e16,
- *       we use floating-point arithmetic rather than resorting
- *       to multiple-precision integers.
- *    6. When asked to produce fewer than 15 digits, we first try
- *       to get by with floating-point arithmetic; we resort to
- *       multiple-precision integer arithmetic only if we cannot
- *       guarantee that the floating-point calculation has given
- *       the correctly rounded result.  For k requested digits and
- *       "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'.
- */
-template<bool roundingNone, bool roundingSignificantFigures, bool roundingDecimalPlaces, bool leftright>
-void dtoa(DtoaBuffer result, double dd, int ndigits, bool& signOut, int& exponentOut, unsigned& precisionOut)
-{
-    // Exactly one rounding mode must be specified.
-    ASSERT(roundingNone + roundingSignificantFigures + roundingDecimalPlaces == 1);
-    // roundingNone only allowed (only sensible?) with leftright set.
-    ASSERT(!roundingNone || leftright);
-
-    ASSERT(!isnan(dd) && !isinf(dd));
-
-    int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0,
-        j, j1, k, k0, k_check, m2, m5, s2, s5,
-        spec_case;
-    int32_t L;
-    int denorm;
-    uint32_t x;
-    BigInt b, delta, mlo, mhi, S;
-    U d2, eps, u;
-    double ds;
-    char* s;
-    char* s0;
-
-    u.d = dd;
-
-    /* Infinity or NaN */
-    ASSERT((word0(&u) & Exp_mask) != Exp_mask);
-
-    // JavaScript toString conversion treats -0 as 0.
-    if (!dval(&u)) {
-        signOut = false;
-        exponentOut = 0;
-        precisionOut = 1;
-        result[0] = '0';
-        result[1] = '\0';
-        return;
-    }
-
-    if (word0(&u) & Sign_bit) {
-        signOut = true;
-        word0(&u) &= ~Sign_bit; // clear sign bit
-    } else
-        signOut = false;
-
-    d2b(b, &u, &be, &bbits);
-    if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) {
-        dval(&d2) = dval(&u);
-        word0(&d2) &= Frac_mask1;
-        word0(&d2) |= Exp_11;
-
-        /* log(x)    ~=~ log(1.5) + (x-1.5)/1.5
-         * log10(x)     =  log(x) / log(10)
-         *        ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
-         * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
-         *
-         * This suggests computing an approximation k to log10(d) by
-         *
-         * k = (i - Bias)*0.301029995663981
-         *    + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
-         *
-         * We want k to be too large rather than too small.
-         * The error in the first-order Taylor series approximation
-         * is in our favor, so we just round up the constant enough
-         * to compensate for any error in the multiplication of
-         * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
-         * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
-         * adding 1e-13 to the constant term more than suffices.
-         * Hence we adjust the constant term to 0.1760912590558.
-         * (We could get a more accurate k by invoking log10,
-         *  but this is probably not worthwhile.)
-         */
-
-        i -= Bias;
-        denorm = 0;
-    } else {
-        /* d is denormalized */
-
-        i = bbits + be + (Bias + (P - 1) - 1);
-        x = (i > 32) ? (word0(&u) << (64 - i)) | (word1(&u) >> (i - 32))
-                : word1(&u) << (32 - i);
-        dval(&d2) = x;
-        word0(&d2) -= 31 * Exp_msk1; /* adjust exponent */
-        i -= (Bias + (P - 1) - 1) + 1;
-        denorm = 1;
-    }
-    ds = (dval(&d2) - 1.5) * 0.289529654602168 + 0.1760912590558 + (i * 0.301029995663981);
-    k = (int)ds;
-    if (ds < 0. && ds != k)
-        k--;    /* want k = floor(ds) */
-    k_check = 1;
-    if (k >= 0 && k <= Ten_pmax) {
-        if (dval(&u) < tens[k])
-            k--;
-        k_check = 0;
-    }
-    j = bbits - i - 1;
-    if (j >= 0) {
-        b2 = 0;
-        s2 = j;
-    } else {
-        b2 = -j;
-        s2 = 0;
-    }
-    if (k >= 0) {
-        b5 = 0;
-        s5 = k;
-        s2 += k;
-    } else {
-        b2 -= k;
-        b5 = -k;
-        s5 = 0;
-    }
-
-    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;
-    }
-
-    s = s0 = result;
-
-    if (ilim >= 0 && ilim <= Quick_max) {
-        /* Try to get by with floating-point arithmetic. */
-
-        i = 0;
-        dval(&d2) = dval(&u);
-        k0 = k;
-        ilim0 = ilim;
-        ieps = 2; /* conservative */
-        if (k > 0) {
-            ds = tens[k & 0xf];
-            j = k >> 4;
-            if (j & Bletch) {
-                /* prevent overflows */
-                j &= Bletch - 1;
-                dval(&u) /= bigtens[n_bigtens - 1];
-                ieps++;
-            }
-            for (; j; j >>= 1, i++) {
-                if (j & 1) {
-                    ieps++;
-                    ds *= bigtens[i];
-                }
-            }
-            dval(&u) /= ds;
-        } else if ((j1 = -k)) {
-            dval(&u) *= tens[j1 & 0xf];
-            for (j = j1 >> 4; j; j >>= 1, i++) {
-                if (j & 1) {
-                    ieps++;
-                    dval(&u) *= bigtens[i];
-                }
-            }
-        }
-        if (k_check && dval(&u) < 1. && ilim > 0) {
-            if (ilim1 <= 0)
-                goto fastFailed;
-            ilim = ilim1;
-            k--;
-            dval(&u) *= 10.;
-            ieps++;
-        }
-        dval(&eps) = (ieps * dval(&u)) + 7.;
-        word0(&eps) -= (P - 1) * Exp_msk1;
-        if (!ilim) {
-            S.clear();
-            mhi.clear();
-            dval(&u) -= 5.;
-            if (dval(&u) > dval(&eps))
-                goto oneDigit;
-            if (dval(&u) < -dval(&eps))
-                goto noDigits;
-            goto fastFailed;
-        }
-        if (leftright) {
-            /* Use Steele & White method of only
-             * generating digits needed.
-             */
-            dval(&eps) = (0.5 / tens[ilim - 1]) - dval(&eps);
-            for (i = 0;;) {
-                L = (long int)dval(&u);
-                dval(&u) -= L;
-                *s++ = '0' + (int)L;
-                if (dval(&u) < dval(&eps))
-                    goto ret;
-                if (1. - dval(&u) < dval(&eps))
-                    goto bumpUp;
-                if (++i >= ilim)
-                    break;
-                dval(&eps) *= 10.;
-                dval(&u) *= 10.;
-            }
-        } else {
-            /* Generate ilim digits, then fix them up. */
-            dval(&eps) *= tens[ilim - 1];
-            for (i = 1;; i++, dval(&u) *= 10.) {
-                L = (int32_t)(dval(&u));
-                if (!(dval(&u) -= L))
-                    ilim = i;
-                *s++ = '0' + (int)L;
-                if (i == ilim) {
-                    if (dval(&u) > 0.5 + dval(&eps))
-                        goto bumpUp;
-                    if (dval(&u) < 0.5 - dval(&eps)) {
-                        while (*--s == '0') { }
-                        s++;
-                        goto ret;
-                    }
-                    break;
-                }
-            }
-        }
-fastFailed:
-        s = s0;
-        dval(&u) = dval(&d2);
-        k = k0;
-        ilim = ilim0;
-    }
-
-    /* Do we have a "small" integer? */
-
-    if (be >= 0 && k <= Int_max) {
-        /* Yes. */
-        ds = tens[k];
-        if (ndigits < 0 && ilim <= 0) {
-            S.clear();
-            mhi.clear();
-            if (ilim < 0 || dval(&u) <= 5 * ds)
-                goto noDigits;
-            goto oneDigit;
-        }
-        for (i = 1;; i++, dval(&u) *= 10.) {
-            L = (int32_t)(dval(&u) / ds);
-            dval(&u) -= L * ds;
-            *s++ = '0' + (int)L;
-            if (!dval(&u)) {
-                break;
-            }
-            if (i == ilim) {
-                dval(&u) += dval(&u);
-                if (dval(&u) > ds || (dval(&u) == ds && (L & 1))) {
-bumpUp:
-                    while (*--s == '9')
-                        if (s == s0) {
-                            k++;
-                            *s = '0';
-                            break;
-                        }
-                    ++*s++;
-                }
-                break;
-            }
-        }
-        goto ret;
-    }
-
-    m2 = b2;
-    m5 = b5;
-    mhi.clear();
-    mlo.clear();
-    if (leftright) {
-        i = denorm ? be + (Bias + (P - 1) - 1 + 1) : 1 + P - bbits;
-        b2 += i;
-        s2 += i;
-        i2b(mhi, 1);
-    }
-    if (m2 > 0 && s2 > 0) {
-        i = m2 < s2 ? m2 : s2;
-        b2 -= i;
-        m2 -= i;
-        s2 -= i;
-    }
-    if (b5 > 0) {
-        if (leftright) {
-            if (m5 > 0) {
-                pow5mult(mhi, m5);
-                mult(b, mhi);
-            }
-            if ((j = b5 - m5))
-                pow5mult(b, j);
-        } else
-            pow5mult(b, b5);
-    }
-    i2b(S, 1);
-    if (s5 > 0)
-        pow5mult(S, s5);
-
-    /* Check for special case that d is a normalized power of 2. */
-
-    spec_case = 0;
-    if ((roundingNone || leftright) && (!word1(&u) && !(word0(&u) & Bndry_mask) && word0(&u) & (Exp_mask & ~Exp_msk1))) {
-        /* The special case */
-        b2 += Log2P;
-        s2 += Log2P;
-        spec_case = 1;
-    }
-
-    /* Arrange for convenient computation of quotients:
-     * shift left if necessary so divisor has 4 leading 0 bits.
-     *
-     * Perhaps we should just compute leading 28 bits of S once
-     * and for all and pass them and a shift to quorem, so it
-     * can do shifts and ors to compute the numerator for q.
-     */
-    if ((i = ((s5 ? 32 - hi0bits(S.words()[S.size() - 1]) : 1) + s2) & 0x1f))
-        i = 32 - i;
-    if (i > 4) {
-        i -= 4;
-        b2 += i;
-        m2 += i;
-        s2 += i;
-    } else if (i < 4) {
-        i += 28;
-        b2 += i;
-        m2 += i;
-        s2 += i;
-    }
-    if (b2 > 0)
-        lshift(b, b2);
-    if (s2 > 0)
-        lshift(S, s2);
-    if (k_check) {
-        if (cmp(b, S) < 0) {
-            k--;
-            multadd(b, 10, 0);    /* we botched the k estimate */
-            if (leftright)
-                multadd(mhi, 10, 0);
-            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);
-
-        /* Compute mlo -- check for special case
-         * that d is a normalized power of 2.
-         */
-
-        mlo = mhi;
-        if (spec_case)
-            lshift(mhi, Log2P);
-
-        for (i = 1;;i++) {
-            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);
-#ifdef DTOA_ROUND_BIASED
-            if (j < 0 || !j) {
-#else
-            // FIXME: ECMA-262 specifies that equidistant results round away from
-            // zero, which probably means we shouldn't be on the unbiased code path
-            // (the (word1(&u) & 1) clause is looking highly suspicious). I haven't
-            // yet understood this code well enough to make the call, but we should
-            // probably be enabling DTOA_ROUND_BIASED. I think the interesting corner
-            // case to understand is probably "Math.pow(0.5, 24).toString()".
-            // I believe this value is interesting because I think it is precisely
-            // representable in binary floating point, and its decimal representation
-            // has a single digit that Steele & White reduction can remove, with the
-            // value 5 (thus equidistant from the next numbers above and below).
-            // We produce the correct answer using either codepath, and I don't as
-            // yet understand why. :-)
-            if (!j1 && !(word1(&u) & 1)) {
-                if (dig == '9')
-                    goto round9up;
-                if (j > 0)
-                    dig++;
-                *s++ = dig;
-                goto ret;
-            }
-            if (j < 0 || (!j && !(word1(&u) & 1))) {
-#endif
-                if ((b.words()[0] || b.size() > 1) && (j1 > 0)) {
-                    lshift(b, 1);
-                    j1 = cmp(b, S);
-                    // 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++;
-                    }
-                }
-                *s++ = dig;
-                goto ret;
-            }
-            if (j1 > 0) {
-                if (dig == '9') { /* possible if i == 1 */
-round9up:
-                    *s++ = '9';
-                    goto roundoff;
-                }
-                *s++ = dig + 1;
-                goto ret;
-            }
-            *s++ = dig;
-            if (i == ilim)
-                break;
-            multadd(b, 10, 0);
-            multadd(mlo, 10, 0);
-            multadd(mhi, 10, 0);
-        }
-    } else {
-        for (i = 1;; i++) {
-            *s++ = dig = quorem(b, S) + '0';
-            if (!b.words()[0] && b.size() <= 1)
-                goto ret;
-            if (i >= ilim)
-                break;
-            multadd(b, 10, 0);
-        }
-    }
-
-    /* Round off last digit */
-
-    lshift(b, 1);
-    j = cmp(b, S);
-    // 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) {
-                k++;
-                *s++ = '1';
-                goto ret;
-            }
-        ++*s++;
-    } else {
-        while (*--s == '0') { }
-        s++;
-    }
-    goto ret;
-noDigits:
-    exponentOut = 0;
-    precisionOut = 1;
-    result[0] = '0';
-    result[1] = '\0';
-    return;
-oneDigit:
-    *s++ = '1';
-    k++;
-    goto ret;
-ret:
-    ASSERT(s > result);
-    *s = 0;
-    exponentOut = k;
-    precisionOut = s - result;
-}
-
-void dtoa(DtoaBuffer result, double dd, bool& sign, int& exponent, unsigned& precision)
-{
-    // flags are roundingNone, leftright.
-    dtoa<true, false, false, true>(result, dd, 0, sign, exponent, precision);
-}
-
-void dtoaRoundSF(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision)
-{
-    // flag is roundingSignificantFigures.
-    dtoa<false, true, false, false>(result, dd, ndigits, sign, exponent, precision);
-}
-
-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);
-}
-
-static ALWAYS_INLINE void copyAsciiToUTF16(UChar* next, const char* src, unsigned size)
-{
-    for (unsigned i = 0; i < size; ++i)
-        *next++ = *src++;
-}
-
-unsigned numberToString(double d, NumberToStringBuffer buffer)
-{
-    // Handle NaN and Infinity.
-    if (isnan(d) || isinf(d)) {
-        if (isnan(d)) {
-            copyAsciiToUTF16(buffer, "NaN", 3);
-            return 3;
-        }
-        if (d > 0) {
-            copyAsciiToUTF16(buffer, "Infinity", 8);
-            return 8;
-        }
-        copyAsciiToUTF16(buffer, "-Infinity", 9);
-        return 9;
-    }
-
-    // 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
diff --git a/wtf/dtoa.h b/wtf/dtoa.h
deleted file mode 100644 (file)
index 3924a1c..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *  Copyright (C) 2003, 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_dtoa_h
-#define WTF_dtoa_h
-
-#include <wtf/unicode/Unicode.h>
-
-namespace WTF {
-class Mutex;
-
-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);
-
-typedef char DtoaBuffer[80];
-
-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);
-
-// Size = 80 for sizeof(DtoaBuffer) + some sign bits, decimal point, 'e', exponent digits.
-const unsigned NumberToStringBufferLength = 96;
-typedef UChar NumberToStringBuffer[NumberToStringBufferLength];
-unsigned numberToString(double, NumberToStringBuffer);
-
-} // namespace WTF
-
-using WTF::NumberToStringBuffer;
-using WTF::numberToString;
-
-#endif // WTF_dtoa_h
diff --git a/wtf/efl/MainThreadEfl.cpp b/wtf/efl/MainThreadEfl.cpp
deleted file mode 100644 (file)
index 8774d20..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
- * Copyright (C) 2008 Diego Gonzalez
- * Copyright (C) 2008 Kenneth Rohde Christiansen
- * Copyright (C) 2009-2010 ProFUSION embedded systems
- * Copyright (C) 2009-2010 Samsung Electronics
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must 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 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 "MainThread.h"
-
-#include <Ecore.h>
-
-namespace WTF {
-
-void initializeMainThreadPlatform()
-{
-}
-
-static Eina_Bool timeoutFired(void*)
-{
-    dispatchFunctionsFromMainThread();
-    return ECORE_CALLBACK_CANCEL;
-}
-
-void scheduleDispatchFunctionsOnMainThread()
-{
-    ecore_timer_add(0, timeoutFired, 0);
-}
-
-
-}
diff --git a/wtf/gobject/GOwnPtr.cpp b/wtf/gobject/GOwnPtr.cpp
deleted file mode 100644 (file)
index 7c51ee1..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2008 Collabora Ltd.
- *
- *  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 "GOwnPtr.h"
-
-#if ENABLE(GLIB_SUPPORT)
-
-#include <gio/gio.h>
-#include <glib.h>
-
-namespace WTF {
-
-template <> void freeOwnedGPtr<GError>(GError* ptr)
-{
-    if (ptr)
-        g_error_free(ptr);
-}
-
-template <> void freeOwnedGPtr<GList>(GList* ptr)
-{
-    g_list_free(ptr);
-}
-
-template <> void freeOwnedGPtr<GCond>(GCond* ptr)
-{
-    if (ptr)
-        g_cond_free(ptr);
-}
-
-template <> void freeOwnedGPtr<GMutex>(GMutex* ptr)
-{
-    if (ptr)
-        g_mutex_free(ptr);
-}
-
-template <> void freeOwnedGPtr<GPatternSpec>(GPatternSpec* ptr)
-{
-    if (ptr)
-        g_pattern_spec_free(ptr);
-}
-
-template <> void freeOwnedGPtr<GDir>(GDir* ptr)
-{
-    if (ptr)
-        g_dir_close(ptr);
-}
-
-} // namespace WTF
-
-#endif // ENABLE(GLIB_SUPPORT)
diff --git a/wtf/gobject/GOwnPtr.h b/wtf/gobject/GOwnPtr.h
deleted file mode 100644 (file)
index 8c7e837..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- *  Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- *  Copyright (C) 2008 Collabora Ltd.
- *
- *  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 GOwnPtr_h
-#define GOwnPtr_h
-
-#if ENABLE(GLIB_SUPPORT)
-
-#include <algorithm>
-#include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
-
-extern "C" void g_free(void*);
-
-namespace WTF {
-
-template <typename T> inline void freeOwnedGPtr(T* ptr);
-template<> void freeOwnedGPtr<GError>(GError*);
-template<> void freeOwnedGPtr<GList>(GList*);
-template<> void freeOwnedGPtr<GCond>(GCond*);
-template<> void freeOwnedGPtr<GMutex>(GMutex*);
-template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*);
-template<> void freeOwnedGPtr<GDir>(GDir*);
-
-template <typename T> class GOwnPtr {
-    WTF_MAKE_NONCOPYABLE(GOwnPtr);
-public:
-    explicit GOwnPtr(T* ptr = 0) : m_ptr(ptr) { }
-    ~GOwnPtr() { freeOwnedGPtr(m_ptr); }
-
-    T* get() const { return m_ptr; }
-    T* release()
-    {
-        T* ptr = m_ptr;
-        m_ptr = 0;
-        return ptr;
-    }
-
-    T*& outPtr()
-    {
-        ASSERT(!m_ptr);
-        return m_ptr;
-    }
-
-    void set(T* ptr)
-    {
-        ASSERT(!ptr || m_ptr != ptr);
-        freeOwnedGPtr(m_ptr);
-        m_ptr = ptr;
-    }
-
-    void clear()
-    {
-        T* ptr = m_ptr;
-        m_ptr = 0;
-        freeOwnedGPtr(ptr);
-    }
-
-    T& operator*() const
-    {
-        ASSERT(m_ptr);
-        return *m_ptr;
-    }
-
-    T* 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.
-    typedef T* GOwnPtr::*UnspecifiedBoolType;
-    operator UnspecifiedBoolType() const { return m_ptr ? &GOwnPtr::m_ptr : 0; }
-
-    void swap(GOwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
-
-private:
-    T* m_ptr;
-};
-
-template <typename T> inline void swap(GOwnPtr<T>& a, GOwnPtr<T>& b)
-{
-    a.swap(b);
-}
-
-template <typename T, typename U> inline bool operator==(const GOwnPtr<T>& a, U* b)
-{ 
-    return a.get() == b; 
-}
-
-template <typename T, typename U> inline bool operator==(T* a, const GOwnPtr<U>& b) 
-{
-    return a == b.get(); 
-}
-
-template <typename T, typename U> inline bool operator!=(const GOwnPtr<T>& a, U* b)
-{
-    return a.get() != b; 
-}
-
-template <typename T, typename U> inline bool operator!=(T* a, const GOwnPtr<U>& b)
-{ 
-    return a != b.get(); 
-}
-
-template <typename T> inline typename GOwnPtr<T>::PtrType getPtr(const GOwnPtr<T>& p)
-{
-    return p.get();
-}
-
-template <typename T> inline void freeOwnedGPtr(T* ptr)
-{
-    g_free(ptr);
-}
-
-} // namespace WTF
-
-using WTF::GOwnPtr;
-
-#endif // ENABLE(GLIB_SUPPORT)
-
-#endif // GOwnPtr_h
-
diff --git a/wtf/gobject/GRefPtr.cpp b/wtf/gobject/GRefPtr.cpp
deleted file mode 100644 (file)
index 1cd22c5..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2009 Martin Robinson
- *
- *  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 "GRefPtr.h"
-
-#if ENABLE(GLIB_SUPPORT)
-
-#include <glib.h>
-
-namespace WTF {
-
-template <> GHashTable* refGPtr(GHashTable* ptr)
-{
-    if (ptr)
-        g_hash_table_ref(ptr);
-    return ptr;
-}
-
-template <> void derefGPtr(GHashTable* ptr)
-{
-    g_hash_table_unref(ptr);
-}
-
-#if GLIB_CHECK_VERSION(2, 24, 0)
-template <> GVariant* refGPtr(GVariant* ptr)
-{
-    if (ptr)
-        g_variant_ref(ptr);
-    return ptr;
-}
-
-template <> void derefGPtr(GVariant* ptr)
-{
-    g_variant_unref(ptr);
-}
-
-#else
-
-// We do this so that we can avoid including the glib.h header in GRefPtr.h.
-typedef struct _GVariant {
-    bool fake;
-} GVariant; 
-
-template <> GVariant* refGPtr(GVariant* ptr)
-{
-    return ptr;
-}
-
-template <> void derefGPtr(GVariant* ptr)
-{
-}
-
-#endif
-
-template <> GSource* refGPtr(GSource* ptr)
-{
-    if (ptr)
-        g_source_ref(ptr);
-    return ptr;
-}
-
-template <> void derefGPtr(GSource* ptr)
-{
-    if (ptr)
-        g_source_unref(ptr);
-}
-
-} // namespace WTF
-
-#endif // ENABLE(GLIB_SUPPORT)
diff --git a/wtf/gobject/GRefPtr.h b/wtf/gobject/GRefPtr.h
deleted file mode 100644 (file)
index 10ebf07..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *  Copyright (C) 2008 Collabora Ltd.
- *  Copyright (C) 2009 Martin Robinson
- *
- *  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_GRefPtr_h
-#define WTF_GRefPtr_h
-
-#if ENABLE(GLIB_SUPPORT)
-
-#include "AlwaysInline.h"
-#include "GRefPtr.h"
-#include "RefPtr.h"
-#include <algorithm>
-
-extern "C" void g_object_unref(gpointer);
-extern "C" gpointer g_object_ref_sink(gpointer);
-
-namespace WTF {
-
-enum GRefPtrAdoptType { GRefPtrAdopt };
-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> 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);
-    }
-
-    void clear()
-    {
-        T* ptr = m_ptr;
-        m_ptr = 0;
-        if (ptr)
-            derefGPtr(ptr);
-    }
-
-    T* leakRef() WARN_UNUSED_RETURN
-    {
-        T* ptr = m_ptr;
-        m_ptr = 0;
-        return ptr;
-    }
-
-    // Hash table deleted values, which are only constructed and never copied or destroyed.
-    GRefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
-    bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
-
-    T* get() const { return m_ptr; }
-    T& operator*() const { return *m_ptr; }
-    ALWAYS_INLINE T* operator->() const { return m_ptr; }
-
-    bool operator!() const { return !m_ptr; }
-
-    // This conversion operator allows implicit conversion to bool but not to other integer types.
-    typedef T* GRefPtr::*UnspecifiedBoolType;
-    operator UnspecifiedBoolType() const { return m_ptr ? &GRefPtr::m_ptr : 0; }
-
-    GRefPtr& operator=(const GRefPtr&);
-    GRefPtr& operator=(T*);
-    template <typename U> GRefPtr& operator=(const GRefPtr<U>&);
-
-    void swap(GRefPtr&);
-    friend GRefPtr adoptGRef<T>(T*);
-
-private:
-    static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
-    // Adopting constructor.
-    GRefPtr(T* ptr, GRefPtrAdoptType) : m_ptr(ptr) {}
-
-    T* m_ptr;
-};
-
-template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(const GRefPtr<T>& o)
-{
-    T* optr = o.get();
-    if (optr)
-        refGPtr(optr);
-    T* ptr = m_ptr;
-    m_ptr = optr;
-    if (ptr)
-        derefGPtr(ptr);
-    return *this;
-}
-
-template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(T* optr)
-{
-    T* ptr = m_ptr;
-    if (optr)
-        refGPtr(optr);
-    m_ptr = optr;
-    if (ptr)
-        derefGPtr(ptr);
-    return *this;
-}
-
-template <class T> inline void GRefPtr<T>::swap(GRefPtr<T>& o)
-{
-    std::swap(m_ptr, o.m_ptr);
-}
-
-template <class T> inline void swap(GRefPtr<T>& a, GRefPtr<T>& b)
-{
-    a.swap(b);
-}
-
-template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, const GRefPtr<U>& b)
-{
-    return a.get() == b.get();
-}
-
-template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, U* b)
-{
-    return a.get() == b;
-}
-
-template <typename T, typename U> inline bool operator==(T* a, const GRefPtr<U>& b)
-{
-    return a == b.get();
-}
-
-template <typename T, typename U> inline bool operator!=(const GRefPtr<T>& a, const GRefPtr<U>& b)
-{
-    return a.get() != b.get();
-}
-
-template <typename T, typename U> inline bool operator!=(const GRefPtr<T>& a, U* b)
-{
-    return a.get() != b;
-}
-
-template <typename T, typename U> inline bool operator!=(T* a, const GRefPtr<U>& b)
-{
-    return a != b.get();
-}
-
-template <typename T, typename U> inline GRefPtr<T> static_pointer_cast(const GRefPtr<U>& p)
-{
-    return GRefPtr<T>(static_cast<T*>(p.get()));
-}
-
-template <typename T, typename U> inline GRefPtr<T> const_pointer_cast(const GRefPtr<U>& p)
-{
-    return GRefPtr<T>(const_cast<T*>(p.get()));
-}
-
-template <typename T> inline T* getPtr(const GRefPtr<T>& p)
-{
-    return p.get();
-}
-
-template <typename T> GRefPtr<T> adoptGRef(T* p)
-{
-    return GRefPtr<T>(p, GRefPtrAdopt);
-}
-
-template <> GHashTable* refGPtr(GHashTable* ptr);
-template <> void derefGPtr(GHashTable* ptr);
-template <> GVariant* refGPtr(GVariant* ptr);
-template <> void derefGPtr(GVariant* ptr);
-template <> GSource* refGPtr(GSource* ptr);
-template <> void derefGPtr(GSource* ptr);
-
-template <typename T> inline T* refGPtr(T* ptr)
-{
-    if (ptr)
-        g_object_ref_sink(ptr);
-    return ptr;
-}
-
-template <typename T> inline void derefGPtr(T* ptr)
-{
-    if (ptr)
-        g_object_unref(ptr);
-}
-
-} // namespace WTF
-
-using WTF::GRefPtr;
-using WTF::adoptGRef;
-
-#endif // ENABLE(GLIB_SUPPORT)
-
-#endif // WTF_GRefPtr_h
diff --git a/wtf/gobject/GTypedefs.h b/wtf/gobject/GTypedefs.h
deleted file mode 100644 (file)
index c7f7ac4..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 */
diff --git a/wtf/gtk/MainThreadGtk.cpp b/wtf/gtk/MainThreadGtk.cpp
deleted file mode 100644 (file)
index 7624247..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 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 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 "MainThread.h"
-
-#include <glib.h>
-
-namespace WTF {
-
-void initializeMainThreadPlatform()
-{
-}
-
-static gboolean timeoutFired(gpointer)
-{
-    dispatchFunctionsFromMainThread();
-    return FALSE;
-}
-
-void scheduleDispatchFunctionsOnMainThread()
-{
-    g_timeout_add(0, timeoutFired, 0);
-}
-
-} // namespace WTF
diff --git a/wtf/gtk/ThreadingGtk.cpp b/wtf/gtk/ThreadingGtk.cpp
deleted file mode 100644 (file)
index 863ee81..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 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 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 "Threading.h"
-
-#if !USE(PTHREADS)
-
-#include "CurrentTime.h"
-#include "HashMap.h"
-#include "MainThread.h"
-#include "RandomNumberSeed.h"
-#include <wtf/StdLibExtras.h>
-
-#include <glib.h>
-#include <limits.h>
-
-namespace WTF {
-
-typedef HashMap<ThreadIdentifier, GThread*> ThreadMap;
-
-static Mutex* atomicallyInitializedStaticMutex;
-
-static Mutex& threadMapMutex()
-{
-    DEFINE_STATIC_LOCAL(Mutex, mutex, ());
-    return mutex;
-}
-
-void initializeThreading()
-{
-    if (!g_thread_supported())
-        g_thread_init(NULL);
-    ASSERT(g_thread_supported());
-
-    if (!atomicallyInitializedStaticMutex) {
-        atomicallyInitializedStaticMutex = new Mutex;
-        threadMapMutex();
-        initializeRandomNumberGenerator();
-    }
-}
-
-void lockAtomicallyInitializedStaticMutex()
-{
-    ASSERT(atomicallyInitializedStaticMutex);
-    atomicallyInitializedStaticMutex->lock();
-}
-
-void unlockAtomicallyInitializedStaticMutex()
-{
-    atomicallyInitializedStaticMutex->unlock();
-}
-
-static ThreadMap& threadMap()
-{
-    DEFINE_STATIC_LOCAL(ThreadMap, map, ());
-    return map;
-}
-
-static ThreadIdentifier identifierByGthreadHandle(GThread*& thread)
-{
-    MutexLocker locker(threadMapMutex());
-
-    ThreadMap::iterator i = threadMap().begin();
-    for (; i != threadMap().end(); ++i) {
-        if (i->second == thread)
-            return i->first;
-    }
-
-    return 0;
-}
-
-static ThreadIdentifier establishIdentifierForThread(GThread*& thread)
-{
-    ASSERT(!identifierByGthreadHandle(thread));
-
-    MutexLocker locker(threadMapMutex());
-
-    static ThreadIdentifier identifierCount = 1;
-
-    threadMap().add(identifierCount, thread);
-
-    return identifierCount++;
-}
-
-static GThread* threadForIdentifier(ThreadIdentifier id)
-{
-    MutexLocker locker(threadMapMutex());
-
-    return threadMap().get(id);
-}
-
-static void clearThreadForIdentifier(ThreadIdentifier id)
-{
-    MutexLocker locker(threadMapMutex());
-
-    ASSERT(threadMap().contains(id));
-
-    threadMap().remove(id);
-}
-
-ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
-{
-    GThread* thread;
-    if (!(thread = g_thread_create(entryPoint, data, TRUE, 0))) {
-        LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
-        return 0;
-    }
-
-    ThreadIdentifier threadID = establishIdentifierForThread(thread);
-    return threadID;
-}
-
-void initializeCurrentThreadInternal(const char*)
-{
-}
-
-int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
-{
-    ASSERT(threadID);
-
-    GThread* thread = threadForIdentifier(threadID);
-
-    void* joinResult = g_thread_join(thread);
-    if (result)
-        *result = joinResult;
-
-    clearThreadForIdentifier(threadID);
-    return 0;
-}
-
-void detachThread(ThreadIdentifier)
-{
-}
-
-ThreadIdentifier currentThread()
-{
-    GThread* currentThread = g_thread_self();
-    if (ThreadIdentifier id = identifierByGthreadHandle(currentThread))
-        return id;
-    return establishIdentifierForThread(currentThread);
-}
-
-void yield()
-{
-    g_thread_yield();
-}
-
-Mutex::Mutex()
-    : m_mutex(g_mutex_new())
-{
-}
-
-Mutex::~Mutex()
-{
-}
-
-void Mutex::lock()
-{
-    g_mutex_lock(m_mutex.get());
-}
-
-bool Mutex::tryLock()
-{
-    return g_mutex_trylock(m_mutex.get());
-}
-
-void Mutex::unlock()
-{
-    g_mutex_unlock(m_mutex.get());
-}
-
-ThreadCondition::ThreadCondition()
-    : m_condition(g_cond_new())
-{
-}
-
-ThreadCondition::~ThreadCondition()
-{
-}
-
-void ThreadCondition::wait(Mutex& mutex)
-{
-    g_cond_wait(m_condition.get(), mutex.impl().get());
-}
-
-bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
-{
-    // Time is in the past - return right away.
-    if (absoluteTime < currentTime())
-        return false;
-    
-    // Time is too far in the future for g_cond_timed_wait - wait forever.
-    if (absoluteTime > INT_MAX) {
-        wait(mutex);
-        return true;
-    }
-
-    int timeSeconds = static_cast<int>(absoluteTime);
-    int timeMicroseconds = static_cast<int>((absoluteTime - timeSeconds) * 1000000.0);
-    
-    GTimeVal targetTime;
-    targetTime.tv_sec = timeSeconds;
-    targetTime.tv_usec = timeMicroseconds;
-
-    return g_cond_timed_wait(m_condition.get(), mutex.impl().get(), &targetTime);
-}
-
-void ThreadCondition::signal()
-{
-    g_cond_signal(m_condition.get());
-}
-
-void ThreadCondition::broadcast()
-{
-    g_cond_broadcast(m_condition.get());
-}
-
-
-}
-
-#endif // !USE(PTHREADS)
diff --git a/wtf/haiku/MainThreadHaiku.cpp b/wtf/haiku/MainThreadHaiku.cpp
deleted file mode 100644 (file)
index 10c4248..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2007 Kevin Ollivier
- * Copyright (C) 2009 Maxime Simon
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must 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 "MainThread.h"
-
-#include "NotImplemented.h"
-
-namespace WTF {
-
-void initializeMainThreadPlatform()
-{
-    notImplemented();
-}
-
-void scheduleDispatchFunctionsOnMainThread()
-{
-    notImplemented();
-}
-
-} // namespace WTF
-
diff --git a/wtf/haiku/StringHaiku.cpp b/wtf/haiku/StringHaiku.cpp
deleted file mode 100644 (file)
index fdf4e72..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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
diff --git a/wtf/iphone/WebCoreThread.cpp b/wtf/iphone/WebCoreThread.cpp
deleted file mode 100644 (file)
index 9c1f8e6..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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 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 "WebCoreThread.h"
-
-bool (*WebCoreWebThreadIsLockedOrDisabled)(void);
diff --git a/wtf/iphone/WebCoreThread.h b/wtf/iphone/WebCoreThread.h
deleted file mode 100644 (file)
index f397dfc..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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 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.
- */
-
-// Since this is a shared header, with the same file name as a file in
-// WebCore we prefix this with JavaScriptCore to make it unique.
-#ifndef JavaScriptCore_WebCoreThread_h
-#define JavaScriptCore_WebCoreThread_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern bool (*WebCoreWebThreadIsLockedOrDisabled)(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/wtf/mac/MainThreadMac.mm b/wtf/mac/MainThreadMac.mm
deleted file mode 100644 (file)
index d8b5a40..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.
- */
-#import "config.h"
-#import "MainThread.h"
-
-#import <CoreFoundation/CoreFoundation.h>
-#import <Foundation/NSThread.h>
-#import <stdio.h>
-#import <wtf/Assertions.h>
-#import <wtf/Threading.h>
-
-@interface WTFMainThreadCaller : NSObject {
-}
-- (void)call;
-@end
-
-@implementation WTFMainThreadCaller
-
-- (void)call
-{
-    WTF::dispatchFunctionsFromMainThread();
-}
-
-@end // implementation WTFMainThreadCaller
-
-namespace WTF {
-
-static WTFMainThreadCaller* staticMainThreadCaller;
-static bool isTimerPosted; // This is only accessed on the 'main' thread.
-static bool mainThreadEstablishedAsPthreadMain;
-static pthread_t mainThreadPthread;
-static NSThread* mainThreadNSThread;
-
-void initializeMainThreadPlatform()
-{
-    ASSERT(!staticMainThreadCaller);
-    staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
-
-    mainThreadEstablishedAsPthreadMain = false;
-    mainThreadPthread = pthread_self();
-    mainThreadNSThread = [[NSThread currentThread] retain];
-}
-
-void initializeMainThreadToProcessMainThreadPlatform()
-{
-    if (!pthread_main_np())
-        NSLog(@"WebKit Threading Violation - initial use of WebKit from a secondary thread.");
-
-    ASSERT(!staticMainThreadCaller);
-    staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
-
-    mainThreadEstablishedAsPthreadMain = true;
-    mainThreadPthread = 0;
-    mainThreadNSThread = nil;
-}
-
-static void timerFired(CFRunLoopTimerRef timer, void*)
-{
-    CFRelease(timer);
-    isTimerPosted = false;
-    WTF::dispatchFunctionsFromMainThread();
-}
-
-static void postTimer()
-{
-    ASSERT(isMainThread());
-
-    if (isTimerPosted)
-        return;
-
-    isTimerPosted = true;
-    CFRunLoopAddTimer(CFRunLoopGetCurrent(), CFRunLoopTimerCreate(0, 0, 0, 0, 0, timerFired, 0), kCFRunLoopCommonModes);
-}
-
-void scheduleDispatchFunctionsOnMainThread()
-{
-    ASSERT(staticMainThreadCaller);
-
-    if (isMainThread()) {
-        postTimer();
-        return;
-    }
-
-    if (mainThreadEstablishedAsPthreadMain) {
-        ASSERT(!mainThreadNSThread);
-        [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO];
-        return;
-    }
-
-    ASSERT(mainThreadNSThread);
-    [staticMainThreadCaller performSelector:@selector(call) onThread:mainThreadNSThread withObject:nil waitUntilDone:NO];
-}
-
-bool isMainThread()
-{
-    if (mainThreadEstablishedAsPthreadMain) {
-        ASSERT(!mainThreadPthread);
-        return pthread_main_np();
-    }
-
-    ASSERT(mainThreadPthread);
-    return pthread_equal(pthread_self(), mainThreadPthread);
-}
-
-// This function is the same as isMainThread() above except that it does not do
-// a ASSERT(mainThreadPthread). This should only be used by code that can get
-// invoked when the WebThread hasn't been started. See <rdar://8502487>.
-bool isWebThread()
-{
-    ASSERT(!mainThreadEstablishedAsPthreadMain);
-    return pthread_equal(pthread_self(), mainThreadPthread);
-}
-
-} // namespace WTF
diff --git a/wtf/qt/MainThreadQt.cpp b/wtf/qt/MainThreadQt.cpp
deleted file mode 100644 (file)
index 98b6a0c..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2007 Staikos Computing Services Inc.
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- * 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.
- */
-
-#include "config.h"
-#include "MainThread.h"
-
-#include <QtCore/QObject>
-#include <QtCore/QCoreApplication>
-#include <QThread>
-
-namespace WTF {
-
-class MainThreadInvoker : public QObject {
-    Q_OBJECT
-public:
-    MainThreadInvoker();
-
-private Q_SLOTS:
-    void dispatch();
-};
-
-MainThreadInvoker::MainThreadInvoker()
-{
-    moveToThread(QCoreApplication::instance()->thread());
-}
-
-void MainThreadInvoker::dispatch()
-{
-    dispatchFunctionsFromMainThread();
-}
-
-Q_GLOBAL_STATIC(MainThreadInvoker, webkit_main_thread_invoker)
-
-void initializeMainThreadPlatform()
-{
-}
-
-void scheduleDispatchFunctionsOnMainThread()
-{
-    QMetaObject::invokeMethod(webkit_main_thread_invoker(), "dispatch", Qt::QueuedConnection);
-}
-
-bool isMainThread()
-{
-    return QThread::currentThread() == QCoreApplication::instance()->thread();
-}
-
-} // namespace WTF
-
-#include "MainThreadQt.moc"
diff --git a/wtf/qt/StringQt.cpp b/wtf/qt/StringQt.cpp
deleted file mode 100644 (file)
index 16dd439..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this 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 <wtf/StdLibExtras.h>
-#include <wtf/text/WTFString.h>
-
-#include <QString>
-
-namespace WTF {
-
-// String conversions
-String::String(const QString& qstr)
-{
-    if (qstr.isNull())
-        return;
-    m_impl = StringImpl::create(reinterpret_cast_ptr<const UChar*>(qstr.constData()), qstr.length());
-}
-
-String::String(const QStringRef& ref)
-{
-    if (!ref.string())
-        return;
-    m_impl = StringImpl::create(reinterpret_cast_ptr<const UChar*>(ref.unicode()), ref.length());
-}
-
-String::operator QString() const
-{
-    return QString(reinterpret_cast<const QChar*>(characters()), length());
-}
-
-QDataStream& operator<<(QDataStream& stream, const String& str)
-{
-    // could be faster
-    stream << QString(str);
-    return stream;
-}
-
-QDataStream& operator>>(QDataStream& stream, String& str)
-{
-    // mabe not the fastest way, but really easy
-    QString tmp;
-    stream >> tmp;
-    str = tmp;
-    return stream;
-}
-
-}
-
-// vim: ts=4 sw=4 et
diff --git a/wtf/qt/ThreadingQt.cpp b/wtf/qt/ThreadingQt.cpp
deleted file mode 100644 (file)
index 8041dea..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-#include "config.h"
-#include "Threading.h"
-
-#if !ENABLE(SINGLE_THREADED)
-
-#include "CurrentTime.h"
-#include "HashMap.h"
-#include "MainThread.h"
-#include "RandomNumberSeed.h"
-
-#include <QCoreApplication>
-#include <QMutex>
-#include <QThread>
-#include <QWaitCondition>
-
-namespace WTF {
-
-class ThreadPrivate : public QThread {
-public:
-    ThreadPrivate(ThreadFunction entryPoint, void* data);
-    void run();
-    void* getReturnValue() { return m_returnValue; }
-private:
-    void* m_data;
-    ThreadFunction m_entryPoint;
-    void* m_returnValue;
-};
-
-ThreadPrivate::ThreadPrivate(ThreadFunction entryPoint, void* data) 
-    : m_data(data)
-    , m_entryPoint(entryPoint)
-    , m_returnValue(0)
-{
-}
-
-void ThreadPrivate::run()
-{
-    m_returnValue = m_entryPoint(m_data);
-}
-
-class ThreadMonitor : public QObject {
-    Q_OBJECT
-public:
-    static ThreadMonitor * instance()
-    {
-        static ThreadMonitor *instance = new ThreadMonitor();
-        return instance;
-    }
-
-public Q_SLOTS:
-    void threadFinished()
-    {
-        sender()->deleteLater();
-    }
-};
-
-static Mutex* atomicallyInitializedStaticMutex;
-
-static Mutex& threadMapMutex()
-{
-    static Mutex mutex;
-    return mutex;
-}
-
-static HashMap<ThreadIdentifier, QThread*>& threadMap()
-{
-    static HashMap<ThreadIdentifier, QThread*> map;
-    return map;
-}
-
-static ThreadIdentifier identifierByQthreadHandle(QThread*& thread)
-{
-    MutexLocker locker(threadMapMutex());
-
-    HashMap<ThreadIdentifier, QThread*>::iterator i = threadMap().begin();
-    for (; i != threadMap().end(); ++i) {
-        if (i->second == thread)
-            return i->first;
-    }
-
-    return 0;
-}
-
-static ThreadIdentifier establishIdentifierForThread(QThread*& thread)
-{
-    ASSERT(!identifierByQthreadHandle(thread));
-
-    MutexLocker locker(threadMapMutex());
-
-    static ThreadIdentifier identifierCount = 1;
-
-    threadMap().add(identifierCount, thread);
-
-    return identifierCount++;
-}
-
-static void clearThreadForIdentifier(ThreadIdentifier id)
-{
-    MutexLocker locker(threadMapMutex());
-
-    ASSERT(threadMap().contains(id));
-
-    threadMap().remove(id);
-}
-
-static QThread* threadForIdentifier(ThreadIdentifier id)
-{
-    MutexLocker locker(threadMapMutex());
-
-    return threadMap().get(id);
-}
-
-void initializeThreading()
-{
-    if (!atomicallyInitializedStaticMutex) {
-        atomicallyInitializedStaticMutex = new Mutex;
-        threadMapMutex();
-        initializeRandomNumberGenerator();
-    }
-}
-
-void lockAtomicallyInitializedStaticMutex()
-{
-    ASSERT(atomicallyInitializedStaticMutex);
-    atomicallyInitializedStaticMutex->lock();
-}
-
-void unlockAtomicallyInitializedStaticMutex()
-{
-    atomicallyInitializedStaticMutex->unlock();
-}
-
-ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
-{
-    ThreadPrivate* thread = new ThreadPrivate(entryPoint, data);
-    if (!thread) {
-        LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
-        return 0;
-    }
-
-    QObject::connect(thread, SIGNAL(finished()), ThreadMonitor::instance(), SLOT(threadFinished()));
-
-    thread->start();
-
-    QThread* threadRef = static_cast<QThread*>(thread);
-
-    return establishIdentifierForThread(threadRef);
-}
-
-void initializeCurrentThreadInternal(const char*)
-{
-}
-
-int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
-{
-    ASSERT(threadID);
-
-    QThread* thread = threadForIdentifier(threadID);
-
-    bool res = thread->wait();
-
-    clearThreadForIdentifier(threadID);
-    if (result)
-        *result = static_cast<ThreadPrivate*>(thread)->getReturnValue();
-
-    return !res;
-}
-
-void detachThread(ThreadIdentifier threadID)
-{
-    ASSERT(threadID);
-    clearThreadForIdentifier(threadID);
-}
-
-ThreadIdentifier currentThread()
-{
-    QThread* currentThread = QThread::currentThread();
-    if (ThreadIdentifier id = identifierByQthreadHandle(currentThread))
-        return id;
-    return establishIdentifierForThread(currentThread);
-}
-
-void yield()
-{
-    QThread::yieldCurrentThread();
-}
-
-Mutex::Mutex()
-    : m_mutex(new QMutex())
-{
-}
-
-Mutex::~Mutex()
-{
-    delete m_mutex;
-}
-
-void Mutex::lock()
-{
-    m_mutex->lock();
-}
-
-bool Mutex::tryLock()
-{
-    return m_mutex->tryLock();
-}
-
-void Mutex::unlock()
-{
-    m_mutex->unlock();
-}
-
-ThreadCondition::ThreadCondition()
-    : m_condition(new QWaitCondition())
-{
-}
-
-ThreadCondition::~ThreadCondition()
-{
-    delete m_condition;
-}
-
-void ThreadCondition::wait(Mutex& mutex)
-{
-    m_condition->wait(mutex.impl());
-}
-
-bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
-{
-    double currentTime = WTF::currentTime();
-
-    // Time is in the past - return immediately.
-    if (absoluteTime < currentTime)
-        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->wait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds));
-}
-
-void ThreadCondition::signal()
-{
-    m_condition->wakeOne();
-}
-
-void ThreadCondition::broadcast()
-{
-    m_condition->wakeAll();
-}
-
-} // namespace WebCore
-
-#include "ThreadingQt.moc"
-
-#endif
diff --git a/wtf/text/AtomicString.cpp b/wtf/text/AtomicString.cpp
deleted file mode 100644 (file)
index 0687977..0000000
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * 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
- * 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 "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 WTF {
-
-using namespace Unicode;
-
-COMPILE_ASSERT(sizeof(AtomicString) == sizeof(String), atomic_string_and_string_must_be_same_size);
-
-class AtomicStringTableLocker {
-    static OSSpinLock s_stringTableLock;
-public:
-    AtomicStringTableLocker() { OSSpinLockLock(&s_stringTableLock); }
-    ~AtomicStringTableLocker() { OSSpinLockUnlock(&s_stringTableLock); }
-};
-OSSpinLock AtomicStringTableLocker::s_stringTableLock = OS_SPINLOCK_INIT;
-
-class AtomicStringTable {
-public:
-    static AtomicStringTable* create()
-    {
-        static AtomicStringTable* sharedStringTable = new AtomicStringTable;
-
-        WTFThreadData& data = wtfThreadData();
-        if (pthread_main_np() || WTF::isWebThread())
-            data.m_atomicStringTable = sharedStringTable;
-        else
-            data.m_atomicStringTable = new AtomicStringTable;
-
-        // The AtomicStringTable is shared between the main UI thread and the
-        // WebThread. We do the following so that its destruction happens only
-        // once - on the main UI thread.
-        if (!WTF::isWebThread())
-            data.m_atomicStringTableDestructor = AtomicStringTable::destroy;
-        return data.m_atomicStringTable;
-    }
-
-    HashSet<StringImpl*>& table()
-    {
-        return m_table;
-    }
-
-private:
-    static void destroy(AtomicStringTable* table)
-    {
-        HashSet<StringImpl*>::iterator end = table->m_table.end();
-        for (HashSet<StringImpl*>::iterator iter = table->m_table.begin(); iter != end; ++iter)
-            (*iter)->setIsAtomic(false);
-        delete table;
-    }
-
-    HashSet<StringImpl*> m_table;
-};
-
-static inline HashSet<StringImpl*>& stringTable()
-{
-    // Once possible we should make this non-lazy (constructed in WTFThreadData's constructor).
-    AtomicStringTable* table = wtfThreadData().atomicStringTable();
-    if (UNLIKELY(!table))
-        table = AtomicStringTable::create();
-    return table->table();
-}
-
-template<typename T, typename HashTranslator>
-static inline PassRefPtr<StringImpl> addToStringTable(const T& value)
-{
-    pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<T, HashTranslator>(value);
-
-    // If the string is newly-translated, then we need to adopt it.
-    // The boolean in the pair tells us if that is so.
-    return addResult.second ? adoptRef(*addResult.first) : *addResult.first;
-}
-
-struct CStringTranslator {
-    static unsigned hash(const char* c)
-    {
-        return StringHasher::computeHash(c);
-    }
-
-    static bool equal(StringImpl* r, const char* s)
-    {
-        int length = r->length();
-        const UChar* d = r->characters();
-        for (int i = 0; i != length; ++i) {
-            unsigned char c = s[i];
-            if (d[i] != c)
-                return false;
-        }
-        return !s[length];
-    }
-
-    static void translate(StringImpl*& location, const char* const& c, unsigned hash)
-    {
-        location = StringImpl::create(c).leakRef();
-        location->setHash(hash);
-        location->setIsAtomic(true);
-    }
-};
-
-bool operator==(const AtomicString& a, const char* b)
-{ 
-    StringImpl* impl = a.impl();
-    if ((!impl || !impl->characters()) && !b)
-        return true;
-    if ((!impl || !impl->characters()) || !b)
-        return false;
-    return CStringTranslator::equal(impl, b); 
-}
-
-PassRefPtr<StringImpl> AtomicString::add(const char* c)
-{
-    if (!c)
-        return 0;
-    if (!*c)
-        return StringImpl::empty();
-
-    AtomicStringTableLocker locker;
-    return addToStringTable<const char*, CStringTranslator>(c);
-}
-
-struct UCharBuffer {
-    const UChar* s;
-    unsigned length;
-};
-
-static inline bool equal(StringImpl* string, const UChar* characters, unsigned length)
-{
-    if (string->length() != length)
-        return false;
-
-    // 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) || CPU(SPARC)
-    const UChar* stringCharacters = string->characters();
-    for (unsigned i = 0; i != length; ++i) {
-        if (*stringCharacters++ != *characters++)
-            return false;
-    }
-    return true;
-#else
-    /* Do it 4-bytes-at-a-time on architectures where it's safe */
-
-    const uint32_t* stringCharacters = reinterpret_cast<const uint32_t*>(string->characters());
-    const uint32_t* bufferCharacters = reinterpret_cast<const uint32_t*>(characters);
-
-    unsigned halfLength = length >> 1;
-    for (unsigned i = 0; i != halfLength; ++i) {
-        if (*stringCharacters++ != *bufferCharacters++)
-            return false;
-    }
-
-    if (length & 1 &&  *reinterpret_cast<const uint16_t*>(stringCharacters) != *reinterpret_cast<const uint16_t*>(bufferCharacters))
-        return false;
-
-    return true;
-#endif
-}
-
-bool operator==(const AtomicString& string, const Vector<UChar>& vector)
-{
-    return string.impl() && equal(string.impl(), vector.data(), vector.size());
-}
-
-struct UCharBufferTranslator {
-    static unsigned hash(const UCharBuffer& buf)
-    {
-        return StringHasher::computeHash(buf.s, buf.length);
-    }
-
-    static bool equal(StringImpl* const& str, const UCharBuffer& buf)
-    {
-        return WTF::equal(str, buf.s, buf.length);
-    }
-
-    static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash)
-    {
-        location = StringImpl::create(buf.s, buf.length).leakRef();
-        location->setHash(hash);
-        location->setIsAtomic(true);
-    }
-};
-
-struct HashAndCharacters {
-    unsigned hash;
-    const UChar* characters;
-    unsigned length;
-};
-
-struct HashAndCharactersTranslator {
-    static unsigned hash(const HashAndCharacters& buffer)
-    {
-        ASSERT(buffer.hash == StringHasher::computeHash(buffer.characters, buffer.length));
-        return buffer.hash;
-    }
-
-    static bool equal(StringImpl* const& string, const HashAndCharacters& buffer)
-    {
-        return WTF::equal(string, buffer.characters, buffer.length);
-    }
-
-    static void translate(StringImpl*& location, const HashAndCharacters& buffer, unsigned hash)
-    {
-        location = StringImpl::create(buffer.characters, buffer.length).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);
-    }
-};
-
-PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length)
-{
-    if (!s)
-        return 0;
-
-    if (!length)
-        return StringImpl::empty();
-    
-    UCharBuffer buffer = { s, length };
-    AtomicStringTableLocker locker;
-    return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
-}
-
-PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length, unsigned existingHash)
-{
-    ASSERT(s);
-    ASSERT(existingHash);
-
-    if (!length)
-        return StringImpl::empty();
-
-    HashAndCharacters buffer = { existingHash, s, length };
-    AtomicStringTableLocker locker;
-    return addToStringTable<HashAndCharacters, HashAndCharactersTranslator>(buffer);
-}
-
-PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
-{
-    if (!s)
-        return 0;
-
-    int length = 0;
-    while (s[length] != UChar(0))
-        length++;
-
-    if (!length)
-        return StringImpl::empty();
-
-    UCharBuffer buffer = { s, length };
-    AtomicStringTableLocker locker;
-    return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
-}
-
-PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r)
-{
-    if (!r || r->isAtomic())
-        return r;
-
-    if (!r->length())
-        return StringImpl::empty();
-
-    AtomicStringTableLocker locker;
-    StringImpl* result = *stringTable().add(r).first;
-    if (result == r)
-        r->setIsAtomic(true);
-    return result;
-}
-
-AtomicStringImpl* AtomicString::find(const UChar* s, unsigned length, unsigned existingHash)
-{
-    ASSERT(s);
-    ASSERT(existingHash);
-
-    if (!length)
-        return static_cast<AtomicStringImpl*>(StringImpl::empty());
-
-    HashAndCharacters buffer = { existingHash, s, length }; 
-    AtomicStringTableLocker locker;
-    HashSet<StringImpl*>::iterator iterator = stringTable().find<HashAndCharacters, HashAndCharactersTranslator>(buffer);
-    if (iterator == stringTable().end())
-        return 0;
-    return static_cast<AtomicStringImpl*>(*iterator);
-}
-
-void AtomicString::remove(StringImpl* r)
-{
-    AtomicStringTableLocker locker;
-    stringTable().remove(r);
-}
-
-AtomicString AtomicString::lower() const
-{
-    // Note: This is a hot function in the Dromaeo benchmark.
-    StringImpl* impl = this->impl();
-    if (UNLIKELY(!impl))
-        return *this;
-    RefPtr<StringImpl> newImpl = impl->lower();
-    if (LIKELY(newImpl == impl))
-        return *this;
-    return AtomicString(newImpl);
-}
-
-AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const char* charactersEnd)
-{
-    HashAndUTF8Characters buffer;
-    buffer.characters = charactersStart;
-    buffer.hash = calculateStringHashAndLengthFromUTF8(charactersStart, charactersEnd, buffer.length, buffer.utf16Length);
-
-    if (!buffer.hash)
-        return nullAtom;
-
-    AtomicString atomicString;
-    AtomicStringTableLocker locker;
-    atomicString.m_string = addToStringTable<HashAndUTF8Characters, HashAndUTF8CharactersTranslator>(buffer);
-    return atomicString;
-}
-
-} // namespace WTF
diff --git a/wtf/text/AtomicString.h b/wtf/text/AtomicString.h
deleted file mode 100644 (file)
index 45d332f..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2004, 2005, 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.
- *
- */
-
-#ifndef AtomicString_h
-#define AtomicString_h
-
-#include "AtomicStringImpl.h"
-#include "WTFString.h"
-
-// Define 'NO_IMPLICIT_ATOMICSTRING' before including this header,
-// to disallow (expensive) implicit String-->AtomicString conversions.
-#ifdef NO_IMPLICIT_ATOMICSTRING
-#define ATOMICSTRING_CONVERSION explicit
-#else
-#define ATOMICSTRING_CONVERSION
-#endif
-
-namespace WTF {
-
-struct AtomicStringHash;
-
-class AtomicString {
-public:
-    static void init();
-
-    AtomicString() { }
-    AtomicString(const char* s) : m_string(add(s)) { }
-    AtomicString(const UChar* s, unsigned length) : m_string(add(s, length)) { }
-    AtomicString(const UChar* s, unsigned length, unsigned existingHash) : m_string(add(s, length, existingHash)) { }
-    AtomicString(const UChar* s) : m_string(add(s)) { }
-    ATOMICSTRING_CONVERSION AtomicString(StringImpl* imp) : m_string(add(imp)) { }
-    AtomicString(AtomicStringImpl* imp) : m_string(imp) { }
-    ATOMICSTRING_CONVERSION AtomicString(const String& s) : m_string(add(s.impl())) { }
-
-    // Hash table deleted values, which are only constructed and never copied or destroyed.
-    AtomicString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDeletedValue) { }
-    bool isHashTableDeletedValue() const { return m_string.isHashTableDeletedValue(); }
-
-    static AtomicStringImpl* find(const UChar* s, unsigned length, unsigned existingHash);
-
-    operator const String&() const { return m_string; }
-    const String& string() const { return m_string; };
-
-    AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl *>(m_string.impl()); }
-    
-    const UChar* characters() const { return m_string.characters(); }
-    unsigned length() const { return m_string.length(); }
-    
-    UChar operator[](unsigned int i) const { return m_string[i]; }
-    
-    bool contains(UChar c) const { return m_string.contains(c); }
-    bool contains(const char* 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); }
-
-    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); }
-    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.startsWith(s, caseSensitive); }
-    bool endsWith(const String& s, bool caseSensitive = true) const
-        { return m_string.endsWith(s, caseSensitive); }
-    
-    AtomicString lower() const;
-    AtomicString upper() const { return AtomicString(impl()->upper()); }
-    
-    int toInt(bool* ok = 0) const { return m_string.toInt(ok); }
-    double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); }
-    float toFloat(bool* ok = 0) const { return m_string.toFloat(ok); }
-    bool percentage(int& p) const { return m_string.percentage(p); }
-
-    bool isNull() const { return m_string.isNull(); }
-    bool isEmpty() const { return m_string.isEmpty(); }
-
-    static void remove(StringImpl*);
-    
-#if USE(CF)
-    AtomicString(CFStringRef s) :  m_string(add(String(s).impl())) { }
-    CFStringRef createCFString() const { return m_string.createCFString(); }
-#endif    
-#ifdef __OBJC__
-    AtomicString(NSString* s) : m_string(add(String(s).impl())) { }
-    operator NSString*() const { return m_string; }
-#endif
-#if PLATFORM(QT)
-    AtomicString(const QString& s) : m_string(add(String(s).impl())) { }
-    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;
-    
-    static PassRefPtr<StringImpl> add(const char*);
-    static PassRefPtr<StringImpl> add(const UChar*, unsigned length);
-    static PassRefPtr<StringImpl> add(const UChar*, unsigned length, unsigned existingHash);
-    static PassRefPtr<StringImpl> add(const UChar*);
-    ALWAYS_INLINE PassRefPtr<StringImpl> add(StringImpl* r)
-    {
-        if (!r || r->isAtomic())
-            return r;
-        return addSlowCase(r);
-    }
-    static PassRefPtr<StringImpl> addSlowCase(StringImpl*);
-    static AtomicString fromUTF8Internal(const char*, const char*);
-};
-
-inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); }
-bool operator==(const AtomicString& a, const char* b);
-bool operator==(const AtomicString& a, const Vector<UChar>& b);
-inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); }
-inline bool operator==(const char* a, const AtomicString& b) { return b == a; }
-inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); }
-inline bool operator==(const Vector<UChar>& a, const AtomicString& b) { return b == a; }
-
-inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); }
-inline bool operator!=(const AtomicString& a, const char *b) { return !(a == b); }
-inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a.impl(), b.impl()); }
-inline bool operator!=(const AtomicString& a, const Vector<UChar>& b) { return !(a == b); }
-inline bool operator!=(const char* a, const AtomicString& b) { return !(b == a); }
-inline bool operator!=(const String& a, const AtomicString& b) { return !equal(a.impl(), b.impl()); }
-inline bool operator!=(const Vector<UChar>& a, const AtomicString& b) { return !(a == b); }
-
-inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
-inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), b); }
-inline bool equalIgnoringCase(const AtomicString& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); }
-inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(a, b.impl()); }
-inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
-
-// 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;
-
-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
-
-// AtomicStringHash is the default hash for AtomicString
-template<typename T> struct DefaultHash;
-template<> struct DefaultHash<AtomicString> {
-    typedef AtomicStringHash Hash;
-};
-
-} // namespace WTF
-
-#ifndef ATOMICSTRING_HIDE_GLOBALS
-using WTF::AtomicString;
-using WTF::nullAtom;
-using WTF::emptyAtom;
-using WTF::textAtom;
-using WTF::commentAtom;
-using WTF::starAtom;
-using WTF::xmlAtom;
-using WTF::xmlnsAtom;
-#endif
-
-#include "StringConcatenate.h"
-#endif // AtomicString_h
diff --git a/wtf/text/AtomicStringHash.h b/wtf/text/AtomicStringHash.h
deleted file mode 100644 (file)
index f6e4ad1..0000000
+++ /dev/null
@@ -1,62 +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. 
- * 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
diff --git a/wtf/text/AtomicStringImpl.h b/wtf/text/AtomicStringImpl.h
deleted file mode 100644 (file)
index 3f0c376..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Computer, 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 AtomicStringImpl_h
-#define AtomicStringImpl_h
-
-#include "StringImpl.h"
-
-namespace WTF {
-
-class AtomicStringImpl : public StringImpl
-{
-public:
-    AtomicStringImpl() : StringImpl(0) {}
-};
-
-}
-
-using WTF::AtomicStringImpl;
-
-#endif
diff --git a/wtf/text/CString.cpp b/wtf/text/CString.cpp
deleted file mode 100644 (file)
index 981d77a..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2003, 2006, 2008, 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. 
- */
-
-
-#include "config.h"
-#include "CString.h"
-
-using namespace std;
-
-namespace WTF {
-
-CString::CString(const char* str)
-{
-    if (!str)
-        return;
-
-    init(str, strlen(str));
-}
-
-CString::CString(const char* str, size_t length)
-{
-    init(str, length);
-}
-
-void CString::init(const char* str, size_t length)
-{
-    if (!str)
-        return;
-
-    // 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->mutableData()[length] = '\0';
-}
-
-char* CString::mutableData()
-{
-    copyBufferIfNeeded();
-    if (!m_buffer)
-        return 0;
-    return m_buffer->mutableData();
-}
-    
-CString CString::newUninitialized(size_t length, char*& characterBuffer)
-{
-    if (length >= numeric_limits<size_t>::max())
-        CRASH();
-
-    CString result;
-    result.m_buffer = CStringBuffer::create(length + 1);
-    char* bytes = result.m_buffer->mutableData();
-    bytes[length] = '\0';
-    characterBuffer = bytes;
-    return result;
-}
-
-void CString::copyBufferIfNeeded()
-{
-    if (!m_buffer || m_buffer->hasOneRef())
-        return;
-
-    RefPtr<CStringBuffer> buffer = m_buffer.release();
-    size_t length = buffer->length();
-    m_buffer = CStringBuffer::create(length);
-    memcpy(m_buffer->mutableData(), buffer->data(), length);
-}
-
-bool operator==(const CString& a, const CString& b)
-{
-    if (a.isNull() != b.isNull())
-        return false;
-    if (a.length() != b.length())
-        return false;
-    return !strncmp(a.data(), b.data(), min(a.length(), b.length()));
-}
-
-} // namespace WTF
diff --git a/wtf/text/CString.h b/wtf/text/CString.h
deleted file mode 100644 (file)
index 343a7a5..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2003, 2006, 2008, 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 CString_h
-#define CString_h
-
-#include "PassRefPtr.h"
-#include "RefCounted.h"
-#include "Vector.h"
-
-namespace WTF {
-
-class CStringBuffer : public RefCounted<CStringBuffer> {
-public:
-    const char* data() { return m_vector.data(); }
-    size_t length() { return m_vector.size(); }
-
-private:
-    friend class CString;
-
-    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;
-};
-
-// A container for a null-terminated char array supporting copy-on-write
-// assignment.  The contained char array may be null.
-class CString {
-public:
-    CString() { }
-    CString(const char*);
-    CString(const char*, size_t length);
-    CString(CStringBuffer* buffer) : m_buffer(buffer) { }
-    static CString newUninitialized(size_t length, char*& characterBuffer);
-
-    const char* data() const
-    {
-        return m_buffer ? m_buffer->data() : 0;
-    }
-    char* mutableData();
-    size_t length() const
-    {
-        return m_buffer ? m_buffer->length() - 1 : 0;
-    }
-
-    bool isNull() const { return !m_buffer; }
-
-    CStringBuffer* buffer() const { return m_buffer.get(); }
-
-private:
-    void copyBufferIfNeeded();
-    void init(const char*, size_t length);
-    RefPtr<CStringBuffer> m_buffer;
-};
-
-bool operator==(const CString& a, const CString& b);
-inline bool operator!=(const CString& a, const CString& b) { return !(a == b); }
-
-} // namespace WTF
-
-using WTF::CString;
-
-#endif // CString_h
diff --git a/wtf/text/StringBuffer.h b/wtf/text/StringBuffer.h
deleted file mode 100644 (file)
index e73d38e..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must 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 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 StringBuffer_h
-#define StringBuffer_h
-
-#include <wtf/Assertions.h>
-#include <wtf/unicode/Unicode.h>
-#include <limits>
-
-namespace WTF {
-
-class StringBuffer {
-    WTF_MAKE_NONCOPYABLE(StringBuffer);
-public:
-    explicit StringBuffer(unsigned length)
-        : m_length(length)
-    {
-        if (m_length > std::numeric_limits<unsigned>::max() / sizeof(UChar))
-            CRASH();
-        m_data = static_cast<UChar*>(fastMalloc(m_length * sizeof(UChar)));
-    }
-
-    ~StringBuffer()
-    {
-        fastFree(m_data);
-    }
-
-    void shrink(unsigned newLength)
-    {
-        ASSERT(newLength <= m_length);
-        m_length = newLength;
-    }
-
-    void resize(unsigned newLength)
-    {
-        if (newLength > m_length) {
-            if (newLength > std::numeric_limits<unsigned>::max() / sizeof(UChar))
-                CRASH();
-            m_data = static_cast<UChar*>(fastRealloc(m_data, newLength * sizeof(UChar)));
-        }
-        m_length = newLength;
-    }
-
-    unsigned length() const { return m_length; }
-    UChar* characters() { return m_data; }
-
-    UChar& operator[](unsigned i) { ASSERT(i < m_length); return m_data[i]; }
-
-    UChar* release() { UChar* data = m_data; m_data = 0; return data; }
-
-private:
-    unsigned m_length;
-    UChar* m_data;
-};
-
-} // namespace WTF
-
-using WTF::StringBuffer;
-
-#endif // StringBuffer_h
diff --git a/wtf/text/StringBuilder.cpp b/wtf/text/StringBuilder.cpp
deleted file mode 100644 (file)
index dfc9ff3..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index f10af64..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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
deleted file mode 100644 (file)
index e8c6331..0000000
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * 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
diff --git a/wtf/text/StringHash.h b/wtf/text/StringHash.h
deleted file mode 100644 (file)
index c47c1d8..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved
- * Copyright (C) Research In Motion Limited 2009. 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 StringHash_h
-#define StringHash_h
-
-#include "AtomicString.h"
-#include "WTFString.h"
-#include <wtf/Forward.h>
-#include <wtf/HashTraits.h>
-#include <wtf/StringHasher.h>
-#include <wtf/unicode/Unicode.h>
-
-namespace WTF {
-
-    // The hash() functions on StringHash and CaseFoldingHash do not support
-    // null strings. get(), contains(), and add() on HashMap<String,..., StringHash>
-    // cause a null-pointer dereference when passed null strings.
-
-    // FIXME: We should really figure out a way to put the computeHash function that's
-    // currently a member function of StringImpl into this file so we can be a little
-    // closer to having all the nearly-identical hash functions in one place.
-
-    struct StringHash {
-        static unsigned hash(StringImpl* key) { return key->hash(); }
-        static bool equal(const StringImpl* a, const StringImpl* b)
-        {
-            if (a == b)
-                return true;
-            if (!a || !b)
-                return false;
-
-            unsigned aLength = a->length();
-            unsigned bLength = b->length();
-            if (aLength != bLength)
-                return false;
-
-            // 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;
-
-            return true;
-#endif
-        }
-
-        static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); }
-        static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b)
-        {
-            return equal(a.get(), b.get());
-        }
-
-        static unsigned hash(const String& key) { return key.impl()->hash(); }
-        static bool equal(const String& a, const String& b)
-        {
-            return equal(a.impl(), b.impl());
-        }
-
-        static const bool safeToCompareToEmptyOrDeleted = false;
-    };
-
-    class CaseFoldingHash {
-    public:
-        template<typename T> static inline UChar foldCase(T ch)
-        {
-            return WTF::Unicode::foldCase(ch);
-        }
-
-        static unsigned hash(const UChar* data, unsigned length)
-        {
-            return StringHasher::computeHash<UChar, foldCase<UChar> >(data, length);
-        }
-
-        static unsigned hash(StringImpl* str)
-        {
-            return hash(str->characters(), str->length());
-        }
-
-        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)
-                return true;
-            if (!a || !b)
-                return false;
-            unsigned length = a->length();
-            if (length != b->length())
-                return false;
-            return WTF::Unicode::umemcasecmp(a->characters(), b->characters(), length) == 0;
-        }
-
-        static unsigned hash(const RefPtr<StringImpl>& key) 
-        {
-            return hash(key.get());
-        }
-
-        static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b)
-        {
-            return equal(a.get(), b.get());
-        }
-
-        static unsigned hash(const String& key)
-        {
-            return hash(key.impl());
-        }
-        static unsigned hash(const AtomicString& key)
-        {
-            return hash(key.impl());
-        }
-        static bool equal(const String& a, const String& b)
-        {
-            return equal(a.impl(), b.impl());
-        }
-        static bool equal(const AtomicString& a, const AtomicString& b)
-        {
-            return (a == b) || equal(a.impl(), b.impl());
-        }
-
-        static const bool safeToCompareToEmptyOrDeleted = false;
-    };
-
-    // This hash can be used in cases where the key is a hash of a string, but we don't
-    // want to store the string. It's not really specific to string hashing, but all our
-    // current uses of it are for strings.
-    struct AlreadyHashed : IntHash<unsigned> {
-        static unsigned hash(unsigned key) { return key; }
-
-        // To use a hash value as a key for a hash table, we need to eliminate the
-        // "deleted" value, which is negative one. That could be done by changing
-        // the string hash function to never generate negative one, but this works
-        // and is still relatively efficient.
-        static unsigned avoidDeletedValue(unsigned hash)
-        {
-            ASSERT(hash);
-            unsigned newHash = hash | (!(hash + 1) << 31);
-            ASSERT(newHash);
-            ASSERT(newHash != 0xFFFFFFFF);
-            return newHash;
-        }
-    };
-
-    template<> struct HashTraits<String> : SimpleClassHashTraits<String> { };
-
-}
-
-using WTF::StringHash;
-using WTF::CaseFoldingHash;
-using WTF::AlreadyHashed;
-
-#endif
diff --git a/wtf/text/StringImpl.cpp b/wtf/text/StringImpl.cpp
deleted file mode 100644 (file)
index ec0c094..0000000
+++ /dev/null
@@ -1,1099 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- *           (C) 2001 Dirk Mueller ( mueller@kde.org )
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
- *
- * 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 "StringImpl.h"
-
-#include "AtomicString.h"
-#include "StringBuffer.h"
-#include "StringHash.h"
-#include <wtf/StdLibExtras.h>
-#include <wtf/WTFThreadData.h>
-
-using namespace std;
-
-namespace WTF {
-
-using namespace Unicode;
-
-static const unsigned minLengthToShare = 20;
-
-COMPILE_ASSERT(sizeof(StringImpl) == 2 * sizeof(int) + 3 * sizeof(void*), StringImpl_should_stay_small);
-
-StringImpl::~StringImpl()
-{
-    ASSERT(!isStatic());
-
-    if (isAtomic())
-        AtomicString::remove(this);
-#if USE(JSC)
-    if (isIdentifier()) {
-        if (!wtfThreadData().currentIdentifierTable()->remove(this))
-            CRASH();
-    }
-#endif
-
-    BufferOwnership ownership = bufferOwnership();
-    if (ownership != BufferInternal) {
-        if (ownership == BufferOwned) {
-            ASSERT(!m_sharedBuffer);
-            ASSERT(m_data);
-            fastFree(const_cast<UChar*>(m_data));
-        } else if (ownership == BufferSubstring) {
-            ASSERT(m_substringBuffer);
-            m_substringBuffer->deref();
-        } else {
-            ASSERT(ownership == BufferShared);
-            ASSERT(m_sharedBuffer);
-            m_sharedBuffer->deref();
-        }
-    }
-}
-
-PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& data)
-{
-    if (!length) {
-        data = 0;
-        return empty();
-    }
-
-    // Allocate a single buffer large enough to contain the StringImpl
-    // struct as well as the data which it contains. This removes one 
-    // heap allocation from this call.
-    if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar)))
-        CRASH();
-    size_t size = sizeof(StringImpl) + length * sizeof(UChar);
-    StringImpl* string = static_cast<StringImpl*>(fastMalloc(size));
-
-    data = reinterpret_cast<UChar*>(string + 1);
-    return adoptRef(new (string) StringImpl(length));
-}
-
-PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length)
-{
-    if (!characters || !length)
-        return empty();
-
-    UChar* data;
-    RefPtr<StringImpl> string = createUninitialized(length, data);
-    memcpy(data, characters, length * sizeof(UChar));
-    return string.release();
-}
-
-PassRefPtr<StringImpl> StringImpl::create(const char* characters, unsigned length)
-{
-    if (!characters || !length)
-        return empty();
-
-    UChar* data;
-    RefPtr<StringImpl> string = createUninitialized(length, data);
-    for (unsigned i = 0; i != length; ++i) {
-        unsigned char c = characters[i];
-        data[i] = c;
-    }
-    return string.release();
-}
-
-PassRefPtr<StringImpl> StringImpl::create(const char* string)
-{
-    if (!string)
-        return empty();
-    size_t length = strlen(string);
-    if (length > numeric_limits<unsigned>::max())
-        CRASH();
-    return create(string, length);
-}
-
-PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer)
-{
-    ASSERT(characters);
-    ASSERT(minLengthToShare && length >= minLengthToShare);
-    return adoptRef(new StringImpl(characters, length, sharedBuffer));
-}
-
-SharedUChar* StringImpl::sharedBuffer()
-{
-    if (m_length < minLengthToShare)
-        return 0;
-    // All static strings are smaller that the minimim length to share.
-    ASSERT(!isStatic());
-
-    BufferOwnership ownership = bufferOwnership();
-
-    if (ownership == BufferInternal)
-        return 0;
-    if (ownership == BufferSubstring)
-        return m_substringBuffer->sharedBuffer();
-    if (ownership == BufferOwned) {
-        ASSERT(!m_sharedBuffer);
-        m_sharedBuffer = SharedUChar::create(new SharableUChar(m_data)).leakRef();
-        m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared;
-    }
-
-    ASSERT(bufferOwnership() == BufferShared);
-    ASSERT(m_sharedBuffer);
-    return m_sharedBuffer;
-}
-
-bool StringImpl::containsOnlyWhitespace()
-{
-    // FIXME: The definition of whitespace here includes a number of characters
-    // that are not whitespace from the point of view of RenderText; I wonder if
-    // that's a problem in practice.
-    for (unsigned i = 0; i < m_length; i++)
-        if (!isASCIISpace(m_data[i]))
-            return false;
-    return true;
-}
-
-PassRefPtr<StringImpl> StringImpl::substring(unsigned start, unsigned length)
-{
-    if (start >= m_length)
-        return empty();
-    unsigned maxLength = m_length - start;
-    if (length >= maxLength) {
-        if (!start)
-            return this;
-        length = maxLength;
-    }
-    return create(m_data + start, length);
-}
-
-UChar32 StringImpl::characterStartingAt(unsigned i)
-{
-    if (U16_IS_SINGLE(m_data[i]))
-        return m_data[i];
-    if (i + 1 < m_length && U16_IS_LEAD(m_data[i]) && U16_IS_TRAIL(m_data[i + 1]))
-        return U16_GET_SUPPLEMENTARY(m_data[i], m_data[i + 1]);
-    return 0;
-}
-
-PassRefPtr<StringImpl> StringImpl::lower()
-{
-    // Note: This is a hot function in the Dromaeo benchmark, specifically the
-    // no-op code path up through the first 'return' statement.
-    
-    // First scan the string for uppercase and non-ASCII characters:
-    UChar ored = 0;
-    bool noUpper = true;
-    const UChar *end = m_data + m_length;
-    for (const UChar* chp = m_data; chp != end; chp++) {
-        if (UNLIKELY(isASCIIUpper(*chp)))
-            noUpper = false;
-        ored |= *chp;
-    }
-    
-    // Nothing to do if the string is all ASCII with no uppercase.
-    if (noUpper && !(ored & ~0x7F))
-        return this;
-
-    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
-        CRASH();
-    int32_t length = m_length;
-
-    UChar* data;
-    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
-
-    if (!(ored & ~0x7F)) {
-        // Do a faster loop for the case where all the characters are ASCII.
-        for (int i = 0; i < length; i++) {
-            UChar c = m_data[i];
-            data[i] = toASCIILower(c);
-        }
-        return newImpl;
-    }
-    
-    // Do a slower implementation for cases that include non-ASCII characters.
-    bool error;
-    int32_t realLength = Unicode::toLower(data, length, m_data, m_length, &error);
-    if (!error && realLength == length)
-        return newImpl;
-    newImpl = createUninitialized(realLength, data);
-    Unicode::toLower(data, realLength, m_data, m_length, &error);
-    if (error)
-        return this;
-    return newImpl;
-}
-
-PassRefPtr<StringImpl> StringImpl::upper()
-{
-    // This function could be optimized for no-op cases the way lower() is,
-    // but in empirical testing, few actual calls to upper() are no-ops, so
-    // it wouldn't be worth the extra time for pre-scanning.
-    UChar* data;
-    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
-
-    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
-        CRASH();
-    int32_t length = m_length;
-
-    // Do a faster loop for the case where all the characters are ASCII.
-    UChar ored = 0;
-    for (int i = 0; i < length; i++) {
-        UChar c = m_data[i];
-        ored |= c;
-        data[i] = toASCIIUpper(c);
-    }
-    if (!(ored & ~0x7F))
-        return newImpl.release();
-
-    // Do a slower implementation for cases that include non-ASCII characters.
-    bool error;
-    int32_t realLength = Unicode::toUpper(data, length, m_data, m_length, &error);
-    if (!error && realLength == length)
-        return newImpl;
-    newImpl = createUninitialized(realLength, data);
-    Unicode::toUpper(data, realLength, m_data, m_length, &error);
-    if (error)
-        return this;
-    return newImpl.release();
-}
-
-PassRefPtr<StringImpl> StringImpl::secure(UChar character, LastCharacterBehavior behavior)
-{
-    if (!m_length)
-        return this;
-
-    UChar* data;
-    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
-    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();
-}
-
-PassRefPtr<StringImpl> StringImpl::foldCase()
-{
-    UChar* data;
-    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
-
-    if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max()))
-        CRASH();
-    int32_t length = m_length;
-
-    // Do a faster loop for the case where all the characters are ASCII.
-    UChar ored = 0;
-    for (int32_t i = 0; i < length; i++) {
-        UChar c = m_data[i];
-        ored |= c;
-        data[i] = toASCIILower(c);
-    }
-    if (!(ored & ~0x7F))
-        return newImpl.release();
-
-    // Do a slower implementation for cases that include non-ASCII characters.
-    bool error;
-    int32_t realLength = Unicode::foldCase(data, length, m_data, m_length, &error);
-    if (!error && realLength == length)
-        return newImpl.release();
-    newImpl = createUninitialized(realLength, data);
-    Unicode::foldCase(data, realLength, m_data, m_length, &error);
-    if (error)
-        return this;
-    return newImpl.release();
-}
-
-PassRefPtr<StringImpl> StringImpl::stripWhiteSpace()
-{
-    if (!m_length)
-        return empty();
-
-    unsigned start = 0;
-    unsigned end = m_length - 1;
-    
-    // skip white space from start
-    while (start <= end && isSpaceOrNewline(m_data[start]))
-        start++;
-    
-    // only white space
-    if (start > end) 
-        return empty();
-
-    // skip white space from end
-    while (end && isSpaceOrNewline(m_data[end]))
-        end--;
-
-    if (!start && end == m_length - 1)
-        return this;
-    return create(m_data + start, end + 1 - start);
-}
-
-PassRefPtr<StringImpl> StringImpl::removeCharacters(CharacterMatchFunctionPtr findMatch)
-{
-    const UChar* from = m_data;
-    const UChar* fromend = from + m_length;
-
-    // Assume the common case will not remove any characters
-    while (from != fromend && !findMatch(*from))
-        from++;
-    if (from == fromend)
-        return this;
-
-    StringBuffer data(m_length);
-    UChar* to = data.characters();
-    unsigned outc = from - m_data;
-
-    if (outc)
-        memcpy(to, m_data, outc * sizeof(UChar));
-
-    while (true) {
-        while (from != fromend && findMatch(*from))
-            from++;
-        while (from != fromend && !findMatch(*from))
-            to[outc++] = *from++;
-        if (from == fromend)
-            break;
-    }
-
-    data.shrink(outc);
-
-    return adopt(data);
-}
-
-PassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace()
-{
-    StringBuffer data(m_length);
-
-    const UChar* from = m_data;
-    const UChar* fromend = from + m_length;
-    int outc = 0;
-    bool changedToSpace = false;
-    
-    UChar* to = data.characters();
-    
-    while (true) {
-        while (from != fromend && isSpaceOrNewline(*from)) {
-            if (*from != ' ')
-                changedToSpace = true;
-            from++;
-        }
-        while (from != fromend && !isSpaceOrNewline(*from))
-            to[outc++] = *from++;
-        if (from != fromend)
-            to[outc++] = ' ';
-        else
-            break;
-    }
-    
-    if (outc > 0 && to[outc - 1] == ' ')
-        outc--;
-    
-    if (static_cast<unsigned>(outc) == m_length && !changedToSpace)
-        return this;
-    
-    data.shrink(outc);
-    
-    return adopt(data);
-}
-
-int StringImpl::toIntStrict(bool* ok, int base)
-{
-    return charactersToIntStrict(m_data, m_length, ok, base);
-}
-
-unsigned StringImpl::toUIntStrict(bool* ok, int base)
-{
-    return charactersToUIntStrict(m_data, m_length, ok, base);
-}
-
-int64_t StringImpl::toInt64Strict(bool* ok, int base)
-{
-    return charactersToInt64Strict(m_data, m_length, ok, base);
-}
-
-uint64_t StringImpl::toUInt64Strict(bool* ok, int base)
-{
-    return charactersToUInt64Strict(m_data, m_length, ok, base);
-}
-
-intptr_t StringImpl::toIntPtrStrict(bool* ok, int base)
-{
-    return charactersToIntPtrStrict(m_data, m_length, ok, base);
-}
-
-int StringImpl::toInt(bool* ok)
-{
-    return charactersToInt(m_data, m_length, ok);
-}
-
-unsigned StringImpl::toUInt(bool* ok)
-{
-    return charactersToUInt(m_data, m_length, ok);
-}
-
-int64_t StringImpl::toInt64(bool* ok)
-{
-    return charactersToInt64(m_data, m_length, ok);
-}
-
-uint64_t StringImpl::toUInt64(bool* ok)
-{
-    return charactersToUInt64(m_data, m_length, ok);
-}
-
-intptr_t StringImpl::toIntPtr(bool* ok)
-{
-    return charactersToIntPtr(m_data, m_length, ok);
-}
-
-double StringImpl::toDouble(bool* ok, bool* didReadNumber)
-{
-    return charactersToDouble(m_data, m_length, ok, didReadNumber);
-}
-
-float StringImpl::toFloat(bool* ok, bool* didReadNumber)
-{
-    return charactersToFloat(m_data, m_length, ok, didReadNumber);
-}
-
-static bool equal(const UChar* a, const char* b, int length)
-{
-    ASSERT(length >= 0);
-    while (length--) {
-        unsigned char bc = *b++;
-        if (*a++ != bc)
-            return false;
-    }
-    return true;
-}
-
-bool equalIgnoringCase(const UChar* a, const char* b, unsigned length)
-{
-    while (length--) {
-        unsigned char bc = *b++;
-        if (foldCase(*a++) != foldCase(bc))
-            return false;
-    }
-    return true;
-}
-
-static inline bool equalIgnoringCase(const UChar* a, const UChar* b, int length)
-{
-    ASSERT(length >= 0);
-    return umemcasecmp(a, b, length) == 0;
-}
-
-int codePointCompare(const StringImpl* s1, const StringImpl* s2)
-{
-    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;
-
-    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();
-    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;
-}
-
-size_t StringImpl::findIgnoringCase(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();
-    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;
-}
-
-size_t StringImpl::find(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::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);
-    
-    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* matchString, bool caseSensitive)
-{
-    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;
-}
-
-PassRefPtr<StringImpl> StringImpl::replace(UChar oldC, UChar newC)
-{
-    if (oldC == newC)
-        return this;
-    unsigned i;
-    for (i = 0; i != m_length; ++i)
-        if (m_data[i] == oldC)
-            break;
-    if (i == m_length)
-        return this;
-
-    UChar* data;
-    RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
-
-    for (i = 0; i != m_length; ++i) {
-        UChar ch = m_data[i];
-        if (ch == oldC)
-            ch = newC;
-        data[i] = ch;
-    }
-    return newImpl.release();
-}
-
-PassRefPtr<StringImpl> StringImpl::replace(unsigned position, unsigned lengthToReplace, StringImpl* str)
-{
-    position = min(position, length());
-    lengthToReplace = min(lengthToReplace, length() - position);
-    unsigned lengthToInsert = str ? str->length() : 0;
-    if (!lengthToReplace && !lengthToInsert)
-        return this;
-    UChar* data;
-
-    if ((length() - lengthToReplace) >= (numeric_limits<unsigned>::max() - lengthToInsert))
-        CRASH();
-
-    RefPtr<StringImpl> newImpl =
-        createUninitialized(length() - lengthToReplace + lengthToInsert, data);
-    memcpy(data, characters(), position * sizeof(UChar));
-    if (str)
-        memcpy(data + position, str->characters(), lengthToInsert * sizeof(UChar));
-    memcpy(data + position + lengthToInsert, characters() + position + lengthToReplace,
-        (length() - position - lengthToReplace) * sizeof(UChar));
-    return newImpl.release();
-}
-
-PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacement)
-{
-    if (!replacement)
-        return this;
-        
-    unsigned repStrLength = replacement->length();
-    size_t srcSegmentStart = 0;
-    unsigned matchCount = 0;
-    
-    // Count the matches
-    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) {
-        ++matchCount;
-        ++srcSegmentStart;
-    }
-    
-    // If we have 0 matches, we don't have to do any more work
-    if (!matchCount)
-        return this;
-    
-    if (repStrLength && matchCount > numeric_limits<unsigned>::max() / repStrLength)
-        CRASH();
-
-    unsigned replaceSize = matchCount * repStrLength;
-    unsigned newSize = m_length - matchCount;
-    if (newSize >= (numeric_limits<unsigned>::max() - replaceSize))
-        CRASH();
-
-    newSize += replaceSize;
-
-    UChar* data;
-    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
-
-    // Construct the new data
-    size_t srcSegmentEnd;
-    unsigned srcSegmentLength;
-    srcSegmentStart = 0;
-    unsigned dstOffset = 0;
-    
-    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) {
-        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
-        memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
-        dstOffset += srcSegmentLength;
-        memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar));
-        dstOffset += repStrLength;
-        srcSegmentStart = srcSegmentEnd + 1;
-    }
-
-    srcSegmentLength = m_length - srcSegmentStart;
-    memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
-
-    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
-
-    return newImpl.release();
-}
-
-PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* replacement)
-{
-    if (!pattern || !replacement)
-        return this;
-
-    unsigned patternLength = pattern->length();
-    if (!patternLength)
-        return this;
-        
-    unsigned repStrLength = replacement->length();
-    size_t srcSegmentStart = 0;
-    unsigned matchCount = 0;
-    
-    // Count the matches
-    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) {
-        ++matchCount;
-        srcSegmentStart += patternLength;
-    }
-    
-    // If we have 0 matches, we don't have to do any more work
-    if (!matchCount)
-        return this;
-    
-    unsigned newSize = m_length - matchCount * patternLength;
-    if (repStrLength && matchCount > numeric_limits<unsigned>::max() / repStrLength)
-        CRASH();
-
-    if (newSize > (numeric_limits<unsigned>::max() - matchCount * repStrLength))
-        CRASH();
-
-    newSize += matchCount * repStrLength;
-
-    UChar* data;
-    RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
-    
-    // Construct the new data
-    size_t srcSegmentEnd;
-    unsigned srcSegmentLength;
-    srcSegmentStart = 0;
-    unsigned dstOffset = 0;
-    
-    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) {
-        srcSegmentLength = srcSegmentEnd - srcSegmentStart;
-        memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
-        dstOffset += srcSegmentLength;
-        memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar));
-        dstOffset += repStrLength;
-        srcSegmentStart = srcSegmentEnd + patternLength;
-    }
-
-    srcSegmentLength = m_length - srcSegmentStart;
-    memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
-
-    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
-
-    return newImpl.release();
-}
-
-bool equal(const StringImpl* a, const StringImpl* b)
-{
-    return StringHash::equal(a, b);
-}
-
-bool equal(const StringImpl* a, const char* b)
-{
-    if (!a)
-        return !b;
-    if (!b)
-        return !a;
-
-    unsigned length = a->length();
-    const UChar* as = a->characters();
-    for (unsigned i = 0; i != length; ++i) {
-        unsigned char bc = b[i];
-        if (!bc)
-            return false;
-        if (as[i] != bc)
-            return false;
-    }
-
-    return !b[length];
-}
-
-bool equalIgnoringCase(StringImpl* a, StringImpl* b)
-{
-    return CaseFoldingHash::equal(a, b);
-}
-
-bool equalIgnoringCase(StringImpl* a, const char* b)
-{
-    if (!a)
-        return !b;
-    if (!b)
-        return !a;
-
-    unsigned length = a->length();
-    const UChar* as = a->characters();
-
-    // Do a faster loop for the case where all the characters are ASCII.
-    UChar ored = 0;
-    bool equal = true;
-    for (unsigned i = 0; i != length; ++i) {
-        char bc = b[i];
-        if (!bc)
-            return false;
-        UChar ac = as[i];
-        ored |= ac;
-        equal = equal && (toASCIILower(ac) == toASCIILower(bc));
-    }
-
-    // Do a slower implementation for cases that include non-ASCII characters.
-    if (ored & ~0x7F) {
-        equal = true;
-        for (unsigned i = 0; i != length; ++i) {
-            unsigned char bc = b[i];
-            equal = equal && (foldCase(as[i]) == foldCase(bc));
-        }
-    }
-
-    return equal && !b[length];
-}
-
-bool equalIgnoringNullity(StringImpl* a, StringImpl* b)
-{
-    if (StringHash::equal(a, b))
-        return true;
-    if (!a && b && !b->length())
-        return true;
-    if (!b && a && !a->length())
-        return true;
-
-    return false;
-}
-
-WTF::Unicode::Direction StringImpl::defaultWritingDirection(bool* hasStrongDirectionality)
-{
-    for (unsigned i = 0; i < m_length; ++i) {
-        WTF::Unicode::Direction charDirection = WTF::Unicode::direction(m_data[i]);
-        if (charDirection == WTF::Unicode::LeftToRight) {
-            if (hasStrongDirectionality)
-                *hasStrongDirectionality = true;
-            return WTF::Unicode::LeftToRight;
-        }
-        if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unicode::RightToLeftArabic) {
-            if (hasStrongDirectionality)
-                *hasStrongDirectionality = true;
-            return WTF::Unicode::RightToLeft;
-        }
-    }
-    if (hasStrongDirectionality)
-        *hasStrongDirectionality = false;
-    return WTF::Unicode::LeftToRight;
-}
-
-// This is a hot function because it's used when parsing HTML.
-PassRefPtr<StringImpl> StringImpl::createStrippingNullCharactersSlowCase(const UChar* characters, unsigned length)
-{
-    StringBuffer strippedCopy(length);
-    unsigned strippedLength = 0;
-    for (unsigned i = 0; i < length; i++) {
-        if (int c = characters[i])
-            strippedCopy[strippedLength++] = c;
-    }
-    ASSERT(strippedLength < length);  // Only take the slow case when stripping.
-    strippedCopy.shrink(strippedLength);
-    return adopt(strippedCopy);
-}
-
-PassRefPtr<StringImpl> StringImpl::adopt(StringBuffer& buffer)
-{
-    unsigned length = buffer.length();
-    if (length == 0)
-        return empty();
-    return adoptRef(new StringImpl(buffer.release(), length));
-}
-
-int StringImpl::wordCount(int maxWordsToCount)
-{
-    unsigned wordCount = 0;
-    unsigned i;
-    bool atWord = false;
-    for (i = 0; i < m_length; i++) {
-        if (u_isspace(m_data[i])) {
-            atWord = false;
-        } else if (!atWord) {
-            wordCount++;
-            if (wordCount >= (unsigned)maxWordsToCount)
-                return wordCount;
-            atWord = true;
-        }
-    }
-    return wordCount;
-}
-
-PassRefPtr<StringImpl> StringImpl::createWithTerminatingNullCharacter(const StringImpl& string)
-{
-    // Use createUninitialized instead of 'new StringImpl' so that the string and its buffer
-    // get allocated in a single memory block.
-    UChar* data;
-    unsigned length = string.m_length;
-    if (length >= numeric_limits<unsigned>::max())
-        CRASH();
-    RefPtr<StringImpl> terminatedString = createUninitialized(length + 1, data);
-    memcpy(data, string.m_data, length * sizeof(UChar));
-    data[length] = 0;
-    terminatedString->m_length--;
-    terminatedString->m_hash = string.m_hash;
-    terminatedString->m_refCountAndFlags |= s_refCountFlagHasTerminatingNullCharacter;
-    return terminatedString.release();
-}
-
-PassRefPtr<StringImpl> StringImpl::threadsafeCopy() const
-{
-    return create(m_data, m_length);
-}
-
-PassRefPtr<StringImpl> StringImpl::crossThreadString()
-{
-    if (SharedUChar* sharedBuffer = this->sharedBuffer())
-        return adoptRef(new StringImpl(m_data, m_length, sharedBuffer->crossThreadCopy()));
-
-    // If no shared buffer is available, create a copy.
-    return threadsafeCopy();
-}
-
-} // namespace WTF
diff --git a/wtf/text/StringImpl.h b/wtf/text/StringImpl.h
deleted file mode 100644 (file)
index 239ab49..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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 StringImpl_h
-#define StringImpl_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/StringHasher.h>
-#include <wtf/Vector.h>
-#include <wtf/text/StringImplBase.h>
-#include <wtf/unicode/Unicode.h>
-
-#if USE(CF)
-typedef const struct __CFString * CFStringRef;
-#endif
-
-#ifdef __OBJC__
-@class NSString;
-#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 JSC {
-struct IdentifierCStringTranslator;
-struct IdentifierUCharBufferTranslator;
-}
-
-namespace WTF {
-
-struct CStringTranslator;
-struct HashAndCharactersTranslator;
-struct HashAndUTF8CharactersTranslator;
-struct UCharBufferTranslator;
-
-enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive };
-
-typedef OwnFastMallocPtr<const UChar> SharableUChar;
-typedef CrossThreadRefCounted<SharableUChar> SharedUChar;
-typedef bool (*CharacterMatchFunctionPtr)(UChar);
-
-class StringImpl : public StringImplBase {
-    friend struct JSC::IdentifierCStringTranslator;
-    friend struct JSC::IdentifierUCharBufferTranslator;
-    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.
-    // This means that the static string will never be destroyed, which is important because
-    // static strings will be shared across threads & ref-counted in a non-threadsafe manner.
-    StringImpl(const UChar* characters, unsigned length, StaticStringConstructType)
-        : StringImplBase(length, ConstructStaticString)
-        , m_data(characters)
-        , m_buffer(0)
-        , m_hash(0)
-    {
-        // Ensure that the hash is computed so that AtomicStringHash can call existingHash()
-        // with impunity. The empty string is special because it is never entered into
-        // AtomicString's HashKey, but still needs to compare correctly.
-        hash();
-    }
-
-    // Create a normal string with internal storage (BufferInternal)
-    StringImpl(unsigned length)
-        : StringImplBase(length, BufferInternal)
-        , m_data(reinterpret_cast<const UChar*>(this + 1))
-        , m_buffer(0)
-        , m_hash(0)
-    {
-        ASSERT(m_data);
-        ASSERT(m_length);
-    }
-
-    // Create a StringImpl adopting ownership of the provided buffer (BufferOwned)
-    StringImpl(const UChar* characters, unsigned length)
-        : StringImplBase(length, BufferOwned)
-        , m_data(characters)
-        , m_buffer(0)
-        , m_hash(0)
-    {
-        ASSERT(m_data);
-        ASSERT(m_length);
-    }
-
-    // Used to create new strings that are a substring of an existing StringImpl (BufferSubstring)
-    StringImpl(const UChar* characters, unsigned length, PassRefPtr<StringImpl> base)
-        : StringImplBase(length, BufferSubstring)
-        , m_data(characters)
-        , m_substringBuffer(base.leakRef())
-        , m_hash(0)
-    {
-        ASSERT(m_data);
-        ASSERT(m_length);
-        ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring);
-    }
-
-    // Used to construct new strings sharing an existing SharedUChar (BufferShared)
-    StringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer)
-        : StringImplBase(length, BufferShared)
-        , m_data(characters)
-        , m_sharedBuffer(sharedBuffer.leakRef())
-        , m_hash(0)
-    {
-        ASSERT(m_data);
-        ASSERT(m_length);
-    }
-
-    // For use only by AtomicString's XXXTranslator helpers.
-    void setHash(unsigned hash)
-    {
-        ASSERT(!isStatic());
-        ASSERT(!m_hash);
-        ASSERT(hash == StringHasher::computeHash(m_data, m_length));
-        m_hash = hash;
-    }
-
-public:
-    ~StringImpl();
-
-    static PassRefPtr<StringImpl> create(const UChar*, unsigned length);
-    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 ALWAYS_INLINE PassRefPtr<StringImpl> create(PassRefPtr<StringImpl> rep, unsigned offset, unsigned length)
-    {
-        ASSERT(rep);
-        ASSERT(length <= rep->length());
-
-        if (!length)
-            return empty();
-
-        StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get();
-        return adoptRef(new StringImpl(rep->m_data + offset, length, ownerRep));
-    }
-
-    static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data);
-    static ALWAYS_INLINE PassRefPtr<StringImpl> tryCreateUninitialized(unsigned length, UChar*& output)
-    {
-        if (!length) {
-            output = 0;
-            return empty();
-        }
-
-        if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar))) {
-            output = 0;
-            return 0;
-        }
-        StringImpl* resultImpl;
-        if (!tryFastMalloc(sizeof(UChar) * length + sizeof(StringImpl)).getValue(resultImpl)) {
-            output = 0;
-            return 0;
-        }
-        output = reinterpret_cast<UChar*>(resultImpl + 1);
-        return adoptRef(new(resultImpl) StringImpl(length));
-    }
-
-    static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data); }
-    static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&);
-    static PassRefPtr<StringImpl> createStrippingNullCharacters(const UChar*, unsigned length);
-
-    template<size_t inlineCapacity>
-    static PassRefPtr<StringImpl> adopt(Vector<UChar, inlineCapacity>& vector)
-    {
-        if (size_t size = vector.size()) {
-            ASSERT(vector.data());
-            if (size > std::numeric_limits<unsigned>::max())
-                CRASH();
-            return adoptRef(new StringImpl(vector.releaseBuffer(), size));
-        }
-        return empty();
-    }
-    static PassRefPtr<StringImpl> adopt(StringBuffer&);
-
-    SharedUChar* sharedBuffer();
-    const UChar* characters() const { return m_data; }
-
-    size_t cost()
-    {
-        // For substrings, return the cost of the base string.
-        if (bufferOwnership() == BufferSubstring)
-            return m_substringBuffer->cost();
-
-        if (m_refCountAndFlags & s_refCountFlagShouldReportedCost) {
-            m_refCountAndFlags &= ~s_refCountFlagShouldReportedCost;
-            return m_length;
-        }
-        return 0;
-    }
-
-    bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; }
-    void setIsIdentifier(bool isIdentifier)
-    {
-        ASSERT(!isStatic());
-        if (isIdentifier)
-            m_refCountAndFlags |= s_refCountFlagIsIdentifier;
-        else
-            m_refCountAndFlags &= ~s_refCountFlagIsIdentifier;
-    }
-
-    bool hasTerminatingNullCharacter() const { return m_refCountAndFlags & s_refCountFlagHasTerminatingNullCharacter; }
-
-    bool isAtomic() const { return m_refCountAndFlags & s_refCountFlagIsAtomic; }
-    void setIsAtomic(bool isIdentifier)
-    {
-        ASSERT(!isStatic());
-        if (isIdentifier)
-            m_refCountAndFlags |= s_refCountFlagIsAtomic;
-        else
-            m_refCountAndFlags &= ~s_refCountFlagIsAtomic;
-    }
-
-    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; }
-
-    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; }
-
-    static StringImpl* empty();
-
-    static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters)
-    {
-        if (numCharacters <= s_copyCharsInlineCutOff) {
-            for (unsigned i = 0; i < numCharacters; ++i)
-                destination[i] = source[i];
-        } else
-            memcpy(destination, source, numCharacters * sizeof(UChar));
-    }
-
-    // Returns a StringImpl suitable for use on another thread.
-    PassRefPtr<StringImpl> crossThreadString();
-    // Makes a deep copy. Helpful only if you need to use a String on another thread
-    // (use crossThreadString if the method call doesn't need to be threadsafe).
-    // Since StringImpl objects are immutable, there's no other reason to make a copy.
-    PassRefPtr<StringImpl> threadsafeCopy() const;
-
-    PassRefPtr<StringImpl> substring(unsigned pos, unsigned len = UINT_MAX);
-
-    UChar operator[](unsigned i) { ASSERT(i < m_length); return m_data[i]; }
-    UChar32 characterStartingAt(unsigned);
-
-    bool containsOnlyWhitespace();
-
-    int toIntStrict(bool* ok = 0, int base = 10);
-    unsigned toUIntStrict(bool* ok = 0, int base = 10);
-    int64_t toInt64Strict(bool* ok = 0, int base = 10);
-    uint64_t toUInt64Strict(bool* ok = 0, int base = 10);
-    intptr_t toIntPtrStrict(bool* ok = 0, int base = 10);
-
-    int toInt(bool* ok = 0); // ignores trailing garbage
-    unsigned toUInt(bool* ok = 0); // ignores trailing garbage
-    int64_t toInt64(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, bool* didReadNumber = 0);
-    float toFloat(bool* ok = 0, bool* didReadNumber = 0);
-
-    PassRefPtr<StringImpl> lower();
-    PassRefPtr<StringImpl> upper();
-
-    enum LastCharacterBehavior { ObscureLastCharacter, DisplayLastCharacter };
-
-    PassRefPtr<StringImpl> secure(UChar, LastCharacterBehavior = ObscureLastCharacter);
-    PassRefPtr<StringImpl> foldCase();
-
-    PassRefPtr<StringImpl> stripWhiteSpace();
-    PassRefPtr<StringImpl> simplifyWhiteSpace();
-
-    PassRefPtr<StringImpl> removeCharacters(CharacterMatchFunctionPtr);
-
-    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);
-
-    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);
-    PassRefPtr<StringImpl> replace(UChar, StringImpl*);
-    PassRefPtr<StringImpl> replace(StringImpl*, StringImpl*);
-    PassRefPtr<StringImpl> replace(unsigned index, unsigned len, StringImpl*);
-
-    int wordCount(int maxWordsToCount = INT_MAX);
-
-    WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0);
-
-#if USE(CF)
-    CFStringRef createCFString();
-#endif
-#ifdef __OBJC__
-    operator NSString*();
-#endif
-
-private:
-    // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings.
-    static const unsigned s_copyCharsInlineCutOff = 20;
-
-    static PassRefPtr<StringImpl> createStrippingNullCharactersSlowCase(const UChar*, unsigned length);
-    
-    BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); }
-    bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; }
-    const UChar* m_data;
-    union {
-        void* m_buffer;
-        StringImpl* m_substringBuffer;
-        SharedUChar* m_sharedBuffer;
-    };
-    mutable unsigned m_hash;
-};
-
-bool equal(const StringImpl*, const StringImpl*);
-bool equal(const StringImpl*, const char*);
-inline bool equal(const char* a, StringImpl* b) { return equal(b, a); }
-
-bool equalIgnoringCase(StringImpl*, StringImpl*);
-bool equalIgnoringCase(StringImpl*, const char*);
-inline bool equalIgnoringCase(const char* a, StringImpl* b) { return equalIgnoringCase(b, a); }
-bool equalIgnoringCase(const UChar* a, const char* b, unsigned length);
-inline bool equalIgnoringCase(const char* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, a, length); }
-
-bool equalIgnoringNullity(StringImpl*, StringImpl*);
-
-template<size_t inlineCapacity>
-bool equalIgnoringNullity(const Vector<UChar, inlineCapacity>& a, StringImpl* b)
-{
-    if (!b)
-        return !a.size();
-    if (a.size() != b->length())
-        return false;
-    return !memcmp(a.data(), b->characters(), b->length());
-}
-
-int codePointCompare(const StringImpl*, const StringImpl*);
-
-static inline bool isSpaceOrNewline(UChar c)
-{
-    // Use isASCIISpace() for basic Latin-1.
-    // This will include newlines, which aren't included in Unicode DirWS.
-    return c <= 0x7F ? WTF::isASCIISpace(c) : WTF::Unicode::direction(c) == WTF::Unicode::WhiteSpaceNeutral;
-}
-
-// This is a hot function because it's used when parsing HTML.
-inline PassRefPtr<StringImpl> StringImpl::createStrippingNullCharacters(const UChar* characters, unsigned length)
-{
-    ASSERT(characters);
-    ASSERT(length);
-
-    // Optimize for the case where there are no Null characters by quickly
-    // searching for nulls, and then using StringImpl::create, which will
-    // memcpy the whole buffer.  This is faster than assigning character by
-    // character during the loop. 
-
-    // Fast case.
-    int foundNull = 0;
-    for (unsigned i = 0; !foundNull && i < length; i++) {
-        int c = characters[i]; // more efficient than using UChar here (at least on Intel Mac OS)
-        foundNull |= !c;
-    }
-    if (!foundNull)
-        return StringImpl::create(characters, length);
-
-    return StringImpl::createStrippingNullCharactersSlowCase(characters, length);
-}
-
-struct StringHash;
-
-// 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
diff --git a/wtf/text/StringImplBase.h b/wtf/text/StringImplBase.h
deleted file mode 100644 (file)
index 26bc1d9..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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 StringImplBase_h
-#define StringImplBase_h
-
-#include <wtf/unicode/Unicode.h>
-
-namespace WTF {
-
-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; }
-    void ref() { m_refCountAndFlags += s_refCountIncrement; }
-
-protected:
-    enum BufferOwnership {
-        BufferInternal,
-        BufferOwned,
-        BufferSubstring,
-        BufferShared,
-    };
-
-    // For SmallStringStorage, which allocates an array and uses an in-place new.
-    StringImplBase() { }
-
-    StringImplBase(unsigned length, BufferOwnership ownership)
-        : m_refCountAndFlags(s_refCountIncrement | s_refCountFlagShouldReportedCost | ownership)
-        , m_length(length)
-    {
-        ASSERT(isStringImpl());
-    }
-
-    enum StaticStringConstructType { ConstructStaticString };
-    StringImplBase(unsigned length, StaticStringConstructType)
-        : m_refCountAndFlags(s_refCountFlagStatic | s_refCountFlagIsIdentifier | BufferOwned)
-        , m_length(length)
-    {
-        ASSERT(isStringImpl());
-    }
-
-    // This constructor is not used when creating StringImpl objects,
-    // and sets the flags into a state marking the object as such.
-    enum NonStringImplConstructType { ConstructNonStringImpl };
-    StringImplBase(NonStringImplConstructType)
-        : m_refCountAndFlags(s_refCountIncrement | s_refCountInvalidForStringImpl)
-        , m_length(0)
-    {
-        ASSERT(!isStringImpl());
-    }
-
-    // The bottom 7 bits hold flags, the top 25 bits hold the ref count.
-    // When dereferencing StringImpls we check for the ref count AND the
-    // static bit both being zero - static strings are never deleted.
-    static const unsigned s_refCountMask = 0xFFFFFF80;
-    static const unsigned s_refCountIncrement = 0x80;
-    static const unsigned s_refCountFlagStatic = 0x40;
-    static const unsigned s_refCountFlagHasTerminatingNullCharacter = 0x20;
-    static const unsigned s_refCountFlagIsAtomic = 0x10;
-    static const unsigned s_refCountFlagShouldReportedCost = 0x8;
-    static const unsigned s_refCountFlagIsIdentifier = 0x4;
-    static const unsigned s_refCountMaskBufferOwnership = 0x3;
-    // An invalid permutation of flags (static & shouldReportedCost - static strings do not
-    // set shouldReportedCost in the constructor, and this bit is only ever cleared, not set).
-    // Used by "ConstructNonStringImpl" constructor, above.
-    static const unsigned s_refCountInvalidForStringImpl = s_refCountFlagStatic | s_refCountFlagShouldReportedCost;
-
-    unsigned m_refCountAndFlags;
-    unsigned m_length;
-};
-
-} // namespace WTF
-
-using WTF::StringImplBase;
-
-#endif
diff --git a/wtf/text/StringOperators.h b/wtf/text/StringOperators.h
deleted file mode 100644 (file)
index e8c2181..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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
diff --git a/wtf/text/StringStatics.cpp b/wtf/text/StringStatics.cpp
deleted file mode 100644 (file)
index 1881464..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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"
-
-#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC
-#define ATOMICSTRING_HIDE_GLOBALS 1
-#endif
-
-#include "AtomicString.h"
-#include "DynamicAnnotations.h"
-#include "StaticConstructors.h"
-#include "StringImpl.h"
-
-namespace WTF {
-
-StringImpl* StringImpl::empty()
-{
-    // FIXME: This works around a bug in our port of PCRE, that a regular expression
-    // run on the empty string may still perform a read from the first element, and
-    // as such we need this to be a valid pointer. No code should ever be reading
-    // from a zero length string, so this should be able to be a non-null pointer
-    // into the zero-page.
-    // Replace this with 'reinterpret_cast<UChar*>(static_cast<intptr_t>(1))' once
-    // 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;
-}
-
-JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, nullAtom)
-JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, emptyAtom, "")
-JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, textAtom, "#text")
-JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, commentAtom, "#comment")
-JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, starAtom, "*")
-JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, xmlAtom, "xml")
-JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, xmlnsAtom, "xmlns")
-
-void AtomicString::init()
-{
-    static bool initialized;
-    if (!initialized) {
-        // On iPhone WebKit, isMainThread() tests for the Web Thread, so use pthread_main_np() instead.
-        ASSERT(pthread_main_np());
-
-        // Use placement new to initialize the globals.
-        new ((void*)&nullAtom) AtomicString;
-        new ((void*)&emptyAtom) AtomicString("");
-        new ((void*)&textAtom) AtomicString("#text");
-        new ((void*)&commentAtom) AtomicString("#comment");
-        new ((void*)&starAtom) AtomicString("*");
-        new ((void*)&xmlAtom) AtomicString("xml");
-        new ((void*)&xmlnsAtom) AtomicString("xmlns");
-
-        initialized = true;
-    }
-}
-
-}
diff --git a/wtf/text/TextPosition.h b/wtf/text/TextPosition.h
deleted file mode 100644 (file)
index bb3ffa4..0000000
+++ /dev/null
@@ -1,150 +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.
- *
- * 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
diff --git a/wtf/text/WTFString.cpp b/wtf/text/WTFString.cpp
deleted file mode 100644 (file)
index 3ab4ff5..0000000
+++ /dev/null
@@ -1,997 +0,0 @@
-/*
- * (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple 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.
- */
-
-#include "config.h"
-#include "WTFString.h"
-
-#include <stdarg.h>
-#include <wtf/ASCIICType.h>
-#include <wtf/text/CString.h>
-#include <wtf/StringExtras.h>
-#include <wtf/Vector.h>
-#include <wtf/dtoa.h>
-#include <wtf/unicode/UTF8.h>
-#include <wtf/unicode/Unicode.h>
-
-using namespace std;
-
-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)
-        return;
-        
-    size_t len = 0;
-    while (str[len] != UChar(0))
-        len++;
-
-    if (len > numeric_limits<unsigned>::max())
-        CRASH();
-    
-    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())
-       return;
-
-    // FIXME: This is extremely inefficient. So much so that we might want to take this
-    // out of String's API. We can make it better by optimizing the case where exactly
-    // one String is pointing at this StringImpl, but even then it's going to require a
-    // call to fastMalloc every single time.
-    if (str.m_impl) {
-        if (m_impl) {
-            UChar* data;
-            if (str.length() > numeric_limits<unsigned>::max() - m_impl->length())
-                CRASH();
-            RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(m_impl->length() + str.length(), data);
-            memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar));
-            memcpy(data + m_impl->length(), str.characters(), str.length() * sizeof(UChar));
-            m_impl = newImpl.release();
-        } else
-            m_impl = str.m_impl;
-    }
-}
-
-void String::append(char c)
-{
-    // FIXME: This is extremely inefficient. So much so that we might want to take this
-    // out of String's API. We can make it better by optimizing the case where exactly
-    // one String is pointing at this StringImpl, but even then it's going to require a
-    // call to fastMalloc every single time.
-    if (m_impl) {
-        UChar* data;
-        if (m_impl->length() >= numeric_limits<unsigned>::max())
-            CRASH();
-        RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(m_impl->length() + 1, data);
-        memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar));
-        data[m_impl->length()] = c;
-        m_impl = newImpl.release();
-    } else
-        m_impl = StringImpl::create(&c, 1);
-}
-
-void String::append(UChar c)
-{
-    // FIXME: This is extremely inefficient. So much so that we might want to take this
-    // out of String's API. We can make it better by optimizing the case where exactly
-    // one String is pointing at this StringImpl, but even then it's going to require a
-    // call to fastMalloc every single time.
-    if (m_impl) {
-        UChar* data;
-        if (m_impl->length() >= numeric_limits<unsigned>::max())
-            CRASH();
-        RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(m_impl->length() + 1, data);
-        memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar));
-        data[m_impl->length()] = c;
-        m_impl = newImpl.release();
-    } else
-        m_impl = StringImpl::create(&c, 1);
-}
-
-int codePointCompare(const String& a, const String& b)
-{
-    return codePointCompare(a.impl(), b.impl());
-}
-
-void String::insert(const String& str, unsigned pos)
-{
-    if (str.isEmpty()) {
-        if (str.isNull())
-            return;
-        if (isNull())
-            m_impl = str.impl();
-        return;
-    }
-    insert(str.characters(), str.length(), pos);
-}
-
-void String::append(const UChar* charactersToAppend, unsigned lengthToAppend)
-{
-    if (!m_impl) {
-        if (!charactersToAppend)
-            return;
-        m_impl = StringImpl::create(charactersToAppend, lengthToAppend);
-        return;
-    }
-
-    if (!lengthToAppend)
-        return;
-
-    ASSERT(charactersToAppend);
-    UChar* data;
-    if (lengthToAppend > numeric_limits<unsigned>::max() - length())
-        CRASH();
-    RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(length() + lengthToAppend, data);
-    memcpy(data, characters(), length() * sizeof(UChar));
-    memcpy(data + length(), charactersToAppend, lengthToAppend * sizeof(UChar));
-    m_impl = newImpl.release();
-}
-
-void String::insert(const UChar* charactersToInsert, unsigned lengthToInsert, unsigned position)
-{
-    if (position >= length()) {
-        append(charactersToInsert, lengthToInsert);
-        return;
-    }
-
-    ASSERT(m_impl);
-
-    if (!lengthToInsert)
-        return;
-
-    ASSERT(charactersToInsert);
-    UChar* data;
-    if (lengthToInsert > numeric_limits<unsigned>::max() - length())
-        CRASH();
-    RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(length() + lengthToInsert, data);
-    memcpy(data, characters(), position * sizeof(UChar));
-    memcpy(data + position, charactersToInsert, lengthToInsert * sizeof(UChar));
-    memcpy(data + position + lengthToInsert, characters() + position, (length() - position) * sizeof(UChar));
-    m_impl = newImpl.release();
-}
-
-UChar32 String::characterStartingAt(unsigned i) const
-{
-    if (!m_impl || i >= m_impl->length())
-        return 0;
-    return m_impl->characterStartingAt(i);
-}
-
-void String::truncate(unsigned position)
-{
-    if (position >= length())
-        return;
-    UChar* data;
-    RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(position, data);
-    memcpy(data, characters(), position * sizeof(UChar));
-    m_impl = newImpl.release();
-}
-
-void String::remove(unsigned position, int lengthToRemove)
-{
-    if (lengthToRemove <= 0)
-        return;
-    if (position >= length())
-        return;
-    if (static_cast<unsigned>(lengthToRemove) > length() - position)
-        lengthToRemove = length() - position;
-    UChar* data;
-    RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(length() - lengthToRemove, data);
-    memcpy(data, characters(), position * sizeof(UChar));
-    memcpy(data + position, characters() + position + lengthToRemove,
-        (length() - lengthToRemove - position) * sizeof(UChar));
-    m_impl = newImpl.release();
-}
-
-String String::substring(unsigned pos, unsigned len) const
-{
-    if (!m_impl) 
-        return String();
-    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)
-        return String();
-    return m_impl->lower();
-}
-
-String String::upper() const
-{
-    if (!m_impl)
-        return String();
-    return m_impl->upper();
-}
-
-String String::stripWhiteSpace() const
-{
-    if (!m_impl)
-        return String();
-    return m_impl->stripWhiteSpace();
-}
-
-String String::simplifyWhiteSpace() const
-{
-    if (!m_impl)
-        return String();
-    return m_impl->simplifyWhiteSpace();
-}
-
-String String::removeCharacters(CharacterMatchFunctionPtr findMatch) const
-{
-    if (!m_impl)
-        return String();
-    return m_impl->removeCharacters(findMatch);
-}
-
-String String::foldCase() const
-{
-    if (!m_impl)
-        return String();
-    return m_impl->foldCase();
-}
-
-bool String::percentage(int& result) const
-{
-    if (!m_impl || !m_impl->length())
-        return false;
-
-    if ((*m_impl)[m_impl->length() - 1] != '%')
-       return false;
-
-    result = charactersToIntStrict(m_impl->characters(), m_impl->length() - 1);
-    return true;
-}
-
-const UChar* String::charactersWithNullTermination()
-{
-    if (!m_impl)
-        return 0;
-    if (m_impl->hasTerminatingNullCharacter())
-        return m_impl->characters();
-    m_impl = StringImpl::createWithTerminatingNullCharacter(*m_impl);
-    return m_impl->characters();
-}
-
-String String::format(const char *format, ...)
-{
-#if PLATFORM(QT)
-    // Use QString::vsprintf to avoid the locale dependent formatting of vsnprintf.
-    // https://bugs.webkit.org/show_bug.cgi?id=18994
-    va_list args;
-    va_start(args, format);
-
-    QString buffer;
-    buffer.vsprintf(format, args);
-
-    va_end(args);
-
-    QByteArray ba = buffer.toUtf8();
-    return StringImpl::create(ba.constData(), ba.length());
-
-#elif OS(WINCE)
-    va_list args;
-    va_start(args, format);
-
-    Vector<char, 256> buffer;
-
-    int bufferSize = 256;
-    buffer.resize(bufferSize);
-    for (;;) {
-        int written = vsnprintf(buffer.data(), bufferSize, format, args);
-        va_end(args);
-
-        if (written == 0)
-            return String("");
-        if (written > 0)
-            return StringImpl::create(buffer.data(), written);
-        
-        bufferSize <<= 1;
-        buffer.resize(bufferSize);
-        va_start(args, format);
-    }
-
-#else
-    va_list args;
-    va_start(args, format);
-
-    Vector<char, 256> buffer;
-
-    // Do the format once to get the length.
-#if COMPILER(MSVC)
-    int result = _vscprintf(format, args);
-#else
-    char ch;
-    int result = vsnprintf(&ch, 1, format, args);
-    // We need to call va_end() and then va_start() again here, as the
-    // contents of args is undefined after the call to vsnprintf
-    // according to http://man.cx/snprintf(3)
-    //
-    // Not calling va_end/va_start here happens to work on lots of
-    // systems, but fails e.g. on 64bit Linux.
-    va_end(args);
-    va_start(args, format);
-#endif
-
-    if (result == 0)
-        return String("");
-    if (result < 0)
-        return String();
-    unsigned len = result;
-    buffer.grow(len + 1);
-    
-    // Now do the formatting again, guaranteed to fit.
-    vsnprintf(buffer.data(), buffer.size(), format, args);
-
-    va_end(args);
-    
-    return StringImpl::create(buffer.data(), len);
-#endif
-}
-
-String String::number(short n)
-{
-    return String::format("%hd", n);
-}
-
-String String::number(unsigned short n)
-{
-    return String::format("%hu", n);
-}
-
-String String::number(int n)
-{
-    return String::format("%d", n);
-}
-
-String String::number(unsigned n)
-{
-    return String::format("%u", n);
-}
-
-String String::number(long n)
-{
-    return String::format("%ld", n);
-}
-
-String String::number(unsigned long n)
-{
-    return String::format("%lu", n);
-}
-
-String String::number(long long n)
-{
-#if OS(WINDOWS) && !PLATFORM(QT)
-    return String::format("%I64i", n);
-#else
-    return String::format("%lli", n);
-#endif
-}
-
-String String::number(unsigned long long n)
-{
-#if OS(WINDOWS) && !PLATFORM(QT)
-    return String::format("%I64u", n);
-#else
-    return String::format("%llu", n);
-#endif
-}
-    
-String String::number(double n)
-{
-    return String::format("%.6lg", n);
-}
-
-int String::toIntStrict(bool* ok, int base) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        return 0;
-    }
-    return m_impl->toIntStrict(ok, base);
-}
-
-unsigned String::toUIntStrict(bool* ok, int base) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        return 0;
-    }
-    return m_impl->toUIntStrict(ok, base);
-}
-
-int64_t String::toInt64Strict(bool* ok, int base) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        return 0;
-    }
-    return m_impl->toInt64Strict(ok, base);
-}
-
-uint64_t String::toUInt64Strict(bool* ok, int base) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        return 0;
-    }
-    return m_impl->toUInt64Strict(ok, base);
-}
-
-intptr_t String::toIntPtrStrict(bool* ok, int base) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        return 0;
-    }
-    return m_impl->toIntPtrStrict(ok, base);
-}
-
-
-int String::toInt(bool* ok) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        return 0;
-    }
-    return m_impl->toInt(ok);
-}
-
-unsigned String::toUInt(bool* ok) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        return 0;
-    }
-    return m_impl->toUInt(ok);
-}
-
-int64_t String::toInt64(bool* ok) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        return 0;
-    }
-    return m_impl->toInt64(ok);
-}
-
-uint64_t String::toUInt64(bool* ok) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        return 0;
-    }
-    return m_impl->toUInt64(ok);
-}
-
-intptr_t String::toIntPtr(bool* ok) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        return 0;
-    }
-    return m_impl->toIntPtr(ok);
-}
-
-double String::toDouble(bool* ok, bool* didReadNumber) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        if (didReadNumber)
-            *didReadNumber = false;
-        return 0.0;
-    }
-    return m_impl->toDouble(ok, didReadNumber);
-}
-
-float String::toFloat(bool* ok, bool* didReadNumber) const
-{
-    if (!m_impl) {
-        if (ok)
-            *ok = false;
-        if (didReadNumber)
-            *didReadNumber = false;
-        return 0.0f;
-    }
-    return m_impl->toFloat(ok, didReadNumber);
-}
-
-String String::threadsafeCopy() const
-{
-    if (!m_impl)
-        return String();
-    return m_impl->threadsafeCopy();
-}
-
-String String::crossThreadString() const
-{
-    if (!m_impl)
-        return String();
-    return m_impl->crossThreadString();
-}
-
-void String::split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const
-{
-    result.clear();
-
-    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 != length())
-        result.append(substring(startPos));
-}
-
-void String::split(const String& separator, Vector<String>& result) const
-{
-    split(separator, false, result);
-}
-
-void String::split(UChar separator, bool allowEmptyEntries, Vector<String>& result) const
-{
-    result.clear();
-
-    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 != length())
-        result.append(substring(startPos));
-}
-
-void String::split(UChar separator, Vector<String>& result) const
-{
-    split(String(&separator, 1), false, result);
-}
-
-CString String::ascii() const
-{
-    // 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
-{
-    // 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 > 0xff ? '?' : ch;
-    }
-
-    return result;
-}
-
-// 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)
-{
-    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 String::utf8(bool strict) const
-{
-    unsigned length = this->length();
-    const UChar* characters = this->characters();
-
-    // Allocate a buffer big enough to hold all the characters
-    // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes).
-    // Optimization ideas, if we find this function is hot:
-    //  * We could speculatively create a CStringBuffer to contain 'length' 
-    //    characters, and resize if necessary (i.e. if the buffer contains
-    //    non-ascii characters). (Alternatively, scan the buffer first for
-    //    ascii characters, so we know this will be sufficient).
-    //  * We could allocate a CStringBuffer with an appropriate size to
-    //    have a good chance of being able to write the string into the
-    //    buffer without reallocing (say, 1.5 x length).
-    if (length > numeric_limits<unsigned>::max() / 3)
-        return CString();
-    Vector<char, 1024> 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(bufferVector.data(), buffer - bufferVector.data());
-}
-
-String String::fromUTF8(const char* stringStart, size_t length)
-{
-    if (length > numeric_limits<unsigned>::max())
-        CRASH();
-
-    if (!stringStart)
-        return String();
-
-    // We'll use a StringImpl as a buffer; if the source string only contains ascii this should be
-    // the right length, if there are any multi-byte sequences this buffer will be too large.
-    UChar* buffer;
-    String stringBuffer(StringImpl::createUninitialized(length, buffer));
-    UChar* bufferEnd = buffer + length;
-
-    // Try converting into the buffer.
-    const char* stringCurrent = stringStart;
-    if (convertUTF8ToUTF16(&stringCurrent, stringStart + length, &buffer, bufferEnd) != conversionOK)
-        return String();
-
-    // stringBuffer is full (the input must have been all ascii) so just return it!
-    if (buffer == bufferEnd)
-        return stringBuffer;
-
-    // stringBuffer served its purpose as a buffer, copy the contents out into a new string.
-    unsigned utf16Length = buffer - stringBuffer.characters();
-    ASSERT(utf16Length < length);
-    return String(stringBuffer.characters(), utf16Length);
-}
-
-String String::fromUTF8(const char* string)
-{
-    if (!string)
-        return String();
-    return fromUTF8(string, strlen(string));
-}
-
-String String::fromUTF8WithLatin1Fallback(const char* string, size_t size)
-{
-    String utf8 = fromUTF8(string, size);
-    if (!utf8)
-        return String(string, size);
-    return utf8;
-}
-
-// String Operations
-
-static bool isCharacterAllowedInBase(UChar c, int base)
-{
-    if (c > 0x7F)
-        return false;
-    if (isASCIIDigit(c))
-        return c - '0' < base;
-    if (isASCIIAlpha(c)) {
-        if (base > 36)
-            base = 36;
-        return (c >= 'a' && c < 'a' + base - 10)
-            || (c >= 'A' && c < 'A' + base - 10);
-    }
-    return false;
-}
-
-template <typename IntegralType>
-static inline IntegralType toIntegralType(const UChar* data, size_t length, bool* ok, int base)
-{
-    static const IntegralType integralMax = numeric_limits<IntegralType>::max();
-    static const bool isSigned = numeric_limits<IntegralType>::is_signed;
-    const IntegralType maxMultiplier = integralMax / base;
-
-    IntegralType value = 0;
-    bool isOk = false;
-    bool isNegative = false;
-
-    if (!data)
-        goto bye;
-
-    // skip leading whitespace
-    while (length && isSpaceOrNewline(*data)) {
-        length--;
-        data++;
-    }
-
-    if (isSigned && length && *data == '-') {
-        length--;
-        data++;
-        isNegative = true;
-    } else if (length && *data == '+') {
-        length--;
-        data++;
-    }
-
-    if (!length || !isCharacterAllowedInBase(*data, base))
-        goto bye;
-
-    while (length && isCharacterAllowedInBase(*data, base)) {
-        length--;
-        IntegralType digitValue;
-        UChar c = *data;
-        if (isASCIIDigit(c))
-            digitValue = c - '0';
-        else if (c >= 'a')
-            digitValue = c - 'a' + 10;
-        else
-            digitValue = c - 'A' + 10;
-
-        if (value > maxMultiplier || (value == maxMultiplier && digitValue > (integralMax % base) + isNegative))
-            goto bye;
-
-        value = base * value + digitValue;
-        data++;
-    }
-
-#if COMPILER(MSVC)
-#pragma warning(push, 0)
-#pragma warning(disable:4146)
-#endif
-
-    if (isNegative)
-        value = -value;
-
-#if COMPILER(MSVC)
-#pragma warning(pop)
-#endif
-
-    // skip trailing space
-    while (length && isSpaceOrNewline(*data)) {
-        length--;
-        data++;
-    }
-
-    if (!length)
-        isOk = true;
-bye:
-    if (ok)
-        *ok = isOk;
-    return isOk ? value : 0;
-}
-
-static unsigned lengthOfCharactersAsInteger(const UChar* data, size_t length)
-{
-    size_t i = 0;
-
-    // Allow leading spaces.
-    for (; i != length; ++i) {
-        if (!isSpaceOrNewline(data[i]))
-            break;
-    }
-    
-    // Allow sign.
-    if (i != length && (data[i] == '+' || data[i] == '-'))
-        ++i;
-    
-    // Allow digits.
-    for (; i != length; ++i) {
-        if (!isASCIIDigit(data[i]))
-            break;
-    }
-
-    return i;
-}
-
-int charactersToIntStrict(const UChar* data, size_t length, bool* ok, int base)
-{
-    return toIntegralType<int>(data, length, ok, base);
-}
-
-unsigned charactersToUIntStrict(const UChar* data, size_t length, bool* ok, int base)
-{
-    return toIntegralType<unsigned>(data, length, ok, base);
-}
-
-int64_t charactersToInt64Strict(const UChar* data, size_t length, bool* ok, int base)
-{
-    return toIntegralType<int64_t>(data, length, ok, base);
-}
-
-uint64_t charactersToUInt64Strict(const UChar* data, size_t length, bool* ok, int base)
-{
-    return toIntegralType<uint64_t>(data, length, ok, base);
-}
-
-intptr_t charactersToIntPtrStrict(const UChar* data, size_t length, bool* ok, int base)
-{
-    return toIntegralType<intptr_t>(data, length, ok, base);
-}
-
-int charactersToInt(const UChar* data, size_t length, bool* ok)
-{
-    return toIntegralType<int>(data, lengthOfCharactersAsInteger(data, length), ok, 10);
-}
-
-unsigned charactersToUInt(const UChar* data, size_t length, bool* ok)
-{
-    return toIntegralType<unsigned>(data, lengthOfCharactersAsInteger(data, length), ok, 10);
-}
-
-int64_t charactersToInt64(const UChar* data, size_t length, bool* ok)
-{
-    return toIntegralType<int64_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10);
-}
-
-uint64_t charactersToUInt64(const UChar* data, size_t length, bool* ok)
-{
-    return toIntegralType<uint64_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10);
-}
-
-intptr_t charactersToIntPtr(const UChar* data, size_t length, bool* ok)
-{
-    return toIntegralType<intptr_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10);
-}
-
-double charactersToDouble(const UChar* data, size_t length, bool* ok, bool* didReadNumber)
-{
-    if (!length) {
-        if (ok)
-            *ok = false;
-        if (didReadNumber)
-            *didReadNumber = false;
-        return 0.0;
-    }
-
-    Vector<char, 256> bytes(length + 1);
-    for (unsigned i = 0; i < length; ++i)
-        bytes[i] = data[i] < 0x7F ? data[i] : '?';
-    bytes[length] = '\0';
-    char* start = bytes.data();
-    char* end;
-    double val = WTF::strtod(start, &end);
-    if (ok)
-        *ok = (end == 0 || *end == '\0');
-    if (didReadNumber)
-        *didReadNumber = end - start;
-    return val;
-}
-
-float charactersToFloat(const UChar* data, size_t length, bool* ok, bool* didReadNumber)
-{
-    // FIXME: This will return ok even when the string fits into a double but not a float.
-    return static_cast<float>(charactersToDouble(data, length, ok, didReadNumber));
-}
-
-const String& emptyString()
-{
-    DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty()));
-    return emptyString;
-}
-
-} // namespace WTF
-
-#ifndef NDEBUG
-// For use in the debugger
-String* string(const char*);
-Vector<char> asciiDebug(StringImpl* impl);
-Vector<char> asciiDebug(String& string);
-
-String* string(const char* 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
diff --git a/wtf/text/WTFString.h b/wtf/text/WTFString.h
deleted file mode 100644 (file)
index 71176b2..0000000
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * (C) 1999 Lars Knoll (knoll@kde.org)
- * 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
- * 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 WTFString_h
-#define WTFString_h
-
-// This file would be called String.h, but that conflicts with <string.h>
-// on systems without case-sensitive file systems.
-
-#include "StringImpl.h"
-
-#ifdef __OBJC__
-#include <objc/objc.h>
-#endif
-
-#if USE(CF)
-typedef const struct __CFString * CFStringRef;
-#endif
-
-#if PLATFORM(QT)
-QT_BEGIN_NAMESPACE
-class QString;
-QT_END_NAMESPACE
-#include <QDataStream>
-#endif
-
-#if PLATFORM(WX)
-class wxString;
-#endif
-
-#if PLATFORM(HAIKU)
-class BString;
-#endif
-
-#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
-
-namespace WTF {
-
-class CString;
-struct StringHash;
-
-// Declarations of string operations
-
-bool charactersAreAllASCII(const UChar*, size_t);
-bool charactersAreAllLatin1(const UChar*, size_t);
-int charactersToIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10);
-unsigned charactersToUIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10);
-int64_t charactersToInt64Strict(const UChar*, size_t, bool* ok = 0, int base = 10);
-uint64_t charactersToUInt64Strict(const UChar*, size_t, bool* ok = 0, int base = 10);
-intptr_t charactersToIntPtrStrict(const UChar*, size_t, bool* ok = 0, int base = 10);
-
-int charactersToInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage
-unsigned charactersToUInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage
-int64_t charactersToInt64(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, bool* didReadNumber = 0);
-float charactersToFloat(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0);
-
-template<bool isSpecialCharacter(UChar)> bool isAllSpecialCharacters(const UChar*, size_t);
-
-class String {
-public:
-    // Construct a null string, distinguishable from an empty string.
-    String() { }
-
-    // Construct a string with UTF-16 data.
-    String(const UChar* characters, unsigned length);
-
-    // 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); }
-    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(); }
-
-    StringImpl* impl() const { return m_impl.get(); }
-
-    unsigned length() const
-    {
-        if (!m_impl)
-            return 0;
-        return m_impl->length();
-    }
-
-    const UChar* characters() const
-    {
-        if (!m_impl)
-            return 0;
-        return m_impl->characters();
-    }
-
-    CString ascii() const;
-    CString latin1() const;
-    CString utf8(bool strict = false) const;
-
-    UChar operator[](unsigned index) const
-    {
-        if (!m_impl || index >= m_impl->length())
-            return 0;
-        return m_impl->characters()[index];
-    }
-
-    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();
-    
-    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
-        { return m_impl ? m_impl->endsWith(s.impl(), caseSensitive) : s.isEmpty(); }
-
-    void append(const String&);
-    void append(char);
-    void append(UChar);
-    void append(const UChar*, unsigned length);
-    void insert(const String&, unsigned pos);
-    void insert(const UChar*, unsigned length, unsigned pos);
-
-    String& replace(UChar a, UChar b) { if (m_impl) m_impl = m_impl->replace(a, b); return *this; }
-    String& replace(UChar a, const String& b) { if (m_impl) m_impl = m_impl->replace(a, b.impl()); return *this; }
-    String& replace(const String& a, const String& b) { if (m_impl) m_impl = m_impl->replace(a.impl(), b.impl()); return *this; }
-    String& replace(unsigned index, unsigned len, const String& b) { if (m_impl) m_impl = m_impl->replace(index, len, b.impl()); return *this; }
-
-    void makeLower() { if (m_impl) m_impl = m_impl->lower(); }
-    void makeUpper() { if (m_impl) m_impl = m_impl->upper(); }
-    void makeSecure(UChar aChar, StringImpl::LastCharacterBehavior behavior = StringImpl::ObscureLastCharacter)
-    {
-        if (m_impl)
-            m_impl = m_impl->secure(aChar, behavior);
-    }
-
-    void truncate(unsigned len);
-    void remove(unsigned pos, int len = 1);
-
-    String substring(unsigned pos, unsigned len = UINT_MAX) const;
-    String substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const;
-    String left(unsigned len) const { return substring(0, len); }
-    String right(unsigned len) const { return substring(length() - len, len); }
-
-    // Returns a lowercase/uppercase version of the string
-    String lower() const;
-    String upper() const;
-
-    String stripWhiteSpace() 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;
-
-#if !PLATFORM(QT)
-    static String format(const char *, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
-#else
-    static String format(const char *, ...);
-#endif
-
-    // Returns an uninitialized string. The characters needs to be written
-    // into the buffer returned in data before the returned string is used.
-    // Failure to do this will have unpredictable results.
-    static String createUninitialized(unsigned length, UChar*& data) { return StringImpl::createUninitialized(length, data); }
-
-    void split(const String& separator, Vector<String>& result) const;
-    void split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const;
-    void split(UChar separator, Vector<String>& result) const;
-    void split(UChar separator, bool allowEmptyEntries, Vector<String>& result) const;
-
-    int toIntStrict(bool* ok = 0, int base = 10) const;
-    unsigned toUIntStrict(bool* ok = 0, int base = 10) const;
-    int64_t toInt64Strict(bool* ok = 0, int base = 10) const;
-    uint64_t toUInt64Strict(bool* ok = 0, int base = 10) const;
-    intptr_t toIntPtrStrict(bool* ok = 0, int base = 10) const;
-
-    int toInt(bool* ok = 0) const;
-    unsigned toUInt(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, bool* didReadNumber = 0) const;
-    float toFloat(bool* ok = 0, bool* didReadNumber = 0) const;
-
-    bool percentage(int& percentage) const;
-
-    // Returns a StringImpl suitable for use on another thread.
-    String crossThreadString() const;
-    // Makes a deep copy. Helpful only if you need to use a String on another thread
-    // (use crossThreadString if the method call doesn't need to be threadsafe).
-    // Since the underlying StringImpl objects are immutable, there's no other reason
-    // to ever prefer copy() over plain old assignment.
-    String threadsafeCopy() const;
-
-    // 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 USE(CF)
-    String(CFStringRef);
-    CFStringRef createCFString() const;
-#endif
-
-#ifdef __OBJC__
-    String(NSString*);
-    
-    // This conversion maps NULL to "", which loses the meaning of NULL, but we 
-    // need this mapping because AppKit crashes when passed nil NSStrings.
-    operator NSString*() const { if (!m_impl) return @""; return *m_impl; }
-#endif
-
-#if PLATFORM(QT)
-    String(const QString&);
-    String(const QStringRef&);
-    operator QString() const;
-#endif
-
-#if PLATFORM(WX)
-    String(const wxString&);
-    operator wxString() const;
-#endif
-
-#if PLATFORM(HAIKU)
-    String(const BString&);
-    operator BString() const;
-#endif
-
-#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*);
-
-    // Tries to convert the passed in string to UTF-8, but will fall back to Latin-1 if the string is not valid UTF-8.
-    static String fromUTF8WithLatin1Fallback(const char*, size_t);
-    
-    // Determines the writing direction using the Unicode Bidi Algorithm rules P2 and P3.
-    WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0) const
-    {
-        if (m_impl)
-            return m_impl->defaultWritingDirection(hasStrongDirectionality);
-        if (hasStrongDirectionality)
-            *hasStrongDirectionality = false;
-        return WTF::Unicode::LeftToRight;
-    }
-
-    bool containsOnlyASCII() const { return charactersAreAllASCII(characters(), length()); }
-    bool containsOnlyLatin1() const { return charactersAreAllLatin1(characters(), length()); }
-
-    // Hash table deleted values, which are only constructed and never copied or destroyed.
-    String(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { }
-    bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); }
-
-private:
-    RefPtr<StringImpl> m_impl;
-};
-
-#if PLATFORM(QT)
-QDataStream& operator<<(QDataStream& stream, const String& str);
-QDataStream& operator>>(QDataStream& stream, String& str);
-#endif
-
-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 bool operator==(const String& a, const char* b) { return equal(a.impl(), b); }
-inline bool operator==(const char* a, const String& b) { return equal(a, b.impl()); }
-
-inline bool operator!=(const String& a, const String& b) { return !equal(a.impl(), b.impl()); }
-inline bool operator!=(const String& a, const char* b) { return !equal(a.impl(), b); }
-inline bool operator!=(const char* a, const String& b) { return !equal(a, b.impl()); }
-
-inline bool equalIgnoringCase(const String& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); }
-inline bool equalIgnoringCase(const String& a, const char* b) { return equalIgnoringCase(a.impl(), b); }
-inline bool equalIgnoringCase(const char* a, const String& b) { return equalIgnoringCase(a, b.impl()); }
-
-inline bool equalPossiblyIgnoringCase(const String& a, const String& b, bool ignoreCase) 
-{
-    return ignoreCase ? equalIgnoringCase(a, b) : (a == b);
-}
-
-inline bool equalIgnoringNullity(const String& a, const String& b) { return equalIgnoringNullity(a.impl(), b.impl()); }
-
-template<size_t inlineCapacity>
-inline bool equalIgnoringNullity(const Vector<UChar, inlineCapacity>& a, const String& b) { return equalIgnoringNullity(a, b.impl()); }
-
-inline bool operator!(const String& str) { return str.isNull(); }
-
-inline void swap(String& a, String& b) { a.swap(b); }
-
-// Definitions of string operations
-
-template<size_t inlineCapacity>
-String::String(const Vector<UChar, inlineCapacity>& vector)
-    : m_impl(vector.size() ? StringImpl::create(vector.data(), vector.size()) : 0)
-{
-}
-
-#ifdef __OBJC__
-// This is for situations in WebKit where the long standing behavior has been
-// "nil if empty", so we try to maintain longstanding behavior for the sake of
-// entrenched clients
-inline NSString* nsStringNilIfEmpty(const String& str) {  return str.isEmpty() ? nil : (NSString*)str; }
-#endif
-
-inline bool charactersAreAllASCII(const UChar* characters, size_t length)
-{
-    UChar ored = 0;
-    for (size_t i = 0; i < length; ++i)
-        ored |= characters[i];
-    return !(ored & 0xFF80);
-}
-
-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)
-{
-    while (index < length) {
-        if (characters[index] == matchCharacter)
-            return index;
-        ++index;
-    }
-    return notFound;
-}
-
-inline size_t find(const UChar* characters, unsigned length, CharacterMatchFunctionPtr matchFunction, unsigned index = 0)
-{
-    while (index < length) {
-        if (matchFunction(characters[index]))
-            return index;
-        ++index;
-    }
-    return notFound;
-}
-
-inline size_t reverseFind(const UChar* characters, unsigned length, UChar matchCharacter, unsigned index = UINT_MAX)
-{
-    if (!length)
-        return notFound;
-    if (index >= length)
-        index = length - 1;
-    while (characters[index] != matchCharacter) {
-        if (!index--)
-            return notFound;
-    }
-    return index;
-}
-
-inline void append(Vector<UChar>& vector, const String& string)
-{
-    vector.append(string.characters(), string.length());
-}
-
-inline void appendNumber(Vector<UChar>& vector, unsigned char number)
-{
-    int numberLength = number > 99 ? 3 : (number > 9 ? 2 : 1);
-    size_t vectorSize = vector.size();
-    vector.grow(vectorSize + numberLength);
-
-    switch (numberLength) {
-    case 3:
-        vector[vectorSize + 2] = number % 10 + '0';
-        number /= 10;
-
-    case 2:
-        vector[vectorSize + 1] = number % 10 + '0';
-        number /= 10;
-
-    case 1:
-        vector[vectorSize] = number % 10 + '0';
-    }
-}
-
-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;
-}
-
-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 { };
-
-// Shared global empty string.
-const String& emptyString();
-
-}
-
-using WTF::CString;
-using WTF::String;
-using WTF::emptyString;
-using WTF::append;
-using WTF::appendNumber;
-using WTF::charactersAreAllASCII;
-using WTF::charactersAreAllLatin1;
-using WTF::charactersToIntStrict;
-using WTF::charactersToUIntStrict;
-using WTF::charactersToInt64Strict;
-using WTF::charactersToUInt64Strict;
-using WTF::charactersToIntPtrStrict;
-using WTF::charactersToInt;
-using WTF::charactersToUInt;
-using WTF::charactersToInt64;
-using WTF::charactersToUInt64;
-using WTF::charactersToIntPtr;
-using WTF::charactersToDouble;
-using WTF::charactersToFloat;
-using WTF::equal;
-using WTF::equalIgnoringCase;
-using WTF::find;
-using WTF::isAllSpecialCharacters;
-using WTF::isSpaceOrNewline;
-using WTF::reverseFind;
-
-#include "AtomicString.h"
-#endif
diff --git a/wtf/unicode/CharacterNames.h b/wtf/unicode/CharacterNames.h
deleted file mode 100644 (file)
index c0c5818..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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
diff --git a/wtf/unicode/Collator.h b/wtf/unicode/Collator.h
deleted file mode 100644 (file)
index 00ab16e..0000000
+++ /dev/null
@@ -1,69 +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.
- * 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_Collator_h
-#define WTF_Collator_h
-
-#include <wtf/FastAllocBase.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/PassOwnPtr.h>
-#include <wtf/unicode/Unicode.h>
-
-#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION
-struct UCollator;
-#endif
-
-namespace WTF {
-
-    class Collator {
-        WTF_MAKE_NONCOPYABLE(Collator); WTF_MAKE_FAST_ALLOCATED;
-    public:
-        enum Result { Equal = 0, Greater = 1, Less = -1 };
-
-        Collator(const char* locale); // Parsing is lenient; e.g. language identifiers (such as "en-US") are accepted, too.
-        ~Collator();
-        void setOrderLowerFirst(bool);
-
-        static PassOwnPtr<Collator> userDefault();
-
-        Result collate(const ::UChar*, size_t, const ::UChar*, size_t) const;
-
-    private:
-#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION
-        void createCollator() const;
-        void releaseCollator();
-        mutable UCollator* m_collator;
-#endif
-        char* m_locale;
-        bool m_lowerFirst;
-    };
-}
-
-using WTF::Collator;
-
-#endif
diff --git a/wtf/unicode/CollatorDefault.cpp b/wtf/unicode/CollatorDefault.cpp
deleted file mode 100644 (file)
index 7bde114..0000000
+++ /dev/null
@@ -1,75 +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.
- * 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 "Collator.h"
-
-#if !USE(ICU_UNICODE) || UCONFIG_NO_COLLATION
-
-namespace WTF {
-
-Collator::Collator(const char*)
-{
-}
-
-Collator::~Collator()
-{
-}
-
-void Collator::setOrderLowerFirst(bool)
-{
-}
-
-PassOwnPtr<Collator> Collator::userDefault()
-{
-    return adoptPtr(new Collator(0));
-}
-
-// A default implementation for platforms that lack Unicode-aware collation.
-Collator::Result Collator::collate(const UChar* lhs, size_t lhsLength, const UChar* rhs, size_t rhsLength) const
-{
-    int lmin = lhsLength < rhsLength ? lhsLength : rhsLength;
-    int l = 0;
-    while (l < lmin && *lhs == *rhs) {
-        lhs++;
-        rhs++;
-        l++;
-    }
-
-    if (l < lmin)
-        return (*lhs > *rhs) ? Greater : Less;
-
-    if (lhsLength == rhsLength)
-        return Equal;
-
-    return (lhsLength > rhsLength) ? Greater : Less;
-}
-
-}
-
-#endif
diff --git a/wtf/unicode/UTF8.cpp b/wtf/unicode/UTF8.cpp
deleted file mode 100644 (file)
index 3a88906..0000000
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * 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
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this 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 "UTF8.h"
-
-#include "ASCIICType.h"
-#include <wtf/StringHasher.h>
-#include <wtf/unicode/CharacterNames.h>
-
-namespace WTF {
-namespace Unicode {
-
-inline int inlineUTF8SequenceLengthNonASCII(char b0)
-{
-    if ((b0 & 0xC0) != 0xC0)
-        return 0;
-    if ((b0 & 0xE0) == 0xC0)
-        return 2;
-    if ((b0 & 0xF0) == 0xE0)
-        return 3;
-    if ((b0 & 0xF8) == 0xF0)
-        return 4;
-    return 0;
-}
-
-inline int inlineUTF8SequenceLength(char b0)
-{
-    return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
-}
-
-int UTF8SequenceLength(char b0)
-{
-    return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
-}
-
-int decodeUTF8Sequence(const char* sequence)
-{
-    // Handle 0-byte sequences (never valid).
-    const unsigned char b0 = sequence[0];
-    const int length = inlineUTF8SequenceLength(b0);
-    if (length == 0)
-        return -1;
-
-    // Handle 1-byte sequences (plain ASCII).
-    const unsigned char b1 = sequence[1];
-    if (length == 1) {
-        if (b1)
-            return -1;
-        return b0;
-    }
-
-    // Handle 2-byte sequences.
-    if ((b1 & 0xC0) != 0x80)
-        return -1;
-    const unsigned char b2 = sequence[2];
-    if (length == 2) {
-        if (b2)
-            return -1;
-        const int c = ((b0 & 0x1F) << 6) | (b1 & 0x3F);
-        if (c < 0x80)
-            return -1;
-        return c;
-    }
-
-    // Handle 3-byte sequences.
-    if ((b2 & 0xC0) != 0x80)
-        return -1;
-    const unsigned char b3 = sequence[3];
-    if (length == 3) {
-        if (b3)
-            return -1;
-        const int c = ((b0 & 0xF) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F);
-        if (c < 0x800)
-            return -1;
-        // UTF-16 surrogates should never appear in UTF-8 data.
-        if (c >= 0xD800 && c <= 0xDFFF)
-            return -1;
-        return c;
-    }
-
-    // Handle 4-byte sequences.
-    if ((b3 & 0xC0) != 0x80)
-        return -1;
-    const unsigned char b4 = sequence[4];
-    if (length == 4) {
-        if (b4)
-            return -1;
-        const int c = ((b0 & 0x7) << 18) | ((b1 & 0x3F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F);
-        if (c < 0x10000 || c > 0x10FFFF)
-            return -1;
-        return c;
-    }
-
-    return -1;
-}
-
-// Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
-// into the first byte, depending on how many bytes follow.  There are
-// as many entries in this table as there are UTF-8 sequence types.
-// (I.e., one byte sequence, two byte... etc.). Remember that sequencs
-// for *legal* UTF-8 will be 4 or fewer bytes total.
-static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-
-ConversionResult convertUTF16ToUTF8(
-    const UChar** sourceStart, const UChar* sourceEnd, 
-    char** targetStart, char* targetEnd, bool strict)
-{
-    ConversionResult result = conversionOK;
-    const UChar* source = *sourceStart;
-    char* target = *targetStart;
-    while (source < sourceEnd) {
-        UChar32 ch;
-        unsigned short bytesToWrite = 0;
-        const UChar32 byteMask = 0xBF;
-        const UChar32 byteMark = 0x80; 
-        const UChar* oldSource = source; // In case we have to back up because of target overflow.
-        ch = static_cast<unsigned short>(*source++);
-        // If we have a surrogate pair, convert to UChar32 first.
-        if (ch >= 0xD800 && ch <= 0xDBFF) {
-            // If the 16 bits following the high surrogate are in the source buffer...
-            if (source < sourceEnd) {
-                UChar32 ch2 = static_cast<unsigned short>(*source);
-                // If it's a low surrogate, convert to UChar32.
-                if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {
-                    ch = ((ch - 0xD800) << 10) + (ch2 - 0xDC00) + 0x0010000;
-                    ++source;
-                } else if (strict) { // it's an unpaired high surrogate
-                    --source; // return to the illegal value itself
-                    result = sourceIllegal;
-                    break;
-                }
-            } else { // We don't have the 16 bits following the high surrogate.
-                --source; // return to the high surrogate
-                result = sourceExhausted;
-                break;
-            }
-        } else if (strict) {
-            // UTF-16 surrogate values are illegal in UTF-32
-            if (ch >= 0xDC00 && ch <= 0xDFFF) {
-                --source; // return to the illegal value itself
-                result = sourceIllegal;
-                break;
-            }
-        }
-        // Figure out how many bytes the result will require
-        if (ch < (UChar32)0x80) {
-            bytesToWrite = 1;
-        } else if (ch < (UChar32)0x800) {
-            bytesToWrite = 2;
-        } else if (ch < (UChar32)0x10000) {
-            bytesToWrite = 3;
-        } else if (ch < (UChar32)0x110000) {
-            bytesToWrite = 4;
-        } else {
-            bytesToWrite = 3;
-            ch = replacementCharacter;
-        }
-
-        target += bytesToWrite;
-        if (target > targetEnd) {
-            source = oldSource; // Back up source pointer!
-            target -= bytesToWrite;
-            result = targetExhausted;
-            break;
-        }
-        switch (bytesToWrite) { // note: everything falls through.
-            case 4: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6;
-            case 3: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6;
-            case 2: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6;
-            case 1: *--target =  (char)(ch | firstByteMark[bytesToWrite]);
-        }
-        target += bytesToWrite;
-    }
-    *sourceStart = source;
-    *targetStart = target;
-    return result;
-}
-
-// This must be called with the length pre-determined by the first byte.
-// If presented with a length > 4, this returns false.  The Unicode
-// definition of UTF-8 goes up to 4-byte sequences.
-static bool isLegalUTF8(const unsigned char* source, int length)
-{
-    unsigned char a;
-    const unsigned char* srcptr = source + length;
-    switch (length) {
-        default: return false;
-        // Everything else falls through when "true"...
-        case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
-        case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
-        case 2: if ((a = (*--srcptr)) > 0xBF) return false;
-
-        switch (*source) {
-            // no fall-through in this inner switch
-            case 0xE0: if (a < 0xA0) return false; break;
-            case 0xED: if (a > 0x9F) return false; break;
-            case 0xF0: if (a < 0x90) return false; break;
-            case 0xF4: if (a > 0x8F) return false; break;
-            default:   if (a < 0x80) return false;
-        }
-
-        case 1: if (*source >= 0x80 && *source < 0xC2) return false;
-    }
-    if (*source > 0xF4)
-        return false;
-    return true;
-}
-
-// Magic values subtracted from a buffer value during UTF8 conversion.
-// This table contains as many values as there might be trailing bytes
-// in a UTF-8 sequence.
-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 result = conversionOK;
-    const char* source = *sourceStart;
-    UChar* target = *targetStart;
-    while (source < sourceEnd) {
-        int utf8SequenceLength = inlineUTF8SequenceLength(*source);
-        if (sourceEnd - source < utf8SequenceLength)  {
-            result = sourceExhausted;
-            break;
-        }
-        // Do this check whether lenient or strict
-        if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(source), utf8SequenceLength)) {
-            result = sourceIllegal;
-            break;
-        }
-
-        UChar32 character = readUTF8Sequence(source, utf8SequenceLength);
-
-        if (target >= targetEnd) {
-            source -= utf8SequenceLength; // Back up source pointer!
-            result = targetExhausted;
-            break;
-        }
-
-        if (U_IS_BMP(character)) {
-            // UTF-16 surrogate values are illegal in UTF-32
-            if (U_IS_SURROGATE(character)) {
-                if (strict) {
-                    source -= utf8SequenceLength; // return to the illegal value itself
-                    result = sourceIllegal;
-                    break;
-                } else
-                    *target++ = replacementCharacter;
-            } else
-                *target++ = character; // normal case
-        } else if (U_IS_SUPPLEMENTARY(character)) {
-            // target is a character in range 0xFFFF - 0x10FFFF
-            if (target + 1 >= targetEnd) {
-                source -= utf8SequenceLength; // Back up source pointer!
-                result = targetExhausted;
-                break;
-            }
-            *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;
-    *targetStart = target;
-    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
diff --git a/wtf/unicode/UTF8.h b/wtf/unicode/UTF8.h
deleted file mode 100644 (file)
index 7b7b75d..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this 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_UTF8_h
-#define WTF_UTF8_h
-
-#include "Unicode.h"
-
-namespace WTF {
-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.
-    // Only allows sequences of up to 4 bytes, since that works for all Unicode characters (U-00000000 to U-0010FFFF).
-    int UTF8SequenceLength(char);
-
-    // Takes a null-terminated C-style string with a UTF-8 sequence in it and converts it to a character.
-    // Only allows Unicode characters (U-00000000 to U-0010FFFF).
-    // Returns -1 if the sequence is not valid (including presence of extra bytes).
-    int decodeUTF8Sequence(const char*);
-
-    typedef enum {
-            conversionOK,       // conversion successful
-            sourceExhausted,    // partial character in source, but hit end
-            targetExhausted,    // insuff. room in target for conversion
-            sourceIllegal       // source sequence is illegal/malformed
-    } ConversionResult;
-
-    // These conversion functions take a "strict" argument. When this
-    // flag is set to strict, both irregular sequences and isolated surrogates
-    // will cause an error.  When the flag is set to lenient, both irregular
-    // sequences and isolated surrogates are converted.
-    // 
-    // Whether the flag is strict or lenient, all illegal sequences will cause
-    // an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
-    // or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
-    // must check for illegal sequences.
-    // 
-    // When the flag is set to lenient, characters over 0x10FFFF are converted
-    // to the replacement character; otherwise (when the flag is set to strict)
-    // they constitute an error.
-
-    ConversionResult convertUTF8ToUTF16(
-                    const char** sourceStart, const char* sourceEnd, 
-                    UChar** targetStart, UChar* 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
diff --git a/wtf/unicode/Unicode.h b/wtf/unicode/Unicode.h
deleted file mode 100644 (file)
index 50524b1..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *  Copyright (C) 2006 George Staikos <staikos@kde.org>
- *  Copyright (C) 2006, 2008, 2009 Apple 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_UNICODE_H
-#define WTF_UNICODE_H
-
-#include <wtf/Assertions.h>
-
-#if USE(QT4_UNICODE)
-#include "qt4/UnicodeQt4.h"
-#elif USE(ICU_UNICODE)
-#include <wtf/unicode/icu/UnicodeIcu.h>
-#elif USE(GLIB_UNICODE)
-#include <wtf/unicode/glib/UnicodeGLib.h>
-#elif USE(WINCE_UNICODE)
-#include <wtf/unicode/wince/UnicodeWinCE.h>
-#elif USE(BREWMP_UNICODE)
-#include <wtf/unicode/brew/UnicodeBrew.h>
-#else
-#error "Unknown Unicode implementation"
-#endif
-
-COMPILE_ASSERT(sizeof(UChar) == 2, UCharIsTwoBytes);
-
-#endif // WTF_UNICODE_H
diff --git a/wtf/unicode/UnicodeMacrosFromICU.h b/wtf/unicode/UnicodeMacrosFromICU.h
deleted file mode 100644 (file)
index 09a7036..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- *  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
deleted file mode 100644 (file)
index 8367f17..0000000
+++ /dev/null
@@ -1,181 +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.
- *  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
deleted file mode 100644 (file)
index 1d7576f..0000000
+++ /dev/null
@@ -1,194 +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.
- *  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
diff --git a/wtf/unicode/glib/UnicodeGLib.cpp b/wtf/unicode/glib/UnicodeGLib.cpp
deleted file mode 100644 (file)
index a01c3ee..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- *  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
- *  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 "UnicodeGLib.h"
-
-#include <wtf/Vector.h>
-#include <wtf/unicode/UTF8.h>
-
-#define UTF8_IS_SURROGATE(character) (character >= 0x10000 && character <= 0x10FFFF)
-
-namespace WTF {
-namespace Unicode {
-
-UChar32 foldCase(UChar32 ch)
-{
-    GOwnPtr<GError> gerror;
-
-    GOwnPtr<char> utf8char;
-    utf8char.set(g_ucs4_to_utf8(reinterpret_cast<gunichar*>(&ch), 1, 0, 0, &gerror.outPtr()));
-    if (gerror)
-        return ch;
-
-    GOwnPtr<char> utf8caseFolded;
-    utf8caseFolded.set(g_utf8_casefold(utf8char.get(), -1));
-
-    GOwnPtr<gunichar> ucs4Result;
-    ucs4Result.set(g_utf8_to_ucs4_fast(utf8caseFolded.get(), -1, 0));
-
-    return *ucs4Result;
-}
-
-static int getUTF16LengthFromUTF8(const gchar* utf8String, int length)
-{
-    int utf16Length = 0;
-    const gchar* inputString = utf8String;
-
-    while ((utf8String + length - inputString > 0) && *inputString) {
-        gunichar character = g_utf8_get_char(inputString);
-
-        utf16Length += UTF8_IS_SURROGATE(character) ? 2 : 1;
-        inputString = g_utf8_next_char(inputString);
-    }
-
-    return utf16Length;
-}
-
-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;
-
-    // Allocate a buffer big enough to hold all the characters.
-    Vector<char> buffer(srcLength * 3);
-    char* utf8Target = buffer.data();
-    const UChar* utf16Source = src;
-    ConversionResult conversionResult = convertUTF16ToUTF8(&utf16Source, utf16Source + srcLength, &utf8Target, utf8Target + buffer.size(), true);
-    if (conversionResult != conversionOK) {
-        *error = true;
-        return -1;
-    }
-    buffer.shrink(utf8Target - buffer.data());
-
-    GOwnPtr<char> utf8Result(caseFunction(buffer.data(), buffer.size()));
-    long utf8ResultLength = strlen(utf8Result.get());
-
-    // Calculate the destination buffer size.
-    int realLength = getUTF16LengthFromUTF8(utf8Result.get(), utf8ResultLength);
-    if (realLength > resultLength) {
-        *error = true;
-        return realLength;
-    }
-
-    // Convert the result to UTF-16.
-    UChar* utf16Target = result;
-    const char* utf8Source = utf8Result.get();
-    conversionResult = convertUTF8ToUTF16(&utf8Source, utf8Source + utf8ResultLength, &utf16Target, utf16Target + resultLength, true);
-    long utf16ResultLength = utf16Target - result;
-    if (conversionResult != conversionOK)
-        *error = true;
-
-    return utf16ResultLength <= 0 ? -1 : utf16ResultLength;
-}
-int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
-{
-    return convertCase(result, resultLength, src, srcLength, error, g_utf8_casefold);
-}
-
-int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
-{
-    return convertCase(result, resultLength, src, srcLength, error, g_utf8_strdown);
-}
-
-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)
-{
-    PangoBidiType type = pango_bidi_type_for_unichar(c);
-    switch (type) {
-    case PANGO_BIDI_TYPE_L:
-        return LeftToRight;
-    case PANGO_BIDI_TYPE_R:
-        return RightToLeft;
-    case PANGO_BIDI_TYPE_AL:
-        return RightToLeftArabic;
-    case PANGO_BIDI_TYPE_LRE:
-        return LeftToRightEmbedding;
-    case PANGO_BIDI_TYPE_RLE:
-        return RightToLeftEmbedding;
-    case PANGO_BIDI_TYPE_LRO:
-        return LeftToRightOverride;
-    case PANGO_BIDI_TYPE_RLO:
-        return RightToLeftOverride;
-    case PANGO_BIDI_TYPE_PDF:
-        return PopDirectionalFormat;
-    case PANGO_BIDI_TYPE_EN:
-        return EuropeanNumber;
-    case PANGO_BIDI_TYPE_AN:
-        return ArabicNumber;
-    case PANGO_BIDI_TYPE_ES:
-        return EuropeanNumberSeparator;
-    case PANGO_BIDI_TYPE_ET:
-        return EuropeanNumberTerminator;
-    case PANGO_BIDI_TYPE_CS:
-        return CommonNumberSeparator;
-    case PANGO_BIDI_TYPE_NSM:
-        return NonSpacingMark;
-    case PANGO_BIDI_TYPE_BN:
-        return BoundaryNeutral;
-    case PANGO_BIDI_TYPE_B:
-        return BlockSeparator;
-    case PANGO_BIDI_TYPE_S:
-        return SegmentSeparator;
-    case PANGO_BIDI_TYPE_WS:
-        return WhiteSpaceNeutral;
-    default:
-        return OtherNeutral;
-    }
-}
-
-int umemcasecmp(const UChar* a, const UChar* b, int len)
-{
-    GOwnPtr<char> utf8a;
-    GOwnPtr<char> utf8b;
-
-    utf8a.set(g_utf16_to_utf8(a, len, 0, 0, 0));
-    utf8b.set(g_utf16_to_utf8(b, len, 0, 0, 0));
-
-    GOwnPtr<char> foldedA;
-    GOwnPtr<char> foldedB;
-
-    foldedA.set(g_utf8_casefold(utf8a.get(), -1));
-    foldedB.set(g_utf8_casefold(utf8b.get(), -1));
-
-    // FIXME: umemcasecmp needs to mimic u_memcasecmp of icu
-    // from the ICU docs:
-    // "Compare two strings case-insensitively using full case folding.
-    // his is equivalent to u_strcmp(u_strFoldCase(s1, n, options), u_strFoldCase(s2, n, options))."
-    //
-    // So it looks like we don't need the full g_utf8_collate here,
-    // but really a bitwise comparison of casefolded unicode chars (not utf-8 bytes).
-    // As there is no direct equivalent to this icu function in GLib, for now
-    // we'll use g_utf8_collate():
-
-    return g_utf8_collate(foldedA.get(), foldedB.get());
-}
-
-}
-}
diff --git a/wtf/unicode/glib/UnicodeGLib.h b/wtf/unicode/glib/UnicodeGLib.h
deleted file mode 100644 (file)
index 46b00ea..0000000
+++ /dev/null
@@ -1,243 +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 UnicodeGLib_h
-#define UnicodeGLib_h
-
-#include "UnicodeMacrosFromICU.h"
-#include "GOwnPtr.h"
-
-#include <glib.h>
-#include <pango/pango.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-typedef uint16_t UChar;
-typedef int32_t UChar32;
-
-namespace WTF {
-namespace Unicode {
-
-enum Direction {
-    LeftToRight,
-    RightToLeft,
-    EuropeanNumber,
-    EuropeanNumberSeparator,
-    EuropeanNumberTerminator,
-    ArabicNumber,
-    CommonNumberSeparator,
-    BlockSeparator,
-    SegmentSeparator,
-    WhiteSpaceNeutral,
-    OtherNeutral,
-    LeftToRightEmbedding,
-    LeftToRightOverride,
-    RightToLeftArabic,
-    RightToLeftEmbedding,
-    RightToLeftOverride,
-    PopDirectionalFormat,
-    NonSpacingMark,
-    BoundaryNeutral
-};
-
-enum DecompositionType {
-    DecompositionNone,
-    DecompositionCanonical,
-    DecompositionCompat,
-    DecompositionCircle,
-    DecompositionFinal,
-    DecompositionFont,
-    DecompositionFraction,
-    DecompositionInitial,
-    DecompositionIsolated,
-    DecompositionMedial,
-    DecompositionNarrow,
-    DecompositionNoBreak,
-    DecompositionSmall,
-    DecompositionSquare,
-    DecompositionSub,
-    DecompositionSuper,
-    DecompositionVertical,
-    DecompositionWide,
-};
-
-enum CharCategory {
-    NoCategory =  0,
-    Other_NotAssigned = U_MASK(G_UNICODE_UNASSIGNED),
-    Letter_Uppercase = U_MASK(G_UNICODE_UPPERCASE_LETTER),
-    Letter_Lowercase = U_MASK(G_UNICODE_LOWERCASE_LETTER),
-    Letter_Titlecase = U_MASK(G_UNICODE_TITLECASE_LETTER),
-    Letter_Modifier = U_MASK(G_UNICODE_MODIFIER_LETTER),
-    Letter_Other = U_MASK(G_UNICODE_OTHER_LETTER),
-
-    Mark_NonSpacing = U_MASK(G_UNICODE_NON_SPACING_MARK),
-    Mark_Enclosing = U_MASK(G_UNICODE_ENCLOSING_MARK),
-    Mark_SpacingCombining = U_MASK(G_UNICODE_COMBINING_MARK),
-
-    Number_DecimalDigit = U_MASK(G_UNICODE_DECIMAL_NUMBER),
-    Number_Letter = U_MASK(G_UNICODE_LETTER_NUMBER),
-    Number_Other = U_MASK(G_UNICODE_OTHER_NUMBER),
-
-    Separator_Space = U_MASK(G_UNICODE_SPACE_SEPARATOR),
-    Separator_Line = U_MASK(G_UNICODE_LINE_SEPARATOR),
-    Separator_Paragraph = U_MASK(G_UNICODE_PARAGRAPH_SEPARATOR),
-
-    Other_Control = U_MASK(G_UNICODE_CONTROL),
-    Other_Format = U_MASK(G_UNICODE_FORMAT),
-    Other_PrivateUse = U_MASK(G_UNICODE_PRIVATE_USE),
-    Other_Surrogate = U_MASK(G_UNICODE_SURROGATE),
-
-    Punctuation_Dash = U_MASK(G_UNICODE_DASH_PUNCTUATION),
-    Punctuation_Open = U_MASK(G_UNICODE_OPEN_PUNCTUATION),
-    Punctuation_Close = U_MASK(G_UNICODE_CLOSE_PUNCTUATION),
-    Punctuation_Connector = U_MASK(G_UNICODE_CONNECT_PUNCTUATION),
-    Punctuation_Other = U_MASK(G_UNICODE_OTHER_PUNCTUATION),
-
-    Symbol_Math = U_MASK(G_UNICODE_MATH_SYMBOL),
-    Symbol_Currency = U_MASK(G_UNICODE_CURRENCY_SYMBOL),
-    Symbol_Modifier = U_MASK(G_UNICODE_MODIFIER_SYMBOL),
-    Symbol_Other = U_MASK(G_UNICODE_OTHER_SYMBOL),
-
-    Punctuation_InitialQuote = U_MASK(G_UNICODE_INITIAL_PUNCTUATION),
-    Punctuation_FinalQuote = U_MASK(G_UNICODE_FINAL_PUNCTUATION)
-};
-
-UChar32 foldCase(UChar32);
-
-int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error);
-
-int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error);
-
-inline UChar32 toLower(UChar32 c)
-{
-    return g_unichar_tolower(c);
-}
-
-inline UChar32 toUpper(UChar32 c)
-{
-    return g_unichar_toupper(c);
-}
-
-int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error);
-
-inline UChar32 toTitleCase(UChar32 c)
-{
-    return g_unichar_totitle(c);
-}
-
-inline bool isArabicChar(UChar32 c)
-{
-    return c >= 0x0600 && c <= 0x06FF;
-}
-
-inline bool isAlphanumeric(UChar32 c)
-{
-    return g_unichar_isalnum(c);
-}
-
-inline bool isFormatChar(UChar32 c)
-{
-    return g_unichar_type(c) == G_UNICODE_FORMAT;
-}
-
-inline bool isSeparatorSpace(UChar32 c)
-{
-    return g_unichar_type(c) == G_UNICODE_SPACE_SEPARATOR;
-}
-
-inline bool isPrintableChar(UChar32 c)
-{
-    return g_unichar_isprint(c);
-}
-
-inline bool isDigit(UChar32 c)
-{
-    return g_unichar_isdigit(c);
-}
-
-inline bool isPunct(UChar32 c)
-{
-    return g_unichar_ispunct(c);
-}
-
-inline bool hasLineBreakingPropertyComplexContext(UChar32 c)
-{
-    // FIXME
-    return false;
-}
-
-inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c)
-{
-    // FIXME
-    return false;
-}
-
-inline UChar32 mirroredChar(UChar32 c)
-{
-    gunichar mirror = 0;
-    g_unichar_get_mirror_char(c, &mirror);
-    return mirror;
-}
-
-inline CharCategory category(UChar32 c)
-{
-    if (c > 0xffff)
-        return NoCategory;
-
-    return (CharCategory) U_MASK(g_unichar_type(c));
-}
-
-Direction direction(UChar32);
-
-inline bool isLower(UChar32 c)
-{
-    return g_unichar_islower(c);
-}
-
-inline int digitValue(UChar32 c)
-{
-    return g_unichar_digit_value(c);
-}
-
-inline uint8_t combiningClass(UChar32 c)
-{
-    // FIXME
-    // return g_unichar_combining_class(c);
-    return 0;
-}
-
-inline DecompositionType decompositionType(UChar32 c)
-{
-    // FIXME
-    return DecompositionNone;
-}
-
-int umemcasecmp(const UChar*, const UChar*, int len);
-
-}
-}
-
-#endif
-
diff --git a/wtf/unicode/icu/CollatorICU.cpp b/wtf/unicode/icu/CollatorICU.cpp
deleted file mode 100644 (file)
index 348693f..0000000
+++ /dev/null
@@ -1,149 +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.
- * 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 "Collator.h"
-
-#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION
-
-#include "Assertions.h"
-#include "Threading.h"
-#include <unicode/ucol.h>
-#include <string.h>
-
-#if OS(DARWIN)
-#include "RetainPtr.h"
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-
-namespace WTF {
-
-static UCollator* cachedCollator;
-static Mutex& cachedCollatorMutex()
-{
-    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
-    return mutex;
-}
-
-Collator::Collator(const char* locale)
-    : m_collator(0)
-    , m_locale(locale ? strdup(locale) : 0)
-    , m_lowerFirst(false)
-{
-}
-
-PassOwnPtr<Collator> Collator::userDefault()
-{
-#if OS(DARWIN) && USE(CF)
-    // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work.
-#if !defined(BUILDING_ON_LEOPARD) && !OS(IOS)
-    RetainPtr<CFLocaleRef> currentLocale(AdoptCF, CFLocaleCopyCurrent());
-    CFStringRef collationOrder = (CFStringRef)CFLocaleGetValue(currentLocale.get(), kCFLocaleCollatorIdentifier);
-#else
-    RetainPtr<CFStringRef> collationOrderRetainer(AdoptCF, (CFStringRef)CFPreferencesCopyValue(CFSTR("AppleCollationOrder"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost));
-    CFStringRef collationOrder = collationOrderRetainer.get();
-#endif
-    char buf[256];
-    if (!collationOrder)
-        return adoptPtr(new Collator(""));
-    CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII);
-    return adoptPtr(new Collator(buf));
-#else
-    return adoptPtr(new Collator(0));
-#endif
-}
-
-Collator::~Collator()
-{
-    releaseCollator();
-    free(m_locale);
-}
-
-void Collator::setOrderLowerFirst(bool lowerFirst)
-{
-    m_lowerFirst = lowerFirst;
-}
-
-Collator::Result Collator::collate(const UChar* lhs, size_t lhsLength, const UChar* rhs, size_t rhsLength) const
-{
-    if (!m_collator)
-        createCollator();
-
-    return static_cast<Result>(ucol_strcoll(m_collator, lhs, lhsLength, rhs, rhsLength));
-}
-
-void Collator::createCollator() const
-{
-    ASSERT(!m_collator);
-    UErrorCode status = U_ZERO_ERROR;
-
-    {
-        Locker<Mutex> lock(cachedCollatorMutex());
-        if (cachedCollator) {
-            const char* cachedCollatorLocale = ucol_getLocaleByType(cachedCollator, ULOC_REQUESTED_LOCALE, &status);
-            ASSERT(U_SUCCESS(status));
-            ASSERT(cachedCollatorLocale);
-
-            UColAttributeValue cachedCollatorLowerFirst = ucol_getAttribute(cachedCollator, UCOL_CASE_FIRST, &status);
-            ASSERT(U_SUCCESS(status));
-
-            // FIXME: default locale is never matched, because ucol_getLocaleByType returns the actual one used, not 0.
-            if (m_locale && 0 == strcmp(cachedCollatorLocale, m_locale)
-                && ((UCOL_LOWER_FIRST == cachedCollatorLowerFirst && m_lowerFirst) || (UCOL_UPPER_FIRST == cachedCollatorLowerFirst && !m_lowerFirst))) {
-                m_collator = cachedCollator;
-                cachedCollator = 0;
-                return;
-            }
-        }
-    }
-
-    m_collator = ucol_open(m_locale, &status);
-    if (U_FAILURE(status)) {
-        status = U_ZERO_ERROR;
-        m_collator = ucol_open("", &status); // Fallback to Unicode Collation Algorithm.
-    }
-    ASSERT(U_SUCCESS(status));
-
-    ucol_setAttribute(m_collator, UCOL_CASE_FIRST, m_lowerFirst ? UCOL_LOWER_FIRST : UCOL_UPPER_FIRST, &status);
-    ASSERT(U_SUCCESS(status));
-}
-
-void Collator::releaseCollator()
-{
-    {
-        Locker<Mutex> lock(cachedCollatorMutex());
-        if (cachedCollator)
-            ucol_close(cachedCollator);
-        cachedCollator = m_collator;
-        m_collator  = 0;
-    }
-}
-
-}
-
-#endif
diff --git a/wtf/unicode/icu/UnicodeIcu.h b/wtf/unicode/icu/UnicodeIcu.h
deleted file mode 100644 (file)
index a2a5c0a..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *  Copyright (C) 2006 George Staikos <staikos@kde.org>
- *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
- *  Copyright (C) 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 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_UNICODE_ICU_H
-#define WTF_UNICODE_ICU_H
-
-#include <stdlib.h>
-#include <unicode/uchar.h>
-#include <unicode/ustring.h>
-#include <unicode/utf16.h>
-
-namespace WTF {
-namespace Unicode {
-
-enum Direction {
-    LeftToRight = U_LEFT_TO_RIGHT,
-    RightToLeft = U_RIGHT_TO_LEFT,
-    EuropeanNumber = U_EUROPEAN_NUMBER,
-    EuropeanNumberSeparator = U_EUROPEAN_NUMBER_SEPARATOR,
-    EuropeanNumberTerminator = U_EUROPEAN_NUMBER_TERMINATOR,
-    ArabicNumber = U_ARABIC_NUMBER,
-    CommonNumberSeparator = U_COMMON_NUMBER_SEPARATOR,
-    BlockSeparator = U_BLOCK_SEPARATOR,
-    SegmentSeparator = U_SEGMENT_SEPARATOR,
-    WhiteSpaceNeutral = U_WHITE_SPACE_NEUTRAL,
-    OtherNeutral = U_OTHER_NEUTRAL,
-    LeftToRightEmbedding = U_LEFT_TO_RIGHT_EMBEDDING,
-    LeftToRightOverride = U_LEFT_TO_RIGHT_OVERRIDE,
-    RightToLeftArabic = U_RIGHT_TO_LEFT_ARABIC,
-    RightToLeftEmbedding = U_RIGHT_TO_LEFT_EMBEDDING,
-    RightToLeftOverride = U_RIGHT_TO_LEFT_OVERRIDE,
-    PopDirectionalFormat = U_POP_DIRECTIONAL_FORMAT,
-    NonSpacingMark = U_DIR_NON_SPACING_MARK,
-    BoundaryNeutral = U_BOUNDARY_NEUTRAL
-};
-
-enum DecompositionType {
-    DecompositionNone = U_DT_NONE,
-    DecompositionCanonical = U_DT_CANONICAL,
-    DecompositionCompat = U_DT_COMPAT,
-    DecompositionCircle = U_DT_CIRCLE,
-    DecompositionFinal = U_DT_FINAL,
-    DecompositionFont = U_DT_FONT,
-    DecompositionFraction = U_DT_FRACTION,
-    DecompositionInitial = U_DT_INITIAL,
-    DecompositionIsolated = U_DT_ISOLATED,
-    DecompositionMedial = U_DT_MEDIAL,
-    DecompositionNarrow = U_DT_NARROW,
-    DecompositionNoBreak = U_DT_NOBREAK,
-    DecompositionSmall = U_DT_SMALL,
-    DecompositionSquare = U_DT_SQUARE,
-    DecompositionSub = U_DT_SUB,
-    DecompositionSuper = U_DT_SUPER,
-    DecompositionVertical = U_DT_VERTICAL,
-    DecompositionWide = U_DT_WIDE,
-};
-
-enum CharCategory {
-    NoCategory =  0,
-    Other_NotAssigned = U_MASK(U_GENERAL_OTHER_TYPES),
-    Letter_Uppercase = U_MASK(U_UPPERCASE_LETTER),
-    Letter_Lowercase = U_MASK(U_LOWERCASE_LETTER),
-    Letter_Titlecase = U_MASK(U_TITLECASE_LETTER),
-    Letter_Modifier = U_MASK(U_MODIFIER_LETTER),
-    Letter_Other = U_MASK(U_OTHER_LETTER),
-
-    Mark_NonSpacing = U_MASK(U_NON_SPACING_MARK),
-    Mark_Enclosing = U_MASK(U_ENCLOSING_MARK),
-    Mark_SpacingCombining = U_MASK(U_COMBINING_SPACING_MARK),
-
-    Number_DecimalDigit = U_MASK(U_DECIMAL_DIGIT_NUMBER),
-    Number_Letter = U_MASK(U_LETTER_NUMBER),
-    Number_Other = U_MASK(U_OTHER_NUMBER),
-
-    Separator_Space = U_MASK(U_SPACE_SEPARATOR),
-    Separator_Line = U_MASK(U_LINE_SEPARATOR),
-    Separator_Paragraph = U_MASK(U_PARAGRAPH_SEPARATOR),
-
-    Other_Control = U_MASK(U_CONTROL_CHAR),
-    Other_Format = U_MASK(U_FORMAT_CHAR),
-    Other_PrivateUse = U_MASK(U_PRIVATE_USE_CHAR),
-    Other_Surrogate = U_MASK(U_SURROGATE),
-
-    Punctuation_Dash = U_MASK(U_DASH_PUNCTUATION),
-    Punctuation_Open = U_MASK(U_START_PUNCTUATION),
-    Punctuation_Close = U_MASK(U_END_PUNCTUATION),
-    Punctuation_Connector = U_MASK(U_CONNECTOR_PUNCTUATION),
-    Punctuation_Other = U_MASK(U_OTHER_PUNCTUATION),
-
-    Symbol_Math = U_MASK(U_MATH_SYMBOL),
-    Symbol_Currency = U_MASK(U_CURRENCY_SYMBOL),
-    Symbol_Modifier = U_MASK(U_MODIFIER_SYMBOL),
-    Symbol_Other = U_MASK(U_OTHER_SYMBOL),
-
-    Punctuation_InitialQuote = U_MASK(U_INITIAL_PUNCTUATION),
-    Punctuation_FinalQuote = U_MASK(U_FINAL_PUNCTUATION)
-};
-
-inline UChar32 foldCase(UChar32 c)
-{
-    return u_foldCase(c, U_FOLD_CASE_DEFAULT);
-}
-
-inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
-{
-    UErrorCode status = U_ZERO_ERROR;
-    int realLength = u_strFoldCase(result, resultLength, src, srcLength, U_FOLD_CASE_DEFAULT, &status);
-    *error = !U_SUCCESS(status);
-    return realLength;
-}
-
-inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
-{
-    UErrorCode status = U_ZERO_ERROR;
-    int realLength = u_strToLower(result, resultLength, src, srcLength, "", &status);
-    *error = !!U_FAILURE(status);
-    return realLength;
-}
-
-inline UChar32 toLower(UChar32 c)
-{
-    return u_tolower(c);
-}
-
-inline UChar32 toUpper(UChar32 c)
-{
-    return u_toupper(c);
-}
-
-inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
-{
-    UErrorCode status = U_ZERO_ERROR;
-    int realLength = u_strToUpper(result, resultLength, src, srcLength, "", &status);
-    *error = !!U_FAILURE(status);
-    return realLength;
-}
-
-inline UChar32 toTitleCase(UChar32 c)
-{
-    return u_totitle(c);
-}
-
-inline bool isArabicChar(UChar32 c)
-{
-      return ublock_getCode(c) == UBLOCK_ARABIC;
-}
-
-inline bool isAlphanumeric(UChar32 c)
-{
-    return u_isalnum(c);
-}
-
-inline bool isSeparatorSpace(UChar32 c)
-{
-    return u_charType(c) == U_SPACE_SEPARATOR;
-}
-
-inline bool isPrintableChar(UChar32 c)
-{
-    return !!u_isprint(c);
-}
-
-inline bool isPunct(UChar32 c)
-{
-    return !!u_ispunct(c);
-}
-
-inline bool hasLineBreakingPropertyComplexContext(UChar32 c)
-{
-    return u_getIntPropertyValue(c, UCHAR_LINE_BREAK) == U_LB_COMPLEX_CONTEXT;
-}
-
-inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c)
-{
-    int32_t prop = u_getIntPropertyValue(c, UCHAR_LINE_BREAK);
-    return prop == U_LB_COMPLEX_CONTEXT || prop == U_LB_IDEOGRAPHIC;
-}
-
-inline UChar32 mirroredChar(UChar32 c)
-{
-    return u_charMirror(c);
-}
-
-inline CharCategory category(UChar32 c)
-{
-    return static_cast<CharCategory>(U_GET_GC_MASK(c));
-}
-
-inline Direction direction(UChar32 c)
-{
-    return static_cast<Direction>(u_charDirection(c));
-}
-
-inline bool isLower(UChar32 c)
-{
-    return !!u_islower(c);
-}
-
-inline uint8_t combiningClass(UChar32 c)
-{
-    return u_getCombiningClass(c);
-}
-
-inline DecompositionType decompositionType(UChar32 c)
-{
-    return static_cast<DecompositionType>(u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE));
-}
-
-inline int umemcasecmp(const UChar* a, const UChar* b, int len)
-{
-    return u_memcasecmp(a, b, len, U_FOLD_CASE_DEFAULT);
-}
-
-} }
-
-#endif // WTF_UNICODE_ICU_H
diff --git a/wtf/unicode/qt4/UnicodeQt4.h b/wtf/unicode/qt4/UnicodeQt4.h
deleted file mode 100644 (file)
index eaa7a07..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- *  Copyright (C) 2006 George Staikos <staikos@kde.org>
- *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
- *  Copyright (C) 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 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_UNICODE_QT4_H
-#define WTF_UNICODE_QT4_H
-
-#include "UnicodeMacrosFromICU.h"
-
-#include <QChar>
-#include <QString>
-
-#include <config.h>
-
-#include <stdint.h>
-#if USE(QT_ICU_TEXT_BREAKING)
-#include <unicode/ubrk.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-namespace QUnicodeTables {
-    struct Properties {
-        ushort category : 8;
-        ushort line_break_class : 8;
-        ushort direction : 8;
-        ushort combiningClass :8;
-        ushort joining : 2;
-        signed short digitValue : 6; /* 5 needed */
-        ushort unicodeVersion : 4;
-        ushort lowerCaseSpecial : 1;
-        ushort upperCaseSpecial : 1;
-        ushort titleCaseSpecial : 1;
-        ushort caseFoldSpecial : 1; /* currently unused */
-        signed short mirrorDiff : 16;
-        signed short lowerCaseDiff : 16;
-        signed short upperCaseDiff : 16;
-        signed short titleCaseDiff : 16;
-        signed short caseFoldDiff : 16;
-    };
-    Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4);
-    Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2);
-}
-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(LINUX))
-typedef wchar_t UChar;
-#else
-typedef uint16_t UChar;
-#endif
-
-#if !USE(QT_ICU_TEXT_BREAKING)
-typedef uint32_t UChar32;
-#endif
-
-namespace WTF {
-namespace Unicode {
-
-enum Direction {
-    LeftToRight = QChar::DirL,
-    RightToLeft = QChar::DirR,
-    EuropeanNumber = QChar::DirEN,
-    EuropeanNumberSeparator = QChar::DirES,
-    EuropeanNumberTerminator = QChar::DirET,
-    ArabicNumber = QChar::DirAN,
-    CommonNumberSeparator = QChar::DirCS,
-    BlockSeparator = QChar::DirB,
-    SegmentSeparator = QChar::DirS,
-    WhiteSpaceNeutral = QChar::DirWS,
-    OtherNeutral = QChar::DirON,
-    LeftToRightEmbedding = QChar::DirLRE,
-    LeftToRightOverride = QChar::DirLRO,
-    RightToLeftArabic = QChar::DirAL,
-    RightToLeftEmbedding = QChar::DirRLE,
-    RightToLeftOverride = QChar::DirRLO,
-    PopDirectionalFormat = QChar::DirPDF,
-    NonSpacingMark = QChar::DirNSM,
-    BoundaryNeutral = QChar::DirBN
-};
-
-enum DecompositionType {
-    DecompositionNone = QChar::NoDecomposition,
-    DecompositionCanonical = QChar::Canonical,
-    DecompositionCompat = QChar::Compat,
-    DecompositionCircle = QChar::Circle,
-    DecompositionFinal = QChar::Final,
-    DecompositionFont = QChar::Font,
-    DecompositionFraction = QChar::Fraction,
-    DecompositionInitial = QChar::Initial,
-    DecompositionIsolated = QChar::Isolated,
-    DecompositionMedial = QChar::Medial,
-    DecompositionNarrow = QChar::Narrow,
-    DecompositionNoBreak = QChar::NoBreak,
-    DecompositionSmall = QChar::Small,
-    DecompositionSquare = QChar::Square,
-    DecompositionSub = QChar::Sub,
-    DecompositionSuper = QChar::Super,
-    DecompositionVertical = QChar::Vertical,
-    DecompositionWide = QChar::Wide
-};
-
-enum CharCategory {
-    NoCategory = 0,
-    Mark_NonSpacing = U_MASK(QChar::Mark_NonSpacing),
-    Mark_SpacingCombining = U_MASK(QChar::Mark_SpacingCombining),
-    Mark_Enclosing = U_MASK(QChar::Mark_Enclosing),
-    Number_DecimalDigit = U_MASK(QChar::Number_DecimalDigit),
-    Number_Letter = U_MASK(QChar::Number_Letter),
-    Number_Other = U_MASK(QChar::Number_Other),
-    Separator_Space = U_MASK(QChar::Separator_Space),
-    Separator_Line = U_MASK(QChar::Separator_Line),
-    Separator_Paragraph = U_MASK(QChar::Separator_Paragraph),
-    Other_Control = U_MASK(QChar::Other_Control),
-    Other_Format = U_MASK(QChar::Other_Format),
-    Other_Surrogate = U_MASK(QChar::Other_Surrogate),
-    Other_PrivateUse = U_MASK(QChar::Other_PrivateUse),
-    Other_NotAssigned = U_MASK(QChar::Other_NotAssigned),
-    Letter_Uppercase = U_MASK(QChar::Letter_Uppercase),
-    Letter_Lowercase = U_MASK(QChar::Letter_Lowercase),
-    Letter_Titlecase = U_MASK(QChar::Letter_Titlecase),
-    Letter_Modifier = U_MASK(QChar::Letter_Modifier),
-    Letter_Other = U_MASK(QChar::Letter_Other),
-    Punctuation_Connector = U_MASK(QChar::Punctuation_Connector),
-    Punctuation_Dash = U_MASK(QChar::Punctuation_Dash),
-    Punctuation_Open = U_MASK(QChar::Punctuation_Open),
-    Punctuation_Close = U_MASK(QChar::Punctuation_Close),
-    Punctuation_InitialQuote = U_MASK(QChar::Punctuation_InitialQuote),
-    Punctuation_FinalQuote = U_MASK(QChar::Punctuation_FinalQuote),
-    Punctuation_Other = U_MASK(QChar::Punctuation_Other),
-    Symbol_Math = U_MASK(QChar::Symbol_Math),
-    Symbol_Currency = U_MASK(QChar::Symbol_Currency),
-    Symbol_Modifier = U_MASK(QChar::Symbol_Modifier),
-    Symbol_Other = U_MASK(QChar::Symbol_Other)
-};
-
-
-// FIXME: handle surrogates correctly in all methods
-
-inline UChar32 toLower(UChar32 ch)
-{
-    return QChar::toLower(uint32_t(ch));
-}
-
-inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
-{
-    const UChar *e = src + srcLength;
-    const UChar *s = src;
-    UChar *r = result;
-    uint rindex = 0;
-
-    // this avoids one out of bounds check in the loop
-    if (s < e && QChar(*s).isLowSurrogate()) {
-        if (r)
-            r[rindex] = *s++;
-        ++rindex;
-    }
-
-    int needed = 0;
-    while (s < e && (rindex < uint(resultLength) || !r)) {
-        uint c = *s;
-        if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
-            c = QChar::surrogateToUcs4(*(s - 1), c);
-        const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
-        if (prop->lowerCaseSpecial) {
-            QString qstring;
-            if (c < 0x10000) {
-                qstring += QChar(c);
-            } else {
-                qstring += QChar(*(s-1));
-                qstring += QChar(*s);
-            }
-            qstring = qstring.toLower();
-            for (int i = 0; i < qstring.length(); ++i) {
-                if (rindex >= uint(resultLength)) {
-                    needed += qstring.length() - i;
-                    break;
-                }
-                if (r)
-                    r[rindex] = qstring.at(i).unicode();
-                ++rindex;
-            }
-        } else {
-            if (r)
-                r[rindex] = *s + prop->lowerCaseDiff;
-            ++rindex;
-        }
-        ++s;
-    }
-    if (s < e)
-        needed += e - s;
-    *error = (needed != 0);
-    if (rindex < uint(resultLength))
-        r[rindex] = 0;
-    return rindex + needed;
-}
-
-inline UChar32 toUpper(UChar32 c)
-{
-    return QChar::toUpper(uint32_t(c));
-}
-
-inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
-{
-    const UChar *e = src + srcLength;
-    const UChar *s = src;
-    UChar *r = result;
-    int rindex = 0;
-
-    // this avoids one out of bounds check in the loop
-    if (s < e && QChar(*s).isLowSurrogate()) {
-        if (r)
-            r[rindex] = *s++;
-        ++rindex;
-    }
-
-    int needed = 0;
-    while (s < e && (rindex < resultLength || !r)) {
-        uint c = *s;
-        if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate())
-            c = QChar::surrogateToUcs4(*(s - 1), c);
-        const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c);
-        if (prop->upperCaseSpecial) {
-            QString qstring;
-            if (c < 0x10000) {
-                qstring += QChar(c);
-            } else {
-                qstring += QChar(*(s-1));
-                qstring += QChar(*s);
-            }
-            qstring = qstring.toUpper();
-            for (int i = 0; i < qstring.length(); ++i) {
-                if (rindex >= resultLength) {
-                    needed += qstring.length() - i;
-                    break;
-                }
-                if (r)
-                    r[rindex] = qstring.at(i).unicode();
-                ++rindex;
-            }
-        } else {
-            if (r)
-                r[rindex] = *s + prop->upperCaseDiff;
-            ++rindex;
-        }
-        ++s;
-    }
-    if (s < e)
-        needed += e - s;
-    *error = (needed != 0);
-    if (rindex < resultLength)
-        r[rindex] = 0;
-    return rindex + needed;
-}
-
-inline int toTitleCase(UChar32 c)
-{
-    return QChar::toTitleCase(uint32_t(c));
-}
-
-inline UChar32 foldCase(UChar32 c)
-{
-    return QChar::toCaseFolded(uint32_t(c));
-}
-
-inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
-{
-    // FIXME: handle special casing. Easiest with some low level API in Qt
-    *error = false;
-    if (resultLength < srcLength) {
-        *error = true;
-        return srcLength;
-    }
-    for (int i = 0; i < srcLength; ++i)
-        result[i] = QChar::toCaseFolded(ushort(src[i]));
-    return srcLength;
-}
-
-inline bool isArabicChar(UChar32 c)
-{
-    return c >= 0x0600 && c <= 0x06FF;
-}
-
-inline bool isPrintableChar(UChar32 c)
-{
-    const uint test = U_MASK(QChar::Other_Control) |
-                      U_MASK(QChar::Other_NotAssigned);
-    return !(U_MASK(QChar::category(uint32_t(c))) & test);
-}
-
-inline bool isSeparatorSpace(UChar32 c)
-{
-    return QChar::category(uint32_t(c)) == QChar::Separator_Space;
-}
-
-inline bool isPunct(UChar32 c)
-{
-    const uint test = U_MASK(QChar::Punctuation_Connector) |
-                      U_MASK(QChar::Punctuation_Dash) |
-                      U_MASK(QChar::Punctuation_Open) |
-                      U_MASK(QChar::Punctuation_Close) |
-                      U_MASK(QChar::Punctuation_InitialQuote) |
-                      U_MASK(QChar::Punctuation_FinalQuote) |
-                      U_MASK(QChar::Punctuation_Other);
-    return U_MASK(QChar::category(uint32_t(c))) & test;
-}
-
-inline bool isLower(UChar32 c)
-{
-    return QChar::category(uint32_t(c)) == QChar::Letter_Lowercase;
-}
-
-inline bool hasLineBreakingPropertyComplexContext(UChar32)
-{
-    // FIXME: Implement this to return whether the character has line breaking property SA (Complex Context).
-    return false;
-}
-
-inline UChar32 mirroredChar(UChar32 c)
-{
-    return QChar::mirroredChar(uint32_t(c));
-}
-
-inline uint8_t combiningClass(UChar32 c)
-{
-    return QChar::combiningClass(uint32_t(c));
-}
-
-inline DecompositionType decompositionType(UChar32 c)
-{
-    return (DecompositionType)QChar::decompositionTag(c);
-}
-
-inline int umemcasecmp(const UChar* a, const UChar* b, int len)
-{
-    // handle surrogates correctly
-    for (int i = 0; i < len; ++i) {
-        uint c1 = QChar::toCaseFolded(ushort(a[i]));
-        uint c2 = QChar::toCaseFolded(ushort(b[i]));
-        if (c1 != c2)
-            return c1 - c2;
-    }
-    return 0;
-}
-
-inline Direction direction(UChar32 c)
-{
-    return (Direction)QChar::direction(uint32_t(c));
-}
-
-inline CharCategory category(UChar32 c)
-{
-    return (CharCategory) U_MASK(QChar::category(uint32_t(c)));
-}
-
-} }
-
-#endif // WTF_UNICODE_QT4_H
diff --git a/wtf/unicode/wince/UnicodeWinCE.cpp b/wtf/unicode/wince/UnicodeWinCE.cpp
deleted file mode 100644 (file)
index 96dac7d..0000000
+++ /dev/null
@@ -1,181 +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 {
-
-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
deleted file mode 100644 (file)
index 2688aa9..0000000
+++ /dev/null
@@ -1,177 +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 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/url/api/ParsedURL.cpp b/wtf/url/api/ParsedURL.cpp
deleted file mode 100644 (file)
index abe0061..0000000
+++ /dev/null
@@ -1,90 +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.
- *
- * 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
deleted file mode 100644 (file)
index ebc19b7..0000000
+++ /dev/null
@@ -1,62 +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.
- *
- * 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
deleted file mode 100644 (file)
index 7395d49..0000000
+++ /dev/null
@@ -1,55 +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.
- *
- * 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
deleted file mode 100644 (file)
index 9bb2e8e..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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
deleted file mode 100644 (file)
index e07402e..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-// 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
deleted file mode 100644 (file)
index ee2014e..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-// 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
deleted file mode 100644 (file)
index 194f6b0..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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
diff --git a/wtf/url/src/URLComponent.h b/wtf/url/src/URLComponent.h
deleted file mode 100644 (file)
index 1b7976e..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// 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 URLComponent_h
-#define URLComponent_h
-
-namespace WTF {
-
-// Represents a substring for URL parsing.
-class URLComponent {
-public:
-    URLComponent() : m_begin(0), m_length(-1) { }
-    URLComponent(int begin, int length) : m_begin(begin), m_length(length) { }
-
-    // Helper that returns a component created with the given begin and ending
-    // points. The ending point is non-inclusive.
-    static inline URLComponent fromRange(int begin, int end)
-    {
-        return URLComponent(begin, end - begin);
-    }
-
-    // Returns true if this component is valid, meaning the length is given. Even
-    // valid components may be empty to record the fact that they exist.
-    bool isValid() const { return m_length != -1; }
-
-    bool isNonEmpty() const { return m_length > 0; }
-    bool isEmptyOrInvalid() const { return m_length <= 0; }
-
-    void reset()
-    {
-        m_begin = 0;
-        m_length = -1;
-    }
-
-    bool operator==(const URLComponent& other) const { return m_begin == other.m_begin && m_length == other.m_length; }
-
-    int begin() const { return m_begin; }
-    void setBegin(int begin) { m_begin = begin; }
-
-    int length() const { return m_length; }
-    void setLength(int length) { m_length = length; }
-
-    int end() const { return m_begin + m_length; }
-
-private:
-    int m_begin; // Byte offset in the string of this component.
-    int m_length; // Will be -1 if the component is unspecified.
-};
-
-} // namespace WTF
-
-#endif // URLComponent_h
diff --git a/wtf/url/src/URLEscape.cpp b/wtf/url/src/URLEscape.cpp
deleted file mode 100644 (file)
index 2987343..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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
deleted file mode 100644 (file)
index cc2b77f..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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
deleted file mode 100644 (file)
index 4d5ca51..0000000
+++ /dev/null
@@ -1,575 +0,0 @@
-/* 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
deleted file mode 100644 (file)
index 7740200..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// 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/url/src/URLSegments.cpp b/wtf/url/src/URLSegments.cpp
deleted file mode 100644 (file)
index bb9542f..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* 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.
- */
-
-#include "config.h"
-#include "URLSegments.h"
-
-namespace WTF {
-
-int URLSegments::length() const
-{
-    if (fragment.isValid())
-        return fragment.end();
-    return charactersBefore(Fragment, false);
-}
-
-int URLSegments::charactersBefore(ComponentType type, bool includeDelimiter) const
-{
-    if (type == Scheme)
-        return scheme.begin();
-
-    int current = 0;
-    if (scheme.isValid())
-        current = scheme.end() + 1; // Advance over the ':' at the end of the scheme.
-
-    if (username.isValid()) {
-        if (type <= Username)
-            return username.begin();
-        current = username.end() + 1; // Advance over the '@' or ':' at the end.
-    }
-
-    if (password.isValid()) {
-        if (type <= Password)
-            return password.begin();
-        current = password.end() + 1; // Advance over the '@' at the end.
-    }
-
-    if (host.isValid()) {
-        if (type <= Host)
-            return host.begin();
-        current = host.end();
-    }
-
-    if (port.isValid()) {
-        if (type < Port || (type == Port && includeDelimiter))
-            return port.begin() - 1; // Back over delimiter.
-        if (type == Port)
-            return port.begin(); // Don't want delimiter counted.
-        current = port.end();
-    }
-
-    if (path.isValid()) {
-        if (type <= Path)
-            return path.begin();
-        current = path.end();
-    }
-
-    if (query.isValid()) {
-        if (type < Query || (type == Query && includeDelimiter))
-            return query.begin() - 1; // Back over delimiter.
-        if (type == Query)
-            return query.begin(); // Don't want delimiter counted.
-        current = query.end();
-    }
-
-    if (fragment.isValid()) {
-        if (type == Fragment && !includeDelimiter)
-            return fragment.begin(); // Back over delimiter.
-
-        // When there is a fragment and we get here, the component we wanted was before
-        // this and not found, so we always know the beginning of the fragment is right.
-        return fragment.begin() - 1; // Don't want delimiter counted.
-    }
-
-    return current;
-}
-
-} // namespace WTF
diff --git a/wtf/url/src/URLSegments.h b/wtf/url/src/URLSegments.h
deleted file mode 100644 (file)
index 436c7fe..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2007, 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 URLSegments_h
-#define URLSegments_h
-
-#include "URLComponent.h"
-
-namespace WTF {
-
-// A structure that holds the identified parts of an input URL. This structure
-// does NOT store the URL itself. The caller will have to store the URL text
-// and its corresponding Parsed structure separately.
-class URLSegments {
-public:
-    // Identifies different components.
-    enum ComponentType {
-        Scheme,
-        Username,
-        Password,
-        Host,
-        Port,
-        Path,
-        Query,
-        Fragment,
-    };
-
-    URLSegments() { }
-
-    // Returns the length of the URL (the end of the last component).
-    //
-    // Note that for some invalid, non-canonical URLs, this may not be the length
-    // of the string. For example "http://": the parsed structure will only
-    // contain an entry for the four-character scheme, and it doesn't know about
-    // the "://". For all other last-components, it will return the real length.
-    int length() const;
-
-    // Returns the number of characters before the given component if it exists,
-    // or where the component would be if it did exist. This will return the
-    // string length if the component would be appended to the end.
-    //
-    // Note that this can get a little funny for the port, query, and fragment
-    // components which have a delimiter that is not counted as part of the
-    // component. The |includeDelimiter| flag controls if you want this counted
-    // as part of the component or not when the component exists.
-    //
-    // This example shows the difference between the two flags for two of these
-    // delimited components that is present (the port and query) and one that
-    // isn't (the reference). The components that this flag affects are marked
-    // with a *.
-    //                 0         1         2
-    //                 012345678901234567890
-    // Example input:  http://foo:80/?query
-    //              include_delim=true,  ...=false  ("<-" indicates different)
-    //      Scheme: 0                    0
-    //    Username: 5                    5
-    //    Password: 5                    5
-    //        Host: 7                    7
-    //       *Port: 10                   11 <-
-    //        Path: 13                   13
-    //      *Query: 14                   15 <-
-    //        *Fragment: 20                   20
-    //
-    int charactersBefore(ComponentType, bool includeDelimiter) const;
-
-    // Each component excludes the related delimiters and has a length of -1
-    // if that component is absent but 0 if the component exists but is empty.
-    URLComponent scheme;
-    URLComponent username;
-    URLComponent password;
-    URLComponent host;
-    URLComponent port;
-    URLComponent path;
-    URLComponent query;
-    URLComponent fragment;
-};
-
-} // namespace WTF
-
-#endif // URLSegments_h
diff --git a/wtf/url/wtfurl.gyp b/wtf/url/wtfurl.gyp
deleted file mode 100644 (file)
index f254ae4..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (C) 2009 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.
-
-{
-  'variables': {
-    'chromium_code': 1,
-  },
-  'targets': [
-    {
-      'target_name': 'wtfurl',
-      'type': '<(library)',
-      'msvs_guid': 'EF5E94AB-B646-4E5B-A058-52EF07B8351C',
-      'dependencies': [
-      ],
-      'sources': [
-        'src/URLComponent.h',
-        'src/URLSegments.cpp',
-        'src/URLSegments.h',
-      ],
-      'direct_dependent_settings': {
-        'include_dirs': [
-          'src',
-        ],
-      },
-    },
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/wtf/win/MainThreadWin.cpp b/wtf/win/MainThreadWin.cpp
deleted file mode 100644 (file)
index ee3a273..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must 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 "MainThread.h"
-
-#include "Assertions.h"
-#include "Threading.h"
-#if !OS(WINCE)
-#include <windows.h>
-#endif
-
-namespace WTF {
-
-static HWND threadingWindowHandle;
-static UINT threadingFiredMessage;
-const LPCWSTR kThreadingWindowClassName = L"ThreadingWindowClass";
-
-LRESULT CALLBACK ThreadingWindowWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
-    if (message == threadingFiredMessage)
-        dispatchFunctionsFromMainThread();
-    else
-        return DefWindowProc(hWnd, message, wParam, lParam);
-    return 0;
-}
-
-void initializeMainThreadPlatform()
-{
-    if (threadingWindowHandle)
-        return;
-
-    HWND hWndParent = 0;
-#if OS(WINCE)
-    WNDCLASS wcex;
-    memset(&wcex, 0, sizeof(WNDCLASS));
-#else
-    WNDCLASSEX wcex;
-    memset(&wcex, 0, sizeof(WNDCLASSEX));
-    wcex.cbSize = sizeof(WNDCLASSEX);
-#endif
-    wcex.lpfnWndProc    = ThreadingWindowWndProc;
-    wcex.lpszClassName  = kThreadingWindowClassName;
-#if OS(WINCE)
-    RegisterClass(&wcex);
-#else
-    RegisterClassEx(&wcex);
-    hWndParent = HWND_MESSAGE;
-#endif
-
-    threadingWindowHandle = CreateWindow(kThreadingWindowClassName, 0, 0,
-       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hWndParent, 0, 0, 0);
-    threadingFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.MainThreadFired");
-
-    initializeCurrentThreadInternal("Main Thread");
-}
-
-void scheduleDispatchFunctionsOnMainThread()
-{
-    ASSERT(threadingWindowHandle);
-    PostMessage(threadingWindowHandle, threadingFiredMessage, 0, 0);
-}
-
-} // namespace WTF
diff --git a/wtf/win/OwnPtrWin.cpp b/wtf/win/OwnPtrWin.cpp
deleted file mode 100644 (file)
index 67a32ff..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2008, 2009 Torch Mobile, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this 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 "OwnPtr.h"
-
-#include <windows.h>
-
-namespace WTF {
-
-void deleteOwnedPtr(HBITMAP ptr)
-{
-    if (ptr)
-        DeleteObject(ptr);
-}
-
-void deleteOwnedPtr(HBRUSH ptr)
-{
-    if (ptr)
-        DeleteObject(ptr);
-}
-
-void deleteOwnedPtr(HDC ptr)
-{
-    if (ptr)
-        DeleteDC(ptr);
-}
-
-void deleteOwnedPtr(HFONT ptr)
-{
-    if (ptr)
-        DeleteObject(ptr);
-}
-
-void deleteOwnedPtr(HPALETTE ptr)
-{
-    if (ptr)
-        DeleteObject(ptr);
-}
-
-void deleteOwnedPtr(HPEN ptr)
-{
-    if (ptr)
-        DeleteObject(ptr);
-}
-
-void deleteOwnedPtr(HRGN ptr)
-{
-    if (ptr)
-        DeleteObject(ptr);
-}
-
-}
diff --git a/wtf/wince/FastMallocWinCE.h b/wtf/wince/FastMallocWinCE.h
deleted file mode 100644 (file)
index d91a5f2..0000000
+++ /dev/null
@@ -1,175 +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 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/MemoryManager.cpp b/wtf/wince/MemoryManager.cpp
deleted file mode 100644 (file)
index 81d4f80..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2008-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 "MemoryManager.h"
-
-#undef malloc
-#undef calloc
-#undef realloc
-#undef free
-#undef strdup
-#undef _strdup
-#undef VirtualAlloc
-#undef VirtualFree
-
-#include <malloc.h>
-#include <windows.h>
-
-namespace WTF {
-
-MemoryManager* memoryManager()
-{
-    static MemoryManager mm;
-    return &mm;
-}
-
-MemoryManager::MemoryManager()
-: m_allocationCanFail(false)
-{
-}
-
-MemoryManager::~MemoryManager()
-{
-}
-
-HBITMAP MemoryManager::createCompatibleBitmap(HDC hdc, int width, int height)
-{
-    return ::CreateCompatibleBitmap(hdc, width, height);
-}
-
-HBITMAP MemoryManager::createDIBSection(const BITMAPINFO* pbmi, void** ppvBits)
-{
-    return ::CreateDIBSection(0, pbmi, DIB_RGB_COLORS, ppvBits, 0, 0);
-}
-
-void* MemoryManager::m_malloc(size_t size)
-{
-    return malloc(size);
-}
-
-void* MemoryManager::m_calloc(size_t num, size_t size)
-{
-    return calloc(num, size);
-}
-
-void* MemoryManager::m_realloc(void* p, size_t size)
-{
-    return realloc(p, size);
-}
-
-void MemoryManager::m_free(void* p)
-{
-    return free(p);
-}
-
-bool MemoryManager::resizeMemory(void*, size_t)
-{
-    return false;
-}
-
-void* MemoryManager::allocate64kBlock()
-{
-    return VirtualAlloc(0, 65536, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
-}
-
-void MemoryManager::free64kBlock(void* p)
-{
-    VirtualFree(p, 65536, MEM_RELEASE);
-}
-
-bool MemoryManager::onIdle(DWORD& timeLimitMs)
-{
-    return false;
-}
-
-LPVOID MemoryManager::virtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect)
-{
-    return ::VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
-}
-
-BOOL MemoryManager::virtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType)
-{
-    return ::VirtualFree(lpAddress, dwSize, dwFreeType);
-}
-
-
-#if defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC
-
-void *fastMalloc(size_t n) { return malloc(n); }
-void *fastCalloc(size_t n_elements, size_t element_size) { return calloc(n_elements, element_size); }
-void fastFree(void* p) { return free(p); }
-void *fastRealloc(void* p, size_t n) { return realloc(p, n); }
-
-#else
-
-void *fastMalloc(size_t n) { return MemoryManager::m_malloc(n); }
-void *fastCalloc(size_t n_elements, size_t element_size) { return MemoryManager::m_calloc(n_elements, element_size); }
-void fastFree(void* p) { return MemoryManager::m_free(p); }
-void *fastRealloc(void* p, size_t n) { return MemoryManager::m_realloc(p, n); }
-
-#endif
-
-#ifndef NDEBUG
-void fastMallocForbid() {}
-void fastMallocAllow() {}
-#endif
-
-void* fastZeroedMalloc(size_t n)
-{
-    void* p = fastMalloc(n);
-    if (p)
-        memset(p, 0, n);
-    return p;
-}
-
-TryMallocReturnValue tryFastMalloc(size_t n)
-{
-    MemoryAllocationCanFail canFail;
-    return fastMalloc(n);
-}
-
-TryMallocReturnValue tryFastZeroedMalloc(size_t n)
-{
-    MemoryAllocationCanFail canFail;
-    return fastZeroedMalloc(n);
-}
-
-TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size)
-{
-    MemoryAllocationCanFail canFail;
-    return fastCalloc(n_elements, element_size);
-}
-
-TryMallocReturnValue tryFastRealloc(void* p, size_t n)
-{
-    MemoryAllocationCanFail canFail;
-    return fastRealloc(p, n);
-}
-
-char* fastStrDup(const char* str)
-{
-    return _strdup(str);
-}
-
-}
\ No newline at end of file
diff --git a/wtf/wince/MemoryManager.h b/wtf/wince/MemoryManager.h
deleted file mode 100644 (file)
index f405612..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2008-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.
- */
-
-#pragma once
-
-#include <winbase.h>
-
-typedef struct HBITMAP__* HBITMAP;
-typedef struct HDC__* HDC;
-typedef void *HANDLE;
-typedef struct tagBITMAPINFO BITMAPINFO;
-
-namespace WTF {
-
-    class MemoryManager {
-    public:
-        MemoryManager();
-        ~MemoryManager();
-
-        bool allocationCanFail() const { return m_allocationCanFail; }
-        void setAllocationCanFail(bool c) { m_allocationCanFail = c; }
-
-        static HBITMAP createCompatibleBitmap(HDC hdc, int width, int height);
-        static HBITMAP createDIBSection(const BITMAPINFO* pbmi, void** ppvBits);
-        static void* m_malloc(size_t size);
-        static void* m_calloc(size_t num, size_t size);
-        static void* m_realloc(void* p, size_t size);
-        static void m_free(void*);
-        static bool resizeMemory(void* p, size_t newSize);
-        static void* allocate64kBlock();
-        static void free64kBlock(void*);
-        static bool onIdle(DWORD& timeLimitMs);
-        static LPVOID virtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect);
-        static BOOL virtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType);
-
-    private:
-        friend MemoryManager* memoryManager();
-
-        bool m_allocationCanFail;
-    };
-
-    MemoryManager* memoryManager();
-
-    class MemoryAllocationCanFail {
-    public:
-        MemoryAllocationCanFail() : m_old(memoryManager()->allocationCanFail()) { memoryManager()->setAllocationCanFail(true); }
-        ~MemoryAllocationCanFail() { memoryManager()->setAllocationCanFail(m_old); }
-    private:
-        bool m_old;
-    };
-
-    class MemoryAllocationCannotFail {
-    public:
-        MemoryAllocationCannotFail() : m_old(memoryManager()->allocationCanFail()) { memoryManager()->setAllocationCanFail(false); }
-        ~MemoryAllocationCannotFail() { memoryManager()->setAllocationCanFail(m_old); }
-    private:
-        bool m_old;
-    };
-}
-
-using WTF::MemoryManager;
-using WTF::memoryManager;
-using WTF::MemoryAllocationCanFail;
-using WTF::MemoryAllocationCannotFail;
diff --git a/wtf/wtf.pri b/wtf/wtf.pri
deleted file mode 100644 (file)
index 10b41e4..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-# 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/MainThreadWx.cpp b/wtf/wx/MainThreadWx.cpp
deleted file mode 100644 (file)
index e1d15c9..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007 Kevin Ollivier
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer. 
- * 2.  Redistributions in binary form must 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 "MainThread.h"
-
-#include <wx/defs.h>
-#include <wx/app.h>
-#include <wx/event.h>
-
-const wxEventType wxEVT_CALL_AFTER = wxNewEventType();
-
-class wxCallAfter : public wxEvtHandler
-{
-public:
-    wxCallAfter() 
-        : wxEvtHandler()
-        {
-            wxTheApp->Connect(-1, -1, wxEVT_CALL_AFTER, wxCommandEventHandler(wxCallAfter::OnCallback));
-            wxCommandEvent event(wxEVT_CALL_AFTER);
-            wxPostEvent(wxTheApp, event);
-        }
-        
-    void OnCallback(wxCommandEvent& event)
-    {
-        WTF::dispatchFunctionsFromMainThread();
-    }
-};
-
-namespace WTF {
-
-void initializeMainThreadPlatform()
-{
-}
-
-void scheduleDispatchFunctionsOnMainThread()
-{
-    wxCallAfter();
-}
-
-} // namespace WTF
diff --git a/wtf/wx/StringWx.cpp b/wtf/wx/StringWx.cpp
deleted file mode 100644 (file)
index d5f6c57..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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
index de64fdd1b3788169370048bf77a8ac521e740f9e..d393e9fa901ce359c790231fc3d7ed51c50cb0af 100644 (file)
@@ -43,6 +43,7 @@ namespace JSC { namespace Yarr {
 #define YarrStackSpaceForBackTrackInfoParentheses 2
 
 static const unsigned quantifyInfinite = UINT_MAX;
 #define YarrStackSpaceForBackTrackInfoParentheses 2
 
 static const unsigned quantifyInfinite = UINT_MAX;
+static const unsigned offsetNoMatch = (unsigned)-1;
 
 // The below limit restricts the number of "recursive" match calls in order to
 // avoid spending exponential time on complex regular expressions.
 
 // The below limit restricts the number of "recursive" match calls in order to
 // avoid spending exponential time on complex regular expressions.
@@ -57,8 +58,10 @@ enum JSRegExpResult {
     JSRegExpErrorInternal = -4
 };
 
     JSRegExpErrorInternal = -4
 };
 
-PassOwnPtr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*);
-int interpret(BytecodePattern*, const UChar* input, unsigned start, unsigned length, int* output);
+enum YarrCharSize {
+    Char8,
+    Char16
+};
 
 } } // namespace JSC::Yarr
 
 
 } } // namespace JSC::Yarr
 
diff --git a/yarr/YarrCanonicalizeUCS2.cpp b/yarr/YarrCanonicalizeUCS2.cpp
new file mode 100644 (file)
index 0000000..7bb3d08
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+// DO NOT EDIT! - this file autogenerated by YarrCanonicalizeUCS2.js
+
+#include "config.h"
+#include "YarrCanonicalizeUCS2.h"
+
+namespace JSC { namespace Yarr {
+
+#include <stdint.h>
+
+uint16_t ucs2CharacterSet0[] = { 0x01c4u, 0x01c5u, 0x01c6u, 0 };
+uint16_t ucs2CharacterSet1[] = { 0x01c7u, 0x01c8u, 0x01c9u, 0 };
+uint16_t ucs2CharacterSet2[] = { 0x01cau, 0x01cbu, 0x01ccu, 0 };
+uint16_t ucs2CharacterSet3[] = { 0x01f1u, 0x01f2u, 0x01f3u, 0 };
+uint16_t ucs2CharacterSet4[] = { 0x0392u, 0x03b2u, 0x03d0u, 0 };
+uint16_t ucs2CharacterSet5[] = { 0x0395u, 0x03b5u, 0x03f5u, 0 };
+uint16_t ucs2CharacterSet6[] = { 0x0398u, 0x03b8u, 0x03d1u, 0 };
+uint16_t ucs2CharacterSet7[] = { 0x0345u, 0x0399u, 0x03b9u, 0x1fbeu, 0 };
+uint16_t ucs2CharacterSet8[] = { 0x039au, 0x03bau, 0x03f0u, 0 };
+uint16_t ucs2CharacterSet9[] = { 0x00b5u, 0x039cu, 0x03bcu, 0 };
+uint16_t ucs2CharacterSet10[] = { 0x03a0u, 0x03c0u, 0x03d6u, 0 };
+uint16_t ucs2CharacterSet11[] = { 0x03a1u, 0x03c1u, 0x03f1u, 0 };
+uint16_t ucs2CharacterSet12[] = { 0x03a3u, 0x03c2u, 0x03c3u, 0 };
+uint16_t ucs2CharacterSet13[] = { 0x03a6u, 0x03c6u, 0x03d5u, 0 };
+uint16_t ucs2CharacterSet14[] = { 0x1e60u, 0x1e61u, 0x1e9bu, 0 };
+
+static const size_t UCS2_CANONICALIZATION_SETS = 15;
+uint16_t* characterSetInfo[UCS2_CANONICALIZATION_SETS] = {
+    ucs2CharacterSet0,
+    ucs2CharacterSet1,
+    ucs2CharacterSet2,
+    ucs2CharacterSet3,
+    ucs2CharacterSet4,
+    ucs2CharacterSet5,
+    ucs2CharacterSet6,
+    ucs2CharacterSet7,
+    ucs2CharacterSet8,
+    ucs2CharacterSet9,
+    ucs2CharacterSet10,
+    ucs2CharacterSet11,
+    ucs2CharacterSet12,
+    ucs2CharacterSet13,
+    ucs2CharacterSet14,
+};
+
+const size_t UCS2_CANONICALIZATION_RANGES = 364;
+UCS2CanonicalizationRange rangeInfo[UCS2_CANONICALIZATION_RANGES] = {
+    { 0x0000u, 0x0040u, 0x0000u, CanonicalizeUnique },
+    { 0x0041u, 0x005au, 0x0020u, CanonicalizeRangeLo },
+    { 0x005bu, 0x0060u, 0x0000u, CanonicalizeUnique },
+    { 0x0061u, 0x007au, 0x0020u, CanonicalizeRangeHi },
+    { 0x007bu, 0x00b4u, 0x0000u, CanonicalizeUnique },
+    { 0x00b5u, 0x00b5u, 0x0009u, CanonicalizeSet },
+    { 0x00b6u, 0x00bfu, 0x0000u, CanonicalizeUnique },
+    { 0x00c0u, 0x00d6u, 0x0020u, CanonicalizeRangeLo },
+    { 0x00d7u, 0x00d7u, 0x0000u, CanonicalizeUnique },
+    { 0x00d8u, 0x00deu, 0x0020u, CanonicalizeRangeLo },
+    { 0x00dfu, 0x00dfu, 0x0000u, CanonicalizeUnique },
+    { 0x00e0u, 0x00f6u, 0x0020u, CanonicalizeRangeHi },
+    { 0x00f7u, 0x00f7u, 0x0000u, CanonicalizeUnique },
+    { 0x00f8u, 0x00feu, 0x0020u, CanonicalizeRangeHi },
+    { 0x00ffu, 0x00ffu, 0x0079u, CanonicalizeRangeLo },
+    { 0x0100u, 0x012fu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x0130u, 0x0131u, 0x0000u, CanonicalizeUnique },
+    { 0x0132u, 0x0137u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x0138u, 0x0138u, 0x0000u, CanonicalizeUnique },
+    { 0x0139u, 0x0148u, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x0149u, 0x0149u, 0x0000u, CanonicalizeUnique },
+    { 0x014au, 0x0177u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x0178u, 0x0178u, 0x0079u, CanonicalizeRangeHi },
+    { 0x0179u, 0x017eu, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x017fu, 0x017fu, 0x0000u, CanonicalizeUnique },
+    { 0x0180u, 0x0180u, 0x00c3u, CanonicalizeRangeLo },
+    { 0x0181u, 0x0181u, 0x00d2u, CanonicalizeRangeLo },
+    { 0x0182u, 0x0185u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x0186u, 0x0186u, 0x00ceu, CanonicalizeRangeLo },
+    { 0x0187u, 0x0188u, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x0189u, 0x018au, 0x00cdu, CanonicalizeRangeLo },
+    { 0x018bu, 0x018cu, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x018du, 0x018du, 0x0000u, CanonicalizeUnique },
+    { 0x018eu, 0x018eu, 0x004fu, CanonicalizeRangeLo },
+    { 0x018fu, 0x018fu, 0x00cau, CanonicalizeRangeLo },
+    { 0x0190u, 0x0190u, 0x00cbu, CanonicalizeRangeLo },
+    { 0x0191u, 0x0192u, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x0193u, 0x0193u, 0x00cdu, CanonicalizeRangeLo },
+    { 0x0194u, 0x0194u, 0x00cfu, CanonicalizeRangeLo },
+    { 0x0195u, 0x0195u, 0x0061u, CanonicalizeRangeLo },
+    { 0x0196u, 0x0196u, 0x00d3u, CanonicalizeRangeLo },
+    { 0x0197u, 0x0197u, 0x00d1u, CanonicalizeRangeLo },
+    { 0x0198u, 0x0199u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x019au, 0x019au, 0x00a3u, CanonicalizeRangeLo },
+    { 0x019bu, 0x019bu, 0x0000u, CanonicalizeUnique },
+    { 0x019cu, 0x019cu, 0x00d3u, CanonicalizeRangeLo },
+    { 0x019du, 0x019du, 0x00d5u, CanonicalizeRangeLo },
+    { 0x019eu, 0x019eu, 0x0082u, CanonicalizeRangeLo },
+    { 0x019fu, 0x019fu, 0x00d6u, CanonicalizeRangeLo },
+    { 0x01a0u, 0x01a5u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x01a6u, 0x01a6u, 0x00dau, CanonicalizeRangeLo },
+    { 0x01a7u, 0x01a8u, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x01a9u, 0x01a9u, 0x00dau, CanonicalizeRangeLo },
+    { 0x01aau, 0x01abu, 0x0000u, CanonicalizeUnique },
+    { 0x01acu, 0x01adu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x01aeu, 0x01aeu, 0x00dau, CanonicalizeRangeLo },
+    { 0x01afu, 0x01b0u, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x01b1u, 0x01b2u, 0x00d9u, CanonicalizeRangeLo },
+    { 0x01b3u, 0x01b6u, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x01b7u, 0x01b7u, 0x00dbu, CanonicalizeRangeLo },
+    { 0x01b8u, 0x01b9u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x01bau, 0x01bbu, 0x0000u, CanonicalizeUnique },
+    { 0x01bcu, 0x01bdu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x01beu, 0x01beu, 0x0000u, CanonicalizeUnique },
+    { 0x01bfu, 0x01bfu, 0x0038u, CanonicalizeRangeLo },
+    { 0x01c0u, 0x01c3u, 0x0000u, CanonicalizeUnique },
+    { 0x01c4u, 0x01c6u, 0x0000u, CanonicalizeSet },
+    { 0x01c7u, 0x01c9u, 0x0001u, CanonicalizeSet },
+    { 0x01cau, 0x01ccu, 0x0002u, CanonicalizeSet },
+    { 0x01cdu, 0x01dcu, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x01ddu, 0x01ddu, 0x004fu, CanonicalizeRangeHi },
+    { 0x01deu, 0x01efu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x01f0u, 0x01f0u, 0x0000u, CanonicalizeUnique },
+    { 0x01f1u, 0x01f3u, 0x0003u, CanonicalizeSet },
+    { 0x01f4u, 0x01f5u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x01f6u, 0x01f6u, 0x0061u, CanonicalizeRangeHi },
+    { 0x01f7u, 0x01f7u, 0x0038u, CanonicalizeRangeHi },
+    { 0x01f8u, 0x021fu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x0220u, 0x0220u, 0x0082u, CanonicalizeRangeHi },
+    { 0x0221u, 0x0221u, 0x0000u, CanonicalizeUnique },
+    { 0x0222u, 0x0233u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x0234u, 0x0239u, 0x0000u, CanonicalizeUnique },
+    { 0x023au, 0x023au, 0x2a2bu, CanonicalizeRangeLo },
+    { 0x023bu, 0x023cu, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x023du, 0x023du, 0x00a3u, CanonicalizeRangeHi },
+    { 0x023eu, 0x023eu, 0x2a28u, CanonicalizeRangeLo },
+    { 0x023fu, 0x0240u, 0x2a3fu, CanonicalizeRangeLo },
+    { 0x0241u, 0x0242u, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x0243u, 0x0243u, 0x00c3u, CanonicalizeRangeHi },
+    { 0x0244u, 0x0244u, 0x0045u, CanonicalizeRangeLo },
+    { 0x0245u, 0x0245u, 0x0047u, CanonicalizeRangeLo },
+    { 0x0246u, 0x024fu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x0250u, 0x0250u, 0x2a1fu, CanonicalizeRangeLo },
+    { 0x0251u, 0x0251u, 0x2a1cu, CanonicalizeRangeLo },
+    { 0x0252u, 0x0252u, 0x2a1eu, CanonicalizeRangeLo },
+    { 0x0253u, 0x0253u, 0x00d2u, CanonicalizeRangeHi },
+    { 0x0254u, 0x0254u, 0x00ceu, CanonicalizeRangeHi },
+    { 0x0255u, 0x0255u, 0x0000u, CanonicalizeUnique },
+    { 0x0256u, 0x0257u, 0x00cdu, CanonicalizeRangeHi },
+    { 0x0258u, 0x0258u, 0x0000u, CanonicalizeUnique },
+    { 0x0259u, 0x0259u, 0x00cau, CanonicalizeRangeHi },
+    { 0x025au, 0x025au, 0x0000u, CanonicalizeUnique },
+    { 0x025bu, 0x025bu, 0x00cbu, CanonicalizeRangeHi },
+    { 0x025cu, 0x025fu, 0x0000u, CanonicalizeUnique },
+    { 0x0260u, 0x0260u, 0x00cdu, CanonicalizeRangeHi },
+    { 0x0261u, 0x0262u, 0x0000u, CanonicalizeUnique },
+    { 0x0263u, 0x0263u, 0x00cfu, CanonicalizeRangeHi },
+    { 0x0264u, 0x0264u, 0x0000u, CanonicalizeUnique },
+    { 0x0265u, 0x0265u, 0xa528u, CanonicalizeRangeLo },
+    { 0x0266u, 0x0267u, 0x0000u, CanonicalizeUnique },
+    { 0x0268u, 0x0268u, 0x00d1u, CanonicalizeRangeHi },
+    { 0x0269u, 0x0269u, 0x00d3u, CanonicalizeRangeHi },
+    { 0x026au, 0x026au, 0x0000u, CanonicalizeUnique },
+    { 0x026bu, 0x026bu, 0x29f7u, CanonicalizeRangeLo },
+    { 0x026cu, 0x026eu, 0x0000u, CanonicalizeUnique },
+    { 0x026fu, 0x026fu, 0x00d3u, CanonicalizeRangeHi },
+    { 0x0270u, 0x0270u, 0x0000u, CanonicalizeUnique },
+    { 0x0271u, 0x0271u, 0x29fdu, CanonicalizeRangeLo },
+    { 0x0272u, 0x0272u, 0x00d5u, CanonicalizeRangeHi },
+    { 0x0273u, 0x0274u, 0x0000u, CanonicalizeUnique },
+    { 0x0275u, 0x0275u, 0x00d6u, CanonicalizeRangeHi },
+    { 0x0276u, 0x027cu, 0x0000u, CanonicalizeUnique },
+    { 0x027du, 0x027du, 0x29e7u, CanonicalizeRangeLo },
+    { 0x027eu, 0x027fu, 0x0000u, CanonicalizeUnique },
+    { 0x0280u, 0x0280u, 0x00dau, CanonicalizeRangeHi },
+    { 0x0281u, 0x0282u, 0x0000u, CanonicalizeUnique },
+    { 0x0283u, 0x0283u, 0x00dau, CanonicalizeRangeHi },
+    { 0x0284u, 0x0287u, 0x0000u, CanonicalizeUnique },
+    { 0x0288u, 0x0288u, 0x00dau, CanonicalizeRangeHi },
+    { 0x0289u, 0x0289u, 0x0045u, CanonicalizeRangeHi },
+    { 0x028au, 0x028bu, 0x00d9u, CanonicalizeRangeHi },
+    { 0x028cu, 0x028cu, 0x0047u, CanonicalizeRangeHi },
+    { 0x028du, 0x0291u, 0x0000u, CanonicalizeUnique },
+    { 0x0292u, 0x0292u, 0x00dbu, CanonicalizeRangeHi },
+    { 0x0293u, 0x0344u, 0x0000u, CanonicalizeUnique },
+    { 0x0345u, 0x0345u, 0x0007u, CanonicalizeSet },
+    { 0x0346u, 0x036fu, 0x0000u, CanonicalizeUnique },
+    { 0x0370u, 0x0373u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x0374u, 0x0375u, 0x0000u, CanonicalizeUnique },
+    { 0x0376u, 0x0377u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x0378u, 0x037au, 0x0000u, CanonicalizeUnique },
+    { 0x037bu, 0x037du, 0x0082u, CanonicalizeRangeLo },
+    { 0x037eu, 0x0385u, 0x0000u, CanonicalizeUnique },
+    { 0x0386u, 0x0386u, 0x0026u, CanonicalizeRangeLo },
+    { 0x0387u, 0x0387u, 0x0000u, CanonicalizeUnique },
+    { 0x0388u, 0x038au, 0x0025u, CanonicalizeRangeLo },
+    { 0x038bu, 0x038bu, 0x0000u, CanonicalizeUnique },
+    { 0x038cu, 0x038cu, 0x0040u, CanonicalizeRangeLo },
+    { 0x038du, 0x038du, 0x0000u, CanonicalizeUnique },
+    { 0x038eu, 0x038fu, 0x003fu, CanonicalizeRangeLo },
+    { 0x0390u, 0x0390u, 0x0000u, CanonicalizeUnique },
+    { 0x0391u, 0x0391u, 0x0020u, CanonicalizeRangeLo },
+    { 0x0392u, 0x0392u, 0x0004u, CanonicalizeSet },
+    { 0x0393u, 0x0394u, 0x0020u, CanonicalizeRangeLo },
+    { 0x0395u, 0x0395u, 0x0005u, CanonicalizeSet },
+    { 0x0396u, 0x0397u, 0x0020u, CanonicalizeRangeLo },
+    { 0x0398u, 0x0398u, 0x0006u, CanonicalizeSet },
+    { 0x0399u, 0x0399u, 0x0007u, CanonicalizeSet },
+    { 0x039au, 0x039au, 0x0008u, CanonicalizeSet },
+    { 0x039bu, 0x039bu, 0x0020u, CanonicalizeRangeLo },
+    { 0x039cu, 0x039cu, 0x0009u, CanonicalizeSet },
+    { 0x039du, 0x039fu, 0x0020u, CanonicalizeRangeLo },
+    { 0x03a0u, 0x03a0u, 0x000au, CanonicalizeSet },
+    { 0x03a1u, 0x03a1u, 0x000bu, CanonicalizeSet },
+    { 0x03a2u, 0x03a2u, 0x0000u, CanonicalizeUnique },
+    { 0x03a3u, 0x03a3u, 0x000cu, CanonicalizeSet },
+    { 0x03a4u, 0x03a5u, 0x0020u, CanonicalizeRangeLo },
+    { 0x03a6u, 0x03a6u, 0x000du, CanonicalizeSet },
+    { 0x03a7u, 0x03abu, 0x0020u, CanonicalizeRangeLo },
+    { 0x03acu, 0x03acu, 0x0026u, CanonicalizeRangeHi },
+    { 0x03adu, 0x03afu, 0x0025u, CanonicalizeRangeHi },
+    { 0x03b0u, 0x03b0u, 0x0000u, CanonicalizeUnique },
+    { 0x03b1u, 0x03b1u, 0x0020u, CanonicalizeRangeHi },
+    { 0x03b2u, 0x03b2u, 0x0004u, CanonicalizeSet },
+    { 0x03b3u, 0x03b4u, 0x0020u, CanonicalizeRangeHi },
+    { 0x03b5u, 0x03b5u, 0x0005u, CanonicalizeSet },
+    { 0x03b6u, 0x03b7u, 0x0020u, CanonicalizeRangeHi },
+    { 0x03b8u, 0x03b8u, 0x0006u, CanonicalizeSet },
+    { 0x03b9u, 0x03b9u, 0x0007u, CanonicalizeSet },
+    { 0x03bau, 0x03bau, 0x0008u, CanonicalizeSet },
+    { 0x03bbu, 0x03bbu, 0x0020u, CanonicalizeRangeHi },
+    { 0x03bcu, 0x03bcu, 0x0009u, CanonicalizeSet },
+    { 0x03bdu, 0x03bfu, 0x0020u, CanonicalizeRangeHi },
+    { 0x03c0u, 0x03c0u, 0x000au, CanonicalizeSet },
+    { 0x03c1u, 0x03c1u, 0x000bu, CanonicalizeSet },
+    { 0x03c2u, 0x03c3u, 0x000cu, CanonicalizeSet },
+    { 0x03c4u, 0x03c5u, 0x0020u, CanonicalizeRangeHi },
+    { 0x03c6u, 0x03c6u, 0x000du, CanonicalizeSet },
+    { 0x03c7u, 0x03cbu, 0x0020u, CanonicalizeRangeHi },
+    { 0x03ccu, 0x03ccu, 0x0040u, CanonicalizeRangeHi },
+    { 0x03cdu, 0x03ceu, 0x003fu, CanonicalizeRangeHi },
+    { 0x03cfu, 0x03cfu, 0x0008u, CanonicalizeRangeLo },
+    { 0x03d0u, 0x03d0u, 0x0004u, CanonicalizeSet },
+    { 0x03d1u, 0x03d1u, 0x0006u, CanonicalizeSet },
+    { 0x03d2u, 0x03d4u, 0x0000u, CanonicalizeUnique },
+    { 0x03d5u, 0x03d5u, 0x000du, CanonicalizeSet },
+    { 0x03d6u, 0x03d6u, 0x000au, CanonicalizeSet },
+    { 0x03d7u, 0x03d7u, 0x0008u, CanonicalizeRangeHi },
+    { 0x03d8u, 0x03efu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x03f0u, 0x03f0u, 0x0008u, CanonicalizeSet },
+    { 0x03f1u, 0x03f1u, 0x000bu, CanonicalizeSet },
+    { 0x03f2u, 0x03f2u, 0x0007u, CanonicalizeRangeLo },
+    { 0x03f3u, 0x03f4u, 0x0000u, CanonicalizeUnique },
+    { 0x03f5u, 0x03f5u, 0x0005u, CanonicalizeSet },
+    { 0x03f6u, 0x03f6u, 0x0000u, CanonicalizeUnique },
+    { 0x03f7u, 0x03f8u, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x03f9u, 0x03f9u, 0x0007u, CanonicalizeRangeHi },
+    { 0x03fau, 0x03fbu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x03fcu, 0x03fcu, 0x0000u, CanonicalizeUnique },
+    { 0x03fdu, 0x03ffu, 0x0082u, CanonicalizeRangeHi },
+    { 0x0400u, 0x040fu, 0x0050u, CanonicalizeRangeLo },
+    { 0x0410u, 0x042fu, 0x0020u, CanonicalizeRangeLo },
+    { 0x0430u, 0x044fu, 0x0020u, CanonicalizeRangeHi },
+    { 0x0450u, 0x045fu, 0x0050u, CanonicalizeRangeHi },
+    { 0x0460u, 0x0481u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x0482u, 0x0489u, 0x0000u, CanonicalizeUnique },
+    { 0x048au, 0x04bfu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x04c0u, 0x04c0u, 0x000fu, CanonicalizeRangeLo },
+    { 0x04c1u, 0x04ceu, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x04cfu, 0x04cfu, 0x000fu, CanonicalizeRangeHi },
+    { 0x04d0u, 0x0527u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x0528u, 0x0530u, 0x0000u, CanonicalizeUnique },
+    { 0x0531u, 0x0556u, 0x0030u, CanonicalizeRangeLo },
+    { 0x0557u, 0x0560u, 0x0000u, CanonicalizeUnique },
+    { 0x0561u, 0x0586u, 0x0030u, CanonicalizeRangeHi },
+    { 0x0587u, 0x109fu, 0x0000u, CanonicalizeUnique },
+    { 0x10a0u, 0x10c5u, 0x1c60u, CanonicalizeRangeLo },
+    { 0x10c6u, 0x1d78u, 0x0000u, CanonicalizeUnique },
+    { 0x1d79u, 0x1d79u, 0x8a04u, CanonicalizeRangeLo },
+    { 0x1d7au, 0x1d7cu, 0x0000u, CanonicalizeUnique },
+    { 0x1d7du, 0x1d7du, 0x0ee6u, CanonicalizeRangeLo },
+    { 0x1d7eu, 0x1dffu, 0x0000u, CanonicalizeUnique },
+    { 0x1e00u, 0x1e5fu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x1e60u, 0x1e61u, 0x000eu, CanonicalizeSet },
+    { 0x1e62u, 0x1e95u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x1e96u, 0x1e9au, 0x0000u, CanonicalizeUnique },
+    { 0x1e9bu, 0x1e9bu, 0x000eu, CanonicalizeSet },
+    { 0x1e9cu, 0x1e9fu, 0x0000u, CanonicalizeUnique },
+    { 0x1ea0u, 0x1effu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x1f00u, 0x1f07u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1f08u, 0x1f0fu, 0x0008u, CanonicalizeRangeHi },
+    { 0x1f10u, 0x1f15u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1f16u, 0x1f17u, 0x0000u, CanonicalizeUnique },
+    { 0x1f18u, 0x1f1du, 0x0008u, CanonicalizeRangeHi },
+    { 0x1f1eu, 0x1f1fu, 0x0000u, CanonicalizeUnique },
+    { 0x1f20u, 0x1f27u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1f28u, 0x1f2fu, 0x0008u, CanonicalizeRangeHi },
+    { 0x1f30u, 0x1f37u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1f38u, 0x1f3fu, 0x0008u, CanonicalizeRangeHi },
+    { 0x1f40u, 0x1f45u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1f46u, 0x1f47u, 0x0000u, CanonicalizeUnique },
+    { 0x1f48u, 0x1f4du, 0x0008u, CanonicalizeRangeHi },
+    { 0x1f4eu, 0x1f50u, 0x0000u, CanonicalizeUnique },
+    { 0x1f51u, 0x1f51u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1f52u, 0x1f52u, 0x0000u, CanonicalizeUnique },
+    { 0x1f53u, 0x1f53u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1f54u, 0x1f54u, 0x0000u, CanonicalizeUnique },
+    { 0x1f55u, 0x1f55u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1f56u, 0x1f56u, 0x0000u, CanonicalizeUnique },
+    { 0x1f57u, 0x1f57u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1f58u, 0x1f58u, 0x0000u, CanonicalizeUnique },
+    { 0x1f59u, 0x1f59u, 0x0008u, CanonicalizeRangeHi },
+    { 0x1f5au, 0x1f5au, 0x0000u, CanonicalizeUnique },
+    { 0x1f5bu, 0x1f5bu, 0x0008u, CanonicalizeRangeHi },
+    { 0x1f5cu, 0x1f5cu, 0x0000u, CanonicalizeUnique },
+    { 0x1f5du, 0x1f5du, 0x0008u, CanonicalizeRangeHi },
+    { 0x1f5eu, 0x1f5eu, 0x0000u, CanonicalizeUnique },
+    { 0x1f5fu, 0x1f5fu, 0x0008u, CanonicalizeRangeHi },
+    { 0x1f60u, 0x1f67u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1f68u, 0x1f6fu, 0x0008u, CanonicalizeRangeHi },
+    { 0x1f70u, 0x1f71u, 0x004au, CanonicalizeRangeLo },
+    { 0x1f72u, 0x1f75u, 0x0056u, CanonicalizeRangeLo },
+    { 0x1f76u, 0x1f77u, 0x0064u, CanonicalizeRangeLo },
+    { 0x1f78u, 0x1f79u, 0x0080u, CanonicalizeRangeLo },
+    { 0x1f7au, 0x1f7bu, 0x0070u, CanonicalizeRangeLo },
+    { 0x1f7cu, 0x1f7du, 0x007eu, CanonicalizeRangeLo },
+    { 0x1f7eu, 0x1fafu, 0x0000u, CanonicalizeUnique },
+    { 0x1fb0u, 0x1fb1u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1fb2u, 0x1fb7u, 0x0000u, CanonicalizeUnique },
+    { 0x1fb8u, 0x1fb9u, 0x0008u, CanonicalizeRangeHi },
+    { 0x1fbau, 0x1fbbu, 0x004au, CanonicalizeRangeHi },
+    { 0x1fbcu, 0x1fbdu, 0x0000u, CanonicalizeUnique },
+    { 0x1fbeu, 0x1fbeu, 0x0007u, CanonicalizeSet },
+    { 0x1fbfu, 0x1fc7u, 0x0000u, CanonicalizeUnique },
+    { 0x1fc8u, 0x1fcbu, 0x0056u, CanonicalizeRangeHi },
+    { 0x1fccu, 0x1fcfu, 0x0000u, CanonicalizeUnique },
+    { 0x1fd0u, 0x1fd1u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1fd2u, 0x1fd7u, 0x0000u, CanonicalizeUnique },
+    { 0x1fd8u, 0x1fd9u, 0x0008u, CanonicalizeRangeHi },
+    { 0x1fdau, 0x1fdbu, 0x0064u, CanonicalizeRangeHi },
+    { 0x1fdcu, 0x1fdfu, 0x0000u, CanonicalizeUnique },
+    { 0x1fe0u, 0x1fe1u, 0x0008u, CanonicalizeRangeLo },
+    { 0x1fe2u, 0x1fe4u, 0x0000u, CanonicalizeUnique },
+    { 0x1fe5u, 0x1fe5u, 0x0007u, CanonicalizeRangeLo },
+    { 0x1fe6u, 0x1fe7u, 0x0000u, CanonicalizeUnique },
+    { 0x1fe8u, 0x1fe9u, 0x0008u, CanonicalizeRangeHi },
+    { 0x1feau, 0x1febu, 0x0070u, CanonicalizeRangeHi },
+    { 0x1fecu, 0x1fecu, 0x0007u, CanonicalizeRangeHi },
+    { 0x1fedu, 0x1ff7u, 0x0000u, CanonicalizeUnique },
+    { 0x1ff8u, 0x1ff9u, 0x0080u, CanonicalizeRangeHi },
+    { 0x1ffau, 0x1ffbu, 0x007eu, CanonicalizeRangeHi },
+    { 0x1ffcu, 0x2131u, 0x0000u, CanonicalizeUnique },
+    { 0x2132u, 0x2132u, 0x001cu, CanonicalizeRangeLo },
+    { 0x2133u, 0x214du, 0x0000u, CanonicalizeUnique },
+    { 0x214eu, 0x214eu, 0x001cu, CanonicalizeRangeHi },
+    { 0x214fu, 0x215fu, 0x0000u, CanonicalizeUnique },
+    { 0x2160u, 0x216fu, 0x0010u, CanonicalizeRangeLo },
+    { 0x2170u, 0x217fu, 0x0010u, CanonicalizeRangeHi },
+    { 0x2180u, 0x2182u, 0x0000u, CanonicalizeUnique },
+    { 0x2183u, 0x2184u, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x2185u, 0x24b5u, 0x0000u, CanonicalizeUnique },
+    { 0x24b6u, 0x24cfu, 0x001au, CanonicalizeRangeLo },
+    { 0x24d0u, 0x24e9u, 0x001au, CanonicalizeRangeHi },
+    { 0x24eau, 0x2bffu, 0x0000u, CanonicalizeUnique },
+    { 0x2c00u, 0x2c2eu, 0x0030u, CanonicalizeRangeLo },
+    { 0x2c2fu, 0x2c2fu, 0x0000u, CanonicalizeUnique },
+    { 0x2c30u, 0x2c5eu, 0x0030u, CanonicalizeRangeHi },
+    { 0x2c5fu, 0x2c5fu, 0x0000u, CanonicalizeUnique },
+    { 0x2c60u, 0x2c61u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x2c62u, 0x2c62u, 0x29f7u, CanonicalizeRangeHi },
+    { 0x2c63u, 0x2c63u, 0x0ee6u, CanonicalizeRangeHi },
+    { 0x2c64u, 0x2c64u, 0x29e7u, CanonicalizeRangeHi },
+    { 0x2c65u, 0x2c65u, 0x2a2bu, CanonicalizeRangeHi },
+    { 0x2c66u, 0x2c66u, 0x2a28u, CanonicalizeRangeHi },
+    { 0x2c67u, 0x2c6cu, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x2c6du, 0x2c6du, 0x2a1cu, CanonicalizeRangeHi },
+    { 0x2c6eu, 0x2c6eu, 0x29fdu, CanonicalizeRangeHi },
+    { 0x2c6fu, 0x2c6fu, 0x2a1fu, CanonicalizeRangeHi },
+    { 0x2c70u, 0x2c70u, 0x2a1eu, CanonicalizeRangeHi },
+    { 0x2c71u, 0x2c71u, 0x0000u, CanonicalizeUnique },
+    { 0x2c72u, 0x2c73u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x2c74u, 0x2c74u, 0x0000u, CanonicalizeUnique },
+    { 0x2c75u, 0x2c76u, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x2c77u, 0x2c7du, 0x0000u, CanonicalizeUnique },
+    { 0x2c7eu, 0x2c7fu, 0x2a3fu, CanonicalizeRangeHi },
+    { 0x2c80u, 0x2ce3u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0x2ce4u, 0x2ceau, 0x0000u, CanonicalizeUnique },
+    { 0x2cebu, 0x2ceeu, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0x2cefu, 0x2cffu, 0x0000u, CanonicalizeUnique },
+    { 0x2d00u, 0x2d25u, 0x1c60u, CanonicalizeRangeHi },
+    { 0x2d26u, 0xa63fu, 0x0000u, CanonicalizeUnique },
+    { 0xa640u, 0xa66du, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0xa66eu, 0xa67fu, 0x0000u, CanonicalizeUnique },
+    { 0xa680u, 0xa697u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0xa698u, 0xa721u, 0x0000u, CanonicalizeUnique },
+    { 0xa722u, 0xa72fu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0xa730u, 0xa731u, 0x0000u, CanonicalizeUnique },
+    { 0xa732u, 0xa76fu, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0xa770u, 0xa778u, 0x0000u, CanonicalizeUnique },
+    { 0xa779u, 0xa77cu, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0xa77du, 0xa77du, 0x8a04u, CanonicalizeRangeHi },
+    { 0xa77eu, 0xa787u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0xa788u, 0xa78au, 0x0000u, CanonicalizeUnique },
+    { 0xa78bu, 0xa78cu, 0x0000u, CanonicalizeAlternatingUnaligned },
+    { 0xa78du, 0xa78du, 0xa528u, CanonicalizeRangeHi },
+    { 0xa78eu, 0xa78fu, 0x0000u, CanonicalizeUnique },
+    { 0xa790u, 0xa791u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0xa792u, 0xa79fu, 0x0000u, CanonicalizeUnique },
+    { 0xa7a0u, 0xa7a9u, 0x0000u, CanonicalizeAlternatingAligned },
+    { 0xa7aau, 0xff20u, 0x0000u, CanonicalizeUnique },
+    { 0xff21u, 0xff3au, 0x0020u, CanonicalizeRangeLo },
+    { 0xff3bu, 0xff40u, 0x0000u, CanonicalizeUnique },
+    { 0xff41u, 0xff5au, 0x0020u, CanonicalizeRangeHi },
+    { 0xff5bu, 0xffffu, 0x0000u, CanonicalizeUnique },
+};
+
+const size_t LATIN_CANONICALIZATION_RANGES = 20;
+LatinCanonicalizationRange latinRangeInfo[LATIN_CANONICALIZATION_RANGES] = {
+    { 0x0000u, 0x0040u, 0x0000u, CanonicalizeLatinSelf },
+    { 0x0041u, 0x005au, 0x0000u, CanonicalizeLatinMask0x20 },
+    { 0x005bu, 0x0060u, 0x0000u, CanonicalizeLatinSelf },
+    { 0x0061u, 0x007au, 0x0000u, CanonicalizeLatinMask0x20 },
+    { 0x007bu, 0x00bfu, 0x0000u, CanonicalizeLatinSelf },
+    { 0x00c0u, 0x00d6u, 0x0000u, CanonicalizeLatinMask0x20 },
+    { 0x00d7u, 0x00d7u, 0x0000u, CanonicalizeLatinSelf },
+    { 0x00d8u, 0x00deu, 0x0000u, CanonicalizeLatinMask0x20 },
+    { 0x00dfu, 0x00dfu, 0x0000u, CanonicalizeLatinSelf },
+    { 0x00e0u, 0x00f6u, 0x0000u, CanonicalizeLatinMask0x20 },
+    { 0x00f7u, 0x00f7u, 0x0000u, CanonicalizeLatinSelf },
+    { 0x00f8u, 0x00feu, 0x0000u, CanonicalizeLatinMask0x20 },
+    { 0x00ffu, 0x00ffu, 0x0000u, CanonicalizeLatinSelf },
+    { 0x0100u, 0x0177u, 0x0000u, CanonicalizeLatinInvalid },
+    { 0x0178u, 0x0178u, 0x00ffu, CanonicalizeLatinOther },
+    { 0x0179u, 0x039bu, 0x0000u, CanonicalizeLatinInvalid },
+    { 0x039cu, 0x039cu, 0x00b5u, CanonicalizeLatinOther },
+    { 0x039du, 0x03bbu, 0x0000u, CanonicalizeLatinInvalid },
+    { 0x03bcu, 0x03bcu, 0x00b5u, CanonicalizeLatinOther },
+    { 0x03bdu, 0xffffu, 0x0000u, CanonicalizeLatinInvalid },
+};
+
+} } // JSC::Yarr
+
diff --git a/yarr/YarrCanonicalizeUCS2.h b/yarr/YarrCanonicalizeUCS2.h
new file mode 100644 (file)
index 0000000..be0ead4
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef YarrCanonicalizeUCS2_H
+#define YarrCanonicalizeUCS2_H
+
+#include <stdint.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace JSC { namespace Yarr {
+
+// This set of data (autogenerated using YarrCanonicalizeUCS2.js into YarrCanonicalizeUCS2.cpp)
+// provides information for each UCS2 code point as to the set of code points that it should
+// match under the ES5.1 case insensitive RegExp matching rules, specified in 15.10.2.8.
+enum UCS2CanonicalizationType {
+    CanonicalizeUnique,               // No canonically equal values, e.g. 0x0.
+    CanonicalizeSet,                  // Value indicates a set in characterSetInfo.
+    CanonicalizeRangeLo,              // Value is positive delta to pair, E.g. 0x41 has value 0x20, -> 0x61.
+    CanonicalizeRangeHi,              // Value is positive delta to pair, E.g. 0x61 has value 0x20, -> 0x41.
+    CanonicalizeAlternatingAligned,   // Aligned consequtive pair, e.g. 0x1f4,0x1f5.
+    CanonicalizeAlternatingUnaligned, // Unaligned consequtive pair, e.g. 0x241,0x242.
+};
+struct UCS2CanonicalizationRange { uint16_t begin, end, value, type; };
+extern const size_t UCS2_CANONICALIZATION_RANGES;
+extern uint16_t* characterSetInfo[];
+extern UCS2CanonicalizationRange rangeInfo[];
+
+// This table is similar to the full rangeInfo table, however this maps from UCS2 codepoints to
+// the set of Latin1 codepoints that could match.
+enum LatinCanonicalizationType {
+    CanonicalizeLatinSelf,     // This character is in the Latin1 range, but has no canonical equivalent in the range.
+    CanonicalizeLatinMask0x20, // One of a pair of characters, under the mask 0x20.
+    CanonicalizeLatinOther,    // This character is not in the Latin1 range, but canonicalizes to another that is.
+    CanonicalizeLatinInvalid,  // Cannot match against Latin1 input.
+};
+struct LatinCanonicalizationRange { uint16_t begin, end, value, type; };
+extern const size_t LATIN_CANONICALIZATION_RANGES;
+extern LatinCanonicalizationRange latinRangeInfo[];
+
+// This searches in log2 time over ~364 entries, so should typically result in 8 compares.
+inline UCS2CanonicalizationRange* rangeInfoFor(UChar ch)
+{
+    UCS2CanonicalizationRange* info = rangeInfo;
+    size_t entries = UCS2_CANONICALIZATION_RANGES;
+
+    while (true) {
+        size_t candidate = entries >> 1;
+        UCS2CanonicalizationRange* candidateInfo = info + candidate;
+        if (ch < candidateInfo->begin)
+            entries = candidate;
+        else if (ch <= candidateInfo->end)
+            return candidateInfo;
+        else {
+            info = candidateInfo + 1;
+            entries -= (candidate + 1);
+        }
+    }
+}
+
+// Should only be called for characters that have one canonically matching value.
+inline UChar getCanonicalPair(UCS2CanonicalizationRange* info, UChar ch)
+{
+    ASSERT(ch >= info->begin && ch <= info->end);
+    switch (info->type) {
+    case CanonicalizeRangeLo:
+        return ch + info->value;
+    case CanonicalizeRangeHi:
+        return ch - info->value;
+    case CanonicalizeAlternatingAligned:
+        return ch ^ 1;
+    case CanonicalizeAlternatingUnaligned:
+        return ((ch - 1) ^ 1) + 1;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+// Returns true if no other UCS2 codepoint can match this value.
+inline bool isCanonicallyUnique(UChar ch)
+{
+    return rangeInfoFor(ch)->type == CanonicalizeUnique;
+}
+
+// Returns true if values are equal, under the canonicalization rules.
+inline bool areCanonicallyEquivalent(UChar a, UChar b)
+{
+    UCS2CanonicalizationRange* info = rangeInfoFor(a);
+    switch (info->type) {
+    case CanonicalizeUnique:
+        return a == b;
+    case CanonicalizeSet: {
+        for (uint16_t* set = characterSetInfo[info->value]; (a = *set); ++set) {
+            if (a == b)
+                return true;
+        }
+        return false;
+    }
+    case CanonicalizeRangeLo:
+        return (a == b) || (a + info->value == b);
+    case CanonicalizeRangeHi:
+        return (a == b) || (a - info->value == b);
+    case CanonicalizeAlternatingAligned:
+        return (a | 1) == (b | 1);
+    case CanonicalizeAlternatingUnaligned:
+        return ((a - 1) | 1) == ((b - 1) | 1);
+    }
+
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+} } // JSC::Yarr
+
+#endif
diff --git a/yarr/YarrCanonicalizeUCS2.js b/yarr/YarrCanonicalizeUCS2.js
new file mode 100644 (file)
index 0000000..00361dd
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+// See ES 5.1, 15.10.2.8
+function canonicalize(ch)
+{
+    var u = String.fromCharCode(ch).toUpperCase();
+    if (u.length > 1)
+        return ch;
+    var cu = u.charCodeAt(0);
+    if (ch >= 128 && cu < 128)
+        return ch;
+    return cu;
+}
+
+var MAX_UCS2 = 0xFFFF;
+var MAX_LATIN = 0xFF;
+
+var groupedCanonically = [];
+// Pass 1: populate groupedCanonically - this is mapping from canonicalized
+// values back to the set of character code that canonicalize to them.
+for (var i = 0; i <= MAX_UCS2; ++i) {
+    var ch = canonicalize(i);
+    if (!groupedCanonically[ch])
+        groupedCanonically[ch] = [];
+    groupedCanonically[ch].push(i);
+}
+
+var typeInfo = [];
+var latinTypeInfo = [];
+var characterSetInfo = [];
+// Pass 2: populate typeInfo & characterSetInfo. For every character calculate
+// a typeInfo value, described by the types above, and a value payload.
+for (cu in groupedCanonically) {
+    // The set of characters that canonicalize to cu
+    var characters = groupedCanonically[cu];
+
+    // If there is only one, it is unique.
+    if (characters.length == 1) {
+        typeInfo[characters[0]] = "CanonicalizeUnique:0";
+        latinTypeInfo[characters[0]] = characters[0] <= MAX_LATIN ? "CanonicalizeLatinSelf:0" : "CanonicalizeLatinInvalid:0";
+        continue;
+    }
+
+    // Sort the array.
+    characters.sort(function(x,y){return x-y;});
+
+    // If there are more than two characters, create an entry in characterSetInfo.
+    if (characters.length > 2) {
+        for (i in characters)
+            typeInfo[characters[i]] = "CanonicalizeSet:" + characterSetInfo.length;
+        characterSetInfo.push(characters);
+
+        if (characters[1] <= MAX_LATIN)
+            throw new Error("sets with more than one latin character not supported!");
+        if (characters[0] <= MAX_LATIN) {
+            for (i in characters)
+                latinTypeInfo[characters[i]] = "CanonicalizeLatinOther:" + characters[0];
+            latinTypeInfo[characters[0]] = "CanonicalizeLatinSelf:0";
+        } else {
+            for (i in characters)
+                latinTypeInfo[characters[i]] = "CanonicalizeLatinInvalid:0";
+        }
+
+        continue;
+    }
+
+    // We have a pair, mark alternating ranges, otherwise track whether this is the low or high partner.
+    var lo = characters[0];
+    var hi = characters[1];
+    var delta = hi - lo;
+    if (delta == 1) {
+        var type = lo & 1 ? "CanonicalizeAlternatingUnaligned:0" : "CanonicalizeAlternatingAligned:0";
+        typeInfo[lo] = type;
+        typeInfo[hi] = type;
+    } else {
+        typeInfo[lo] = "CanonicalizeRangeLo:" + delta;
+        typeInfo[hi] = "CanonicalizeRangeHi:" + delta;
+    }
+
+    if (lo > MAX_LATIN) {
+        latinTypeInfo[lo] = "CanonicalizeLatinInvalid:0"; 
+        latinTypeInfo[hi] = "CanonicalizeLatinInvalid:0";
+    } else if (hi > MAX_LATIN) {
+        latinTypeInfo[lo] = "CanonicalizeLatinSelf:0"; 
+        latinTypeInfo[hi] = "CanonicalizeLatinOther:" + lo;
+    } else {
+        if (delta != 0x20 || lo & 0x20)
+            throw new Error("pairs of latin characters that don't mask with 0x20 not supported!");
+        latinTypeInfo[lo] = "CanonicalizeLatinMask0x20:0";
+        latinTypeInfo[hi] = "CanonicalizeLatinMask0x20:0";
+    }
+}
+
+var rangeInfo = [];
+// Pass 3: coallesce types into ranges.
+for (var end = 0; end <= MAX_UCS2; ++end) {
+    var begin = end;
+    var type = typeInfo[end];
+    while (end < MAX_UCS2 && typeInfo[end + 1] == type)
+        ++end;
+    rangeInfo.push({begin:begin, end:end, type:type});
+}
+
+var latinRangeInfo = [];
+// Pass 4: coallesce latin-1 types into ranges.
+for (var end = 0; end <= MAX_UCS2; ++end) {
+    var begin = end;
+    var type = latinTypeInfo[end];
+    while (end < MAX_UCS2 && latinTypeInfo[end + 1] == type)
+        ++end;
+    latinRangeInfo.push({begin:begin, end:end, type:type});
+}
+
+
+// Helper function to convert a number to a fixed width hex representation of a C uint16_t.
+function hex(x)
+{
+    var s = Number(x).toString(16);
+    while (s.length < 4)
+        s = 0 + s;
+    return "0x" + s + "u";
+}
+
+var copyright = (
+    "/*"                                                                            + "\n" +
+    " * Copyright (C) 2012 Apple Inc. All rights reserved."                         + "\n" +
+    " *"                                                                            + "\n" +
+    " * Redistribution and use in source and binary forms, with or without"         + "\n" +
+    " * modification, are permitted provided that the following conditions"         + "\n" +
+    " * are met:"                                                                   + "\n" +
+    " * 1. Redistributions of source code must retain the above copyright"          + "\n" +
+    " *    notice, this list of conditions and the following disclaimer."           + "\n" +
+    " * 2. Redistributions in binary form must reproduce the above copyright"       + "\n" +
+    " *    notice, this list of conditions and the following disclaimer in the"     + "\n" +
+    " *    documentation and/or other materials provided with the distribution."    + "\n" +
+    " *"                                                                            + "\n" +
+    " * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY"                  + "\n" +
+    " * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE"          + "\n" +
+    " * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR"         + "\n" +
+    " * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR"                   + "\n" +
+    " * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,"      + "\n" +
+    " * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,"        + "\n" +
+    " * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR"         + "\n" +
+    " * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY"        + "\n" +
+    " * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT"               + "\n" +
+    " * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE"      + "\n" +
+    " * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. "      + "\n" +
+    " */");
+
+print(copyright);
+print();
+print("// DO NOT EDIT! - this file autogenerated by YarrCanonicalizeUCS2.js");
+print();
+print('#include "config.h"');
+print('#include "YarrCanonicalizeUCS2.h"');
+print();
+print("namespace JSC { namespace Yarr {");
+print();
+print("#include <stdint.h>");
+print();
+
+for (i in characterSetInfo) {
+    var characters = ""
+    var set = characterSetInfo[i];
+    for (var j in set)
+        characters += hex(set[j]) + ", ";
+    print("uint16_t ucs2CharacterSet" + i + "[] = { " + characters + "0 };");
+}
+print();
+print("static const size_t UCS2_CANONICALIZATION_SETS = " + characterSetInfo.length + ";");
+print("uint16_t* characterSetInfo[UCS2_CANONICALIZATION_SETS] = {");
+for (i in characterSetInfo)
+print("    ucs2CharacterSet" + i + ",");
+print("};");
+print();
+print("const size_t UCS2_CANONICALIZATION_RANGES = " + rangeInfo.length + ";");
+print("UCS2CanonicalizationRange rangeInfo[UCS2_CANONICALIZATION_RANGES] = {");
+for (i in rangeInfo) {
+    var info = rangeInfo[i];
+    var typeAndValue = info.type.split(':');
+    print("    { " + hex(info.begin) + ", " + hex(info.end) + ", " + hex(typeAndValue[1]) + ", " + typeAndValue[0] + " },");
+}
+print("};");
+print();
+print("const size_t LATIN_CANONICALIZATION_RANGES = " + latinRangeInfo.length + ";");
+print("LatinCanonicalizationRange latinRangeInfo[LATIN_CANONICALIZATION_RANGES] = {");
+for (i in latinRangeInfo) {
+    var info = latinRangeInfo[i];
+    var typeAndValue = info.type.split(':');
+    print("    { " + hex(info.begin) + ", " + hex(info.end) + ", " + hex(typeAndValue[1]) + ", " + typeAndValue[0] + " },");
+}
+print("};");
+print();
+print("} } // JSC::Yarr");
+print();
+
index c8312aa86252127bf8382b019d9df11d6aad09ea..ba10171bfe8ebf1b970dbfb8e1d27cd055edb615 100644 (file)
 #include "config.h"
 #include "YarrInterpreter.h"
 
 #include "config.h"
 #include "YarrInterpreter.h"
 
+#include "UString.h"
 #include "Yarr.h"
 #include "Yarr.h"
+#include "YarrCanonicalizeUCS2.h"
 #include <wtf/BumpPointerAllocator.h>
 #include <wtf/BumpPointerAllocator.h>
+#include <wtf/DataLog.h>
+#include <wtf/text/CString.h>
 
 #ifndef NDEBUG
 #include <stdio.h>
 
 #ifndef NDEBUG
 #include <stdio.h>
@@ -38,6 +42,7 @@ using namespace WTF;
 
 namespace JSC { namespace Yarr {
 
 
 namespace JSC { namespace Yarr {
 
+template<typename CharType>
 class Interpreter {
 public:
     struct ParenthesesDisjunctionContext;
 class Interpreter {
 public:
     struct ParenthesesDisjunctionContext;
@@ -108,7 +113,7 @@ public:
         allocatorPool = allocatorPool->ensureCapacity(size);
         if (!allocatorPool)
             CRASH();
         allocatorPool = allocatorPool->ensureCapacity(size);
         if (!allocatorPool)
             CRASH();
-        return new(allocatorPool->alloc(size)) DisjunctionContext();
+        return new (allocatorPool->alloc(size)) DisjunctionContext();
     }
 
     void freeDisjunctionContext(DisjunctionContext* context)
     }
 
     void freeDisjunctionContext(DisjunctionContext* context)
@@ -118,7 +123,7 @@ public:
 
     struct ParenthesesDisjunctionContext
     {
 
     struct ParenthesesDisjunctionContext
     {
-        ParenthesesDisjunctionContext(int* output, ByteTerm& term)
+        ParenthesesDisjunctionContext(unsigned* output, ByteTerm& term)
             : next(0)
         {
             unsigned firstSubpatternId = term.atom.subpatternId;
             : next(0)
         {
             unsigned firstSubpatternId = term.atom.subpatternId;
@@ -126,10 +131,10 @@ public:
 
             for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i) {
                 subpatternBackup[i] = output[(firstSubpatternId << 1) + i];
 
             for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i) {
                 subpatternBackup[i] = output[(firstSubpatternId << 1) + i];
-                output[(firstSubpatternId << 1) + i] = -1;
+                output[(firstSubpatternId << 1) + i] = offsetNoMatch;
             }
 
             }
 
-            new(getDisjunctionContext(term)) DisjunctionContext();
+            new (getDisjunctionContext(term)) DisjunctionContext();
         }
 
         void* operator new(size_t, void* where)
         }
 
         void* operator new(size_t, void* where)
@@ -137,7 +142,7 @@ public:
             return where;
         }
 
             return where;
         }
 
-        void restoreOutput(int* output, unsigned firstSubpatternId, unsigned numNestedSubpatterns)
+        void restoreOutput(unsigned* output, unsigned firstSubpatternId, unsigned numNestedSubpatterns)
         {
             for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i)
                 output[(firstSubpatternId << 1) + i] = subpatternBackup[i];
         {
             for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i)
                 output[(firstSubpatternId << 1) + i] = subpatternBackup[i];
@@ -149,16 +154,16 @@ public:
         }
 
         ParenthesesDisjunctionContext* next;
         }
 
         ParenthesesDisjunctionContext* next;
-        int subpatternBackup[1];
+        unsigned subpatternBackup[1];
     };
 
     };
 
-    ParenthesesDisjunctionContext* allocParenthesesDisjunctionContext(ByteDisjunction* disjunction, int* output, ByteTerm& term)
+    ParenthesesDisjunctionContext* allocParenthesesDisjunctionContext(ByteDisjunction* disjunction, unsigned* 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);
+        size_t size = sizeof(ParenthesesDisjunctionContext) - sizeof(unsigned) + (term.atom.parenthesesDisjunction->m_numSubpatterns << 1) * sizeof(unsigned) + sizeof(DisjunctionContext) - sizeof(uintptr_t) + disjunction->m_frameSize * sizeof(uintptr_t);
         allocatorPool = allocatorPool->ensureCapacity(size);
         if (!allocatorPool)
             CRASH();
         allocatorPool = allocatorPool->ensureCapacity(size);
         if (!allocatorPool)
             CRASH();
-        return new(allocatorPool->alloc(size)) ParenthesesDisjunctionContext(output, term);
+        return new (allocatorPool->alloc(size)) ParenthesesDisjunctionContext(output, term);
     }
 
     void freeParenthesesDisjunctionContext(ParenthesesDisjunctionContext* context)
     }
 
     void freeParenthesesDisjunctionContext(ParenthesesDisjunctionContext* context)
@@ -168,7 +173,7 @@ public:
 
     class InputStream {
     public:
 
     class InputStream {
     public:
-        InputStream(const UChar* input, unsigned start, unsigned length)
+        InputStream(const CharType* input, unsigned start, unsigned length)
             : input(input)
             , pos(start)
             , length(length)
             : input(input)
             , pos(start)
             , length(length)
@@ -200,11 +205,11 @@ public:
             return input[pos] | input[pos + 1] << 16;
         }
 
             return input[pos] | input[pos + 1] << 16;
         }
 
-        int readChecked(int position)
+        int readChecked(unsigned negativePositionOffest)
         {
         {
-            ASSERT(position < 0);
-            ASSERT(static_cast<unsigned>(-position) <= pos);
-            unsigned p = pos + position;
+            if (pos < negativePositionOffest)
+                CRASH();
+            unsigned p = pos - negativePositionOffest;
             ASSERT(p < length);
             return input[p];
         }
             ASSERT(p < length);
             return input[p];
         }
@@ -248,37 +253,41 @@ public:
             return length;
         }
 
             return length;
         }
 
-        bool checkInput(int count)
+        bool checkInput(unsigned count)
         {
         {
-            if ((pos + count) <= length) {
+            if (((pos + count) <= length) && ((pos + count) >= pos)) {
                 pos += count;
                 return true;
             }
             return false;
         }
 
                 pos += count;
                 return true;
             }
             return false;
         }
 
-        void uncheckInput(int count)
+        void uncheckInput(unsigned count)
         {
         {
+            if (pos < count)
+                CRASH();
             pos -= count;
         }
 
             pos -= count;
         }
 
-        bool atStart(int position)
+        bool atStart(unsigned negativePositionOffest)
         {
         {
-            return (pos + position) == 0;
+            return pos == negativePositionOffest;
         }
 
         }
 
-        bool atEnd(int position)
+        bool atEnd(unsigned negativePositionOffest)
         {
         {
-            return (pos + position) == length;
+            if (pos < negativePositionOffest)
+                CRASH();
+            return (pos - negativePositionOffest) == length;
         }
 
         }
 
-        bool isNotAvailableInput(int position)
+        bool isAvailableInput(unsigned offset)
         {
         {
-            return (pos + position) > length;
+            return (((pos + offset) <= length) && ((pos + offset) >= pos));
         }
 
     private:
         }
 
     private:
-        const UChar* input;
+        const CharType* input;
         unsigned pos;
         unsigned length;
     };
         unsigned pos;
         unsigned length;
     };
@@ -304,45 +313,52 @@ public:
         return false;
     }
 
         return false;
     }
 
-    bool checkCharacter(int testChar, int inputPosition)
+    bool checkCharacter(int testChar, unsigned negativeInputOffset)
     {
     {
-        return testChar == input.readChecked(inputPosition);
+        return testChar == input.readChecked(negativeInputOffset);
     }
 
     }
 
-    bool checkCasedCharacter(int loChar, int hiChar, int inputPosition)
+    bool checkCasedCharacter(int loChar, int hiChar, unsigned negativeInputOffset)
     {
     {
-        int ch = input.readChecked(inputPosition);
+        int ch = input.readChecked(negativeInputOffset);
         return (loChar == ch) || (hiChar == ch);
     }
 
         return (loChar == ch) || (hiChar == ch);
     }
 
-    bool checkCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition)
+    bool checkCharacterClass(CharacterClass* characterClass, bool invert, unsigned negativeInputOffset)
     {
     {
-        bool match = testCharacterClass(characterClass, input.readChecked(inputPosition));
+        bool match = testCharacterClass(characterClass, input.readChecked(negativeInputOffset));
         return invert ? !match : match;
     }
 
         return invert ? !match : match;
     }
 
-    bool tryConsumeBackReference(int matchBegin, int matchEnd, int inputOffset)
+    bool tryConsumeBackReference(int matchBegin, int matchEnd, unsigned negativeInputOffset)
     {
     {
-        int matchSize = matchEnd - matchBegin;
+        unsigned matchSize = (unsigned)(matchEnd - matchBegin);
 
         if (!input.checkInput(matchSize))
             return false;
 
         if (pattern->m_ignoreCase) {
 
         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;
-                }
+            for (unsigned i = 0; i < matchSize; ++i) {
+                int oldCh = input.reread(matchBegin + i);
+                int ch = input.readChecked(negativeInputOffset + matchSize - i);
+
+                if (oldCh == ch)
+                    continue;
+
+                // The definition for canonicalize (see ES 5.1, 15.10.2.8) means that
+                // unicode values are never allowed to match against ascii ones.
+                if (isASCII(oldCh) || isASCII(ch)) {
+                    if (toASCIIUpper(oldCh) == toASCIIUpper(ch))
+                        continue;
+                } else if (areCanonicallyEquivalent(oldCh, ch))
+                    continue;
+
+                input.uncheckInput(matchSize);
+                return false;
             }
         } else {
             }
         } else {
-            for (int i = 0; i < matchSize; ++i) {
-                if (!checkCharacter(input.reread(matchBegin + i), inputOffset - matchSize + i)) {
+            for (unsigned i = 0; i < matchSize; ++i) {
+                if (!checkCharacter(input.reread(matchBegin + i), negativeInputOffset + matchSize - i)) {
                     input.uncheckInput(matchSize);
                     return false;
                 }
                     input.uncheckInput(matchSize);
                     return false;
                 }
@@ -354,7 +370,7 @@ public:
 
     bool matchAssertionBOL(ByteTerm& term)
     {
 
     bool matchAssertionBOL(ByteTerm& term)
     {
-        return (input.atStart(term.inputPosition)) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.readChecked(term.inputPosition - 1)));
+        return (input.atStart(term.inputPosition)) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.readChecked(term.inputPosition + 1)));
     }
 
     bool matchAssertionEOL(ByteTerm& term)
     }
 
     bool matchAssertionEOL(ByteTerm& term)
@@ -367,7 +383,7 @@ public:
 
     bool matchAssertionWordBoundary(ByteTerm& term)
     {
 
     bool matchAssertionWordBoundary(ByteTerm& term)
     {
-        bool prevIsWordchar = !input.atStart(term.inputPosition) && testCharacterClass(pattern->wordcharCharacterClass, input.readChecked(term.inputPosition - 1));
+        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));
         bool readIsWordchar;
         if (term.inputPosition)
             readIsWordchar = !input.atEnd(term.inputPosition) && testCharacterClass(pattern->wordcharCharacterClass, input.readChecked(term.inputPosition));
@@ -397,7 +413,7 @@ public:
         case QuantifierNonGreedy:
             if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
                 ++backTrack->matchAmount;
         case QuantifierNonGreedy:
             if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
                 ++backTrack->matchAmount;
-                if (checkCharacter(term.atom.patternCharacter, term.inputPosition - 1))
+                if (checkCharacter(term.atom.patternCharacter, term.inputPosition + 1))
                     return true;
             }
             input.uncheckInput(backTrack->matchAmount);
                     return true;
             }
             input.uncheckInput(backTrack->matchAmount);
@@ -426,7 +442,7 @@ public:
         case QuantifierNonGreedy:
             if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
                 ++backTrack->matchAmount;
         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))
+                if (checkCasedCharacter(term.atom.casedCharacter.lo, term.atom.casedCharacter.hi, term.inputPosition + 1))
                     return true;
             }
             input.uncheckInput(backTrack->matchAmount);
                     return true;
             }
             input.uncheckInput(backTrack->matchAmount);
@@ -444,7 +460,7 @@ public:
         switch (term.atom.quantityType) {
         case QuantifierFixedCount: {
             for (unsigned matchAmount = 0; matchAmount < term.atom.quantityCount; ++matchAmount) {
         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))
+                if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - matchAmount))
                     return false;
             }
             return true;
                     return false;
             }
             return true;
@@ -453,7 +469,7 @@ public:
         case QuantifierGreedy: {
             unsigned matchAmount = 0;
             while ((matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
         case QuantifierGreedy: {
             unsigned matchAmount = 0;
             while ((matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
-                if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - 1)) {
+                if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition + 1)) {
                     input.uncheckInput(1);
                     break;
                 }
                     input.uncheckInput(1);
                     break;
                 }
@@ -493,7 +509,7 @@ public:
         case QuantifierNonGreedy:
             if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
                 ++backTrack->matchAmount;
         case QuantifierNonGreedy:
             if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
                 ++backTrack->matchAmount;
-                if (checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - 1))
+                if (checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition + 1))
                     return true;
             }
             input.uncheckInput(backTrack->matchAmount);
                     return true;
             }
             input.uncheckInput(backTrack->matchAmount);
@@ -508,16 +524,19 @@ public:
         ASSERT(term.type == ByteTerm::TypeBackReference);
         BackTrackInfoBackReference* backTrack = reinterpret_cast<BackTrackInfoBackReference*>(context->frame + term.frameLocation);
 
         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];
+        unsigned matchBegin = output[(term.atom.subpatternId << 1)];
+        unsigned 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 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)
+        if (matchEnd == offsetNoMatch)
             return true;
 
             return true;
 
-        ASSERT((matchBegin == -1) || (matchBegin <= matchEnd));
+        if (matchBegin == offsetNoMatch)
+            return true;
+
+        ASSERT(matchBegin <= matchEnd);
 
         if (matchBegin == matchEnd)
             return true;
 
         if (matchBegin == matchEnd)
             return true;
@@ -557,9 +576,13 @@ public:
         ASSERT(term.type == ByteTerm::TypeBackReference);
         BackTrackInfoBackReference* backTrack = reinterpret_cast<BackTrackInfoBackReference*>(context->frame + term.frameLocation);
 
         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));
+        unsigned matchBegin = output[(term.atom.subpatternId << 1)];
+        unsigned matchEnd = output[(term.atom.subpatternId << 1) + 1];
+
+        if (matchBegin == offsetNoMatch)
+            return false;
+
+        ASSERT(matchBegin <= matchEnd);
 
         if (matchBegin == matchEnd)
             return false;
 
         if (matchBegin == matchEnd)
             return false;
@@ -648,7 +671,7 @@ public:
 
         if (term.capture()) {
             unsigned subpatternId = term.atom.subpatternId;
 
         if (term.capture()) {
             unsigned subpatternId = term.atom.subpatternId;
-            output[(subpatternId << 1)] = input.getPos() + term.inputPosition;
+            output[(subpatternId << 1)] = input.getPos() - term.inputPosition;
         }
 
         return true;
         }
 
         return true;
@@ -680,8 +703,8 @@ public:
 
         if (term.capture()) {
             unsigned subpatternId = term.atom.subpatternId;
 
         if (term.capture()) {
             unsigned subpatternId = term.atom.subpatternId;
-            output[(subpatternId << 1)] = -1;
-            output[(subpatternId << 1) + 1] = -1;
+            output[(subpatternId << 1)] = offsetNoMatch;
+            output[(subpatternId << 1) + 1] = offsetNoMatch;
         }
 
         switch (term.atom.quantityType) {
         }
 
         switch (term.atom.quantityType) {
@@ -862,12 +885,11 @@ public:
                     resetMatches(term, context);
                     freeParenthesesDisjunctionContext(context);
 
                     resetMatches(term, context);
                     freeParenthesesDisjunctionContext(context);
 
-                    if (result == JSRegExpNoMatch) {
-                        JSRegExpResult backtrackResult = parenthesesDoBacktrack(term, backTrack);
-                        if (backtrackResult != JSRegExpMatch)
-                            return backtrackResult;
-                    } else
+                    if (result != JSRegExpNoMatch)
                         return result;
                         return result;
+                    JSRegExpResult backtrackResult = parenthesesDoBacktrack(term, backTrack);
+                    if (backtrackResult != JSRegExpMatch)
+                        return backtrackResult;
                 }
             }
 
                 }
             }
 
@@ -949,12 +971,11 @@ public:
                     resetMatches(term, context);
                     freeParenthesesDisjunctionContext(context);
 
                     resetMatches(term, context);
                     freeParenthesesDisjunctionContext(context);
 
-                    if (result == JSRegExpNoMatch) {
-                        JSRegExpResult backtrackResult = parenthesesDoBacktrack(term, backTrack);
-                        if (backtrackResult != JSRegExpMatch)
-                            return backtrackResult;
-                    } else
+                    if (result != JSRegExpNoMatch)
                         return result;
                         return result;
+                    JSRegExpResult backtrackResult = parenthesesDoBacktrack(term, backTrack);
+                    if (backtrackResult != JSRegExpMatch)
+                        return backtrackResult;
                 }
             }
 
                 }
             }
 
@@ -1038,7 +1059,8 @@ public:
                 popParenthesesDisjunctionContext(backTrack);
                 freeParenthesesDisjunctionContext(context);
 
                 popParenthesesDisjunctionContext(backTrack);
                 freeParenthesesDisjunctionContext(context);
 
-                return result;
+                if (result != JSRegExpNoMatch)
+                    return result;
             }
 
             return JSRegExpNoMatch;
             }
 
             return JSRegExpNoMatch;
@@ -1139,7 +1161,7 @@ public:
         case ByteTerm::TypePatternCharacterOnce:
         case ByteTerm::TypePatternCharacterFixed: {
             for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityCount; ++matchAmount) {
         case ByteTerm::TypePatternCharacterOnce:
         case ByteTerm::TypePatternCharacterFixed: {
             for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityCount; ++matchAmount) {
-                if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition + matchAmount))
+                if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition - matchAmount))
                     BACKTRACK();
             }
             MATCH_NEXT();
                     BACKTRACK();
             }
             MATCH_NEXT();
@@ -1148,7 +1170,7 @@ public:
             BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
             unsigned matchAmount = 0;
             while ((matchAmount < currentTerm().atom.quantityCount) && input.checkInput(1)) {
             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)) {
+                if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition + 1)) {
                     input.uncheckInput(1);
                     break;
                 }
                     input.uncheckInput(1);
                     break;
                 }
@@ -1167,7 +1189,7 @@ public:
         case ByteTerm::TypePatternCasedCharacterOnce:
         case ByteTerm::TypePatternCasedCharacterFixed: {
             for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityCount; ++matchAmount) {
         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))
+                if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition - matchAmount))
                     BACKTRACK();
             }
             MATCH_NEXT();
                     BACKTRACK();
             }
             MATCH_NEXT();
@@ -1176,7 +1198,7 @@ public:
             BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
             unsigned matchAmount = 0;
             while ((matchAmount < currentTerm().atom.quantityCount) && input.checkInput(1)) {
             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)) {
+                if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition + 1)) {
                     input.uncheckInput(1);
                     break;
                 }
                     input.uncheckInput(1);
                     break;
                 }
@@ -1394,15 +1416,18 @@ public:
         return result;
     }
 
         return result;
     }
 
-    int interpret()
+    unsigned interpret()
     {
     {
+        if (!input.isAvailableInput(0))
+            return offsetNoMatch;
+
+        for (unsigned i = 0; i < pattern->m_body->m_numSubpatterns + 1; ++i)
+            output[i << 1] = offsetNoMatch;
+
         allocatorPool = pattern->m_allocator->startAllocator();
         if (!allocatorPool)
             CRASH();
 
         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);
         DisjunctionContext* context = allocDisjunctionContext(pattern->m_body.get());
 
         JSRegExpResult result = matchDisjunction(pattern->m_body.get(), context, false);
@@ -1415,15 +1440,14 @@ public:
 
         pattern->m_allocator->stopAllocator();
 
 
         pattern->m_allocator->stopAllocator();
 
-        // RegExp.cpp currently expects all error to be converted to -1.
-        ASSERT((result == JSRegExpMatch) == (output[0] != -1));
+        ASSERT((result == JSRegExpMatch) == (output[0] != offsetNoMatch));
         return output[0];
     }
 
         return output[0];
     }
 
-    Interpreter(BytecodePattern* pattern, int* output, const UChar* inputChar, unsigned start, unsigned length)
+    Interpreter(BytecodePattern* pattern, unsigned* output, const CharType* input, unsigned length, unsigned start)
         : pattern(pattern)
         , output(output)
         : pattern(pattern)
         , output(output)
-        , input(inputChar, start, length)
+        , input(input, start, length)
         , allocatorPool(0)
         , remainingMatchCount(matchLimit)
     {
         , allocatorPool(0)
         , remainingMatchCount(matchLimit)
     {
@@ -1431,7 +1455,7 @@ public:
 
 private:
     BytecodePattern* pattern;
 
 private:
     BytecodePattern* pattern;
-    int* output;
+    unsigned* output;
     InputStream input;
     BumpPointerPool* allocatorPool;
     unsigned remainingMatchCount;
     InputStream input;
     BumpPointerPool* allocatorPool;
     unsigned remainingMatchCount;
@@ -1476,22 +1500,22 @@ public:
         m_bodyDisjunction->terms.append(ByteTerm::UncheckInput(count));
     }
     
         m_bodyDisjunction->terms.append(ByteTerm::UncheckInput(count));
     }
     
-    void assertionBOL(int inputPosition)
+    void assertionBOL(unsigned inputPosition)
     {
         m_bodyDisjunction->terms.append(ByteTerm::BOL(inputPosition));
     }
 
     {
         m_bodyDisjunction->terms.append(ByteTerm::BOL(inputPosition));
     }
 
-    void assertionEOL(int inputPosition)
+    void assertionEOL(unsigned inputPosition)
     {
         m_bodyDisjunction->terms.append(ByteTerm::EOL(inputPosition));
     }
 
     {
         m_bodyDisjunction->terms.append(ByteTerm::EOL(inputPosition));
     }
 
-    void assertionWordBoundary(bool invert, int inputPosition)
+    void assertionWordBoundary(bool invert, unsigned inputPosition)
     {
         m_bodyDisjunction->terms.append(ByteTerm::WordBoundary(invert, inputPosition));
     }
 
     {
         m_bodyDisjunction->terms.append(ByteTerm::WordBoundary(invert, inputPosition));
     }
 
-    void atomPatternCharacter(UChar ch, int inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType)
+    void atomPatternCharacter(UChar ch, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType)
     {
         if (m_pattern.m_ignoreCase) {
             UChar lo = Unicode::toLower(ch);
     {
         if (m_pattern.m_ignoreCase) {
             UChar lo = Unicode::toLower(ch);
@@ -1506,7 +1530,7 @@ public:
         m_bodyDisjunction->terms.append(ByteTerm(ch, inputPosition, frameLocation, quantityCount, quantityType));
     }
 
         m_bodyDisjunction->terms.append(ByteTerm(ch, inputPosition, frameLocation, quantityCount, quantityType));
     }
 
-    void atomCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType)
+    void atomCharacterClass(CharacterClass* characterClass, bool invert, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType)
     {
         m_bodyDisjunction->terms.append(ByteTerm(characterClass, invert, inputPosition));
 
     {
         m_bodyDisjunction->terms.append(ByteTerm(characterClass, invert, inputPosition));
 
@@ -1515,7 +1539,7 @@ public:
         m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
     }
 
         m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
     }
 
-    void atomBackReference(unsigned subpatternId, int inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType)
+    void atomBackReference(unsigned subpatternId, unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType)
     {
         ASSERT(subpatternId);
 
     {
         ASSERT(subpatternId);
 
@@ -1526,7 +1550,7 @@ public:
         m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
     }
 
         m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
     }
 
-    void atomParenthesesOnceBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
+    void atomParenthesesOnceBegin(unsigned subpatternId, bool capture, unsigned inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
     {
         int beginTerm = m_bodyDisjunction->terms.size();
 
     {
         int beginTerm = m_bodyDisjunction->terms.size();
 
@@ -1539,7 +1563,7 @@ public:
         m_currentAlternativeIndex = beginTerm + 1;
     }
 
         m_currentAlternativeIndex = beginTerm + 1;
     }
 
-    void atomParenthesesTerminalBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
+    void atomParenthesesTerminalBegin(unsigned subpatternId, bool capture, unsigned inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
     {
         int beginTerm = m_bodyDisjunction->terms.size();
 
     {
         int beginTerm = m_bodyDisjunction->terms.size();
 
@@ -1552,7 +1576,7 @@ public:
         m_currentAlternativeIndex = beginTerm + 1;
     }
 
         m_currentAlternativeIndex = beginTerm + 1;
     }
 
-    void atomParenthesesSubpatternBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
+    void atomParenthesesSubpatternBegin(unsigned subpatternId, bool capture, unsigned 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.
     {
         // 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.
@@ -1582,7 +1606,7 @@ public:
         m_currentAlternativeIndex = beginTerm + 1;
     }
 
         m_currentAlternativeIndex = beginTerm + 1;
     }
 
-    void atomParentheticalAssertionEnd(int inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType)
+    void atomParentheticalAssertionEnd(unsigned inputPosition, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType)
     {
         unsigned beginTerm = popParenthesesStack();
         closeAlternative(beginTerm + 1);
     {
         unsigned beginTerm = popParenthesesStack();
         closeAlternative(beginTerm + 1);
@@ -1626,10 +1650,10 @@ public:
 #ifndef NDEBUG
     void dumpDisjunction(ByteDisjunction* disjunction)
     {
 #ifndef NDEBUG
     void dumpDisjunction(ByteDisjunction* disjunction)
     {
-        printf("ByteDisjunction(%p):\n\t", disjunction);
+        dataLog("ByteDisjunction(%p):\n\t", disjunction);
         for (unsigned i = 0; i < disjunction->terms.size(); ++i)
         for (unsigned i = 0; i < disjunction->terms.size(); ++i)
-            printf("{ %d } ", disjunction->terms[i].type);
-        printf("\n");
+            dataLog("{ %d } ", disjunction->terms[i].type);
+        dataLog("\n");
     }
 #endif
 
     }
 #endif
 
@@ -1814,27 +1838,27 @@ public:
 
                 switch (term.type) {
                 case PatternTerm::TypeAssertionBOL:
 
                 switch (term.type) {
                 case PatternTerm::TypeAssertionBOL:
-                    assertionBOL(term.inputPosition - currentCountAlreadyChecked);
+                    assertionBOL(currentCountAlreadyChecked - term.inputPosition);
                     break;
 
                 case PatternTerm::TypeAssertionEOL:
                     break;
 
                 case PatternTerm::TypeAssertionEOL:
-                    assertionEOL(term.inputPosition - currentCountAlreadyChecked);
+                    assertionEOL(currentCountAlreadyChecked - term.inputPosition);
                     break;
 
                 case PatternTerm::TypeAssertionWordBoundary:
                     break;
 
                 case PatternTerm::TypeAssertionWordBoundary:
-                    assertionWordBoundary(term.invert(), term.inputPosition - currentCountAlreadyChecked);
+                    assertionWordBoundary(term.invert(), currentCountAlreadyChecked - term.inputPosition);
                     break;
 
                 case PatternTerm::TypePatternCharacter:
                     break;
 
                 case PatternTerm::TypePatternCharacter:
-                    atomPatternCharacter(term.patternCharacter, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
+                    atomPatternCharacter(term.patternCharacter, currentCountAlreadyChecked - term.inputPosition, term.frameLocation, term.quantityCount, term.quantityType);
                     break;
 
                 case PatternTerm::TypeCharacterClass:
                     break;
 
                 case PatternTerm::TypeCharacterClass:
-                    atomCharacterClass(term.characterClass, term.invert(), term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
+                    atomCharacterClass(term.characterClass, term.invert(), currentCountAlreadyChecked- term.inputPosition, term.frameLocation, term.quantityCount, term.quantityType);
                     break;
 
                 case PatternTerm::TypeBackReference:
                     break;
 
                 case PatternTerm::TypeBackReference:
-                    atomBackReference(term.backReferenceSubpatternId, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
+                    atomBackReference(term.backReferenceSubpatternId, currentCountAlreadyChecked - term.inputPosition, term.frameLocation, term.quantityCount, term.quantityType);
                         break;
 
                 case PatternTerm::TypeForwardReference:
                         break;
 
                 case PatternTerm::TypeForwardReference:
@@ -1850,17 +1874,17 @@ public:
                         else
                             alternativeFrameLocation += YarrStackSpaceForBackTrackInfoParenthesesOnce;
                         unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
                         else
                             alternativeFrameLocation += YarrStackSpaceForBackTrackInfoParenthesesOnce;
                         unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
-                        atomParenthesesOnceBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, alternativeFrameLocation);
+                        atomParenthesesOnceBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount - delegateEndInputOffset, 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;
                         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);
+                        atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount - delegateEndInputOffset, 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;
                         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);
+                        atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.capture(), disjunctionAlreadyCheckedCount - delegateEndInputOffset, 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);
                     }
                         emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
                         atomParenthesesSubpatternEnd(term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize);
                     }
@@ -1910,18 +1934,31 @@ PassOwnPtr<BytecodePattern> byteCompile(YarrPattern& pattern, BumpPointerAllocat
     return ByteCompiler(pattern).compile(allocator);
 }
 
     return ByteCompiler(pattern).compile(allocator);
 }
 
-int interpret(BytecodePattern* bytecode, const UChar* input, unsigned start, unsigned length, int* output)
+unsigned interpret(BytecodePattern* bytecode, const UString& input, unsigned start, unsigned* output)
+{
+    if (input.is8Bit())
+        return Interpreter<LChar>(bytecode, output, input.characters8(), input.length(), start).interpret();
+    return Interpreter<UChar>(bytecode, output, input.characters16(), input.length(), start).interpret();
+}
+
+unsigned interpret(BytecodePattern* bytecode, const LChar* input, unsigned length, unsigned start, unsigned* output)
+{
+    return Interpreter<LChar>(bytecode, output, input, length, start).interpret();
+}
+
+unsigned interpret(BytecodePattern* bytecode, const UChar* input, unsigned length, unsigned start, unsigned* output)
 {
 {
-    return Interpreter(bytecode, output, input, start, length).interpret();
+    return Interpreter<UChar>(bytecode, output, input, length, start).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);
+// These should be the same for both UChar & LChar.
+COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoPatternCharacter) == (YarrStackSpaceForBackTrackInfoPatternCharacter * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoPatternCharacter);
+COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoCharacterClass) == (YarrStackSpaceForBackTrackInfoCharacterClass * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoCharacterClass);
+COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoBackReference) == (YarrStackSpaceForBackTrackInfoBackReference * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoBackReference);
+COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoAlternative) == (YarrStackSpaceForBackTrackInfoAlternative * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoAlternative);
+COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoParentheticalAssertion) == (YarrStackSpaceForBackTrackInfoParentheticalAssertion * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParentheticalAssertion);
+COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoParenthesesOnce) == (YarrStackSpaceForBackTrackInfoParenthesesOnce * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParenthesesOnce);
+COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoParentheses) == (YarrStackSpaceForBackTrackInfoParentheses * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParentheses);
 
 
 } }
 
 
 } }
index eb5fdc6dccb9b16d7dbf60eea027a1a54c477fd5..4ecd69eca703cd6b884ca61a4424917c03f91dc6 100644 (file)
@@ -105,7 +105,7 @@ struct ByteTerm {
     unsigned frameLocation;
     bool m_capture : 1;
     bool m_invert : 1;
     unsigned frameLocation;
     bool m_capture : 1;
     bool m_invert : 1;
-    int inputPosition;
+    unsigned inputPosition;
 
     ByteTerm(UChar ch, int inputPos, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType)
         : frameLocation(frameLocation)
 
     ByteTerm(UChar ch, int inputPos, unsigned frameLocation, Checked<unsigned> quantityCount, QuantifierType quantityType)
         : frameLocation(frameLocation)
@@ -375,6 +375,11 @@ private:
     Vector<CharacterClass*> m_userCharacterClasses;
 };
 
     Vector<CharacterClass*> m_userCharacterClasses;
 };
 
+JS_EXPORT_PRIVATE PassOwnPtr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*);
+JS_EXPORT_PRIVATE unsigned interpret(BytecodePattern*, const UString& input, unsigned start, unsigned* output);
+unsigned interpret(BytecodePattern*, const LChar* input, unsigned length, unsigned start, unsigned* output);
+unsigned interpret(BytecodePattern*, const UChar* input, unsigned length, unsigned start, unsigned* output);
+
 } } // namespace JSC::Yarr
 
 #endif // YarrInterpreter_h
 } } // namespace JSC::Yarr
 
 #endif // YarrInterpreter_h
index 06496615a4fc53b930f9ec57d80b7cbf832fd578..60519ebd8e48001d755be330997225a7d36fad49 100644 (file)
 #include "config.h"
 #include "YarrJIT.h"
 
 #include "config.h"
 #include "YarrJIT.h"
 
-#include "ASCIICType.h"
+#include <wtf/ASCIICType.h>
 #include "LinkBuffer.h"
 #include "Yarr.h"
 #include "LinkBuffer.h"
 #include "Yarr.h"
+#include "YarrCanonicalizeUCS2.h"
 
 #if ENABLE(YARR_JIT)
 
 
 #if ENABLE(YARR_JIT)
 
@@ -36,6 +37,7 @@ using namespace WTF;
 
 namespace JSC { namespace Yarr {
 
 
 namespace JSC { namespace Yarr {
 
+template<YarrJITCompileMode compileMode>
 class YarrGenerator : private MacroAssembler {
     friend void jitCompile(JSGlobalData*, YarrCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline);
 
 class YarrGenerator : private MacroAssembler {
     friend void jitCompile(JSGlobalData*, YarrCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline);
 
@@ -49,6 +51,7 @@ class YarrGenerator : private MacroAssembler {
     static const RegisterID regT1 = ARMRegisters::r6;
 
     static const RegisterID returnRegister = ARMRegisters::r0;
     static const RegisterID regT1 = ARMRegisters::r6;
 
     static const RegisterID returnRegister = ARMRegisters::r0;
+    static const RegisterID returnRegister2 = ARMRegisters::r1;
 #elif CPU(MIPS)
     static const RegisterID input = MIPSRegisters::a0;
     static const RegisterID index = MIPSRegisters::a1;
 #elif CPU(MIPS)
     static const RegisterID input = MIPSRegisters::a0;
     static const RegisterID index = MIPSRegisters::a1;
@@ -59,6 +62,7 @@ class YarrGenerator : private MacroAssembler {
     static const RegisterID regT1 = MIPSRegisters::t5;
 
     static const RegisterID returnRegister = MIPSRegisters::v0;
     static const RegisterID regT1 = MIPSRegisters::t5;
 
     static const RegisterID returnRegister = MIPSRegisters::v0;
+    static const RegisterID returnRegister2 = MIPSRegisters::v1;
 #elif CPU(SH4)
     static const RegisterID input = SH4Registers::r4;
     static const RegisterID index = SH4Registers::r5;
 #elif CPU(SH4)
     static const RegisterID input = SH4Registers::r4;
     static const RegisterID index = SH4Registers::r5;
@@ -69,6 +73,7 @@ class YarrGenerator : private MacroAssembler {
     static const RegisterID regT1 = SH4Registers::r1;
 
     static const RegisterID returnRegister = SH4Registers::r0;
     static const RegisterID regT1 = SH4Registers::r1;
 
     static const RegisterID returnRegister = SH4Registers::r0;
+    static const RegisterID returnRegister2 = SH4Registers::r1;
 #elif CPU(X86)
     static const RegisterID input = X86Registers::eax;
     static const RegisterID index = X86Registers::edx;
 #elif CPU(X86)
     static const RegisterID input = X86Registers::eax;
     static const RegisterID index = X86Registers::edx;
@@ -79,6 +84,7 @@ class YarrGenerator : private MacroAssembler {
     static const RegisterID regT1 = X86Registers::esi;
 
     static const RegisterID returnRegister = X86Registers::eax;
     static const RegisterID regT1 = X86Registers::esi;
 
     static const RegisterID returnRegister = X86Registers::eax;
+    static const RegisterID returnRegister2 = X86Registers::edx;
 #elif CPU(X86_64)
     static const RegisterID input = X86Registers::edi;
     static const RegisterID index = X86Registers::esi;
 #elif CPU(X86_64)
     static const RegisterID input = X86Registers::edi;
     static const RegisterID index = X86Registers::esi;
@@ -89,6 +95,7 @@ class YarrGenerator : private MacroAssembler {
     static const RegisterID regT1 = X86Registers::ebx;
 
     static const RegisterID returnRegister = X86Registers::eax;
     static const RegisterID regT1 = X86Registers::ebx;
 
     static const RegisterID returnRegister = X86Registers::eax;
+    static const RegisterID returnRegister2 = X86Registers::edx;
 #endif
 
     void optimizeAlternative(PatternAlternative* alternative)
 #endif
 
     void optimizeAlternative(PatternAlternative* alternative)
@@ -256,19 +263,27 @@ class YarrGenerator : private MacroAssembler {
         return branch32(NotEqual, index, length);
     }
 
         return branch32(NotEqual, index, length);
     }
 
-    Jump jumpIfCharEquals(UChar ch, int inputPosition)
+    Jump jumpIfCharNotEquals(UChar ch, int inputPosition, RegisterID character)
     {
     {
-        return branch16(Equal, BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), Imm32(ch));
-    }
+        readCharacter(inputPosition, character);
 
 
-    Jump jumpIfCharNotEquals(UChar ch, int inputPosition)
-    {
-        return branch16(NotEqual, BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), Imm32(ch));
+        // For case-insesitive compares, non-ascii characters that have different
+        // upper & lower case representations are converted to a character class.
+        ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || isCanonicallyUnique(ch));
+        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
+            or32(TrustedImm32(0x20), character);
+            ch |= 0x20;
+        }
+
+        return branch32(NotEqual, character, Imm32(ch));
     }
 
     void readCharacter(int inputPosition, RegisterID reg)
     {
     }
 
     void readCharacter(int inputPosition, RegisterID reg)
     {
-        load16(BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), reg);
+        if (m_charSize == Char8)
+            load8(BaseIndex(input, index, TimesOne, inputPosition * sizeof(char)), reg);
+        else
+            load16(BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), reg);
     }
 
     void storeToFrame(RegisterID reg, unsigned frameLocation)
     }
 
     void storeToFrame(RegisterID reg, unsigned frameLocation)
@@ -296,6 +311,65 @@ class YarrGenerator : private MacroAssembler {
         jump(Address(stackPointerRegister, frameLocation * sizeof(void*)));
     }
 
         jump(Address(stackPointerRegister, frameLocation * sizeof(void*)));
     }
 
+    void initCallFrame()
+    {
+        unsigned callFrameSize = m_pattern.m_body->m_callFrameSize;
+        if (callFrameSize)
+            subPtr(Imm32(callFrameSize * sizeof(void*)), stackPointerRegister);
+    }
+    void removeCallFrame()
+    {
+        unsigned callFrameSize = m_pattern.m_body->m_callFrameSize;
+        if (callFrameSize)
+            addPtr(Imm32(callFrameSize * sizeof(void*)), stackPointerRegister);
+    }
+
+    // Used to record subpatters, should only be called if compileMode is IncludeSubpatterns.
+    void setSubpatternStart(RegisterID reg, unsigned subpattern)
+    {
+        ASSERT(subpattern);
+        // FIXME: should be able to ASSERT(compileMode == IncludeSubpatterns), but then this function is conditionally NORETURN. :-(
+        store32(reg, Address(output, (subpattern << 1) * sizeof(int)));
+    }
+    void setSubpatternEnd(RegisterID reg, unsigned subpattern)
+    {
+        ASSERT(subpattern);
+        // FIXME: should be able to ASSERT(compileMode == IncludeSubpatterns), but then this function is conditionally NORETURN. :-(
+        store32(reg, Address(output, ((subpattern << 1) + 1) * sizeof(int)));
+    }
+    void clearSubpatternStart(unsigned subpattern)
+    {
+        ASSERT(subpattern);
+        // FIXME: should be able to ASSERT(compileMode == IncludeSubpatterns), but then this function is conditionally NORETURN. :-(
+        store32(TrustedImm32(-1), Address(output, (subpattern << 1) * sizeof(int)));
+    }
+
+    // We use one of three different strategies to track the start of the current match,
+    // while matching.
+    // 1) If the pattern has a fixed size, do nothing! - we calculate the value lazily
+    //    at the end of matching. This is irrespective of compileMode, and in this case
+    //    these methods should never be called.
+    // 2) If we're compiling IncludeSubpatterns, 'output' contains a pointer to an output
+    //    vector, store the match start in the output vector.
+    // 3) If we're compiling MatchOnly, 'output' is unused, store the match start directly
+    //    in this register.
+    void setMatchStart(RegisterID reg)
+    {
+        ASSERT(!m_pattern.m_body->m_hasFixedSize);
+        if (compileMode == IncludeSubpatterns)
+            store32(reg, output);
+        else
+            move(reg, output);
+    }
+    void getMatchStart(RegisterID reg)
+    {
+        ASSERT(!m_pattern.m_body->m_hasFixedSize);
+        if (compileMode == IncludeSubpatterns)
+            load32(output, reg);
+        else
+            move(output, reg);
+    }
+
     enum YarrOpCode {
         // These nodes wrap body alternatives - those in the main disjunction,
         // rather than subpatterns or assertions. These are chained together in
     enum YarrOpCode {
         // These nodes wrap body alternatives - those in the main disjunction,
         // rather than subpatterns or assertions. These are chained together in
@@ -371,6 +445,10 @@ class YarrGenerator : private MacroAssembler {
         Label m_reentry;
         JumpList m_jumps;
 
         Label m_reentry;
         JumpList m_jumps;
 
+        // Used for backtracking when the prior alternative did not consume any
+        // characters but matched.
+        Jump m_zeroLengthMatch;
+
         // This flag is used to null out the second pattern character, when
         // two are fused to match a pair together.
         bool m_isDeadCode;
         // This flag is used to null out the second pattern character, when
         // two are fused to match a pair together.
         bool m_isDeadCode;
@@ -647,59 +725,109 @@ class YarrGenerator : private MacroAssembler {
     {
         YarrOp& op = m_ops[opIndex];
 
     {
         YarrOp& op = m_ops[opIndex];
 
+        if (op.m_isDeadCode)
+            return;
+        
         // 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());
         // 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;
+        YarrOp* nextOp = &m_ops[opIndex + 1];
 
         PatternTerm* term = op.m_term;
         UChar ch = term->patternCharacter;
 
 
         PatternTerm* term = op.m_term;
         UChar ch = term->patternCharacter;
 
+        if ((ch > 0xff) && (m_charSize == Char8)) {
+            // Have a 16 bit pattern character and an 8 bit string - short circuit
+            op.m_jumps.append(jump());
+            return;
+        }
+
         const RegisterID character = regT0;
         const RegisterID character = regT0;
+        int maxCharactersAtOnce = m_charSize == Char8 ? 4 : 2;
+        unsigned ignoreCaseMask = 0;
+        int allCharacters = ch;
+        int numberCharacters;
+        int startTermPosition = term->inputPosition;
 
 
-        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)) {
+        // For case-insesitive compares, non-ascii characters that have different
+        // upper & lower case representations are converted to a character class.
+        ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || isCanonicallyUnique(ch));
 
 
-                UChar ch2 = nextTerm->patternCharacter;
+        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch))
+            ignoreCaseMask |= 32;
 
 
-                int mask = 0;
-                int chPair = ch | (ch2 << 16);
+        for (numberCharacters = 1; numberCharacters < maxCharactersAtOnce && nextOp->m_op == OpTerm; ++numberCharacters, nextOp = &m_ops[opIndex + numberCharacters]) {
+            PatternTerm* nextTerm = nextOp->m_term;
+            
+            if (nextTerm->type != PatternTerm::TypePatternCharacter
+                || nextTerm->quantityType != QuantifierFixedCount
+                || nextTerm->quantityCount != 1
+                || nextTerm->inputPosition != (startTermPosition + numberCharacters))
+                break;
 
 
-                if (m_pattern.m_ignoreCase) {
-                    if (isASCIIAlpha(ch))
-                        mask |= 32;
-                    if (isASCIIAlpha(ch2))
-                        mask |= 32 << 16;
-                }
+            nextOp->m_isDeadCode = true;
 
 
-                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)));
+            int shiftAmount = (m_charSize == Char8 ? 8 : 16) * numberCharacters;
 
 
-                nextOp.m_isDeadCode = true;
+            UChar currentCharacter = nextTerm->patternCharacter;
+
+            if ((currentCharacter > 0xff) && (m_charSize == Char8)) {
+                // Have a 16 bit pattern character and an 8 bit string - short circuit
+                op.m_jumps.append(jump());
                 return;
             }
                 return;
             }
+
+            // For case-insesitive compares, non-ascii characters that have different
+            // upper & lower case representations are converted to a character class.
+            ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(currentCharacter) || isCanonicallyUnique(currentCharacter));
+
+            allCharacters |= (currentCharacter << shiftAmount);
+
+            if ((m_pattern.m_ignoreCase) && (isASCIIAlpha(currentCharacter)))
+                ignoreCaseMask |= 32 << shiftAmount;                    
         }
 
         }
 
-        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))));
+        if (m_charSize == Char8) {
+            switch (numberCharacters) {
+            case 1:
+                op.m_jumps.append(jumpIfCharNotEquals(ch, startTermPosition - m_checked, character));
+                return;
+            case 2: {
+                BaseIndex address(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar));
+                load16Unaligned(address, character);
+                break;
+            }
+            case 3: {
+                BaseIndex highAddress(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar));
+                load16Unaligned(highAddress, character);
+                if (ignoreCaseMask)
+                    or32(Imm32(ignoreCaseMask), character);
+                op.m_jumps.append(branch32(NotEqual, character, Imm32((allCharacters & 0xffff) | ignoreCaseMask)));
+                op.m_jumps.append(jumpIfCharNotEquals(allCharacters >> 16, startTermPosition + 2 - m_checked, character));
+                return;
+            }
+            case 4: {
+                BaseIndex address(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar));
+                load32WithUnalignedHalfWords(address, character);
+                break;
+            }
+            }
         } else {
         } else {
-            ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
-            op.m_jumps.append(jumpIfCharNotEquals(ch, term->inputPosition - m_checked));
+            switch (numberCharacters) {
+            case 1:
+                op.m_jumps.append(jumpIfCharNotEquals(ch, term->inputPosition - m_checked, character));
+                return;
+            case 2:
+                BaseIndex address(input, index, TimesTwo, (term->inputPosition - m_checked) * sizeof(UChar));
+                load32WithUnalignedHalfWords(address, character);
+                break;
+            }
         }
         }
+
+        if (ignoreCaseMask)
+            or32(Imm32(ignoreCaseMask), character);
+        op.m_jumps.append(branch32(NotEqual, character, Imm32(allCharacters | ignoreCaseMask)));
+        return;
     }
     void backtrackPatternCharacterOnce(size_t opIndex)
     {
     }
     void backtrackPatternCharacterOnce(size_t opIndex)
     {
@@ -719,16 +847,22 @@ class YarrGenerator : private MacroAssembler {
         sub32(Imm32(term->quantityCount.unsafeGet()), countRegister);
 
         Label loop(this);
         sub32(Imm32(term->quantityCount.unsafeGet()), countRegister);
 
         Label loop(this);
-        BaseIndex address(input, countRegister, TimesTwo, ((term->inputPosition - m_checked + Checked<int>(term->quantityCount)) * static_cast<int>(sizeof(UChar))).unsafeGet());
+        BaseIndex address(input, countRegister, m_charScale, (Checked<int>(term->inputPosition - m_checked + Checked<int64_t>(term->quantityCount)) * static_cast<int>(m_charSize == Char8 ? sizeof(char) : sizeof(UChar))).unsafeGet());
 
 
-        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
+        if (m_charSize == Char8)
+            load8(address, character);
+        else
             load16(address, character);
             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)));
+
+        // For case-insesitive compares, non-ascii characters that have different
+        // upper & lower case representations are converted to a character class.
+        ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || isCanonicallyUnique(ch));
+        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
+            or32(TrustedImm32(0x20), character);
+            ch |= 0x20;
         }
         }
+
+        op.m_jumps.append(branch32(NotEqual, character, Imm32(ch)));
         add32(TrustedImm32(1), countRegister);
         branch32(NotEqual, countRegister, index).linkTo(loop, this);
     }
         add32(TrustedImm32(1), countRegister);
         branch32(NotEqual, countRegister, index).linkTo(loop, this);
     }
@@ -748,30 +882,25 @@ class YarrGenerator : private MacroAssembler {
 
         move(TrustedImm32(0), countRegister);
 
 
         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.unsafeGet())).linkTo(loop, this);
+        // Unless have a 16 bit pattern character and an 8 bit string - short circuit
+        if (!((ch > 0xff) && (m_charSize == Char8))) {
+            JumpList failures;
+            Label loop(this);
+            failures.append(atEndOfInput());
+            failures.append(jumpIfCharNotEquals(ch, term->inputPosition - m_checked, character));
+
+            add32(TrustedImm32(1), countRegister);
+            add32(TrustedImm32(1), index);
+            if (term->quantityCount == quantifyInfinite)
+                jump(loop);
+            else
+                branch32(NotEqual, countRegister, Imm32(term->quantityCount.unsafeGet())).linkTo(loop, this);
 
 
-        failures.link(this);
+            failures.link(this);
+        }
         op.m_reentry = label();
 
         storeToFrame(countRegister, term->frameLocation);
         op.m_reentry = label();
 
         storeToFrame(countRegister, term->frameLocation);
-
     }
     void backtrackPatternCharacterGreedy(size_t opIndex)
     {
     }
     void backtrackPatternCharacterGreedy(size_t opIndex)
     {
@@ -809,30 +938,25 @@ class YarrGenerator : private MacroAssembler {
         const RegisterID character = regT0;
         const RegisterID countRegister = regT1;
 
         const RegisterID character = regT0;
         const RegisterID countRegister = regT1;
 
-        JumpList nonGreedyFailures;
-
         m_backtrackingState.link(this);
 
         loadFromFrame(term->frameLocation, countRegister);
 
         m_backtrackingState.link(this);
 
         loadFromFrame(term->frameLocation, countRegister);
 
-        nonGreedyFailures.append(atEndOfInput());
-        if (term->quantityCount != quantifyInfinite)
-            nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount.unsafeGet())));
-        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));
-        }
+        // Unless have a 16 bit pattern character and an 8 bit string - short circuit
+        if (!((ch > 0xff) && (m_charSize == Char8))) {
+            JumpList nonGreedyFailures;
+            nonGreedyFailures.append(atEndOfInput());
+            if (term->quantityCount != quantifyInfinite)
+                nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount.unsafeGet())));
+            nonGreedyFailures.append(jumpIfCharNotEquals(ch, term->inputPosition - m_checked, character));
 
 
-        add32(TrustedImm32(1), countRegister);
-        add32(TrustedImm32(1), index);
+            add32(TrustedImm32(1), countRegister);
+            add32(TrustedImm32(1), index);
 
 
-        jump(op.m_reentry);
+            jump(op.m_reentry);
+            nonGreedyFailures.link(this);
+        }
 
 
-        nonGreedyFailures.link(this);
         sub32(countRegister, index);
         m_backtrackingState.fallthrough();
     }
         sub32(countRegister, index);
         m_backtrackingState.fallthrough();
     }
@@ -873,7 +997,10 @@ class YarrGenerator : private MacroAssembler {
 
         Label loop(this);
         JumpList matchDest;
 
         Label loop(this);
         JumpList matchDest;
-        load16(BaseIndex(input, countRegister, TimesTwo, ((term->inputPosition - m_checked + Checked<int>(term->quantityCount)) * static_cast<int>(sizeof(UChar))).unsafeGet()), character);
+        if (m_charSize == Char8)
+            load8(BaseIndex(input, countRegister, TimesOne, (Checked<int>(term->inputPosition - m_checked + Checked<int64_t>(term->quantityCount)) * static_cast<int>(sizeof(char))).unsafeGet()), character);
+        else
+            load16(BaseIndex(input, countRegister, TimesTwo, (Checked<int>(term->inputPosition - m_checked + Checked<int64_t>(term->quantityCount)) * static_cast<int>(sizeof(UChar))).unsafeGet()), character);
         matchCharacterClass(character, matchDest, term->characterClass);
 
         if (term->invert())
         matchCharacterClass(character, matchDest, term->characterClass);
 
         if (term->invert())
@@ -968,7 +1095,6 @@ class YarrGenerator : private MacroAssembler {
 
         m_backtrackingState.link(this);
 
 
         m_backtrackingState.link(this);
 
-        Label backtrackBegin(this);
         loadFromFrame(term->frameLocation, countRegister);
 
         nonGreedyFailures.append(atEndOfInput());
         loadFromFrame(term->frameLocation, countRegister);
 
         nonGreedyFailures.append(atEndOfInput());
@@ -1007,16 +1133,16 @@ class YarrGenerator : private MacroAssembler {
         JumpList saveStartIndex;
         JumpList foundEndingNewLine;
 
         JumpList saveStartIndex;
         JumpList foundEndingNewLine;
 
-        if (m_pattern.m_body->m_hasFixedSize) {
-            move(index, matchPos);
-            sub32(Imm32(m_checked), matchPos);
-        } else
-            load32(Address(output), matchPos);
+        ASSERT(!m_pattern.m_body->m_hasFixedSize);
+        getMatchStart(matchPos);
 
         saveStartIndex.append(branchTest32(Zero, matchPos));
         Label findBOLLoop(this);
         sub32(TrustedImm32(1), matchPos);
 
         saveStartIndex.append(branchTest32(Zero, matchPos));
         Label findBOLLoop(this);
         sub32(TrustedImm32(1), matchPos);
-        load16(BaseIndex(input, matchPos, TimesTwo, 0), character);
+        if (m_charSize == Char8)
+            load8(BaseIndex(input, matchPos, TimesOne, 0), character);
+        else
+            load16(BaseIndex(input, matchPos, TimesTwo, 0), character);
         matchCharacterClass(character, foundBeginningNewLine, m_pattern.newlineCharacterClass());
         branchTest32(NonZero, matchPos).linkTo(findBOLLoop, this);
         saveStartIndex.append(jump());
         matchCharacterClass(character, foundBeginningNewLine, m_pattern.newlineCharacterClass());
         branchTest32(NonZero, matchPos).linkTo(findBOLLoop, this);
         saveStartIndex.append(jump());
@@ -1028,13 +1154,17 @@ class YarrGenerator : private MacroAssembler {
         if (!m_pattern.m_multiline && term->anchors.bolAnchor)
             op.m_jumps.append(branchTest32(NonZero, matchPos));
 
         if (!m_pattern.m_multiline && term->anchors.bolAnchor)
             op.m_jumps.append(branchTest32(NonZero, matchPos));
 
-        store32(matchPos, Address(output));
+        ASSERT(!m_pattern.m_body->m_hasFixedSize);
+        setMatchStart(matchPos);
 
         move(index, matchPos);
 
         Label findEOLLoop(this);        
         foundEndingNewLine.append(branch32(Equal, matchPos, length));
 
         move(index, matchPos);
 
         Label findEOLLoop(this);        
         foundEndingNewLine.append(branch32(Equal, matchPos, length));
-        load16(BaseIndex(input, matchPos, TimesTwo, 0), character);
+        if (m_charSize == Char8)
+            load8(BaseIndex(input, matchPos, TimesOne, 0), character);
+        else
+            load16(BaseIndex(input, matchPos, TimesTwo, 0), character);
         matchCharacterClass(character, foundEndingNewLine, m_pattern.newlineCharacterClass());
         add32(TrustedImm32(1), matchPos);
         jump(findEOLLoop);
         matchCharacterClass(character, foundEndingNewLine, m_pattern.newlineCharacterClass());
         add32(TrustedImm32(1), matchPos);
         jump(findEOLLoop);
@@ -1247,8 +1377,7 @@ class YarrGenerator : private MacroAssembler {
                 // If we get here, the prior alternative matched - return success.
                 
                 // Adjust the stack pointer to remove the pattern's frame.
                 // 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);
+                removeCallFrame();
 
                 // 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
 
                 // 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
@@ -1258,10 +1387,14 @@ class YarrGenerator : private MacroAssembler {
                     move(index, returnRegister);
                     if (priorAlternative->m_minimumSize)
                         sub32(Imm32(priorAlternative->m_minimumSize), returnRegister);
                     move(index, returnRegister);
                     if (priorAlternative->m_minimumSize)
                         sub32(Imm32(priorAlternative->m_minimumSize), returnRegister);
-                    store32(returnRegister, output);
+                    if (compileMode == IncludeSubpatterns)
+                        store32(returnRegister, output);
                 } else
                 } else
-                    load32(Address(output), returnRegister);
-                store32(index, Address(output, 4));
+                    getMatchStart(returnRegister);
+                if (compileMode == IncludeSubpatterns)
+                    store32(index, Address(output, 4));
+                move(index, returnRegister2);
+
                 generateReturn();
 
                 // This is the divide between the tail of the prior alternative, above, and
                 generateReturn();
 
                 // This is the divide between the tail of the prior alternative, above, and
@@ -1280,7 +1413,7 @@ class YarrGenerator : private MacroAssembler {
                         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,
                         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.
+                    // jumped to when the last alternative fails to match.
                     op.m_reentry = label();
                     sub32(Imm32(priorAlternative->m_minimumSize), index);
                 }
                     op.m_reentry = label();
                     sub32(Imm32(priorAlternative->m_minimumSize), index);
                 }
@@ -1319,7 +1452,7 @@ class YarrGenerator : private MacroAssembler {
                     op.m_checkAdjust -= disjunction->m_minimumSize;
                 if (op.m_checkAdjust)
                     op.m_jumps.append(jumpIfNoAvailableInput(op.m_checkAdjust));
                     op.m_checkAdjust -= disjunction->m_minimumSize;
                 if (op.m_checkAdjust)
                     op.m_jumps.append(jumpIfNoAvailableInput(op.m_checkAdjust));
+
                 m_checked += op.m_checkAdjust;
                 break;
             }
                 m_checked += op.m_checkAdjust;
                 break;
             }
@@ -1338,6 +1471,12 @@ class YarrGenerator : private MacroAssembler {
                     op.m_returnAddress = storeToFrameWithPatch(alternativeFrameLocation);
                 }
 
                     op.m_returnAddress = storeToFrameWithPatch(alternativeFrameLocation);
                 }
 
+                if (term->quantityType != QuantifierFixedCount && !m_ops[op.m_previousOp].m_alternative->m_minimumSize) {
+                    // If the previous alternative matched without consuming characters then
+                    // backtrack to try to match while consumming some input.
+                    op.m_zeroLengthMatch = branch32(Equal, index, Address(stackPointerRegister, term->frameLocation * sizeof(void*)));
+                }
+
                 // If we reach here then the last alternative has matched - jump to the
                 // End node, to skip over any further alternatives.
                 //
                 // If we reach here then the last alternative has matched - jump to the
                 // End node, to skip over any further alternatives.
                 //
@@ -1382,6 +1521,12 @@ class YarrGenerator : private MacroAssembler {
                     op.m_returnAddress = storeToFrameWithPatch(alternativeFrameLocation);
                 }
 
                     op.m_returnAddress = storeToFrameWithPatch(alternativeFrameLocation);
                 }
 
+                if (term->quantityType != QuantifierFixedCount && !m_ops[op.m_previousOp].m_alternative->m_minimumSize) {
+                    // If the previous alternative matched without consuming characters then
+                    // backtrack to try to match while consumming some input.
+                    op.m_zeroLengthMatch = branch32(Equal, index, Address(stackPointerRegister, term->frameLocation * sizeof(void*)));
+                }
+
                 // 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.
                 // 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.
@@ -1432,30 +1577,34 @@ class YarrGenerator : private MacroAssembler {
                 // FIXME: could avoid offsetting this value in JIT code, apply
                 // offsets only afterwards, at the point the results array is
                 // being accessed.
                 // 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;
+                if (term->capture() && compileMode == IncludeSubpatterns) {
                     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);
                     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)));
+                        setSubpatternStart(indexTemporary, term->parentheses.subpatternId);
                     } else
                     } else
-                        store32(index, Address(output, offsetId * sizeof(int)));
+                        setSubpatternStart(index, term->parentheses.subpatternId);
                 }
                 break;
             }
             case OpParenthesesSubpatternOnceEnd: {
                 PatternTerm* term = op.m_term;
                 }
                 break;
             }
             case OpParenthesesSubpatternOnceEnd: {
                 PatternTerm* term = op.m_term;
-                unsigned parenthesesFrameLocation = term->frameLocation;
                 const RegisterID indexTemporary = regT0;
                 ASSERT(term->quantityCount == 1);
 
                 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*))));
+#ifndef NDEBUG
+                // Runtime ASSERT to make sure that the nested alternative handled the
+                // "no input consumed" check.
+                if (term->quantityType != QuantifierFixedCount && !term->parentheses.disjunction->m_minimumSize) {
+                    Jump pastBreakpoint;
+                    pastBreakpoint = branch32(NotEqual, index, Address(stackPointerRegister, term->frameLocation * sizeof(void*)));
+                    breakpoint();
+                    pastBreakpoint.link(this);
+                }
+#endif
 
                 // If the parenthese are capturing, store the ending index value to the
                 // captures array, offsetting as necessary.
 
                 // If the parenthese are capturing, store the ending index value to the
                 // captures array, offsetting as necessary.
@@ -1463,15 +1612,14 @@ class YarrGenerator : private MacroAssembler {
                 // FIXME: could avoid offsetting this value in JIT code, apply
                 // offsets only afterwards, at the point the results array is
                 // being accessed.
                 // 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;
+                if (term->capture() && compileMode == IncludeSubpatterns) {
                     int inputOffset = term->inputPosition - m_checked;
                     if (inputOffset) {
                         move(index, indexTemporary);
                         add32(Imm32(inputOffset), indexTemporary);
                     int inputOffset = term->inputPosition - m_checked;
                     if (inputOffset) {
                         move(index, indexTemporary);
                         add32(Imm32(inputOffset), indexTemporary);
-                        store32(indexTemporary, Address(output, offsetId * sizeof(int)));
+                        setSubpatternEnd(indexTemporary, term->parentheses.subpatternId);
                     } else
                     } else
-                        store32(index, Address(output, offsetId * sizeof(int)));
+                        setSubpatternEnd(index, term->parentheses.subpatternId);
                 }
 
                 // If the parentheses are quantified Greedy then add a label to jump back
                 }
 
                 // If the parentheses are quantified Greedy then add a label to jump back
@@ -1502,15 +1650,21 @@ class YarrGenerator : private MacroAssembler {
                 break;
             }
             case OpParenthesesSubpatternTerminalEnd: {
                 break;
             }
             case OpParenthesesSubpatternTerminalEnd: {
+                YarrOp& beginOp = m_ops[op.m_previousOp];
+#ifndef NDEBUG
                 PatternTerm* term = op.m_term;
 
                 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);
+                // Runtime ASSERT to make sure that the nested alternative handled the
+                // "no input consumed" check.
+                Jump pastBreakpoint;
+                pastBreakpoint = branch32(NotEqual, index, Address(stackPointerRegister, term->frameLocation * sizeof(void*)));
+                breakpoint();
+                pastBreakpoint.link(this);
+#endif
 
 
-                // Reject the match - backtrack back into the subpattern.
-                op.m_jumps.append(jump());
+                // We know that the match is non-zero, we can accept it  and
+                // loop back up to the head of the subpattern.
+                jump(beginOp.m_reentry);
 
                 // This is the entry point to jump to when we stop matching - we will
                 // do so once the subpattern cannot match any more.
 
                 // This is the entry point to jump to when we stop matching - we will
                 // do so once the subpattern cannot match any more.
@@ -1555,9 +1709,9 @@ class YarrGenerator : private MacroAssembler {
             }
 
             case OpMatchFailed:
             }
 
             case OpMatchFailed:
-                if (m_pattern.m_body->m_callFrameSize)
-                    addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
-                move(TrustedImm32(-1), returnRegister);
+                removeCallFrame();
+                move(TrustedImmPtr((void*)WTF::notFound), returnRegister);
+                move(TrustedImm32(0), returnRegister2);
                 generateReturn();
                 break;
             }
                 generateReturn();
                 break;
             }
@@ -1652,14 +1806,14 @@ class YarrGenerator : private MacroAssembler {
                         // 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)
                         // 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));
+                                setMatchStart(index);
                             else {
                                 move(index, regT0);
                                 if (alternative->m_minimumSize)
                                     sub32(Imm32(alternative->m_minimumSize - 1), regT0);
                                 else
                             else {
                                 move(index, regT0);
                                 if (alternative->m_minimumSize)
                                     sub32(Imm32(alternative->m_minimumSize - 1), regT0);
                                 else
-                                    add32(Imm32(1), regT0);
-                                store32(regT0, Address(output));
+                                    add32(TrustedImm32(1), regT0);
+                                setMatchStart(regT0);
                             }
                         }
 
                             }
                         }
 
@@ -1745,7 +1899,7 @@ class YarrGenerator : private MacroAssembler {
                 // disjunction is 0, e.g. /a*|b/).
                 if (needsToUpdateMatchStart && alternative->m_minimumSize == 1) {
                     // index is already incremented by 1, so just store it now!
                 // 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));
+                    setMatchStart(index);
                     needsToUpdateMatchStart = false;
                 }
 
                     needsToUpdateMatchStart = false;
                 }
 
@@ -1757,7 +1911,7 @@ class YarrGenerator : private MacroAssembler {
                 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.
                 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);
+                    add32(TrustedImm32(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!
                 } 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!
@@ -1769,11 +1923,11 @@ class YarrGenerator : private MacroAssembler {
 
                 if (needsToUpdateMatchStart) {
                     if (!m_pattern.m_body->m_minimumSize)
 
                 if (needsToUpdateMatchStart) {
                     if (!m_pattern.m_body->m_minimumSize)
-                        store32(index, Address(output));
+                        setMatchStart(index);
                     else {
                         move(index, regT0);
                         sub32(Imm32(m_pattern.m_body->m_minimumSize), regT0);
                     else {
                         move(index, regT0);
                         sub32(Imm32(m_pattern.m_body->m_minimumSize), regT0);
-                        store32(regT0, Address(output));
+                        setMatchStart(regT0);
                     }
                 }
 
                     }
                 }
 
@@ -1795,9 +1949,9 @@ class YarrGenerator : private MacroAssembler {
                 // run any matches, and need to return a failure state from JIT code.
                 matchFailed.link(this);
 
                 // 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);
+                removeCallFrame();
+                move(TrustedImmPtr((void*)WTF::notFound), returnRegister);
+                move(TrustedImm32(0), returnRegister2);
                 generateReturn();
                 break;
             }
                 generateReturn();
                 break;
             }
@@ -1862,7 +2016,7 @@ class YarrGenerator : private MacroAssembler {
                         // An alternative that is not the last should jump to its successor.
                         jump(nextOp.m_reentry);
                     } else if (!isBegin) {
                         // 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.
+                        // The last of more than one alternatives must jump back to the beginning.
                         nextOp.m_jumps.append(jump());
                     } else {
                         // A single alternative on its own can fall through.
                         nextOp.m_jumps.append(jump());
                     } else {
                         // A single alternative on its own can fall through.
@@ -1874,12 +2028,16 @@ class YarrGenerator : private MacroAssembler {
                         // An alternative that is not the last should jump to its successor.
                         m_backtrackingState.linkTo(nextOp.m_reentry, this);
                     } else if (!isBegin) {
                         // 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.
+                        // The last of more than one alternatives must jump back to the beginning.
                         m_backtrackingState.takeBacktracksToJumpList(nextOp.m_jumps, this);
                     }
                     // In the case of a single alternative on its own do nothing - it can fall through.
                 }
 
                         m_backtrackingState.takeBacktracksToJumpList(nextOp.m_jumps, this);
                     }
                     // In the case of a single alternative on its own do nothing - it can fall through.
                 }
 
+                // If there is a backtrack jump from a zero length match link it here.
+                if (op.m_zeroLengthMatch.isSet())
+                    m_backtrackingState.append(op.m_zeroLengthMatch);
+
                 // At this point we've handled the backtracking back into this node.
                 // Now link any backtracks that need to jump to here.
 
                 // At this point we've handled the backtracking back into this node.
                 // Now link any backtracks that need to jump to here.
 
@@ -1912,6 +2070,10 @@ class YarrGenerator : private MacroAssembler {
             case OpNestedAlternativeEnd: {
                 PatternTerm* term = op.m_term;
 
             case OpNestedAlternativeEnd: {
                 PatternTerm* term = op.m_term;
 
+                // If there is a backtrack jump from a zero length match link it here.
+                if (op.m_zeroLengthMatch.isSet())
+                    m_backtrackingState.append(op.m_zeroLengthMatch);
+
                 // 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
                 // 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
@@ -1956,12 +2118,12 @@ class YarrGenerator : private MacroAssembler {
                 ASSERT(term->quantityCount == 1);
 
                 // We only need to backtrack to thispoint if capturing or greedy.
                 ASSERT(term->quantityCount == 1);
 
                 // We only need to backtrack to thispoint if capturing or greedy.
-                if (term->capture() || term->quantityType == QuantifierGreedy) {
+                if ((term->capture() && compileMode == IncludeSubpatterns) || term->quantityType == QuantifierGreedy) {
                     m_backtrackingState.link(this);
 
                     // If capturing, clear the capture (we only need to reset start).
                     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 (term->capture() && compileMode == IncludeSubpatterns)
+                        clearSubpatternStart(term->parentheses.subpatternId);
 
                     // If Greedy, jump to the end.
                     if (term->quantityType == QuantifierGreedy) {
 
                     // If Greedy, jump to the end.
                     if (term->quantityType == QuantifierGreedy) {
@@ -2351,9 +2513,11 @@ class YarrGenerator : private MacroAssembler {
         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, 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);
+        if (compileMode == IncludeSubpatterns)
+            loadPtr(Address(X86Registers::ebp, 5 * sizeof(void*)), output);
     #else
     #else
-        loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), output);
+        if (compileMode == IncludeSubpatterns)
+            loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), output);
     #endif
 #elif CPU(ARM)
         push(ARMRegisters::r4);
     #endif
 #elif CPU(ARM)
         push(ARMRegisters::r4);
@@ -2362,7 +2526,8 @@ class YarrGenerator : private MacroAssembler {
 #if CPU(ARM_TRADITIONAL)
         push(ARMRegisters::r8); // scratch register
 #endif
 #if CPU(ARM_TRADITIONAL)
         push(ARMRegisters::r8); // scratch register
 #endif
-        move(ARMRegisters::r3, output);
+        if (compileMode == IncludeSubpatterns)
+            move(ARMRegisters::r3, output);
 #elif CPU(SH4)
         push(SH4Registers::r11);
         push(SH4Registers::r13);
 #elif CPU(SH4)
         push(SH4Registers::r11);
         push(SH4Registers::r13);
@@ -2398,8 +2563,10 @@ class YarrGenerator : private MacroAssembler {
     }
 
 public:
     }
 
 public:
-    YarrGenerator(YarrPattern& pattern)
+    YarrGenerator(YarrPattern& pattern, YarrCharSize charSize)
         : m_pattern(pattern)
         : m_pattern(pattern)
+        , m_charSize(charSize)
+        , m_charScale(m_charSize == Char8 ? TimesOne: TimesTwo)
         , m_shouldFallBack(false)
         , m_checked(0)
     {
         , m_shouldFallBack(false)
         , m_checked(0)
     {
@@ -2409,11 +2576,21 @@ public:
     {
         generateEnter();
 
     {
         generateEnter();
 
+        Jump hasInput = checkInput();
+        move(TrustedImmPtr((void*)WTF::notFound), returnRegister);
+        move(TrustedImm32(0), returnRegister2);
+        generateReturn();
+        hasInput.link(this);
+
+        if (compileMode == IncludeSubpatterns) {
+            for (unsigned i = 0; i < m_pattern.m_numSubpatterns + 1; ++i)
+                store32(TrustedImm32(-1), Address(output, (i << 1) * sizeof(int)));
+        }
+
         if (!m_pattern.m_body->m_hasFixedSize)
         if (!m_pattern.m_body->m_hasFixedSize)
-            store32(index, Address(output));
+            setMatchStart(index);
 
 
-        if (m_pattern.m_body->m_callFrameSize)
-            subPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+        initCallFrame();
 
         // Compile the pattern to the internal 'YarrOp' representation.
         opCompileBody(m_pattern.m_body);
 
         // Compile the pattern to the internal 'YarrOp' representation.
         opCompileBody(m_pattern.m_body);
@@ -2429,15 +2606,30 @@ public:
         backtrack();
 
         // Link & finalize the code.
         backtrack();
 
         // Link & finalize the code.
-        LinkBuffer linkBuffer(*globalData, this, globalData->regexAllocator);
+        LinkBuffer linkBuffer(*globalData, this, REGEXP_CODE_ID);
         m_backtrackingState.linkDataLabels(linkBuffer);
         m_backtrackingState.linkDataLabels(linkBuffer);
-        jitObject.set(linkBuffer.finalizeCode());
+
+        if (compileMode == MatchOnly) {
+            if (m_charSize == Char8)
+                jitObject.set8BitCodeMatchOnly(linkBuffer.finalizeCode());
+            else
+                jitObject.set16BitCodeMatchOnly(linkBuffer.finalizeCode());
+        } else {
+            if (m_charSize == Char8)
+                jitObject.set8BitCode(linkBuffer.finalizeCode());
+            else
+                jitObject.set16BitCode(linkBuffer.finalizeCode());
+        }
         jitObject.setFallBack(m_shouldFallBack);
     }
 
 private:
     YarrPattern& m_pattern;
 
         jitObject.setFallBack(m_shouldFallBack);
     }
 
 private:
     YarrPattern& m_pattern;
 
+    YarrCharSize m_charSize;
+
+    Scale m_charScale;
+
     // 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;
     // 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;
@@ -2461,14 +2653,12 @@ private:
     BacktrackingState m_backtrackingState;
 };
 
     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)
+void jitCompile(YarrPattern& pattern, YarrCharSize charSize, JSGlobalData* globalData, YarrCodeBlock& jitObject, YarrJITCompileMode mode)
 {
 {
-    return jitObject.execute(input, start, length, output);
+    if (mode == MatchOnly)
+        YarrGenerator<MatchOnly>(pattern, charSize).compile(globalData, jitObject);
+    else
+        YarrGenerator<IncludeSubpatterns>(pattern, charSize).compile(globalData, jitObject);
 }
 
 }}
 }
 
 }}
index 91c5b85c916f4e52f29ff91a7047fd307afa9d04..71928e73ce7dd4156c2e83551d63d3fea0a7738e 100644 (file)
 #if ENABLE(YARR_JIT)
 
 #include "JSGlobalData.h"
 #if ENABLE(YARR_JIT)
 
 #include "JSGlobalData.h"
-#include "MacroAssembler.h"
+#include "MacroAssemblerCodeRef.h"
+#include "MatchResult.h"
 #include "UString.h"
 #include "UString.h"
+#include "Yarr.h"
 #include "YarrPattern.h"
 
 #if CPU(X86) && !COMPILER(MSVC)
 #include "YarrPattern.h"
 
 #if CPU(X86) && !COMPILER(MSVC)
@@ -47,7 +49,17 @@ class ExecutablePool;
 namespace Yarr {
 
 class YarrCodeBlock {
 namespace Yarr {
 
 class YarrCodeBlock {
-    typedef int (*YarrJITCode)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+#if CPU(X86_64)
+    typedef MatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+    typedef MatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+    typedef MatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL;
+    typedef MatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL;
+#else
+    typedef EncodedMatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+    typedef EncodedMatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+    typedef EncodedMatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL;
+    typedef EncodedMatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL;
+#endif
 
 public:
     YarrCodeBlock()
 
 public:
     YarrCodeBlock()
@@ -61,24 +73,67 @@ public:
 
     void setFallBack(bool fallback) { m_needFallBack = fallback; }
     bool isFallBack() { return m_needFallBack; }
 
     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)
+    bool has8BitCode() { return m_ref8.size(); }
+    bool has16BitCode() { return m_ref16.size(); }
+    void set8BitCode(MacroAssemblerCodeRef ref) { m_ref8 = ref; }
+    void set16BitCode(MacroAssemblerCodeRef ref) { m_ref16 = ref; }
+
+    bool has8BitCodeMatchOnly() { return m_matchOnly8.size(); }
+    bool has16BitCodeMatchOnly() { return m_matchOnly16.size(); }
+    void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly8 = matchOnly; }
+    void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly16 = matchOnly; }
+
+    MatchResult execute(const LChar* input, unsigned start, unsigned length, int* output)
     {
     {
-        return reinterpret_cast<YarrJITCode>(m_ref.m_code.executableAddress())(input, start, length, output);
+        ASSERT(has8BitCode());
+        return MatchResult(reinterpret_cast<YarrJITCode8>(m_ref8.code().executableAddress())(input, start, length, output));
+    }
+
+    MatchResult execute(const UChar* input, unsigned start, unsigned length, int* output)
+    {
+        ASSERT(has16BitCode());
+        return MatchResult(reinterpret_cast<YarrJITCode16>(m_ref16.code().executableAddress())(input, start, length, output));
+    }
+
+    MatchResult execute(const LChar* input, unsigned start, unsigned length)
+    {
+        ASSERT(has8BitCodeMatchOnly());
+        return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly8>(m_matchOnly8.code().executableAddress())(input, start, length));
+    }
+
+    MatchResult execute(const UChar* input, unsigned start, unsigned length)
+    {
+        ASSERT(has16BitCodeMatchOnly());
+        return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly16>(m_matchOnly16.code().executableAddress())(input, start, length));
     }
 
 #if ENABLE(REGEXP_TRACING)
     }
 
 #if ENABLE(REGEXP_TRACING)
-    void *getAddr() { return m_ref.m_code.executableAddress(); }
+    void *getAddr() { return m_ref.code().executableAddress(); }
 #endif
 
 #endif
 
+    void clear()
+    {
+        m_ref8 = MacroAssemblerCodeRef();
+        m_ref16 = MacroAssemblerCodeRef();
+        m_matchOnly8 = MacroAssemblerCodeRef();
+        m_matchOnly16 = MacroAssemblerCodeRef();
+        m_needFallBack = false;
+    }
+
 private:
 private:
-    MacroAssembler::CodeRef m_ref;
+    MacroAssemblerCodeRef m_ref8;
+    MacroAssemblerCodeRef m_ref16;
+    MacroAssemblerCodeRef m_matchOnly8;
+    MacroAssemblerCodeRef m_matchOnly16;
     bool m_needFallBack;
 };
 
     bool m_needFallBack;
 };
 
-void jitCompile(YarrPattern&, JSGlobalData*, YarrCodeBlock& jitObject);
-int execute(YarrCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output);
+enum YarrJITCompileMode {
+    MatchOnly,
+    IncludeSubpatterns
+};
+void jitCompile(YarrPattern&, YarrCharSize, JSGlobalData*, YarrCodeBlock& jitObject, YarrJITCompileMode = IncludeSubpatterns);
 
 } } // namespace JSC::Yarr
 
 
 } } // namespace JSC::Yarr
 
index 65fb41da125221dbac2d9afaf6a8afa7a8fc1923..1182d790781b700850209f3635602149ddebabe6 100644 (file)
@@ -43,7 +43,7 @@ enum BuiltInCharacterClassID {
 };
 
 // The Parser class should not be used directly - only via the Yarr::parse() method.
 };
 
 // The Parser class should not be used directly - only via the Yarr::parse() method.
-template<class Delegate>
+template<class Delegate, typename CharType>
 class Parser {
 private:
     template<class FriendDelegate>
 class Parser {
 private:
     template<class FriendDelegate>
@@ -54,6 +54,7 @@ private:
         PatternTooLarge,
         QuantifierOutOfOrder,
         QuantifierWithoutAtom,
         PatternTooLarge,
         QuantifierOutOfOrder,
         QuantifierWithoutAtom,
+        QuantifierTooLarge,
         MissingParentheses,
         ParenthesesUnmatched,
         ParenthesesTypeInvalid,
         MissingParentheses,
         ParenthesesUnmatched,
         ParenthesesTypeInvalid,
@@ -211,8 +212,8 @@ private:
 
         // parseEscape() should never call these delegate methods when
         // invoked with inCharacterClass set.
 
         // parseEscape() should never call these delegate methods when
         // invoked with inCharacterClass set.
-        void assertionWordBoundary(bool) { ASSERT_NOT_REACHED(); }
-        void atomBackReference(unsigned) { ASSERT_NOT_REACHED(); }
+        NO_RETURN_DUE_TO_ASSERT void assertionWordBoundary(bool) { ASSERT_NOT_REACHED(); }
+        NO_RETURN_DUE_TO_ASSERT void atomBackReference(unsigned) { ASSERT_NOT_REACHED(); }
 
     private:
         Delegate& m_delegate;
 
     private:
         Delegate& m_delegate;
@@ -231,13 +232,13 @@ private:
         : m_delegate(delegate)
         , m_backReferenceLimit(backReferenceLimit)
         , m_err(NoError)
         : m_delegate(delegate)
         , m_backReferenceLimit(backReferenceLimit)
         , m_err(NoError)
-        , m_data(pattern.characters())
+        , m_data(pattern.getCharacters<CharType>())
         , m_size(pattern.length())
         , m_index(0)
         , m_parenthesesNestingDepth(0)
     {
     }
         , m_size(pattern.length())
         , m_index(0)
         , m_parenthesesNestingDepth(0)
     {
     }
-    
+
     /*
      * parseEscape():
      *
     /*
      * parseEscape():
      *
@@ -546,6 +547,11 @@ private:
         ASSERT(!m_err);
         ASSERT(min <= max);
 
         ASSERT(!m_err);
         ASSERT(min <= max);
 
+        if (min == UINT_MAX) {
+            m_err = QuantifierTooLarge;
+            return;
+        }
+
         if (lastTokenWasAnAtom)
             m_delegate.quantifyAtom(min, max, !tryConsume('?'));
         else
         if (lastTokenWasAnAtom)
             m_delegate.quantifyAtom(min, max, !tryConsume('?'));
         else
@@ -685,6 +691,7 @@ private:
             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 "regular expression too large",
             REGEXP_ERROR_PREFIX "numbers out of order in {} quantifier",
             REGEXP_ERROR_PREFIX "nothing to repeat",
+            REGEXP_ERROR_PREFIX "number too large in {} quantifier",
             REGEXP_ERROR_PREFIX "missing )",
             REGEXP_ERROR_PREFIX "unmatched parentheses",
             REGEXP_ERROR_PREFIX "unrecognized character after (?",
             REGEXP_ERROR_PREFIX "missing )",
             REGEXP_ERROR_PREFIX "unmatched parentheses",
             REGEXP_ERROR_PREFIX "unrecognized character after (?",
@@ -696,7 +703,6 @@ private:
         return errorMessages[m_err];
     }
 
         return errorMessages[m_err];
     }
 
-
     // Misc helper functions:
 
     typedef unsigned ParseState;
     // Misc helper functions:
 
     typedef unsigned ParseState;
@@ -793,7 +799,7 @@ private:
     Delegate& m_delegate;
     unsigned m_backReferenceLimit;
     ErrorCode m_err;
     Delegate& m_delegate;
     unsigned m_backReferenceLimit;
     ErrorCode m_err;
-    const UChar* m_data;
+    const CharType* m_data;
     unsigned m_size;
     unsigned m_index;
     unsigned m_parenthesesNestingDepth;
     unsigned m_size;
     unsigned m_index;
     unsigned m_parenthesesNestingDepth;
@@ -864,7 +870,9 @@ private:
 template<class Delegate>
 const char* parse(Delegate& delegate, const UString& pattern, unsigned backReferenceLimit = quantifyInfinite)
 {
 template<class Delegate>
 const char* parse(Delegate& delegate, const UString& pattern, unsigned backReferenceLimit = quantifyInfinite)
 {
-    return Parser<Delegate>(delegate, pattern, backReferenceLimit).parse();
+    if (pattern.is8Bit())
+        return Parser<Delegate, LChar>(delegate, pattern, backReferenceLimit).parse();
+    return Parser<Delegate, UChar>(delegate, pattern, backReferenceLimit).parse();
 }
 
 } } // namespace JSC::Yarr
 }
 
 } } // namespace JSC::Yarr
index bf150c120dc4d939353f40a720373c3a31904cf9..bbda9c5266f23797e56673987ffa94cd737b9629 100644 (file)
@@ -28,6 +28,7 @@
 #include "YarrPattern.h"
 
 #include "Yarr.h"
 #include "YarrPattern.h"
 
 #include "Yarr.h"
+#include "YarrCanonicalizeUCS2.h"
 #include "YarrParser.h"
 #include <wtf/Vector.h>
 
 #include "YarrParser.h"
 #include <wtf/Vector.h>
 
@@ -66,32 +67,43 @@ public:
 
     void putChar(UChar ch)
     {
 
     void putChar(UChar ch)
     {
+        // Handle ascii cases.
         if (ch <= 0x7f) {
             if (m_isCaseInsensitive && isASCIIAlpha(ch)) {
                 addSorted(m_matches, toASCIIUpper(ch));
                 addSorted(m_matches, toASCIILower(ch));
             } else
                 addSorted(m_matches, 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);
+            return;
         }
         }
-    }
 
 
-    // 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);
+        // Simple case, not a case-insensitive match.
+        if (!m_isCaseInsensitive) {
+            addSorted(m_matchesUnicode, ch);
+            return;
+        }
+
+        // Add multiple matches, if necessary.
+        UCS2CanonicalizationRange* info = rangeInfoFor(ch);
+        if (info->type == CanonicalizeUnique)
+            addSorted(m_matchesUnicode, ch);
+        else
+            putUnicodeIgnoreCase(ch, info);
     }
 
     }
 
-    // returns true if this character has another case, and 'ch' is the lower case form.
-    static inline bool isUnicodeLower(UChar ch)
+    void putUnicodeIgnoreCase(UChar ch, UCS2CanonicalizationRange* info)
     {
     {
-        return ch != Unicode::toUpper(ch);
+        ASSERT(m_isCaseInsensitive);
+        ASSERT(ch > 0x7f);
+        ASSERT(ch >= info->begin && ch <= info->end);
+        ASSERT(info->type != CanonicalizeUnique);
+        if (info->type == CanonicalizeSet) {
+            for (uint16_t* set = characterSetInfo[info->value]; (ch = *set); ++set)
+                addSorted(m_matchesUnicode, ch);
+        } else {
+            addSorted(m_matchesUnicode, ch);
+            addSorted(m_matchesUnicode, getCanonicalPair(info, ch));
+        }
     }
 
     void putRange(UChar lo, UChar hi)
     }
 
     void putRange(UChar lo, UChar hi)
@@ -108,48 +120,69 @@ public:
                     addSortedRange(m_ranges, std::max(asciiLo, 'a')+('A'-'a'), std::min(asciiHi, 'z')+('A'-'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;
-                }
+        if (hi <= 0x7f)
+            return;
+
+        lo = std::max(lo, (UChar)0x80);
+        addSortedRange(m_rangesUnicode, lo, hi);
+        
+        if (!m_isCaseInsensitive)
+            return;
+
+        UCS2CanonicalizationRange* info = rangeInfoFor(lo);
+        while (true) {
+            // Handle the range [lo .. end]
+            UChar end = std::min<UChar>(info->end, hi);
+
+            switch (info->type) {
+            case CanonicalizeUnique:
+                // Nothing to do - no canonical equivalents.
+                break;
+            case CanonicalizeSet: {
+                UChar ch;
+                for (uint16_t* set = characterSetInfo[info->value]; (ch = *set); ++set)
+                    addSorted(m_matchesUnicode, ch);
+                break;
             }
             }
-        }
+            case CanonicalizeRangeLo:
+                addSortedRange(m_rangesUnicode, lo + info->value, end + info->value);
+                break;
+            case CanonicalizeRangeHi:
+                addSortedRange(m_rangesUnicode, lo - info->value, end - info->value);
+                break;
+            case CanonicalizeAlternatingAligned:
+                // Use addSortedRange since there is likely an abutting range to combine with.
+                if (lo & 1)
+                    addSortedRange(m_rangesUnicode, lo - 1, lo - 1);
+                if (!(end & 1))
+                    addSortedRange(m_rangesUnicode, end + 1, end + 1);
+                break;
+            case CanonicalizeAlternatingUnaligned:
+                // Use addSortedRange since there is likely an abutting range to combine with.
+                if (!(lo & 1))
+                    addSortedRange(m_rangesUnicode, lo - 1, lo - 1);
+                if (end & 1)
+                    addSortedRange(m_rangesUnicode, end + 1, end + 1);
+                break;
+            }
+
+            if (hi == end)
+                return;
+
+            ++info;
+            lo = info->begin;
+        };
+
     }
 
     CharacterClass* charClass()
     {
         CharacterClass* characterClass = new CharacterClass(0);
 
     }
 
     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();
+        characterClass->m_matches.swap(m_matches);
+        characterClass->m_ranges.swap(m_ranges);
+        characterClass->m_matchesUnicode.swap(m_matchesUnicode);
+        characterClass->m_rangesUnicode.swap(m_rangesUnicode);
 
         return characterClass;
     }
 
         return characterClass;
     }
@@ -282,12 +315,21 @@ public:
     {
         // We handle case-insensitive checking of unicode characters which do have both
         // cases by handling them as if they were defined using a CharacterClass.
     {
         // 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
+        if (!m_pattern.m_ignoreCase || isASCII(ch)) {
+            m_alternative->m_terms.append(PatternTerm(ch));
+            return;
+        }
+
+        UCS2CanonicalizationRange* info = rangeInfoFor(ch);
+        if (info->type == CanonicalizeUnique) {
             m_alternative->m_terms.append(PatternTerm(ch));
             m_alternative->m_terms.append(PatternTerm(ch));
+            return;
+        }
+
+        m_characterClassConstructor.putUnicodeIgnoreCase(ch, info);
+        CharacterClass* newCharacterClass = m_characterClassConstructor.charClass();
+        m_pattern.m_userCharacterClasses.append(newCharacterClass);
+        m_alternative->m_terms.append(PatternTerm(newCharacterClass, false));
     }
 
     void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert)
     }
 
     void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert)
@@ -478,14 +520,23 @@ public:
         ASSERT(term.type > PatternTerm::TypeAssertionWordBoundary);
         ASSERT((term.quantityCount == 1) && (term.quantityType == QuantifierFixedCount));
 
         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 (term.type == PatternTerm::TypeParentheticalAssertion) {
+            // If an assertion is quantified with a minimum count of zero, it can simply be removed.
+            // This arises from the RepeatMatcher behaviour in the spec. Matching an assertion never
+            // results in any input being consumed, however the continuation passed to the assertion
+            // (called in steps, 8c and 9 of the RepeatMatcher definition, ES5.1 15.10.2.5) will
+            // reject all zero length matches (see step 2.1). A match from the continuation of the
+            // expression will still be accepted regardless (via steps 8a and 11) - the upshot of all
+            // this is that matches from the assertion are not required, and won't be accepted anyway,
+            // so no need to ever run it.
             if (!min)
                 m_alternative->removeLastTerm();
             if (!min)
                 m_alternative->removeLastTerm();
+            // We never need to run an assertion more than once. Subsequent interations will be run
+            // with the same start index (since assertions are non-capturing) and the same captures
+            // (per step 4 of RepeatMatcher in ES5.1 15.10.2.5), and as such will always produce the
+            // same result and captures. If the first match succeeds then the subsequent (min - 1)
+            // matches will too. Any additional optional matches will fail (on the same basis as the
+            // minimum zero quantified assertions, above), but this will still result in a match.
             return;
         }
 
             return;
         }
 
index e46479ef59cb14b3aa8d60778536c3df014e7cce..a31deee67294644e5dc4aad4d7a06b073b20b79f 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <runtime/UString.h>
 #include <wtf/CheckedArithmetic.h>
 
 #include <runtime/UString.h>
 #include <wtf/CheckedArithmetic.h>
+#include <wtf/RefCounted.h>
 #include <wtf/Vector.h>
 #include <wtf/unicode/Unicode.h>
 
 #include <wtf/Vector.h>
 #include <wtf/unicode/Unicode.h>
 
@@ -315,7 +316,7 @@ struct TermChain {
 };
 
 struct YarrPattern {
 };
 
 struct YarrPattern {
-    YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, const char** error);
+    JS_EXPORT_PRIVATE YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, const char** error);
 
     ~YarrPattern()
     {
 
     ~YarrPattern()
     {
index a7b12422c7d88b6eded372dd9bcfa1a5781c14db..623098fd3af7b30e00ee8531425336cc82d400e9 100644 (file)
@@ -1,7 +1,18 @@
-# Yet Another Regex Runtime - Qt4 build info
+# -------------------------------------------------------------------
+# Project file for YARR
+#
+# See 'Tools/qmake/README' for an overview of the build system
+# -------------------------------------------------------------------
 
 SOURCES += \
 
 SOURCES += \
-    yarr/YarrInterpreter.cpp \
-    yarr/YarrPattern.cpp \
-    yarr/YarrSyntaxChecker.cpp
+    $$PWD/YarrInterpreter.cpp \
+    $$PWD/YarrPattern.cpp \
+    $$PWD/YarrSyntaxChecker.cpp \
+    $$PWD/YarrCanonicalizeUCS2.cpp
 
 
+# For UString.h
+v8 {
+    INCLUDEPATH += \
+        $$PWD/.. \
+        $$PWD/../runtime
+}